/** * @author ETSI / STF544 * @version $URL$ * $Id$ * @desc Module containing functions for ITS PKI ATS * @copyright ETSI Copyright Notification * No part may be reproduced except as authorized by written permission. * The copyright and the foregoing restriction extend to reproduction in all media. * All rights reserved. * */ module LibItsPki_Functions { // LibCommon import from LibCommon_Time all; import from LibCommon_VerdictControl all; import from LibCommon_Sync all; import from LibCommon_BasicTypesAndValues all; import from LibCommon_DataStrings all; // LibIts import from IEEE1609dot2BaseTypes language "ASN.1:1997" all; import from IEEE1609dot2 language "ASN.1:1997" all; import from EtsiTs102941BaseTypes language "ASN.1:1997" all; import from EtsiTs102941TypesEnrolment language "ASN.1:1997" all; import from EtsiTs102941TypesAuthorization language "ASN.1:1997" all; import from EtsiTs102941TypesAuthorizationValidation language "ASN.1:1997" all; import from EtsiTs102941MessagesItss language "ASN.1:1997" all; import from EtsiTs103097Module language "ASN.1:1997" all; import from ITS_Container language "ASN.1:1997" all; import from CAM_PDU_Descriptions language "ASN.1:1997" all; // LibItsCommon import from LibItsCommon_TypesAndValues all; import from LibItsCommon_Functions all; import from LibItsCommon_ASN1_NamedNumbers all; import from LibItsCommon_Pixits all; // LibItsGeoNetworking import from LibItsGeoNetworking_Pixits all; // LibItsSecurity import from LibItsSecurity_TypesAndValues all; import from LibItsSecurity_Templates all; import from LibItsSecurity_Functions all; import from LibItsSecurity_Pixits all; import from LibItsSecurity_TestSystem all; // LibItsHttp import from LibItsHttp_TypesAndValues all; import from LibItsHttp_Templates all; import from LibItsHttp_TestSystem all; // LibItsPki import from LibItsPki_TypesAndValues all; import from LibItsPki_Templates all; import from LibItsPki_Pics all; import from LibItsPki_TestSystem all; group pkiConfigurationFunctions { /** * @desc Setups default configuration * @param p_certificateId The certificate identifier the TA shall use in case of secured IUT */ function f_cfUp( in charstring p_certificateId := "CERT_TS_A_EA", // TODO Use a constant in charstring p_peerCertificateId := "CERT_IUT_A_EA" ) runs on ItsPki /* TITAN TODO: system ItsPkiSystem */ { map(self:pkiPort, system:pkiPort); map(self:acPort, system:acPort); f_connect4SelfOrClientSync(); f_initialiseSecuredMode(p_certificateId, p_peerCertificateId); f_readCertificate(p_certificateId, vc_eaCertificate); f_getCertificateDigest(p_certificateId, vc_eaHashedId8); activate(a_default_pki()); } // End of function f_cfUp /** * @desc Setups default configuration * @param p_certificateId The certificate identifier the TA shall use in case of secured IUT */ function f_cfHttpUp( in charstring p_certificateId := "CERT_TS_A_EA", // TODO Use a constant in charstring p_peerCertificateId := "CERT_IUT_A_EA" ) runs on ItsPkiHttp /* TITAN TODO: system ItsPkiHttpSystem */ { map(self:httpPort, system:httpPort); f_connect4SelfOrClientSync(); f_initialiseSecuredMode(p_certificateId, p_peerCertificateId); f_readCertificate(p_certificateId, vc_eaCertificate); f_readSigningKey(p_certificateId, vc_eaPrivateKey); f_readEncryptingKey(p_certificateId, vc_eaPrivateEncKey); f_getCertificateDigest(p_certificateId, vc_eaHashedId8); f_readCertificate(p_peerCertificateId, vc_peerEaCertificate); f_getCertificateHash(p_peerCertificateId, vc_eaPeerWholeHash); activate(a_default_pki_http()); } // End of function f_cfHttpUp function f_cfUp_itss( in charstring p_certificateId := "CERT_TS_A_EA" // TODO Use a constant ) runs on ItsPkiItss /* TITAN TODO: system ItsPkiItssSystem */ { f_cfUp(); map(self:geoNetworkingPort, system:geoNetworkingPort); map(self:utPort, system:utPort); map(self:acPort, system:acPort); f_initializeState(); activate(a_default_pki()); } // End of function f_cfUp_itss /** * @desc Deletes default configuration */ function f_cfDown() runs on ItsPki /* TITAN TODO: system ItsPkiSystem */ { unmap(self:pkiPort, system:pkiPort); unmap(self:acPort, system:acPort); f_disconnect4SelfOrClientSync(); f_uninitialiseSecuredMode(); } // End of function f_cfDown /** * @desc Deletes default configuration */ function f_cfHttpDown() runs on ItsPkiHttp /* TITAN TODO: system ItsPkiHttpSystem */ { unmap(self:httpPort, system:httpPort); f_disconnect4SelfOrClientSync(); f_uninitialiseSecuredMode(); } // End of function f_cfHttpDown /** * @desc Deletes default configuration */ function f_cfDown_itss() runs on ItsPkiItss /* TITAN TODO: system ItsPkiItssSystem */ { unmap(self:geoNetworkingPort, system:geoNetworkingPort); unmap(self:utPort, system:utPort); unmap(self:acPort, system:acPort); f_cfDown(); } // End of function f_cfDown /** * @desc Initialise secure mode if required */ function f_initialiseSecuredMode( in charstring p_certificateId := "CERT_TS_A_EA", // TODO Use a constant in charstring p_peerCertificateId := "CERT_IUT_A_EA" ) runs on ItsSecurityBaseComponent { // Local variables // Load certificates if( not f_loadCertificates(PX_IUT_SEC_CONFIG_NAME) ) { log("*** INFO: TEST CASE NOW STOPPING ITSELF! ***"); setverdict(inconc); stop; } f_prepareCertificates(p_certificateId, vc_aaCertificate, vc_atCertificate); } // End of function f_initialiseSecuredMode() function f_uninitialiseSecuredMode() runs on ItsSecurityBaseComponent { f_unloadCertificates(); } // End of function f_uninitialiseSecuredMode() function f_initializeState() runs on ItsPkiItss { var Oct8 v_hashedId8ToBeUsed := f_setupIutCertificate(vc_hashedId8ToBeUsed); f_utInitializeIut(UtPkiInitialize: { v_hashedId8ToBeUsed } ); f_sleep(PX_NEIGHBOUR_DISCOVERY_DELAY); // f_acLoadScenario(p_scenario); // f_acStartScenario(); } } // End of pkiConfigurationFunctions group ac_port { function f_sendAcPkiPrimitive( in charstring p_certificate, in octetstring p_private_key, in octetstring p_publicKeyCompressed, in integer p_compressedMode ) runs on ItsPki { var AcSetSecurityData v_ac_set_security_data; v_ac_set_security_data := { p_certificate, PICS_IUT_CERTIFICATE_ID, p_private_key, p_publicKeyCompressed, p_compressedMode }; acPort.send(AcPkiPrimitive: { acSetSecurityData := v_ac_set_security_data }); tc_ac.start; alt { [] acPort.receive(AcPkiResponse: { result := true }) { tc_ac.stop; } [] acPort.receive(AcPkiResponse: { result := false }) { tc_ac.stop; log("*** f_sendAcPkiPrimitive: ERROR: Received unexpected message ***"); f_selfOrClientSyncAndVerdict("error", e_error); } [] tc_ac.timeout { log("*** f_sendAcPkiPrimitive: ERROR: Timeout while waiting for adapter control event result ***"); f_selfOrClientSyncAndVerdict("error", e_timeout); } } // End of 'alt' statement } // End of function f_sendAcPkiPrimitive } // End of group ac_port group ut_port { function f_utInitializeIut(template (value) UtPkiInitialize p_init) runs on ItsPkiItss { utPort.send(p_init); tc_wait.start; alt { [] utPort.receive(UtPkiResults: { utPkiInitializeResult := true }) { tc_wait.stop; log("*** f_utInitializeIut: INFO: IUT initialized ***"); } [] utPort.receive { tc_wait.stop; log("*** f_utInitializeIut: INFO: IUT could not be initialized ***"); f_selfOrClientSyncAndVerdict("error", e_error); } [] tc_wait.timeout { log("*** f_utInitializeIut: INFO: IUT could not be initialized in time ***"); f_selfOrClientSyncAndVerdict("error", e_timeout); } } } // End of function f_utInitializeIut function f_sendUtTriggerPrimitive( in charstring p_cannonicalId, in Oct1 p_encAlgorithm, in octetstring p_private_key, in octetstring p_publicKeyCompressed, in integer p_compressedMode ) runs on ItsPkiItss { var TriggerEnrolmentRequest v_ut_trigger_enrolment_request; var octetstring v_compressed_public_key; if (p_compressedMode == 2) { // TODO v_compressed_public_key := int2oct(p_compressedMode, 1) & p_publicKeyCompressed? v_compressed_public_key := '02'O & p_publicKeyCompressed; } else { v_compressed_public_key := '03'O & p_publicKeyCompressed; } v_ut_trigger_enrolment_request := { p_cannonicalId, p_encAlgorithm, p_private_key, v_compressed_public_key }; utPort.send(UtPkiTrigger: { triggerEnrolmentRequest := v_ut_trigger_enrolment_request }); tc_ac.start; alt { [] utPort.receive(UtPkiResults: { utPkiTriggerResult := true }) { tc_ac.stop; } [] utPort.receive(UtPkiResults: { utPkiTriggerResult := false }) { tc_ac.stop; log("*** f_sendUtTriggerPrimitive: ERROR: Received unexpected message ***"); f_selfOrClientSyncAndVerdict("error", e_error); } [] tc_ac.timeout { log("*** f_sendAcPkiPrimitive: ERROR: Timeout while waiting for adapter control event result ***"); f_selfOrClientSyncAndVerdict("error", e_timeout); } } // End of 'alt' statement } // End of function f_sendUtTriggerPrimitive } // End of group ut_port group http { function f_http_build_inner_ec_request( out octetstring p_private_key, out octetstring p_publicKeyCompressed, out integer p_compressedMode, out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data, out Oct32 p_hash_inner_ec_request_signed_for_pop ) runs on ItsPkiHttp { var octetstring v_publicKeyX; var octetstring v_publicKeyY var InnerEcRequest v_inner_ec_request; var Ieee1609Dot2Data v_inner_ec_request_signed_for_pop; var bitstring v_inner_ec_request_signed_for_pop_msg; if (f_generate_inner_ec_request(p_private_key, p_publicKeyCompressed, p_compressedMode, v_inner_ec_request) == false) { log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequest ***"); f_selfOrClientSyncAndVerdict("error", e_error); } // Generate InnerEcRequestSignedForPoP if (f_generate_inner_ec_request_signed_for_pop(p_private_key, v_inner_ec_request, v_inner_ec_request_signed_for_pop) == false) { log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***"); f_selfOrClientSyncAndVerdict("error", e_error); } // Secure InnerEcRequestSignedForPoP message v_inner_ec_request_signed_for_pop_msg := encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop)); // Prepae for getting the 16 most bytes of SHA256 of InnerEcRequestSignedForPop p_hash_inner_ec_request_signed_for_pop := f_hashWithSha256(bit2oct(v_inner_ec_request_signed_for_pop_msg)); if (f_build_pki_secured_message(vc_eaPrivateKey, valueof(m_signerIdentifier_self), vc_eaHashedId8, p_publicKeyCompressed, p_compressedMode, bit2oct(v_inner_ec_request_signed_for_pop_msg), p_ieee1609dot2_signed_and_encrypted_data) == false) { log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***"); f_selfOrClientSyncAndVerdict("error", e_error); } log("*** f_http_build_inner_ec_request: DEBUG: v_inner_ec_request_signed_for_pop_msg= ", v_inner_ec_request_signed_for_pop_msg); log("*** f_http_build_inner_ec_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data); log("*** f_http_build_inner_ec_request: DEBUG: p_hash_inner_ec_request_signed_for_pop= ", p_hash_inner_ec_request_signed_for_pop); } // End of function f_http_build_inner_ec_request function f_http_build_invalid_enrolment_request( out octetstring p_private_key, out octetstring p_publicKeyCompressed, out integer p_compressedMode, out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data, out Oct32 p_hash_inner_ec_request_signed_for_pop ) runs on ItsPkiHttp { var InnerEcRequest v_inner_ec_request; var Ieee1609Dot2Data v_inner_ec_request_signed_for_pop; var bitstring v_inner_ec_request_signed_for_pop_msg; if (f_generate_inner_ec_request(p_private_key, p_publicKeyCompressed, p_compressedMode, v_inner_ec_request) == false) { log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequest ***"); f_selfOrClientSyncAndVerdict("error", e_error); } // Generate InnerEcRequestSignedForPoP if (f_generate_inner_ec_request_signed_for_pop(p_private_key, v_inner_ec_request, v_inner_ec_request_signed_for_pop) == false) { log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***"); f_selfOrClientSyncAndVerdict("error", e_error); } // Secure InnerEcRequestSignedForPoP message v_inner_ec_request_signed_for_pop_msg := encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop)); // Get 16 last byte of SHA256 of InnerEcRequestSignedForPop p_hash_inner_ec_request_signed_for_pop := f_hashWithSha256(int2oct(12345, 32)); // Invalid InnseEcRequestSignedForPop if (f_build_pki_secured_message(vc_eaPrivateKey, valueof(m_signerIdentifier_self), vc_eaHashedId8, p_publicKeyCompressed, p_compressedMode, bit2oct(v_inner_ec_request_signed_for_pop_msg), p_ieee1609dot2_signed_and_encrypted_data) == false) { log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***"); f_selfOrClientSyncAndVerdict("error", e_error); } log("*** f_http_build_invalid_enrolment_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data = ", p_ieee1609dot2_signed_and_encrypted_data); } // End of function f_http_build_invalid_enrolment_request function f_http_build_authorization_validation_request( out octetstring p_private_key, out octetstring p_publicKeyCompressed, out integer p_compressedMode, out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data ) runs on ItsPkiHttp { log("*** f_http_build_invalid_enrolment_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data = ", p_ieee1609dot2_signed_and_encrypted_data); } } // End of group http group generate_certificates { function f_generate_ec_certificate( in octetstring p_private_key, in InnerEcRequest p_inner_ec_request, out Certificate p_ec_certificate ) return boolean { var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) }; var template (value) EtsiTs103097Certificate v_cert; var bitstring v_tbs; var Oct32 v_sig; var bitstring v_enc_msg; v_cert := m_etsiTs103097Certificate( m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(f_hashWithSha256('616263'O))), m_toBeSignedCertificate_at( v_appPermissions, m_verificationKeyIndicator_verificationKey( m_publicVerificationKey_ecdsaNistP256( p_inner_ec_request.publicKeys.verificationKey.ecdsaNistP256 )), m_validityPeriod( 17469212, m_duration_years(10) ), m_geographicRegion_identifiedRegion( { m_identifiedRegion_country_only(12), m_identifiedRegion_country_only(34) } ) ) ); // Encode it ==> Get octetstring v_tbs := encvalue(v_cert.toBeSigned); // Sign the certificate using ECDSA/SHA-256 (NIST p-256) v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_tbs), int2oct(11, 32), p_private_key); v_cert.signature_ := m_signature_ecdsaNistP256( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only( substr(v_sig, 0, 32) ), substr(v_sig, 32, 32) ) ); log("v_cert= ", v_cert); p_ec_certificate := valueof(v_cert); return true; } // End of function f_generate_ec_certificate function f_generate_at_certificate( in octetstring p_private_key, in InnerEcRequest p_inner_ec_request, out Certificate p_at_certificate ) return boolean { var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) }; var template (value) EtsiTs103097Certificate v_cert; var bitstring v_tbs; var Oct32 v_sig; var bitstring v_enc_msg; v_cert := m_etsiTs103097Certificate( m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(f_hashWithSha256('616263'O))), m_toBeSignedCertificate_at( v_appPermissions, m_verificationKeyIndicator_verificationKey( m_publicVerificationKey_ecdsaNistP256( p_inner_ec_request.publicKeys.verificationKey.ecdsaNistP256 )), m_validityPeriod( 17469212, m_duration_years(10) ), m_geographicRegion_identifiedRegion( { m_identifiedRegion_country_only(12), m_identifiedRegion_country_only(34) } ) ) ); // Encode it ==> Get octetstring v_tbs := encvalue(v_cert.toBeSigned); // Sign the certificate using ECDSA/SHA-256 (NIST p-256) v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_tbs), int2oct(11, 32), p_private_key); v_cert.signature_ := m_signature_ecdsaNistP256( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only( substr(v_sig, 0, 32) ), substr(v_sig, 32, 32) ) ); log("v_cert= ", v_cert); p_at_certificate := valueof(v_cert); return true; } // End of function f_generate_at_certificate } // End of group generate_certificates group inner_ec_xxx { function f_generate_inner_ec_request( out octetstring p_private_key, out octetstring p_publicKeyCompressed, out integer p_compressedMode, out InnerEcRequest p_inner_ec_request ) return boolean { // Local variables var Oct32 v_publicKeyX; var Oct32 v_publicKeyY; var EccP256CurvePoint v_eccP256_curve_point; log (">>> f_generate_inner_ec_request"); // Generate keys for the certificate to be requested if (f_generate_key_pair_nistp256(p_private_key, v_publicKeyX, v_publicKeyY, p_publicKeyCompressed, p_compressedMode) == false) { log ("f_generate_inner_ec_request: failed to generate keys"); return false; } if (p_compressedMode == 0) { v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_publicKeyCompressed)); } else { v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_publicKeyCompressed)); } log ("f_generate_inner_ec_request: ", v_eccP256_curve_point); // Build the Proof of Possession InnerEcRequest p_inner_ec_request := valueof( m_innerEcRequest( PICS_ITS_S_CANONICAL_ID, m_publicKeys( m_publicVerificationKey_ecdsaNistP256(v_eccP256_curve_point) ), m_certificateSubjectAttributes( { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), // TODO Use PIXIT valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) // TODO Use PIXIT }, m_validityPeriod( 17469212, m_duration_years(10) // TODO Use PIXIT ), m_geographicRegion_identifiedRegion( { m_identifiedRegion_country_only(12), // TODO Use PIXIT m_identifiedRegion_country_only(34) // TODO Use PIXIT } ), 'C0'O // TODO Use PIXIT ) ) ); log ("f_generate_inner_ec_request: ", p_inner_ec_request); return true; } // End of function f_generate_inner_ec_request function f_generate_inner_ec_request_signed_for_pop( in octetstring p_private_key, in InnerEcRequest p_inner_ec_request, out Ieee1609Dot2Data p_inner_ec_request_signed_for_pop ) return boolean { // Local variables var template (value) EccP256CurvePoint v_eccP256_curve_point; var octetstring v_encoded_inner_ec_request; var template (value) ToBeSignedData v_tbs; var octetstring v_tbs_signed; // Encode it v_encoded_inner_ec_request := bit2oct(encvalue(p_inner_ec_request)); // Signed the encoded InnerEcRequestSignedForPop v_tbs := m_toBeSignedData( m_signedDataPayload( m_etsiTs103097Data_unsecured( v_encoded_inner_ec_request ) ), m_headerInfo_inner_ec_request( c_its_aid_SCR, f_getCurrentTimeUtc()) ); // Signed the encoded InnerEcRequestSignedForPop v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key); // Finalyse signed InnerEcRequestSignedForPop p_inner_ec_request_signed_for_pop := valueof( m_etsiTs103097Data_signed( m_signedData( sha256, v_tbs, m_signerIdentifier_self, m_signature_ecdsaNistP256( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only( substr(v_tbs_signed, 0, 32) ), substr(v_tbs_signed, 32, 32) ) ) ) ) ); return true; } // End of function f_generate_inner_ec_request_signed_for_pop function f_generate_inner_ec_response( in octetstring p_inner_ec_request_hashed_id, in EtsiTs103097Certificate p_certificate, out InnerEcResponse p_inner_ec_response ) return boolean { // Local variables // Build the Proof of Possession InnerEcResponse p_inner_ec_response := valueof( m_innerEcResponse_ok( substr(p_inner_ec_request_hashed_id, 0, 16), p_certificate ) ); return true; } // End of function f_generate_inner_ec_response } // End of group inner_ec_xxx group inner_at_xxx { function f_generate_inner_at_request( in Certificate p_ec_certificate, in octetstring p_private_key, in Certificate p_ea_certificate, in HashedId8 p_eaHashedId8, in boolean p_itss_privacy, out octetstring p_private_enc_key, out octetstring p_publicEncKeyCompressed, out integer p_compressedMode, out InnerAtRequest p_inner_at_request, out Ieee1609Dot2Data p_inner_at_request_data ) return boolean { // Local variables var octetstring public_enc_key_x; var octetstring public_enc_key_y; var template (value) EccP256CurvePoint v_eccP256_curve_point; var Oct32 v_hmac_key; var octetstring v_message_to_tag; var Oct16 v_key_tag; var octetstring v_whole_certificate_hash; var octetstring v_hash_shared_at_request; var template (value) ToBeSignedData v_tbs; var octetstring v_tbs_signed; var Ieee1609Dot2Data v_signed_ec_signature; // Generate encryption keys for the certificate to be requested if (f_generate_key_pair_nistp256(p_private_enc_key, public_enc_key_x, public_enc_key_y, p_publicEncKeyCompressed, p_compressedMode) == false) { return false; } if (p_compressedMode == 0) { v_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_0(p_publicEncKeyCompressed); } else { v_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_1(p_publicEncKeyCompressed); } // Generate 32 octets length secret key v_hmac_key := f_hashWithSha256(int2oct(f_getCurrentTime(), 128)); log("v_hmac_key=", v_hmac_key); // Generate tag based on the concatenation of ??? if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey)) { if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256)) { if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) { v_message_to_tag := '02'O & p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0; } else { v_message_to_tag := '03'O & p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1; } } else { // TODO /* if (ischosen(p_ec_certificate.verifyKeyIndicator.ecdsaBrainpoolP256.compressed_y_0)) { */ /* v_message_to_tag := '02'O & p_ec_certificate.verifyKeyIndicator.ecdsaBrainpoolP256.compressed_y_0; */ /* } else { */ /* v_message_to_tag := '03'O & p_ec_certificate.verifyKeyIndicator.ecdsaBrainpoolP256.compressed_y_1; */ /* } */ } } else { return false; } if (p_compressedMode == 0) { v_message_to_tag := v_message_to_tag & '02'O & p_publicEncKeyCompressed; } else { v_message_to_tag := v_message_to_tag & '03'O & p_publicEncKeyCompressed; } log("v_message_to_tag=", v_message_to_tag); v_key_tag := fx_test_hmac_sha256(v_hmac_key, v_message_to_tag); // TODO Rename and use a wrapper function log("v_key_tag=", v_key_tag); // Build the SharedAtRequest p_inner_at_request.publicKeys := valueof( m_publicKeys( m_publicVerificationKey_ecdsaNistP256( p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256 ), m_encryptionKey( -, m_publicEncryptionKey_ecdsaNistP256(v_eccP256_curve_point) ) ) ); p_inner_at_request.hmacKey := v_hmac_key; p_inner_at_request.sharedAtRequest := valueof( m_shared_at_request( p_eaHashedId8, v_key_tag, valueof( m_certificate_subject_attributes( p_ec_certificate.toBeSigned.id, p_ec_certificate.toBeSigned.validityPeriod, p_ec_certificate.toBeSigned.region, p_ec_certificate.toBeSigned.assuranceLevel, p_ec_certificate.toBeSigned.appPermissions )))); v_hash_shared_at_request := f_hashWithSha256(bit2oct(encvalue(p_inner_at_request.sharedAtRequest))); log("v_hash_shared_at_request=", v_hash_shared_at_request); // Build the ToBeSigned payload v_tbs := m_toBeSignedData( m_signedDataPayload_ext(v_hash_shared_at_request), m_headerInfo_inner_ec_request( c_its_aid_SCR, f_getCurrentTimeUtc()) ); // Signed ToBeSigned payload v_whole_certificate_hash := f_hashWithSha256(bit2oct(encvalue(p_ec_certificate))); v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_whole_certificate_hash, p_private_key); v_signed_ec_signature := valueof( m_etsiTs103097Data_signed( m_signedData( sha256, v_tbs, m_signerIdentifier_digest( f_HashedId8FromSha256( v_whole_certificate_hash ) ), m_signature_ecdsaNistP256( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only( substr(v_tbs_signed, 0, 32) ), substr(v_tbs_signed, 32, 32) ) ) ) ) ); // Encrypt EcSignature with EA certificate if (p_itss_privacy) { var octetstring v_public_enc_key; var integer v_compressed_mode; var Oct12 v_nonce; var Oct16 v_authentication_vector; var Oct16 v_encrypted_sym_key; var HashedId8 v_recipientId; var octetstring v_publicEphemeralKeyCompressed; var integer v_ephemeralKeyModeCompressed; var octetstring v_enc_signed_ec_signature; v_enc_signed_ec_signature := f_encryptWithEciesNistp256WithSha256(bit2oct(encvalue(v_signed_ec_signature)), v_public_enc_key, v_compressed_mode, v_publicEphemeralKeyCompressed, v_ephemeralKeyModeCompressed, v_encrypted_sym_key, v_authentication_vector, v_nonce); v_recipientId := p_eaHashedId8; log("v_recipientId=", v_recipientId); // Fill Certificate template with the public compressed keys (canonical form) if (v_ephemeralKeyModeCompressed == 0) { v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_publicEphemeralKeyCompressed)); } else { v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_publicEphemeralKeyCompressed)); } p_inner_at_request.ecSignature := valueof( m_ec_signature( m_etsiTs103097Data_encrypted( m_encryptedData( { m_recipientInfo_signedDataRecipInfo( m_pKRecipientInfo( v_recipientId, m_encryptedDataEncryptionKey_eciesNistP256( m_evciesP256EncryptedKey( v_eccP256_curve_point, v_encrypted_sym_key, v_authentication_vector )))) }, m_SymmetricCiphertext_aes128ccm( m_aesCcmCiphertext( v_nonce, v_enc_signed_ec_signature ) ) ) ) ) ); } else { p_inner_at_request.ecSignature := valueof(m_ec_signature_ext_payload(v_signed_ec_signature)); } log("p_inner_at_request=", p_inner_at_request); return true; } // End of function f_generate_inner_at_request function f_generate_inner_at_response( in Certificate p_ec_certificate, in octetstring p_private_key, in HashedId8 p_eaHashedId8, out octetstring p_private_enc_key, out octetstring p_publicEncKeyX, out octetstring p_publicEncKeyY, out octetstring p_publicEncKeyCompressed, out integer p_compressedMode, out InnerAtRequest p_inner_at_request, out Ieee1609Dot2Data p_inner_at_request_data ) return boolean { // Local variables return false; } // End of function f_generate_inner_at_response } // End of group inner_at_xxx group authorization_validation_xxx { function f_generate_authorization_validation_request( in InnerAtRequest p_inner_at_request, in Certificate p_certificate, out AuthorizationValidationRequest p_authorization_validation_request ) return boolean { p_authorization_validation_request.sharedAtRequest := p_inner_at_request.sharedAtRequest; p_authorization_validation_request.ecSignature := p_inner_at_request.ecSignature; return true; } // End of function f_generate_authorization_validation_request function f_generate_authorization_validation_response( in InnerAtRequest p_inner_at_request, in Certificate p_certificate, out AuthorizationValidationResponse p_authorization_validation_response ) return boolean { // TODO return false; } // End of function f_generate_authorization_validation_response } // End of group authorization_validation_xxx group pki_functions { /** * @desc Build a signed and encrypted PKI message * @param p_private_key Private key for signature * @param p_signer_identifier Signer identifier for signature, could be self or certificate HashedId8 * @param p_recipientId Recipient identifier to be inclued in encrypted layer. * If value is int2oct(0. 8), the recipient id is the HashedId8 of the symmetric key used by the sender to encrypt the message to which the response is built * @param p_publicKeyCompressed The public compressed key (canonical form) for encryption * @param p_compressedMode The compressed mode of the public compressed key (canonical form) for encryption * @param p_pki_message The PKI message to be secured * @param p_ieee1609dot2_signed_and_encrypted_data The secured message * @return true on success, false otherwise */ function f_build_pki_secured_message( in octetstring p_private_key, in SignerIdentifier p_signer_identifier, in HashedId8 p_recipientId, in octetstring p_publicKeyCompressed, in integer p_compressedMode, in octetstring p_pki_message, out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data ) return boolean { // Local variables var template (value) EccP256CurvePoint v_eccP256_curve_point; var template (value) ToBeSignedData v_tbs; var octetstring v_tbs_signed; var template (value) Ieee1609Dot2Data v_ieee1609dot2_signed_data; var octetstring v_encoded_inner_ec_request; var Oct12 v_nonce; var Oct16 v_authentication_vector; var Oct16 v_encrypted_sym_key; var HashedId8 v_recipientId; var octetstring v_publicEphemeralKeyCompressed; var integer v_ephemeralKeyModeCompressed; var octetstring v_encrypted_inner_ec_request; // Signed the encoded PKI message v_tbs := m_toBeSignedData( m_signedDataPayload( m_etsiTs103097Data_unsecured(p_pki_message) ), m_headerInfo_inner_ec_request(c_its_aid_SCR, f_getCurrentTimeUtc()) ); if (ischosen(p_signer_identifier.self_)) { v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key); } else { var charstring v_certificate_id; var octetstring v_hash; fx_readCertificateFromDigest(p_signer_identifier.digest, v_certificate_id); // TODO Add a wrapper function f_getCertificateHash(v_certificate_id, v_hash); v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_hash, p_private_key); } // Add the signature and create EtsiTs103097Data-Signed data structure v_ieee1609dot2_signed_data := m_etsiTs103097Data_signed( m_signedData( sha256, v_tbs, p_signer_identifier, m_signature_ecdsaNistP256( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only( substr(v_tbs_signed, 0, 32) ), substr(v_tbs_signed, 32, 32) ) ) ) ); // Encode EtsiTs103097Data-Signed data structure v_encoded_inner_ec_request := bit2oct(encvalue(v_ieee1609dot2_signed_data)); // Encrypt encode EtsiTs103097Data-Signed data structure v_encrypted_inner_ec_request := f_encryptWithEciesNistp256WithSha256(v_encoded_inner_ec_request, p_publicKeyCompressed, p_compressedMode, v_publicEphemeralKeyCompressed, v_ephemeralKeyModeCompressed, v_encrypted_sym_key, v_authentication_vector, v_nonce); log("p_recipientId=", p_recipientId); if (p_recipientId == int2oct(0, 8)) { log("v_encrypted_sym_key=", v_encrypted_sym_key); log("f_hashWithSha256(v_encrypted_sym_key=", f_hashWithSha256(v_encrypted_sym_key)); v_recipientId := f_HashedId8FromSha256(f_hashWithSha256(v_encrypted_sym_key)); } else { v_recipientId := p_recipientId; } log("v_recipientId=", v_recipientId); // Fill Certificate template with the public compressed keys (canonical form) if (v_ephemeralKeyModeCompressed == 0) { v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_publicEphemeralKeyCompressed)); } else { v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_publicEphemeralKeyCompressed)); } p_ieee1609dot2_signed_and_encrypted_data := valueof( m_etsiTs103097Data_encrypted( m_encryptedData( { m_recipientInfo_signedDataRecipInfo( m_pKRecipientInfo( v_recipientId, m_encryptedDataEncryptionKey_eciesNistP256( m_evciesP256EncryptedKey( v_eccP256_curve_point, v_encrypted_sym_key, v_authentication_vector )))) }, m_SymmetricCiphertext_aes128ccm( m_aesCcmCiphertext( v_nonce, v_encrypted_inner_ec_request ) ) ) ) ); return true; } // End of function f_build_pki_secured_message /** * @desc Verify the protocol element of the Pki message * @param p_private_key Private key for encryption * @param p_issuer Issuer * @param p_peer_certificate IUT EA certificate identifier * @param p_ieee1609dot2_encrypted_and_signed_data The public compressed key (canonical form) for encryption * @param p_check_security Set to true to check signatures * @param p_etsi_ts_102941_data The EtsiTs102941Data message * @return true on success, false otherwise */ function f_verify_pki_message( in octetstring v_private_enc_key, in octetstring p_issuer, in Certificate p_peer_certificate, in Ieee1609Dot2Data p_ieee1609dot2_encrypted_and_signed_data, in boolean p_check_security := true, out EtsiTs102941Data p_etsi_ts_102941_data ) return boolean { // Local variables var Ieee1609Dot2Data v_ieee1609dot2_signed_data; var bitstring v_etsi_ts_102941_data_msg; var bitstring v_tbs; var boolean v_ret; // 1. Decrypt the data if (f_decrypt(v_private_enc_key, p_ieee1609dot2_encrypted_and_signed_data, v_ieee1609dot2_signed_data) == false) { if (p_check_security == true) { return false; } } log("v_ieee1609dot2_signed_data= ", v_ieee1609dot2_signed_data); // 2. Check the signature v_tbs := encvalue(v_ieee1609dot2_signed_data.content.signedData.tbsData); if (ischosen(p_peer_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) { v_ret := f_verifyWithEcdsaNistp256WithSha256( bit2oct(v_tbs), p_issuer, v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only & v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.sSig, p_peer_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0, 0); } else { v_ret := f_verifyWithEcdsaNistp256WithSha256( bit2oct(v_tbs), p_issuer, v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only & v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.sSig, p_peer_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1, 1); } if (v_ret == false) { if (p_check_security == true) { return false; } } // 3. Retrun the PKI message v_etsi_ts_102941_data_msg := oct2bit(v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData); if (decvalue(v_etsi_ts_102941_data_msg, p_etsi_ts_102941_data) != 0) { return false; } if (p_etsi_ts_102941_data.version != PkiProtocolVersion) { if (p_check_security == true) { return false; } } return true; } // End of function f_verify_pki_message /** * @desc Verify the generated EA certificate * @param p_ea_certificate The new EA certificate * @param p_publicKeyCompressed The public compressed key (canonical form) for signature check * @param p_compressedMode The public compressed key mode * @return true on success, false otherwise */ function f_verify_ea_certificate( in Certificate p_ea_certificate, in octetstring p_publicKeyCompressed, in integer p_compressedMode ) return boolean { var bitstring v_encoded_tbs; var boolean v_result; // Check certificate format v_result := match(p_ea_certificate, mw_etsiTs103097Certificate(mw_issuerIdentifier_self, mw_toBeSignedCertificate_ea, -)); // Check the signer // Check EA certificate signature v_encoded_tbs := encvalue(p_ea_certificate.toBeSigned); v_result := v_result and f_verifyWithEcdsaNistp256WithSha256( bit2oct(v_encoded_tbs), int2oct(0, 32), // self p_ea_certificate.signature_.ecdsaNistP256Signature.rSig.x_only & p_ea_certificate.signature_.ecdsaNistP256Signature.sSig, p_publicKeyCompressed, p_compressedMode); return v_result; } // End of function f_verify_ea_certificate /** * @desc Verify the generated AA certificate * @param p_aa_certificate The new EA certificate * @param p_publicKeyCompressed The public compressed key (canonical form) for signature check * @param p_compressedMode The public compressed key mode * @return true on success, false otherwise */ function f_verify_aa_certificate( in Certificate p_aa_certificate, in octetstring p_publicKeyCompressed, in integer p_compressedMode ) return boolean { var bitstring v_encoded_tbs; var boolean v_result; // Check certificate format v_result := match(p_aa_certificate, mw_etsiTs103097Certificate(mw_issuerIdentifier_self, mw_toBeSignedCertificate_aa, -)); // Check the signer // Check EA certificate signature v_encoded_tbs := encvalue(p_aa_certificate.toBeSigned); v_result := v_result and f_verifyWithEcdsaNistp256WithSha256( bit2oct(v_encoded_tbs), int2oct(0, 32), // self p_aa_certificate.signature_.ecdsaNistP256Signature.rSig.x_only & p_aa_certificate.signature_.ecdsaNistP256Signature.sSig, p_publicKeyCompressed, p_compressedMode); return v_result; } // End of function f_verify_aa_certificate } // End of group inner_ec_xxx group altstes { altstep a_default_pki() runs on ItsPki { [] pkiPort.receive { tc_ac.stop; log("*** a_default: ERROR: Unexpected PKI message received ***"); f_selfOrClientSyncAndVerdict("error", e_error); } } altstep a_default_pki_http() runs on ItsPkiHttp { [] httpPort.receive( mw_http_response( mw_http_response_ko )) { tc_ac.stop; log("*** a_default: ERROR: HTTP Server error ***"); f_selfOrClientSyncAndVerdict("error", e_error); } [] httpPort.receive(mw_http_request) { tc_ac.stop; log("*** a_default: ERROR: Unexpected HTTP Request received ***"); f_selfOrClientSyncAndVerdict("error", e_error); } [] httpPort.receive(mw_http_response) { tc_ac.stop; log("*** a_default: ERROR: Unexpected HTTP Response received ***"); f_selfOrClientSyncAndVerdict("error", e_error); } [] httpPort.receive { tc_ac.stop; log("*** a_default: ERROR: Unexpected HTTP message received ***"); f_selfOrClientSyncAndVerdict("error", e_error); } } } } // End of module LibItsPki_Functions