/** * @author ETSI / STF481 * @version $URL$ * $Id$ * @desc Module containing functions for Security Protocol * */ module LibItsSecurity_Functions { // Libcommon import from LibCommon_DataStrings all; // LibItsCommon import from LibItsCommon_Functions all; // LibItsSecurity import from LibItsSecurity_TypesAndValues all; import from LibItsSecurity_Templates all; import from LibItsSecurity_Pixits all; group helpersFunctions { /** * @desc Produces a 256-bit (32-byte) hash value * @param p_toBeHashedData Data to be used to calculate the hash value * @return The hash value */ function f_hashWithSha256(in octetstring p_toBeHashedData) return Oct32 { return fx_hashWithSha256(p_toBeHashedData); } // End of function f_hashWithSha256 /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signaturee * @param p_toBeSignedSecuredMessage The data to be signed * @return The signature value */ function f_signWithEcdsaNistp256WithSha256(in Oct32 p_toBeSignedSecuredMessage) return octetstring { return fx_signWithEcdsaNistp256WithSha256( p_toBeSignedSecuredMessage, PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].signingPrivateKey ); } // End of function f_signWithEcdsaNistp256WithSha256 /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_signature The signature * @param p_ecdsaNistp256PublicKeyX The public key (x coordinate) * @param p_ecdsaNistp256PublicKeyY The public key (y coordinate) * @return true on success, false otherwise */ function f_verifyWithEcdsaNistp256WithSha256( in octetstring p_toBeVerifiedData, in octetstring p_signature, in octetstring p_ecdsaNistp256PublicKeyX, in octetstring p_ecdsaNistp256PublicKeyY ) return boolean { return fx_verifyWithEcdsaNistp256WithSha256( p_toBeVerifiedData, p_signature, p_ecdsaNistp256PublicKeyX, p_ecdsaNistp256PublicKeyY); } // End of function f_verifyWithEcdsaNistp256WithSha256 /** * @desc Calculate digest over the certificate * @param cert The certificate * @return the digest */ function f_calculateDigest(in Certificate cert) return HashedId8 { return '0000000000000000'O; } group hostSignatureHelpers { /** * @desc Build a template of a secured beacon to be used for the Test Adapter secured beaconing processing */ function f_buildSecuredMessagePayloadToBeSigned() return ToBeSignedSecuredMessage { // Local variables var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage; // Build the beacon template v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileOthers, { // Field HeaderFields m_header_field_signer_info( m_signerInfo_certificate( PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate ) // End of template m_signerInfo_certificate ), // End of template m_header_field_signer_info m_header_field_generation_time(oct2int('BBBBBBBB'O)), // To be replaced by TA with current time m_header_field_generation_location( PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].location ) }, // End of field HeaderFields { m_payload_unsecured( 'AAAAAAAAAA'O // To be replaced by TA with real payload ) }, // End of field HeaderFields e_signature ); return v_toBeSignedSecuredMessage; } /** * @desc This function build and sign the SecureMessage part covered by the signature process * @param p_securedMessage The signed SecureMessage part * @param p_unsecuredPayload The unsigned payload (e.g. a beacon) * @param p_threeDLocation The ThreeDLocation value * @param p_headerFields Additional HeaderFields * @return true on success, false otherwise * @verdict Unchanged */ function f_buildGnSecuredCam( out template (value) SecuredMessage p_securedMessage, in octetstring p_unsecuredPayload, in ThreeDLocation p_threeDLocation, in template (omit) HeaderFields p_headerFields := omit ) return boolean { // Local variables var octetstring v_secPayload, v_signature; var Oct32 v_hash; var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage; // Create SecuredMessage payload to be signed v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileOthers, { // Field HeaderFields m_header_field_signer_info( m_signerInfo_certificate( PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate ) // End of template m_signerInfo_certificate ), // End of template m_header_field_signer_info m_header_field_generation_time(f_getCurrentTime()), m_header_field_generation_location( p_threeDLocation ), m_header_field_message_type(c_messageType_CAM) }, // End of field HeaderFields { m_payload_unsecured( p_unsecuredPayload ) }, // End of field HeaderFields e_signature ); // Add additional header fields if any if (ispresent(p_headerFields) == true) { var integer v_addItemIndex := lengthof(v_toBeSignedSecuredMessage.header_fields); var integer v_counter; for (v_counter := 0; v_counter < lengthof(p_headerFields); v_counter := v_counter + 1) { v_toBeSignedSecuredMessage.header_fields[v_addItemIndex] := p_headerFields[v_counter]; v_addItemIndex := v_addItemIndex + 1; } // End of 'for' statement } v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage)); // Calculate the hash of the SecuredMessage payload to be signed v_hash := f_hashWithSha256(v_secPayload); // Signed payload v_signature := f_signWithEcdsaNistp256WithSha256( v_hash ); p_securedMessage := m_securedMessage_profileOther( // See Clause 7.3 Generic security profile for other signed messages v_toBeSignedSecuredMessage.header_fields, v_toBeSignedSecuredMessage.payload_fields, { m_trailer_field_signature( m_signature( m_ecdsaSignature( m_eccPointecdsa_nistp256_with_sha256_y_coordinate_only( substr(v_signature, 2, 32) ), substr(v_signature, 34, 32) ) ) ) } ); // End of template m_securedMessageBeacon return true; } /** * @desc This function build and sign the SecureMessage part covered by the signature process * @param p_securedMessage The signed SecureMessage part * @param p_unsecuredPayload The unsigned payload (e.g. a beacon) * @param p_threeDLocation The ThreeDLocation value * @param p_headerFields Additional HeaderFields * @return true on success, false otherwise * @verdict Unchanged */ function f_buildGnSecuredDenm( out template (value) SecuredMessage p_securedMessage, in octetstring p_unsecuredPayload, in ThreeDLocation p_threeDLocation, in template (omit) HeaderFields p_headerFields := omit ) return boolean { // Local variables var octetstring v_secPayload, v_signature; var Oct32 v_hash; var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage; // Create SecuredMessage payload to be signed v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileOthers, { // Field HeaderFields m_header_field_signer_info( m_signerInfo_certificate( PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate ) // End of template m_signerInfo_certificate ), // End of template m_header_field_signer_info m_header_field_generation_time(f_getCurrentTime()), m_header_field_generation_location( p_threeDLocation ), m_header_field_message_type(c_messageType_DENM) }, // End of field HeaderFields { m_payload_unsecured( p_unsecuredPayload ) }, // End of field HeaderFields e_signature ); // Add additional header fields if any if (ispresent(p_headerFields) == true) { var integer v_addItemIndex := lengthof(v_toBeSignedSecuredMessage.header_fields); var integer v_counter; for (v_counter := 0; v_counter < lengthof(p_headerFields); v_counter := v_counter + 1) { v_toBeSignedSecuredMessage.header_fields[v_addItemIndex] := p_headerFields[v_counter]; v_addItemIndex := v_addItemIndex + 1; } // End of 'for' statement } v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage)); // Calculate the hash of the SecuredMessage payload to be signed v_hash := f_hashWithSha256(v_secPayload); // Signed payload v_signature := f_signWithEcdsaNistp256WithSha256( v_hash ); p_securedMessage := m_securedMessage_profileOther( // See Clause 7.3 Generic security profile for other signed messages v_toBeSignedSecuredMessage.header_fields, v_toBeSignedSecuredMessage.payload_fields, { m_trailer_field_signature( m_signature( m_ecdsaSignature( m_eccPointecdsa_nistp256_with_sha256_y_coordinate_only( substr(v_signature, 2, 32) ), substr(v_signature, 34, 32) ) ) ) } ); // End of template m_securedMessageBeacon return true; } // End of function f_buildGnSecuredDenm /** * @desc This function build and sign the SecureMessage part covered by the signature process * @param p_securedMessage The signed SecureMessage part * @param p_unsecuredPayload The unsigned payload (e.g. a beacon) * @param p_threeDLocation The ThreeDLocation value * @param p_headerFields Additional HeaderFields * @return true on success, false otherwise * @verdict Unchanged */ function f_buildGnSecuredOtherMessage( out template (value) SecuredMessage p_securedMessage, in octetstring p_unsecuredPayload, in ThreeDLocation p_threeDLocation, in template (omit) HeaderFields p_headerFields := omit ) return boolean { // Local variables var octetstring v_secPayload, v_signature; var Oct32 v_hash; var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage; // Create SecuredMessage payload to be signed v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileOthers, { // Field HeaderFields m_header_field_signer_info( m_signerInfo_certificate( PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate ) // End of template m_signerInfo_certificate ), // End of template m_header_field_signer_info m_header_field_generation_time(f_getCurrentTime()), m_header_field_generation_location( p_threeDLocation ) }, // End of field HeaderFields { m_payload_unsecured( p_unsecuredPayload ) }, // End of field HeaderFields e_signature ); // Add additional header fields if any if (ispresent(p_headerFields) == true) { var integer v_addItemIndex := lengthof(v_toBeSignedSecuredMessage.header_fields); var integer v_counter; for (v_counter := 0; v_counter < lengthof(p_headerFields); v_counter := v_counter + 1) { v_toBeSignedSecuredMessage.header_fields[v_addItemIndex] := p_headerFields[v_counter]; v_addItemIndex := v_addItemIndex + 1; } // End of 'for' statement } log("v_toBeSignedSecuredMessage= ", v_toBeSignedSecuredMessage); v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage)); // Calculate the hash of the SecuredMessage payload to be signed v_hash := f_hashWithSha256(v_secPayload); // Signed payload v_signature := f_signWithEcdsaNistp256WithSha256( v_hash ); p_securedMessage := m_securedMessage_profileOther( // See Clause 7.3 Generic security profile for other signed messages v_toBeSignedSecuredMessage.header_fields, v_toBeSignedSecuredMessage.payload_fields, { m_trailer_field_signature( m_signature( m_ecdsaSignature( m_eccPointecdsa_nistp256_with_sha256_y_coordinate_only( substr(v_signature, 2, 32) ), substr(v_signature, 34, 32) ) ) ) } ); // End of template m_securedMessageBeacon return true; } // End of function f_buildGnSecuredOtherMessage } // End of group hostSignatureHelpers group deviceSignatureHelpers { /** * @desc Verify the signature of the provided secured message * @param p_aaCertifcate Enrolment Credential certificate * @param p_atCertificate Authorization Ticket certificate * @return true on success, false otherwise * @verdict */ function f_verifyCertificateSignatureWithIssuingCertificate( in template (value) Certificate p_aaCertifcate, in template (value) Certificate p_atCertificate ) return boolean { // Local variables var octetstring v_secPayload; var octetstring v_signedData; var Oct32 v_hash; var boolean v_result := false; var template (value) ToBeSignedCertificate v_toBeSignedCertificate; // Create Certificate payload to be signed v_toBeSignedCertificate := m_toBeSignedCertificate(p_atCertificate); v_secPayload := bit2oct(encvalue(v_toBeSignedCertificate)); // Calculate the hash of the SecuredMessage payload to be signed v_hash := fx_hashWithSha256(v_secPayload); // Verify payload v_signedData := '0000'O & p_atCertificate.signature_.signature_.ecdsa_signature.r.x & p_atCertificate.signature_.signature_.ecdsa_signature.s; v_result := f_verifyWithEcdsaNistp256WithSha256( v_hash, v_signedData, p_aaCertifcate.subject_attributes[0].attribute.key.public_key.eccPoint.x, p_aaCertifcate.subject_attributes[0].attribute.key.public_key.eccPoint.y.y ); return v_result; } // End of function f_verifyGnSecuredOtherMessage } // End of group hostSignatureHelpers group deviceSignatureHelpers { /** * @desc Verify the signature of the provided certificate * @param p_cert Certificate to be verified * @param p_key Public key to verify * @return true on success, false otherwise * @verdict */ function f_verifyCertificateSignatureWithPublicKey( in template (value) Certificate p_cert, in template (value) PublicKey key ) return boolean { // TODO To be implemented return false; } /** * @desc Verify the signature of the provided secured message * @param p_cert Certificate to be verified * @param p_verify Certificate to be used to verify * @return true on success, false otherwise * @verdict */ function f_verifyCertificateSignatureWithIssuingCertificate( in template (value) Certificate p_cert, in template (value) Certificate p_verify ) return boolean { return f_verifyCertificateSignatureWithPublicKey(p_cert, p_verify.subject_attributes[0].attribute.key); } /** * @desc Verify the signature of the provided secured message * @param p_securedMessage The message to be verified * @param p_publicKey The ECDSA public key to verify a signature * @param p_certificate Certificate to be used to verify the message * @return true on success, false otherwise * @verdict */ function f_verifyCertificateSignatureWithPublicKey( in template (value) SecuredMessage p_securedMessage, in template (value) PublicKey p_publicKey ) return boolean { // Local variables var octetstring v_secPayload; var octetstring v_signedData; var Oct32 v_hash; var integer v_counter; var boolean v_result := false; var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage; // Create SecuredMessage payload to be signed v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( p_securedMessage.security_profile, p_securedMessage.header_fields, p_securedMessage.payload_fields, e_signature ); v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage)); // Calculate the hash of the SecuredMessage payload to be signed v_hash := fx_hashWithSha256(v_secPayload); // Verify payload for (v_counter := 0; v_counter < lengthof(p_securedMessage.trailer_fields); v_counter := v_counter + 1) { if ( (p_securedMessage.trailer_fields[v_counter].type_ == e_signature) and (p_securedMessage.trailer_fields[v_counter].trailerField.signature_.algorithm == e_ecdsa_nistp256_with_sha256) ) { v_signedData := '0000'O & p_securedMessage.trailer_fields[v_counter].trailerField.signature_.signature_.ecdsa_signature.r.x & p_securedMessage.trailer_fields[v_counter].trailerField.signature_.signature_.ecdsa_signature.s; v_result := f_verifyWithEcdsaNistp256WithSha256( v_hash, v_signedData, p_publicKey.public_key.eccPoint.x, p_publicKey.public_key.eccPoint.y.y ); } } // End of 'for' statement return v_result; } // End of function f_verifyCertificateSignatureWithPublicKey /** * @desc Verify the signature of the provided secured message * @param p_securedMessage * @param p_certificate Certificate to be used to verify the message * @return true on success, false otherwise * @verdict */ function f_verifyGnSecuredMessageWithDeviceCertificate( in template (value) SecuredMessage p_securedMessage, in template (value) Certificate p_certificate ) return boolean { return f_verifyGnSecuredMessageWithPublicKey(p_securedMessage, p_certificate.subject_attributes[0].attribute.key); } // End of function f_verifyGnSecuredOtherMessageWithDeviceCertificate } // End of group deviceSignatureHelpers group messageGetters { /** * @desc return SecuredMessage header field of given type or null if none * @param p_msg the SecuredMessage * @param p_type header field type * @return HeaderField of given type if any or null */ function f_getMsgHeaderField( in SecuredMessage p_securedMessage, in HeaderFieldType p_headerFieldType ) return HeaderField { var HeaderField v_return; var integer v_length := lengthof(p_securedMessage.header_fields); var integer v_index; for (v_index := 0; v_index < v_length; v_index := v_index + 1) { if (p_securedMessage.header_fields[v_index].type_ == p_headerFieldType) { v_return := p_securedMessage.header_fields[v_index]; break; } } return v_return; } /** * @desc return SignerInfo SecuredMessage field */ function f_getMsgSignerInfo( in SecuredMessage p_securedMessage ) return SignerInfo { var HeaderField v_hf := f_getMsgHeaderField(p_securedMessage, e_signer_info); if (isbound(v_hf)) { return v_hf.headerField.signer; } return null; } }// End of group messageGetters group certificateGetters { function f_getCertificateValidityRestriction( in Certificate p_cert, in ValidityRestrictionType p_type ) return ValidityRestriction { var ValidityRestriction v_return; var integer v_length := lengthof(p_cert.validity_restrictions); var integer v_index; for (v_index := 0; v_index < v_length; v_index := v_index + 1) { if( p_cert.validity_restrictions[v_index].type_ == p_type ) { v_return := p_cert.validity_restrictions[v_index]; break; } } return v_return; } function f_getCertificateSignerInfo (in Certificate p_cert) return SignerInfo { var SignerInfo ret; if (lengthof(p_cert.signer_infos) > 0) { ret := p_cert.signer_infos[0]; } return ret; } }// End of group certificateGetters group CertRequests{ function f_askForCertificate (in HashedId3 p_digest) { } } // End of group CertRequests } // End of group helpersFunctions group externalFunctions { /** * @desc Produces a 256-bit (32-byte) hash value * @param p_toBeHashedData Data to be used to calculate the hash value * @return The hash value */ external function fx_hashWithSha256(in octetstring p_toBeHashedData) return Oct32; /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signaturee * @param p_toBeSignedSecuredMessage The data to be signed * @param p_privateKey The private key * @return The signature value */ external function fx_signWithEcdsaNistp256WithSha256(in octetstring p_toBeSignedSecuredMessage, in octetstring/*UInt64*/ p_privateKey) return octetstring; /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_signature The signature * @param p_ecdsaNistp256PublicKeyX The public key (x coordinate) * @param p_ecdsaNistp256PublicKeyY The public key (y coordinate) * @return true on success, false otherwise */ external function fx_verifyWithEcdsaNistp256WithSha256(in octetstring p_toBeVerifiedData, in octetstring p_signature, in octetstring p_ecdsaNistp256PublicKeyX, in octetstring p_ecdsaNistp256PublicKeyY) return boolean; /** * @desc Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. * This function should not be used by the ATS * @param p_privateKey The new private key value * @param p_publicKeyX The new public key value (x coordinate) * @param p_publicKeyX The new public key value (y coordinate) * @return true on success, false otherwise */ external function fx_generateKeyPair(out octetstring/*UInt64*/ p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; } // End of group externalFunctions } // End of module LibItsSecurity_Functions