Skip to content
LibItsSecurity_Functions.ttcn3 105 KiB
Newer Older
garciay's avatar
garciay committed
/**
 *  @author   ETSI / STF481
 *  @version  $URL$
 *            $Id$
 *  @desc     Module containing functions for Security Protocol
 *
 */
module LibItsSecurity_Functions {
    import from LibCommon_BasicTypesAndValues all;
    // LibItsCommon
    import from LibItsCommon_Functions all;
    
    // LibItsSecurity
    import from LibItsSecurity_TypesAndValues all;
    import from LibItsSecurity_Templates all;
    import from LibItsSecurity_Pixits all;
    import from LibItsSecurity_TestSystem all;
garciay's avatar
garciay committed
    
    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
        */
garciay's avatar
garciay committed
                                  in octetstring p_toBeHashedData
            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 octetstring p_toBeSignedSecuredMessage,
                                                   in Oct32 p_privateKey
        ) runs on ItsSecurityBaseComponent return octetstring {
            return fx_signWithEcdsaNistp256WithSha256(
                p_toBeSignedSecuredMessage,
        } // End of function f_signWithEcdsaNistp256WithSha256
        * @desc Compute the HashedId8 value from the hash value
        * @param p_hash The hash value
        * @return The HashedId8 value
        * @verdict
        */
        function f_HashedId8FromSha256(
garciay's avatar
garciay committed
                                       in Oct32 p_hash
        ) return HashedId8 {
            return substr(p_hash, lengthof(p_hash) - 8, 8);
        } // End of function f_HashedId8FromSha256
        * @desc Compute the HashedId3 value from the HashedId8 value
        * @param p_hashp_hashedId8 The HashedId8 value
        * @return The HashedId3 value
        * @verdict Unchanged
        */
garciay's avatar
garciay committed
        function f_HashedId3FromHashedId8(
                                          in HashedId8 p_hashedId8
        ) return HashedId3 {
            return substr(p_hashedId8, lengthof(p_hashedId8) - 3, 3);
        }  // End of function f_HashedId3FromHashedId8
        * @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(
garciay's avatar
garciay committed
                                                     in octetstring p_toBeVerifiedData,
                                                     in octetstring p_signature,
                                                     in octetstring p_ecdsaNistp256PublicKeyX,
                                                     in octetstring p_ecdsaNistp256PublicKeyY
//            log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaNistp256WithSha256: signature", p_signature);
//            log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyX", p_ecdsaNistp256PublicKeyX);
//            log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyY", p_ecdsaNistp256PublicKeyY);
            return fx_verifyWithEcdsaNistp256WithSha256(
                p_toBeVerifiedData,
                p_signature,
                p_ecdsaNistp256PublicKeyX,
                p_ecdsaNistp256PublicKeyY);
        } // End of function f_verifyWithEcdsaNistp256WithSha256
        * @desc    Calculate digest over the certificate
        * @param   p_cert The certificate
        * @return  the HashedId8 value
        * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.13   HashedId8
        function f_calculateDigestFromCertificate(
garciay's avatar
garciay committed
                                                  in Certificate p_cert
            var octetstring v_toBeHashedData;
            var octetstring v_hash;
            v_toBeHashedData := bit2oct(encvalue(p_cert));
            v_hash := f_hashWithSha256(v_toBeHashedData);
            return substr(v_hash, lengthof(v_hash) - 8, 8);
        } // End of function f_calculateDigestFromCertificate
garciay's avatar
garciay committed
        function f_duration2time(
                                 in Duration p_duration
        ) return Time32 {
            if (p_duration.unit == e_seconds) {
                return p_duration.duration_;
            } else if (p_duration.unit == e_minutes) { 
                return p_duration.duration_ * 60;
            } else if (p_duration.unit == e_hours) { 
                return p_duration.duration_ * 3600;
            } else if (p_duration.unit == e_hoursBlock) {
                return p_duration.duration_ * 216000;
            }
            
            return p_duration.duration_ * 31556925;
        } // End of function f_duration2time
        
        group hostSignatureHelpers {
            /**
            * @desc    Initialize [out] certificates according to the specified certificate name
            * @param   p_certificateName The certificate name to be used
            * @param   p_aaCertificate The AA certificate [out]
            * @param   p_atCertificate The AT certificate [out]
            * @return  true on succes, false otherwise
            * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.13   HashedId8
            function f_prepareCertificates(
                                           in template (omit) charstring p_certificateName,
                                           out Certificate p_aaCertificate,
                                           out Certificate p_atCertificate
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Load certificates if required
garciay's avatar
garciay committed
                if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCert_A)) {
                    if (f_readCertificate(valueof(p_certificateName), p_atCertificate) == false){
                        return false;
                    }
                    if (f_readCertificate(oct2str(p_atCertificate.signer_info.signerInfo.digest), p_aaCertificate) == false) {
                        return false;
                    }
                } else {
                    p_atCertificate := vc_atCertificate;
                    p_aaCertificate := vc_aaCertificate;
                }
                // Store the certificte to build this message
                vc_lastAtCertificateUsed := p_atCertificate;
                
                return true;
            } // End of function f_prepareCertificates
berge's avatar
berge committed
             * @desc  This function build and sign the SecureMessage part covered by the signature process
             * @param p_securedMessage      The signed  SecureMessage part
             * @param p_payloadField       Payloads to be included in the message
berge's avatar
berge committed
             * @param p_mandatoryHeaders    Mandatory headers for the selected profile 
             * @param p_headerFields        HeaderFields to be inserted in the message
             * @param p_securityProfile     Selected security profile
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredMessage(
garciay's avatar
garciay committed
                                             out template (value) SecuredMessage p_securedMessage,
                                             in template (value) charstring p_certificateName,
                                             in template (value) SecPayload p_payloadField,
garciay's avatar
garciay committed
                                             in template (value) HeaderFields p_mandatoryHeaders,
                                             in template (omit) HeaderFields p_headerFields := omit
            ) runs on ItsSecurityBaseComponent return boolean {
                // Local variables
                var octetstring v_secPayload, v_signature;
                var Oct32 v_hash;
                var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
                var integer i, j, k, n;
garciay's avatar
garciay committed
                var HeaderFields v_headerFields := {};
                var SecPayload v_toBeSignedPayload;
                var Oct32 v_privateKey;
berge's avatar
berge committed
                // Prepare headers
garciay's avatar
garciay committed
                if (not(ispresent(p_headerFields))) {
                    v_headerFields := valueof(p_mandatoryHeaders);
garciay's avatar
garciay committed
                } else {
berge's avatar
berge committed
                    // Merge p_headerFields and v_mandatoryHeaders into v_headerFields
berge's avatar
berge committed
                    i := 0; // index for p_headerFields
                    j := 0; // index for v_mandatoryHeaders
                    k := 0; // index for v_headerFields
berge's avatar
berge committed
                    // Special processing for signer_info
garciay's avatar
garciay committed
                    if (lengthof(valueof(p_headerFields)) > 0 and valueof(p_headerFields[i].type_) == e_signer_info) {
berge's avatar
berge committed
                        v_headerFields[k] := valueof(p_headerFields[i]);
                        k := k + 1;
                        i := i + 1;
                    }
garciay's avatar
garciay committed
                    for (j := j; j < lengthof(p_mandatoryHeaders); j := j + 1) {
berge's avatar
berge committed
                        // Search for mandatory header in p_HeaderFields
garciay's avatar
garciay committed
                        for (n := 0; n < lengthof(p_headerFields); n := n + 1) {
                            if (valueof(p_headerFields[n].type_) == valueof(p_mandatoryHeaders[j].type_)) {
berge's avatar
berge committed
                                // mandatory header already in p_HeaderFields
                                break;
garciay's avatar
garciay committed
                        } // End of 'for' statement
                        if (n >= lengthof(p_headerFields)) {
garciay's avatar
garciay committed
                            if (valueof(p_mandatoryHeaders[j].type_) != e_signer_info) {
berge's avatar
berge committed
                                // Add headers from p_headerFields having lower number than mandatory header
garciay's avatar
garciay committed
                                for (n := i; n < lengthof(p_headerFields) and valueof(p_headerFields[n].type_) < valueof(p_mandatoryHeaders[j].type_); n := n + 1) {
berge's avatar
berge committed
                                    v_headerFields[k] := valueof(p_headerFields[n]);
                                    k := k + 1;
                                    i := i + 1;
berge's avatar
berge committed
                            // Add mandatory header
                            v_headerFields[k] := valueof(p_mandatoryHeaders[j]);
                            k := k + 1;
                        }
garciay's avatar
garciay committed
                    } // End of 'for' statement
berge's avatar
berge committed
                        
                    // Add remaining headers from p_HeaderFields
garciay's avatar
garciay committed
                    for ( i := i; i < lengthof(p_headerFields); i := i + 1) {
berge's avatar
berge committed
                        // Add headers from p_headerFields having lower number than mandatory header
                        v_headerFields[k] := valueof(p_headerFields[i]);
                        k := k + 1;
garciay's avatar
garciay committed
                    } // End of 'for' statement
berge's avatar
berge committed
                }
                // Prepare payload to be signed
                v_toBeSignedPayload := valueof(p_payloadField);
                v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
                    v_headerFields,
                    e_signature
                );
                
                v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage));
                
                // Signed payload
                if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCert_A)) {
                    if(not f_readSigningKey(valueof(p_certificateName), v_privateKey)){
                        return false;
                    }
                } else {
                    if(not f_readSigningKey(valueof(cc_taCert_A), v_privateKey)){
                        return false;
                    }
                }
                v_signature := f_signWithEcdsaNistp256WithSha256(
                p_securedMessage := m_securedMessage(
                    v_toBeSignedSecuredMessage.header_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)
                                )
berge's avatar
berge committed
                );
            } // End of function f_buildGnSecuredMessage
            
            /**
             * @desc  This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases
             * @param p_securedMessage      The signed  SecureMessage part
             * @param p_certificateName     The certificate name
             * @param  p_protocolVersion    The protocol version to be set. Default: 2
             * @param  p_trailerStatus      The Traile behaviour:
             *                              <li>0 for no trailer</li>
             *                              <li>1 for invalid trailer</li>
             *                              <li>2 for duplicated trailer</li>
             * @param p_payloadField        Payloads to be included in the message
             * @param p_mandatoryHeaders    Mandatory headers for the selected profile 
             * @param p_headerFields        HeaderFields to be inserted in the message
             * @param p_securityProfile     Selected security profile
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredMessage_Bo(
                                                out template (value) SecuredMessage p_securedMessage,
                                                in template (value) charstring p_certificateName,
garciay's avatar
garciay committed
                                                in UInt8 p_protocolVersion := c_protocol_version,
                                                in integer p_trailerStatus := 0,
                                                in template (value) SecPayload p_payloadField,
                                                in template (value) HeaderFields p_mandatoryHeaders,
                                                in template (omit) HeaderFields p_headerFields := omit
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var octetstring v_secPayload, v_signature;
                var Oct32 v_hash;
                var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
                var integer i, j, k, n;
                var HeaderFields v_headerFields := {};
                var SecPayload v_toBeSignedPayload;
                var Oct32 v_privateKey;
                var UInt8 v_trailerSize;
                
                // Prepare headers
                if (not(ispresent(p_headerFields))) {
                    v_headerFields := valueof(p_mandatoryHeaders);
                } else {
                    // Merge p_headerFields and v_mandatoryHeaders into v_headerFields
                        
                    i := 0; // index for p_headerFields
                    j := 0; // index for v_mandatoryHeaders
                    k := 0; // index for v_headerFields
                        
                    // Special processing for signer_info
                    if (lengthof(valueof(p_headerFields)) > 0 and valueof(p_headerFields[i].type_) == e_signer_info) {
                        v_headerFields[k] := valueof(p_headerFields[i]);
                        k := k + 1;
                        i := i + 1;
                    }
                    
                    for (j := j; j < lengthof(p_mandatoryHeaders); j := j + 1) {
                        // Search for mandatory header in p_HeaderFields
                        for (n := 0; n < lengthof(p_headerFields); n := n + 1) {
                            if (valueof(p_headerFields[n].type_) == valueof(p_mandatoryHeaders[j].type_)) {
                                // mandatory header already in p_HeaderFields
                                break;
                            }
                        } // End of 'for' statement
                        if (n >= lengthof(p_headerFields)) {
                            if (valueof(p_mandatoryHeaders[j].type_) != e_signer_info) {
                                // Add headers from p_headerFields having lower number than mandatory header
                                for (n := i; n < lengthof(p_headerFields) and valueof(p_headerFields[n].type_) < valueof(p_mandatoryHeaders[j].type_); n := n + 1) {
                                    v_headerFields[k] := valueof(p_headerFields[n]);
                                    k := k + 1;
                                    i := i + 1;
                                }
                            }
                            // Add mandatory header
                            v_headerFields[k] := valueof(p_mandatoryHeaders[j]);
                            k := k + 1;
                        }
                    } // End of 'for' statement
                        
                    // Add remaining headers from p_HeaderFields
                    for ( i := i; i < lengthof(p_headerFields); i := i + 1) {
                        // Add headers from p_headerFields having lower number than mandatory header
                        v_headerFields[k] := valueof(p_headerFields[i]);
                        k := k + 1;
                    } // End of 'for' statement
                }
                
                // Prepare payload to be signed
                v_toBeSignedPayload := valueof(p_payloadField);
garciay's avatar
garciay committed
//                log("p_trailerStatus=", p_trailerStatus);
                if (p_trailerStatus == 0) {
                    v_trailerSize := 0;
                } else if (p_trailerStatus == 1) {
                    v_trailerSize := 67;
                } else if (p_trailerStatus == 2) {
                    v_trailerSize := 2 * 67;
                } else {
                    v_trailerSize := 67;
                }
                v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage_wrong_protocol(
                    v_headerFields,
                    v_toBeSignedPayload,
                    e_signature,
                    p_protocolVersion,
                    v_trailerSize
                );
garciay's avatar
garciay committed
                log("m_toBeSignedSecuredMessage_wrong_protocol=", v_toBeSignedSecuredMessage);
                
                v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage));
garciay's avatar
garciay committed
                log("v_secPayload=", v_secPayload);
                
                // Signed payload
                if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCert_A)) {
                    if(not f_readSigningKey(valueof(p_certificateName), v_privateKey)){
                        return false;
                    }
                } else {
                    if(not f_readSigningKey(valueof(cc_taCert_A), v_privateKey)){
                        return false;
                    }
                }
                v_signature := f_signWithEcdsaNistp256WithSha256(
                    v_secPayload, 
                    v_privateKey 
                );
garciay's avatar
garciay committed
                log("v_signature=", v_signature);
garciay's avatar
garciay committed
//                log("p_trailerStatus=", p_trailerStatus);
                if (p_trailerStatus == 0) { // No signature
garciay's avatar
garciay committed
                    p_securedMessage := m_securedMessage_wrong_protocol(
                        p_protocolVersion,
                        v_toBeSignedSecuredMessage.header_fields,
                        p_payloadField,
                        { }
                    );
                    v_trailerSize := 0;
                } else if (p_trailerStatus == 2) { // Duplicate signature
garciay's avatar
garciay committed
                    p_securedMessage := m_securedMessage_wrong_protocol(
                        p_protocolVersion,
                        v_toBeSignedSecuredMessage.header_fields,
                        p_payloadField,
                        {
                            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)
                                    )
                                )
                            ), 
                            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)
                                    )
                                )
                            ) 
                        }
                    );
garciay's avatar
garciay committed
                } else if (p_trailerStatus == 3) { // Signature with reserved algorthm
                    p_securedMessage := m_securedMessage_wrong_protocol(
                        p_protocolVersion,
                        v_toBeSignedSecuredMessage.header_fields,
                        p_payloadField,
                        {
                            m_trailer_field_signature(
                                m_unknownSignature(
                                    v_signature
                                )
                            )
                        }
                    );
                } else { // Invalid signature
garciay's avatar
garciay committed
                    p_securedMessage := m_securedMessage_wrong_protocol(
                        p_protocolVersion,
                        v_toBeSignedSecuredMessage.header_fields,
                        p_payloadField,
                        {
                            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)
                                    )
                                )
                            )
                        }
                    );
garciay's avatar
garciay committed
                    p_securedMessage.trailer_fields[0].trailerField.signature_.signature_.ecdsa_signature.s := not4b(valueof(p_securedMessage.trailer_fields[0].trailerField.signature_.signature_.ecdsa_signature.s));
                } 
                
                return true;
            } // End of function f_buildGnSecuredMessage_Bo
            * @desc This function build and sign the SecureMessage part covered by the signature process
garciay's avatar
garciay committed
            * @param p_securedMessage               The signed  SecureMessage part
            * @param p_payloadField                 Payloads to be included in the message
            * @param p_signerInfoType               Add digest or AT certificate or certificate chain
            * @param p_threeDLocation               The 3D location
            * @param p_headerFields                 HeaderFields to be inserted in the message
            * @param p_certificateName              The certificate identifier to be used. Default: TA_CERT_A
            * @param p_addMissingHeaders            Whether to add mandatory headers not present in p_headerFields
            * @return true on success, false otherwise
            * @see Draft ETSI TS 103 097 V1.1.14 Clause 7.1  Security profile for CAMs
berge's avatar
berge committed
            function f_buildGnSecuredCam(
garciay's avatar
garciay committed
                                         out template (value) SecuredMessage p_securedMessage,
                                         in template (value) SecPayload p_payloadField,
                                         in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
garciay's avatar
garciay committed
                                         in template (omit) HeaderFields p_headerFields := omit,
                                         in template (omit) charstring p_certificateName := omit,
                                         in boolean p_addMissingHeaders := true
            ) runs on ItsSecurityBaseComponent return boolean {
                // Local variables
berge's avatar
berge committed
                var Certificate v_aaCertificate, v_atCertificate;
                var HeaderFields v_mandatoryHeaders := {};
                var HeaderField v_signerInfo;
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
garciay's avatar
garciay committed
                if (p_addMissingHeaders == true) {
berge's avatar
berge committed
                    // Prepare mandatory headers
                    if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificate(
                                    v_atCertificate
                        )));
berge's avatar
berge committed
                    }
                    if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
berge's avatar
berge committed
                        ));
                    }
                    if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_digest(
                                    f_calculateDigestFromCertificate(v_atCertificate)
berge's avatar
berge committed
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_field_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_field_its_aid(c_its_aid_CAM))
berge's avatar
berge committed
                    }
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField, v_mandatoryHeaders, p_headerFields);
garciay's avatar
garciay committed
            } // End of function f_buildGnSecuredCam
berge's avatar
berge committed
            /**
            * @desc This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases
garciay's avatar
garciay committed
            * @param p_securedMessage               The signed  SecureMessage part
            * @param  p_protocolVersion             The protocol version to be set. Default: 2
            * @param  p_trailerStatus               The Traile behaviour:
            *                                       <li>0 for no trailer</li>
            *                                       <li>1 for invalid trailer</li>
            *                                       <li>2 for duplicated trailer</li>
            * @param p_payloadField                 Payloads to be included in the message
            * @param p_signerInfoType               Add digest or AT certificate or certificate chain
            * @param p_threeDLocation               The 3D location
            * @param p_headerFields                 HeaderFields to be inserted in the message
            * @param p_certificateName              The certificate identifier to be used. Default: TA_CERT_A
            * @param p_addMissingHeaders            Whether to add mandatory headers not present in p_headerFields
            * @param p_alterATCertificateSignature  Set to true to alter the AT certificate signature
            * @param p_alterAACertificateSignature  Set to true to alter the AA certificate signature
berge's avatar
berge committed
            * @return true on success, false otherwise
            * 
            * @see Draft ETSI TS 103 097 V1.1.14 Clause 7.1  Security profile for CAMs
berge's avatar
berge committed
            */
            function f_buildGnSecuredCam_Bo(
                                            out template (value) SecuredMessage p_securedMessage,
garciay's avatar
garciay committed
                                            in UInt8 p_protocolVersion := c_protocol_version,
                                            in integer p_trailerStatus := 0,
                                            in template (value) SecPayload p_payloadField,
                                            in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
                                            in template (omit) HeaderFields p_headerFields := omit,
                                            in template (omit) charstring p_certificateName := omit,
garciay's avatar
garciay committed
                                            in boolean p_addMissingHeaders := true,
                                            in boolean p_alterATCertificateSignature := false,
                                            in boolean p_alterAACertificateSignature := false
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var Certificate v_aaCertificate, v_atCertificate;
                var HeaderFields v_mandatoryHeaders := {};
                var HeaderField v_signerInfo;
                 
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                
garciay's avatar
garciay committed
                if (p_alterATCertificateSignature == true) {
                    v_atCertificate.signature_.signature_.ecdsa_signature.s := not4b(v_atCertificate.signature_.signature_.ecdsa_signature.s);
                }
                
                if (p_alterAACertificateSignature == true) {
                    v_aaCertificate.signature_.signature_.ecdsa_signature.s := not4b(v_aaCertificate.signature_.signature_.ecdsa_signature.s);
                }
                
                if (p_addMissingHeaders == true) {
                    // Prepare mandatory headers
                    if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificate(
                                    v_atCertificate
                        )));
                    }
                    if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
                        ));
                    }
                    if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_digest(
                                    f_calculateDigestFromCertificate(v_atCertificate)
                        )));
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_field_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_field_its_aid(c_its_aid_CAM))
                    }
                }
                
                return f_buildGnSecuredMessage_Bo(p_securedMessage, p_certificateName, p_protocolVersion, p_trailerStatus, p_payloadField, v_mandatoryHeaders, p_headerFields);
                
            } // End of function f_buildGnSecuredCam_Bo
            
            /**
             * @desc This function build and sign the SecureMessage part covered by the signature process
             * @param p_securedMessage       The signed  SecureMessage part
             * @param p_payloadField        Payloads to be included in the message
             * @param p_signerInfoType       Add digest or AT certificate or certificate chain
             * @param p_threeDLocation       The 3D location
             * @param p_headerFields         HeaderFields to be inserted in the message
             * @param p_certificateName      The certificate identifier to be used. Default: TA_CERT_A
             * @param p_addMissingHeaders    Whether to add mandatory headers not present in p_headerFields
             * @return true on success, false otherwise
             */
berge's avatar
berge committed
            function f_buildGnSecuredDenm(
garciay's avatar
garciay committed
                                          out template (value) SecuredMessage p_securedMessage,
                                          in template (value) SecPayload p_payloadField,
                                          in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
garciay's avatar
garciay committed
                                          in ThreeDLocation p_threeDLocation,
                                          in template (omit) HeaderFields p_headerFields := omit,
                                          in template (omit) charstring p_certificateName := omit,
                                          in boolean p_addMissingHeaders := true
berge's avatar
berge committed
            ) runs on ItsSecurityBaseComponent return boolean {
berge's avatar
berge committed
                // Local variables
                var Certificate v_aaCertificate, v_atCertificate;
                var HeaderFields v_mandatoryHeaders := {};
                var HeaderField v_signerInfo;
                 
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
berge's avatar
berge committed
                }
                // Add additional headers if required
garciay's avatar
garciay committed
                if (p_addMissingHeaders == true) {
berge's avatar
berge committed
                    // Prepare mandatory headers
                    if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificate(
                                    v_atCertificate
                        )));
berge's avatar
berge committed
                    }
                    if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
berge's avatar
berge committed
                        ));
                    if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_digest(
                                    v_atCertificate.signer_info.signerInfo.digest
berge's avatar
berge committed
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_field_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_field_generation_location(p_threeDLocation)),
                        valueof(m_header_field_its_aid(c_its_aid_DENM))
                // Build the secured message and return it
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField, v_mandatoryHeaders, p_headerFields);
garciay's avatar
garciay committed
            } // End of function f_buildGnSecuredDenm
            /**
             * @desc This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases
             * @param p_securedMessage       The signed  SecureMessage part
             * @param  p_protocolVersion     The protocol version to be set. Default: 2
             * @param  p_trailerStatus       The Traile behaviour:
             *                               <li>0 for no trailer</li>
             *                               <li>1 for invalid trailer</li>
             *                               <li>2 for duplicated trailer</li>
             * @param p_payloadField        Payloads to be included in the message
             * @param p_signerInfoType       Add digest or AT certificate or certificate chain
             * @param p_threeDLocation       The 3D location
             * @param p_headerFields         HeaderFields to be inserted in the message
             * @param p_certificateName      The certificate identifier to be used. Default: TA_CERT_A
             * @param p_addMissingHeaders    Whether to add mandatory headers not present in p_headerFields
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredDenm_Bo(
                                             out template (value) SecuredMessage p_securedMessage,
garciay's avatar
garciay committed
                                             in UInt8 p_protocolVersion := c_protocol_version,
                                             in integer p_trailerStatus := 0,
                                             in template (value) SecPayload p_payloadField,
                                             in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
                                             in ThreeDLocation p_threeDLocation,
                                             in template (omit) HeaderFields p_headerFields := omit,
                                             in template (omit) charstring p_certificateName := omit,
                                             in boolean p_addMissingHeaders := true
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var Certificate v_aaCertificate, v_atCertificate;
                var HeaderFields v_mandatoryHeaders := {};
                var HeaderField v_signerInfo;
                 
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                
                // Add additional headers if required
                if (p_addMissingHeaders == true) {
                    // Prepare mandatory headers
                    if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificate(
                                    v_atCertificate
                        )));
                    }
                    if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
                        ));
                    }
                    if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_digest(
                                    v_atCertificate.signer_info.signerInfo.digest
                        )));
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_field_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_field_generation_location(p_threeDLocation)),
                        valueof(m_header_field_its_aid(c_its_aid_DENM))
                    }
                }
                
                // Build the secured message and return it
                return f_buildGnSecuredMessage_Bo(p_securedMessage, p_certificateName, p_protocolVersion, p_trailerStatus, p_payloadField, v_mandatoryHeaders, p_headerFields);
                
            } // End of function f_buildGnSecuredDenm_Bo
            
            * @desc This function build and sign the SecureMessage part covered by the signature process
berge's avatar
berge committed
            * @param p_securedMessage       The signed  SecureMessage part
            * @param p_payloadField         Payloads to be included in the message
berge's avatar
berge committed
            * @param p_signerInfoType       Add digest or AT certificate or certificate chain
            * @param p_threeDLocation       The 3D location
            * @param p_headerFields         HeaderFields to be inserted in the message
            * @param p_certificateName      The certificate identifier to be used. Default: TA_CERT_A
            * @param p_addMissingHeaders    Whether to add mandatory headers not present in p_headerFields
            * @return true on success, false otherwise
            */
            function f_buildGnSecuredOtherMessage(
garciay's avatar
garciay committed
                                                  out template (value) SecuredMessage p_securedMessage,
                                                  in template (value) SecPayload p_payloadField,
                                                  in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
garciay's avatar
garciay committed
                                                  in ThreeDLocation p_threeDLocation,
                                                  in template (omit) HeaderFields p_headerFields := omit,
                                                  in template (omit) charstring p_certificateName := omit,
                                                  in boolean p_addMissingHeaders := true
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
berge's avatar
berge committed
                var Certificate v_aaCertificate, v_atCertificate;
                var HeaderFields v_mandatoryHeaders := {};
                var HeaderField v_signerInfo;
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                // Add additional headers if required
garciay's avatar
garciay committed
                if (p_addMissingHeaders == true) {
berge's avatar
berge committed
                    // Prepare mandatory headers
                    if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificate(
                                    v_atCertificate
                        )));
berge's avatar
berge committed
                    }
                    if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
berge's avatar
berge committed
                        ));
                    }
                    if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_digest(
                                    v_atCertificate.signer_info.signerInfo.digest
berge's avatar
berge committed
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_field_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_field_generation_location(p_threeDLocation))
                // Build the secured message and return it
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField, v_mandatoryHeaders, p_headerFields);
            } // End of function f_buildGnSecuredOtherMessage
garciay's avatar
garciay committed
            /**
             * @desc This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases
             * @param p_securedMessage       The signed  SecureMessage part
             * @param  p_protocolVersion     The protocol version to be set. Default: 2
             * @param  p_trailerStatus       The Traile behaviour:
             *                               <li>0 for no trailer</li>
             *                               <li>1 for invalid trailer</li>
             *                               <li>2 for duplicated trailer</li>
             * @param p_payloadField        Payloads to be included in the message
             * @param p_signerInfoType       Add digest or AT certificate or certificate chain
             * @param p_threeDLocation       The 3D location
             * @param p_headerFields         HeaderFields to be inserted in the message
             * @param p_certificateName      The certificate identifier to be used. Default: TA_CERT_A
             * @param p_addMissingHeaders    Whether to add mandatory headers not present in p_headerFields
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredOtherMessage_Bo(
                                                     out template (value) SecuredMessage p_securedMessage,
garciay's avatar
garciay committed
                                                     in UInt8 p_protocolVersion := c_protocol_version,
garciay's avatar
garciay committed
                                                     in integer p_trailerStatus := 0,
                                                     in template (value) SecPayload p_payloadField,
                                                     in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
                                                     in ThreeDLocation p_threeDLocation,
                                                     in template (omit) HeaderFields p_headerFields := omit,
                                                     in template (omit) charstring p_certificateName := omit,
                                                     in boolean p_addMissingHeaders := true
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var Certificate v_aaCertificate, v_atCertificate;
                var HeaderFields v_mandatoryHeaders := {};
                var HeaderField v_signerInfo;
                
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                
                // Add additional headers if required
                if (p_addMissingHeaders == true) {
                    // Prepare mandatory headers
                    if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificate(
                                    v_atCertificate
                        )));
                    }
                    if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
                        ));
                    }
                    if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_field_signer_info(
                                m_signerInfo_digest(
                                    v_atCertificate.signer_info.signerInfo.digest
                        )));
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_field_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_field_generation_location(p_threeDLocation))
                    }
                }
                
                // FIXME To be done 
                
                // Build the secured message and return it
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField, v_mandatoryHeaders, p_headerFields);
            } // End of function f_buildGnSecuredOtherMessage_Bo
            
        } // End of group hostSignatureHelpers
        
        group deviceSignatureHelpers {
            
            /**
             * @desc Retrieve the HashedId8 to be sent to the IUT, based on the provided certificate identifier
             * @param p_certificateName The certificate the IUT shall use
             * @return The HashedId8 to be sent to the IUT in the UtInitialize command
             * @verdict Unchanged
             * @remark Component variable vc_hashedId8ToBeUsed shall be set with the IUT certificate to be used
             */
garciay's avatar
garciay committed
            function f_setupIutCertificate(
                                           in charstring p_certificateName
            ) runs on ItsSecurityBaseComponent return HashedId8 {
                // Local variables
                var Certificate v_atCertificate;
                var HashedId8   v_hashedId8 := '0000000000000000'O;
                
                // Sanity check
                if (lengthof(p_certificateName) == 0) {
                    return v_hashedId8;
                }
                
                // Load certificates
                if(f_getCertificateDigest(p_certificateName, v_hashedId8) == false) {
                    v_hashedId8 := '0000000000000000'O;
garciay's avatar
garciay committed
                }
                
                return v_hashedId8;
            } // End of function f_setupIutCertificate
             
garciay's avatar
garciay committed
            /**
            * @desc Verify the signature of the provided certificate
            * @param p_certificateToBeVerified Certificate to be verified
            * @param p_publicKey               Public key to verify the certificate signature
            * @return true on success, false otherwise
            * @verdict
            */
garciay's avatar
garciay committed
            function f_verifyCertificateSignatureWithPublicKey(
garciay's avatar
garciay committed
                                                               in template (value) Certificate p_certificateToBeVerified,
                                                               in template (value) PublicKey   p_publicKey
            ) return boolean {
                // Local variables
                var octetstring toBeVerifiedData;
                var octetstring v_signature;
                var boolean v_result := false;
                var template (value) ToBeSignedCertificate v_toBeSignedCertificate;
                
                // Create Certificate payload to be verified
                v_toBeSignedCertificate := m_toBeSignedCertificate(p_certificateToBeVerified);
                toBeVerifiedData := bit2oct(encvalue(v_toBeSignedCertificate));
garciay's avatar
garciay committed
                               
                // Build the signature
                v_signature :=
                    '0000'O &
                    valueof(p_certificateToBeVerified.signature_.signature_.ecdsa_signature.r.x) &