LibIpv6_Interface_Functions.ttcn 12.5 KB
Newer Older
/*
 *	@author 	STF 276
 *  @version 	$Id$
 *	@desc		This module specifies functions definitions
 *              based on the IPv6 meta message type.  
 *  
 */
 module LibIpv6_Interface_Functions {

	//LibCommon
	import from LibCommon_BasicTypesAndValues all;
	import from LibCommon_DataStrings all;
	import from LibCommon_VerdictControl { type FncRetCode };
	//LibIpv6
	import from LibIpv6_Interface_TypesAndValues all;
	import from LibIpv6_Interface_Templates all;
	import from LibIpv6_ModuleParameters all;
	import from LibIpv6_ExternalFunctions all;
	import from LibIpv6_CommonRfcs_Functions all;
	import from LibIpv6_CommonRfcs_TypesAndValues all;
	
group rfc2460Root_Functions {
	
	group ipv6Packets {	

	/*
	 * @desc 	This sends a General IPv6 packet
	 *			from an IPv6 node to any NUT.
	 *			A General IPv6 packet is used in the case where only Extension headers
	 *			need to be sent.
	 * @remark  Time limit is defined by module parameter PX_TAC (see comp type)
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendGeneralIpv6(template Ipv6Packet p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var Ipv6Packet v_ipPkt;
		v_ipPkt := valueof(p_msg);
		//set extensionHeaders
		if (ispresent(v_ipPkt.extHdrList)) {
			if(f_setExtensionHeaders(	v_ipPkt.extHdrList,
										v_ipPkt.ipv6Hdr.sourceAddress,
										v_ipPkt.ipv6Hdr.destinationAddress,
										v_ipPkt) != e_success) {
				log(" **** f_sendGeneralIpv6: Error when calculating length of extension headers ****");
				return e_error;
			}
		}
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendGeneralIpv6

	group extHdrFns {

	/*
	 * @desc 	This goes through the extension header list and calculates length, checksum
	 *			and other specific functions of the different extension headers
	 * @param 	p_srcAddr Source Address of IPv6 packet
	 * @param 	p_dstAddr Dst Address of IPv6 packet
	 * @param 	p_extHdrList Extension Header List
	 * @return 	execution status 
	*/
	function f_setExtensionHeaders(	inout ExtensionHeaderList p_extHdrList,
									in Ipv6Address p_srcAddr,
									in Ipv6Address p_dstAddr,
									in Ipv6Packet p_ipv6Packet)
	runs on LibIpv6Node
	return FncRetCode {
		var UInt8 i;
		var Ipv6Address v_homeAddress := c_16ZeroBytes;
		var UInt8 v_nrOfTunnelHdr := 0;

		for (i:=0; i<sizeof(p_extHdrList);i:=i+1) {
			if (ischosen(p_extHdrList[i].mipHeader)) {
				if (f_isPresentHomeAddressOption(p_extHdrList, v_homeAddress) == e_success) {
					f_setMipHeader(	v_homeAddress,
									p_dstAddr,
									p_extHdrList[i].mipHeader,
									p_ipv6Packet);	
				}
				else if (f_isPresentRoutingHeaderType2(p_extHdrList, v_homeAddress) == e_success) {
					f_setMipHeader(	p_srcAddr,
									v_homeAddress,									
									p_extHdrList[i].mipHeader,
									p_ipv6Packet);	
				}
				else {
					f_setMipHeader(	p_srcAddr,
									p_dstAddr,
									p_extHdrList[i].mipHeader,
									p_ipv6Packet);
				}
			}
			else if (ischosen(p_extHdrList[i].tunneledIpv6)) {
				v_nrOfTunnelHdr := v_nrOfTunnelHdr + 1;
				p_extHdrList[i].tunneledIpv6.payloadLength := fx_tunnelledPayloadLength(p_ipv6Packet, v_nrOfTunnelHdr);
			}
		/*	else if (ischosen(p_extHdrList[i].)) {
				f_setSecurityHdr();
			}  */
		}//end for

		return e_success;
	}//end f_setExtensionHeaders
		
	}//end group extHdrFns


    } //end group ipv6Packets
	
}//end group rfc2460Root_Functions

group rfc3775Mipv6_ExtHdrFunctions {

	/*
	 * @desc 	This goes through the Mip header and calculates length, checksum
	 *			and other specific functions of the different messages.
	 *			This function is used when sending messages.
	 * @param 	p_msg ExtensionHeaderList to be treated	
	 * @return 	execution status 
	*/
	function f_setMipHeader(in Ipv6Address p_srcAddr,
							in Ipv6Address p_dstAddr,
							inout MipHeader p_mipHeader,
							in Ipv6Packet p_ipv6Packet)
	runs on LibIpv6Node
	return FncRetCode {
		var MipHeader v_mipHeader := valueof(p_mipHeader);
		var Ipv6Address v_homeAddress := c_16ZeroBytes ;

		//if (ischosen(p_mipHeader.mipMessage.homeTestInit)) {
			//calc homeInitCookie
			//p_mipHeader.mipMessage.homeTestInit.homeInitCookie := f_createInitCookie();
		//}
		//else if (ischosen(p_mipHeader.mipMessage.homeTest)) {//CNSimu sends this message
		//}
		//else if (ischosen(p_mipHeader.mipMessage.careOfTestInit) and (PX_TEST_IPSEC == true)) {
		//SMU TODO
		//}
		//else if (ischosen(p_mipHeader.mipMessage.careOfTest) and (PX_TEST_IPSEC == true)) {
		//SMU TODO
		//}
		if (ischosen(p_mipHeader.mipMessage.bindingUpdate)) {//Authorization data is only needed for BU sent to CN=IUT
			var UInt8 v_position := 0;
			//Concept of including bindingAuthentication
			// specifiy on template level all options
			// 1) if authenticator == c_20ZeroBytes then value is calculated in f_setMipHeader
			// 2) if authenticator != c_20ZeroBytes then no value is calculated in f_setMipHeader,
			//     because it's assumed that the correct value was set on template level
			// 3) same applies to nonceIndex etc

			if (f_isPresentNonceIndices(p_mipHeader.mipMessage.bindingUpdate, v_position) == e_success
				and vc_mipSec.mnSimuParams.receivedHomeNonceIndex != c_uInt16Zero
				and vc_mipSec.mnSimuParams.receivedCareOfNonceIndex != c_uInt16Zero) {
					p_mipHeader.mipMessage.bindingUpdate.mipOptions[v_position].mipOptNonceIndices.homeNonceIndex
					:= vc_mipSec.mnSimuParams.receivedHomeNonceIndex;
					p_mipHeader.mipMessage.bindingUpdate.mipOptions[v_position].mipOptNonceIndices.careOfNonceIndex
					:= vc_mipSec.mnSimuParams.receivedCareOfNonceIndex;
			}
			else {
				log("f_setMipHeader: Error: NonceIndices included in Binding Update, but mnSimuParams.receivedCareOfNonceIndex/receivedHomeNonceIndex not initialized");
				return e_error;	
			}
			if (f_isPresentBindingAuthorizationDataOption(p_mipHeader.mipMessage.bindingUpdate, v_position) == e_success
				and vc_mipSec.mnSimuParams.receivedHomeKeygenToken != c_64ZeroBits
				and vc_mipSec.mnSimuParams.receivedCareOfKeygenToken != c_64ZeroBits) {
				
					vc_mipSec.mnSimuParams.kbm := fx_integrity(		e_sha1_96, c_1ZeroByte,
																	bit2oct(vc_mipSec.mnSimuParams.receivedHomeKeygenToken)
																	& bit2oct(vc_mipSec.mnSimuParams.receivedCareOfKeygenToken));
				
					var Oct20 v_bindingAuthenticator := fx_integrity(	e_hmac_sha1_96, vc_mipSec.mnSimuParams.kbm,
																		p_srcAddr//careOfaddr 
																		& p_dstAddr//cnAddr
																		& fx_mipHdrToOct(p_mipHeader) );

					p_mipHeader.mipMessage.bindingUpdate.mipOptions[v_position].mipBindingAuthorizationData := {
							mipOptType := 5,
							mipOptLen := lengthof(v_bindingAuthenticator),
							authenticator := v_bindingAuthenticator
					}
			}
			else {
				log("f_setMipHeader: Error: BindingAuthorizationDataOption included in Binding Update, but receivedHomeKeygenToken/receivedCareOfKeygenToken not initialized");
				return e_error;	
			}
		}
	//	else if (ischosen(p_mipHeader.mipMessage.bindingAck) and (PX_TEST_IPSEC == true)) {
		//SMU TODO
		//}
		//calc mipHeaderLen
		p_mipHeader.headerLen := fx_mipHeaderLength(p_mipHeader);

// modified by PK to easily send packets with wrong checksum
		//set mipChecksum to zero
		//p_mipHeader.checksum := c_2ZeroBytes;  
		//calc mipChecksum
		p_mipHeader.checksum := fx_mipHeaderChecksum ( p_srcAddr,
														p_dstAddr,
														p_mipHeader);

		return e_success;
	}
		


		/*
	 * @desc 	This goes through the BindingUpdate and
	 *			checks if a NonceIndicesOption is present.
	 * @param 	p_bindingUpdate Binding Update to be treated
	 * @param 	v_position Position of the NonceIndicesOption in the MipOptionList
	 * @return 	execution status 
	*/
	function f_isPresentNonceIndices(	in BindingUpdate p_bindingUpdate,
														inout UInt8 v_position)
	runs on LibIpv6Node
	return FncRetCode {
		var FncRetCode v_ret := e_error;
		var UInt8 i;

		//select ext hdrs that need special calculation
		for (i:=0; i<sizeof(p_bindingUpdate.mipOptions) and (v_ret != e_success); i:=i+1) {
			if (ischosen(p_bindingUpdate.mipOptions[i].mipOptNonceIndices)) {
					v_position := i;
					v_ret := e_success;
				}
		}
		return v_ret;
	}//end function f_isPresentNonceIndices

	/*
	 * @desc 	This goes through the BindingUpdate and
	 *			checks if a AuthorizationDataOption is present.
	 * @param 	p_bindingUpdate Binding Update to be treated
	 * @param 	v_position Position of the AuthorizationDataOption in the MipOptionList
	 * @return 	execution status 
	*/
	function f_isPresentBindingAuthorizationDataOption(	in BindingUpdate p_bindingUpdate,
														inout UInt8 v_position)
	runs on LibIpv6Node
	return FncRetCode {
		var FncRetCode v_ret := e_error;
		var UInt8 i;

		//select ext hdrs that need special calculation
		for (i:=0; i<sizeof(p_bindingUpdate.mipOptions) and (v_ret != e_success); i:=i+1) {
			if (ischosen(p_bindingUpdate.mipOptions[i].mipBindingAuthorizationData)) {
					v_position := i;
					v_ret := e_success;
				}
		}
		return v_ret;
	}//end function f_isPresentBindingAuthorizationDataOption
	
}//end group rfc3775Mipv6_ExtHdrFunctions


group rfc4303Esp_ExtHdrFunctions {
	
	function f_initParams()
	runs on LibIpv6Node {
		
		vc_sad[0] := {
			securityParametersIndex := f_createSpi(),
			sequenceNumber := c_uInt32Zero,
			// AH Integrity
			ahIntegrityAlgo := PX_INTEGRITY_ALGO,
			ahIntegrityKey := f_createSecretKey(),
			// ESP encryption
			espEncryptionAlgo := PX_ENCRYPTION_ALGO,
			espEncryptionKey := f_createSecretKey(),
			// ESP integrity
			espIntegrityAlgo := PX_INTEGRITY_ALGO,
			espIntegrityKey := f_createSecretKey(),
			// Combined mode
			espCombinedModeAlgo := PX_COMBINED_MODE_ALGO,
			espCombinedModeKey := f_createSecretKey(),
			// Protocol mode
			ipSecProtocolMode := PX_IP_SEC_PROTOCOL_MODE
		}
		
	}//end f_initParams


	/*
	 * @desc 	This generates Security Parameters Index
	 * @return 	Security Parameters Index
	*/
	function f_createSpi()
	runs on LibIpv6Node
	return UInt32 {
		var Oct4 v_spi := int2oct(float2int(int2float(20000-5000)*rnd())+5000, 4);

		return oct2int(v_spi);
	}//end f_createSpi

	/*
	 * @desc 	This generates a secret key
	 * @return 	Secret key
	*/
	function f_createSecretKey()
	runs on LibIpv6Node
	return octetstring {
		var Oct20 v_key := int2oct(float2int(int2float(20000-5000)*rnd())+5000, 20);

		return v_key;
	}//end f_createSecretKey

	function f_buildEspExtHdr(	
			in Sa p_sa,
			in PlaintextData p_plaintextData,
			out ExtensionHeader p_extensionHeader)
	runs on LibIpv6Node
	return FncRetCode {
		// Variables
		var EncryptResult v_encryptResult;
		var IntegrityResult v_integrityResult;
		var FncRetCode v_ret := e_error;
		var octetstring v_padding := c_1ZeroByte;

		// Encrypt espPayloadData
		v_ret := fx_encrypt(	p_sa.ipSecProtocolMode,
								p_sa.espEncryptionAlgo,
								p_sa.espEncryptionKey,
								p_plaintextData,
								v_encryptResult);
		if ( v_ret != e_success ) {return v_ret;}
	
		// Fill EspExtHdr
		var EspHeader v_espHdr := valueof(m_espHdr_dummy);
		// Header
		v_espHdr.securityParametersIndex := p_sa.securityParametersIndex;
		v_espHdr.sequenceNumber := p_sa.sequenceNumber;
		// Payload
		if (ispresent(v_encryptResult.iv)) {
			v_espHdr.iv := v_encryptResult.iv;
		}
		// Encrypted payload is assigend for integrity calculation.
		// Afterwards plaintext will be assigned
		v_espHdr.espPayloadData.ciphertextData := v_encryptResult.ciphertextData;
		if (ispresent(v_encryptResult.tfcPadding)) {
			v_espHdr.tfcPadding := v_encryptResult.tfcPadding;
		}
		// Byte Align
		v_ret := fx_byteAlignEspHeader(4, v_espHdr, v_padding);
		if ( v_ret != e_success ) {return v_ret;}

		if (v_padding != c_1ZeroByte) {
			v_espHdr.padding := v_padding;
			v_espHdr.padLength := lengthof(v_padding);
		}

		// Integrity
		v_ret := fx_integrityEspHdr(	p_sa.espIntegrityAlgo,
									p_sa.espIntegrityKey,
									v_espHdr,
									v_integrityResult);
		if ( v_ret != e_success ) {return v_ret;}
		if (ispresent(v_integrityResult.icv)) {
			v_espHdr.icv := v_integrityResult.icv;
		}

		// Assign Plaintext EspPayload
		v_espHdr.espPayloadData.plaintextData := p_plaintextData;
		p_extensionHeader := {espHeader := v_espHdr};

		return e_success;

	}//end function f_buildEspExtHdr	
	
}//end group rfc4303Esp_ExtHdrFunctions

	
} // end module LibIpv6_Interface_Functions