anchor.diff:  %%% limitations under the License.
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   %%%  @doc Test suite for authentication using Extensible Authentication
  -%%% 	Protocol (EAP) using only a password (EAP-PWD)
  +%%% 	Protocol (EAP) using only a password (EAP-AKA)
   %%% 	of the {@link //ocs. ocs} application.
   %%%
   -module(ocs_eap_aka_SUITE).
  
positive.code: %% Returns a list of all test cases in this test suite.
  %%
  all() ->
  	[eap_identity_over_radius].
  
  %%---------------------------------------------------------------------
  %%  Test cases
  %%---------------------------------------------------------------------
  
  eap_identity_over_radius() ->
  	[{userdata, [{doc, "Send an EAP-Identity/Response using RADIUS to peer"}]}].
  
  eap_identity_over_radius(Config) ->
  	MAC = "AA-BB-CC-DD-EE-FF",
  	PeerId = <<"12345678">>,
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth = radius:authenticator(),
  	RadId = 1, EapId = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth, EapId, RadId),
  	NextEapId = EapId + 1,
  	{NextEapId, _Token, _ServerID} = receive_radius_id(Socket, Address,
  			Port, Secret, ReqAuth, RadId).
  
  <<<<<<< HEAD
  eap_identity_over_diameter() ->
     [{userdata, [{doc, "Send an EAP-Identity/Response using DIAMETER to peer"}]}].
  
  eap_identity_over_diameter(_Config) ->
  	Ref = erlang:ref_to_list(make_ref()),
  	SId = diameter:session_id(Ref),
  	EapId = 1,
  	PeerId = <<"12345678">>,
  	DEA = send_diameter_identity(SId, EapId, PeerId),
  	SIdbin = list_to_binary(SId),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH'} = DEA.
  
  pwd_id_over_radius() ->
     [{userdata, [{doc, "Send an EAP-pwd-ID/Response to peer"}]}].
  
  pwd_id_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId} =  add_service(ProdRef),
  	MAC = "BB-CC-DD-EE-FF-AA",
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth1 = radius:authenticator(),
  	RadId1 = 2, EapId1 = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth1, EapId1, RadId1),
  	EapId2 = EapId1 + 1,
  	{EapId2, Token, _ServerID} = receive_radius_id(Socket, Address,
  			Port, Secret, ReqAuth1, RadId1),
  	RadId2 = RadId1 + 1,
  	ReqAuth2 = radius:authenticator(),
  	send_radius_id(Socket, Address, Port, Secret,
  			ReqAuth2, UserName, NasId, PeerId, MAC, Token, EapId2, RadId2),
  	EapId3 = EapId2 + 1,
  	{EapId3, _ElementS, _ScalarS} = receive_radius_commit(Socket, Address,
  			Port, Secret, ReqAuth2, RadId2).
  
  pwd_id_over_diameter() ->
     [{userdata, [{doc, "Send an EAP-pwd-ID/Response to peer using DIAMETER"}]}].
  
  pwd_id_over_diameter(_Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId} =  add_service(ProdRef),
  	Ref = erlang:ref_to_list(make_ref()),
  	SId = diameter:session_id(Ref),
  	EapId0 = 0,
  	DEA = send_diameter_identity(SId, EapId0, PeerId),
  	SIdbin = list_to_binary(SId),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH',
  			'EAP-Payload' = [Payload]} = DEA,
  	#eap_packet{code = request, type = ?PWD, identifier = EapId,
  		data = EapData} = ocs_eap_codec:eap_packet(Payload),
  	#eap_pwd{length = false, more = false, pwd_exch = id,
  			data = EapPwdData} = ocs_eap_codec:eap_pwd(EapData),
  	#eap_pwd_id{group_desc = 19, random_fun = 16#1,
  			prf = 16#1, pwd_prep = none, token = Token,
  			identity = _ServerId} = ocs_eap_codec:eap_pwd_id(EapPwdData),
  	DEA1 = send_diameter_id(SId, Token, PeerId, EapId),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH',
  			'EAP-Payload' = [Payload1]} = DEA1,
  	#eap_packet{code = request, type = ?PWD, identifier = EapId1,
  		data = EapData1} = ocs_eap_codec:eap_packet(Payload1),
  	EapId1 = EapId + 1,
  	#eap_pwd{length = false, more = false, pwd_exch = commit,
  			data = EapPwdData1} = ocs_eap_codec:eap_pwd(EapData1),
  	#eap_pwd_commit{element = Element, scalar = Scalar} = ocs_eap_codec:eap_pwd_commit(EapPwdData1),
  	true = is_binary(Element),
  	true = is_binary(Scalar),
  	ok = ocs:delete_service(PeerId).
  
  pwd_commit_over_radius() ->
  	[{userdata, [{doc, "Send an EAP-pwd-Commit/Response using RADIUS to peer"}]}].
  
  pwd_commit_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId, password = PeerAuth} =  add_service(ProdRef),
  	MAC = "CC-DD-EE-FF-AA-BB",
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth1 = radius:authenticator(),
  	RadId1 = 5, EapId1 = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth1, EapId1, RadId1),
  	EapId2 = EapId1 + 1,
  	{EapId2, Token, ServerID} = receive_radius_id(Socket, Address,
  			Port, Secret, ReqAuth1, RadId1),
  	RadId2 = RadId1 + 1,
  	ReqAuth2 = radius:authenticator(),
  	send_radius_id(Socket, Address, Port, Secret,
  			ReqAuth2, UserName, NasId, PeerId, MAC, Token, EapId2, RadId2),
  	EapId3 = EapId2 + 1,
  	{EapId3, _ElementS, _ScalarS} = receive_radius_commit(Socket, Address,
  			Port, Secret, ReqAuth2, RadId2),
  	Prand = crypto:rand_uniform(1, ?R),
  	PWE = ocs_eap_pwd:compute_pwe(Token, PeerId, ServerID, PeerAuth),
  	{ScalarP, ElementP} = ocs_eap_pwd:compute_scalar(<<Prand:256>>, PWE),
  	RadId3 = RadId2 + 1,
  	ReqAuth3 = radius:authenticator(),
  	ok = send_radius_commit(Socket, Address, Port, Secret, ReqAuth3,
  			UserName, NasId, MAC, ScalarP, ElementP, EapId3, RadId3),
  	EapId4 = EapId3 + 1,
  	{EapId4, _ConfirmS} = receive_radius_confirm(Socket,
  			Address, Port, Secret, ReqAuth3, RadId3).
  
  pwd_commit_over_diameter() ->
     [{userdata, [{doc, "Send an EAP-pwd-Commit/Response to peer using DIAMETER"}]}].
  
  pwd_commit_over_diameter(_Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId, password = PeerAuth} =  add_service(ProdRef),
  	Ref = erlang:ref_to_list(make_ref()),
  	SId = diameter:session_id(Ref),
  	EapId0 = 0,
  	DEA = send_diameter_identity(SId, EapId0, PeerId),
  	SIdbin = list_to_binary(SId),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH',
  			'EAP-Payload' = [Payload]} = DEA,
  	#eap_packet{code = request, type = ?PWD, identifier = EapId,
  		data = EapData} = ocs_eap_codec:eap_packet(Payload),
  	#eap_pwd{length = false, more = false, pwd_exch = id,
  			data = EapPwdData} = ocs_eap_codec:eap_pwd(EapData),
  	#eap_pwd_id{group_desc = 19, random_fun = 16#1,
  			prf = 16#1, pwd_prep = none, token = Token,
  			identity = ServerId} = ocs_eap_codec:eap_pwd_id(EapPwdData),
  	DEA1 = send_diameter_id(SId, Token, PeerId, EapId),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH',
  			'EAP-Payload' = [Payload1]} = DEA1,
  	#eap_packet{code = request, type = ?PWD, identifier = EapId1,
  		data = EapData1} = ocs_eap_codec:eap_packet(Payload1),
  	EapId1 = EapId + 1,
  	#eap_pwd{length = false, more = false, pwd_exch = commit,
  			data = EapPwdData1} = ocs_eap_codec:eap_pwd(EapData1),
  	#eap_pwd_commit{element = ElementS, scalar = ScalarS} = ocs_eap_codec:eap_pwd_commit(EapPwdData1),
  	true = is_binary(ElementS),
  	true = is_binary(ScalarS),
  	Prand = crypto:rand_uniform(1, ?R),
  	PWE = ocs_eap_pwd:compute_pwe(Token, PeerId, ServerId, PeerAuth),
  	{ScalarP, ElementP} = ocs_eap_pwd:compute_scalar(<<Prand:256>>, PWE),
  	DEA2 = send_diameter_commit(SId, ScalarP, ElementP, EapId1),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH',
  			'EAP-Payload' = [Payload2]} = DEA2,
  	#eap_packet{code = request, type = ?PWD, identifier = EapId2,
  		data = EapData2} = ocs_eap_codec:eap_packet(Payload2),
  	EapId2 = EapId1 + 1,
  	#eap_pwd{length = false, more = false, pwd_exch = confirm,
  			data = _EapPwdData2} = ocs_eap_codec:eap_pwd(EapData2),
  	ok = ocs:delete_service(PeerId).
  	
  pwd_confirm_over_radius() ->
  	[{userdata, [{doc, "Send an EAP-pwd-Confirm/Response using RADIUS to peer"}]}].
  
  pwd_confirm_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId, password = PeerAuth} =  add_service(ProdRef),
  	B1 = bucket(octets, rand:uniform(100000)),
  	_BId = add_bucket(ProdRef, B1),
  	MAC = "DD-EE-FF-AA-BB-CC",
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth1 = radius:authenticator(),
  	RadId1 = 8, EapId1 = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth1, EapId1, RadId1),
  	EapId2 = EapId1 + 1,
  	{EapId2, Token, ServerID} = receive_radius_id(Socket, Address,
  			Port, Secret, ReqAuth1, RadId1),
  	RadId2 = RadId1 + 1,
  	ReqAuth2 = radius:authenticator(),
  	send_radius_id(Socket, Address, Port, Secret,
  			ReqAuth2, UserName, NasId, PeerId, MAC, Token, EapId2, RadId2),
  	EapId3 = EapId2 + 1,
  	{EapId3, ElementS, ScalarS} = receive_radius_commit(Socket, Address,
  			Port, Secret, ReqAuth2, RadId2),
  	PWE = ocs_eap_pwd:compute_pwe(Token, PeerId, ServerID, PeerAuth),
  	Prand = crypto:rand_uniform(1, ?R),
  	{ScalarP, ElementP} = ocs_eap_pwd:compute_scalar(<<Prand:256>>, PWE),
  	RadId3 = RadId2 + 1,
  	ReqAuth3 = radius:authenticator(),
  	ok = send_radius_commit(Socket, Address, Port, Secret, ReqAuth3,
  			UserName, NasId, MAC, ScalarP, ElementP, EapId3, RadId3),
  	EapId4 = EapId3 + 1,
  	{EapId4, _ConfirmS} = receive_radius_confirm(Socket,
  			Address, Port, Secret, ReqAuth3, RadId3),
  	Ciphersuite = <<19:16, 1, 1>>,
  	Kp = ocs_eap_pwd:compute_ks(<<Prand:256>>, PWE, ScalarS, ElementS),
  	Input = [Kp, ElementP, ScalarP, ElementS, ScalarS, Ciphersuite],
  	ConfirmP = ocs_eap_pwd:h(Input),
  	RadId4 = RadId3 + 1,
  	ReqAuth4 = radius:authenticator(),
  	send_radius_confirm(Socket, Address, Port, Secret, ReqAuth4, UserName,
  			NasId, MAC, ConfirmP, EapId4, RadId4),
  	EapId4 = receive_radius_success(Socket, Address, Port, Secret, ReqAuth4, RadId4).
  
  pwd_confirm_over_diameter() ->
     [{userdata, [{doc, "Send an EAP-pwd-Confirm/Response to peer using DIAMETER"}]}].
  
  pwd_confirm_over_diameter(_Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId, password = PeerAuth} =  add_service(ProdRef),
  	B1 = bucket(octets, rand:uniform(100000)),
  	_BId = add_bucket(ProdRef, B1),
  	Ref = erlang:ref_to_list(make_ref()),
  	SId = diameter:session_id(Ref),
  	EapId0 = 0,
  	DEA = send_diameter_identity(SId, EapId0, PeerId),
  	SIdbin = list_to_binary(SId),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH',
  			'EAP-Payload' = [Payload]} = DEA,
  	#eap_packet{code = request, type = ?PWD, identifier = EapId,
  		data = EapData} = ocs_eap_codec:eap_packet(Payload),
  	#eap_pwd{length = false, more = false, pwd_exch = id,
  			data = EapPwdData} = ocs_eap_codec:eap_pwd(EapData),
  	#eap_pwd_id{group_desc = 19, random_fun = 16#1,
  			prf = 16#1, pwd_prep = none, token = Token,
  			identity = ServerId} = ocs_eap_codec:eap_pwd_id(EapPwdData),
  	DEA1 = send_diameter_id(SId, Token, PeerId, EapId),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH',
  			'EAP-Payload' = [Payload1]} = DEA1,
  	#eap_packet{code = request, type = ?PWD, identifier = EapId1,
  		data = EapData1} = ocs_eap_codec:eap_packet(Payload1),
  	EapId1 = EapId + 1,
  	#eap_pwd{length = false, more = false, pwd_exch = commit,
  			data = EapPwdData1} = ocs_eap_codec:eap_pwd(EapData1),
  	#eap_pwd_commit{element = ElementS, scalar = ScalarS} = ocs_eap_codec:eap_pwd_commit(EapPwdData1),
  	true = is_binary(ElementS),
  	true = is_binary(ScalarS),
  	Prand = crypto:rand_uniform(1, ?R),
  	PWE = ocs_eap_pwd:compute_pwe(Token, PeerId, ServerId, PeerAuth),
  	{ScalarP, ElementP} = ocs_eap_pwd:compute_scalar(<<Prand:256>>, PWE),
  	DEA2 = send_diameter_commit(SId, ScalarP, ElementP, EapId1),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_MULTI_ROUND_AUTH',
  			'EAP-Payload' = [Payload2]} = DEA2,
  	#eap_packet{code = request, type = ?PWD, identifier = EapId2,
  		data = EapData2} = ocs_eap_codec:eap_packet(Payload2),
  	EapId2 = EapId1 + 1,
  	#eap_pwd{length = false, more = false, pwd_exch = confirm,
  			data = _EapPwdData2} = ocs_eap_codec:eap_pwd(EapData2),
  	Ciphersuite = <<19:16, 1, 1>>,
  	Kp = ocs_eap_pwd:compute_ks(<<Prand:256>>, PWE, ScalarS, ElementS),
  	Input = [Kp, ElementP, ScalarP, ElementS, ScalarS, Ciphersuite],
  	ConfirmP = ocs_eap_pwd:h(Input),
  	DEA3 = send_diameter_confirm(SId, ConfirmP, EapId2),
  	#diameter_eap_app_DEA{'Session-Id' = SIdbin, 'Auth-Application-Id' = ?EAP_APPLICATION_ID,
  			'Auth-Request-Type' =  ?'DIAMETER_BASE_AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE',
  			'Result-Code' = ?'DIAMETER_BASE_RESULT-CODE_SUCCESS',
  			'EAP-Payload' = [Payload3]} = DEA3,
  	#eap_packet{code = success,
  			identifier = EapId2} = ocs_eap_codec:eap_packet(Payload3),
  	ok = ocs:delete_service(PeerId).
  
  message_authentication_over_radius() ->
  	[{userdata, [{doc, "Send corrupt Message-Authenticator using RADIUS"}]}].
  
  message_authentication_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId} =  add_service(ProdRef),
  	MAC = "EE-FF-AA-BB-CC-DD",
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ocs:generate_password(),
  	ReqAuth = radius:authenticator(),
  	RadId = 13, EapId = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth, EapId, RadId),
  	{error, timeout} = gen_udp:recv(Socket, 0, 2000).
  
  role_reversal_over_radius() ->
  	[{userdata, [{doc, "Send EAP-Request (unsupported role reversal) using RADIUS"}]}].
  
  role_reversal_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId} =  add_service(ProdRef),
  	MAC = "FF-AA-BB-CC-DD-FF",
  	Socket = ?config(socket, Config),
  	Address = {127, 0, 0, 1},
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth = radius:authenticator(),
  	RadId = 14, EapId = 1,
  	Token = crypto:strong_rand_bytes(4),
  	EapPwdId = #eap_pwd_id{group_desc = 19, random_fun = 16#1, prf = 16#1,
  			token = Token, pwd_prep = none, identity = PeerId},
  	EapPwd = #eap_pwd{pwd_exch = id, data = ocs_eap_codec:eap_pwd_id(EapPwdId)},
  	EapPacket  = #eap_packet{code = request, type = ?PWD,
  			identifier = EapId, data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	ok = radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, ReqAuth, RadId, EapMsg),
  	{EapId, <<0>>} = receive_radius_nak(Socket, Address, Port, Secret, ReqAuth, RadId).
  
  validate_pwd_id_cipher_over_radius() ->
  	[{userdata, [{doc, "Send invalid EAP-pwd-ID (bad cipher) using RADIUS"}]}].
  
  validate_pwd_id_cipher_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId} =  add_service(ProdRef),
  	MAC = "AB-CD-EF-FE-DC-BA",
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth1 = radius:authenticator(),
  	RadId1 = 16, EapId1 = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth1, EapId1, RadId1),
  	EapId2 = EapId1 + 1,
  	{EapId2, Token, _ServerID} = receive_radius_id(Socket, Address,
  			Port, Secret, ReqAuth1, RadId1),
  	RadId2 = RadId1 + 1,
  	ReqAuth2 = radius:authenticator(),
  	InvalidGroup = 20, % 384-bit random ECP group
  	EapPwdId = #eap_pwd_id{group_desc = InvalidGroup, random_fun = 16#1, prf = 16#1,
  			token = Token, pwd_prep = none, identity = PeerId},
  	EapPwd = #eap_pwd{pwd_exch = id, data = ocs_eap_codec:eap_pwd_id(EapPwdId)},
  	EapPacket  = #eap_packet{code = response, type = ?PWD,
  			identifier = EapId2, data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	ok = radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, ReqAuth2, RadId2, EapMsg),
  	EapId2 = receive_radius_failure(Socket, Address, Port, Secret, ReqAuth2, RadId2).
  
  validate_pwd_id_prep_over_radius() ->
  	[{userdata, [{doc, "Send invalid EAP-pwd-ID (bad prep) using RADIUS"}]}].
  
  validate_pwd_id_prep_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId} =  add_service(ProdRef),
  	MAC = "CD-EF-FE-DC-BA-AB",
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth1 = radius:authenticator(),
  	RadId1 = 16, EapId1 = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth1, EapId1, RadId1),
  	EapId2 = EapId1 + 1,
  	{EapId2, Token, _ServerID} = receive_radius_id(Socket, Address,
  			Port, Secret, ReqAuth1, RadId1),
  	RadId2 = RadId1 + 1,
  	ReqAuth2 = radius:authenticator(),
  	UnimplementedPrep = saslprep,
  	EapPwdId = #eap_pwd_id{group_desc = 20, random_fun = 16#1, prf = 16#1,
  			token = Token, pwd_prep = UnimplementedPrep, identity = PeerId},
  	EapPwd = #eap_pwd{pwd_exch = id, data = ocs_eap_codec:eap_pwd_id(EapPwdId)},
  	EapPacket  = #eap_packet{code = response, type = ?PWD,
  			identifier = EapId2, data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	ok = radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, ReqAuth2, RadId2, EapMsg),
  	EapId2 = receive_radius_failure(Socket, Address, Port, Secret, ReqAuth2, RadId2).
  
  validate_pwd_id_token_over_radius() ->
  	[{userdata, [{doc, "Send invalid EAP-pwd-ID (bad token) using RADIUS"}]}].
  
  validate_pwd_id_token_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId} =  add_service(ProdRef),
  	MAC = "EF-FE-DC-BA-AB-CD",
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth1 = radius:authenticator(),
  	RadId1 = 16, EapId1 = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth1, EapId1, RadId1),
  	EapId2 = EapId1 + 1,
  	{EapId2, _Token, _ServerID} = receive_radius_id(Socket, Address,
  			Port, Secret, ReqAuth1, RadId1),
  	RadId2 = RadId1 + 1,
  	ReqAuth2 = radius:authenticator(),
  	InvalidToken = crypto:strong_rand_bytes(4),
  	EapPwdId = #eap_pwd_id{group_desc = 20, random_fun = 16#1, prf = 16#1,
  			token = InvalidToken, pwd_prep = none, identity = PeerId},
  	EapPwd = #eap_pwd{pwd_exch = id, data = ocs_eap_codec:eap_pwd_id(EapPwdId)},
  	EapPacket  = #eap_packet{code = response, type = ?PWD,
  			identifier = EapId2, data = ocs_eap_codec:eap_pwd(EapPwd)},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	ok = radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, ReqAuth2, RadId2, EapMsg),
  	EapId2 = receive_radius_failure(Socket, Address, Port, Secret, ReqAuth2, RadId2).
  
  negotiate_method_over_radius() ->
  	[{userdata, [{doc, "Send EAP-Nak with alternate methods using RADIUS"}]}].
  
  negotiate_method_over_radius(Config) ->
  	P1 = price(usage, octets, rand:uniform(1000000), rand:uniform(100)),
  	OfferId = add_offer([P1], 4),
  	ProdRef = add_product(OfferId),
  	#service{name = PeerId} =  add_service(ProdRef),
  	MAC = "FE-DC-BA-AB-CD-EF",
  	Socket = ?config(socket, Config),
  	{ok, RadiusConfig} = application:get_env(ocs, radius),
  	{auth, [{Address, Port, _} | _]} = lists:keyfind(auth, 1, RadiusConfig),
  	NasId = ?config(nas_id, Config),
  	UserName = ct:get_config(radius_username),
  	Secret = ct:get_config(radius_shared_secret),
  	ReqAuth1 = radius:authenticator(),
  	RadId1 = 16, EapId1 = 1,
  	ok = send_radius_identity(Socket, Address, Port, NasId, UserName,
  			Secret, PeerId, MAC, ReqAuth1, EapId1, RadId1),
  	EapId2 = EapId1 + 1,
  	EapMsg1 = radius_access_challenge(Socket, Address, Port,
  			Secret, RadId1, ReqAuth1),
  	#eap_packet{code = request, type = Method,
  			identifier = EapId2} = ocs_eap_codec:eap_packet(EapMsg1),
  	true = (((Method > 4) and (Method < 254)) or (Method == 255)),
  	RadId2 = RadId1 + 1,
  	ReqAuth2 = radius:authenticator(),
  	Methods = [?PEAP, ?TLS, ?TTLS, ?SIM, ?AKA, ?AKAprime, ?PWD],
  	AlternateMethods = lists:delete(Method, Methods),
  	EapPacket  = #eap_packet{code = response,
  			type = ?LegacyNak, identifier = EapId2,
  			data = list_to_binary(AlternateMethods)},
  	EapMsg2 = ocs_eap_codec:eap_packet(EapPacket),
  	ok = radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, ReqAuth2, RadId2, EapMsg2),
  	EapMsg3 = radius_access_challenge(Socket, Address, Port,
  			Secret, RadId2, ReqAuth2),
  	EapId3 = EapId2 + 1,
  	#eap_packet{code = request, type = Type,
  			identifier = EapId3} = ocs_eap_codec:eap_packet(EapMsg3),
  	true = lists:member(Type, AlternateMethods).
  
  =======
  >>>>>>> parent of 5faadd0... add test cases
  %%---------------------------------------------------------------------
  %%  Internal functions
  %%---------------------------------------------------------------------
  
  radius_access_request(Socket, Address, Port, NasId,
  		UserName, Secret, MAC, Auth, RadId, EapMsg)
  		when is_binary(UserName) ->
  	radius_access_request(Socket, Address, Port, NasId,
  			binary_to_list(UserName), Secret, MAC, Auth, RadId,
  			EapMsg);       
  radius_access_request(Socket, Address, Port, NasId,
  		UserName, Secret, MAC, Auth, RadId, EapMsg) ->
  	A0 = radius_attributes:new(),
  	A1 = radius_attributes:add(?UserName, UserName, A0), 
  	A2 = radius_attributes:add(?NasPort, 0, A1), 
  	A3 = radius_attributes:add(?NasIdentifier, NasId, A2), 
  	A4 = radius_attributes:add(?CallingStationId, MAC, A3), 
  	A5 = radius_attributes:add(?CalledStationId,
  			"FE-EF-DE-ED-CE-ED:TestSSID", A4),
  	A6 = radius_attributes:add(?EAPMessage, EapMsg, A5), 
  	A7 = radius_attributes:add(?MessageAuthenticator, <<0:128>>, A6), 
  	Request1 = #radius{code = ?AccessRequest, id = RadId,
        authenticator = Auth, attributes = A7},
     ReqPacket1 = radius:codec(Request1),
     MsgAuth1 = crypto:hmac(md5, Secret, ReqPacket1),
     A8 = radius_attributes:store(?MessageAuthenticator, MsgAuth1, A7), 
     Request2 = Request1#radius{attributes = A8}, 
     ReqPacket2 = radius:codec(Request2),
     gen_udp:send(Socket, Address, Port, ReqPacket2).
  
  send_radius_identity(Socket, Address, Port, NasId,
  		UserName, Secret, PeerId, MAC, Auth, EapId, RadId) ->
  	EapPacket  = #eap_packet{code = response, type = ?Identity,
  	identifier = EapId, data = PeerId},
  	EapMsg = ocs_eap_codec:eap_packet(EapPacket),
  	radius_access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, Auth, RadId, EapMsg).
  
  receive_radius_id(Socket, Address, Port, Secret, ReqAuth, RadId) ->
  	EapMsg = radius_access_challenge(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = request, type = ?PWD, identifier = EapId,
  			data = EapData} = ocs_eap_codec:eap_packet(EapMsg),
  	#eap_pwd{length = false, more = false, pwd_exch = id,
  			data = EapPwdData} = ocs_eap_codec:eap_pwd(EapData),
  	#eap_pwd_id{group_desc = 19, random_fun = 16#1,
  			prf = 16#1, pwd_prep = none, token = Token,
  			identity = ServerID} = ocs_eap_codec:eap_pwd_id(EapPwdData),
  	{EapId, Token, ServerID}.
  
  %% @hidden
  client_service_opts() ->
  
negative.code: 			[{raddr, RemAddr}, {rport, RemPort},
  			{reuseaddr, true}, {ip, LocalAddr}]}].
  
  