LibItsSecurity_Functions.ttcn 227 KB
Newer Older
garciay's avatar
garciay committed
//                log("v_signature=", v_signature);
                
//                log("p_trailerStatus=", p_trailerStatus);
                /* FIXME To be reviewed if (p_trailerStatus == 0) { // No signature
                    p_securedMessage := m_securedMessage(
                        valueof(v_toBeSignedData.header_fields),
                        p_payloadField,
                        { }
                    );
                    v_trailerSize := 0;
                } else if (p_trailerStatus == 2) { // Duplicate signature
                    p_securedMessage := m_securedMessage(
                        valueof(v_toBeSignedData.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)
                                    )
                                )
                            ) 
                        }
                    );
                } else if (p_trailerStatus == 3) { // Signature with reserved algorthm
                    p_securedMessage := m_ieee1609Dot2Data_wrong_protocol(
                        p_protocolVersion,
                        valueof(v_toBeSignedData.header_fields),
                        p_payloadField,
                        {
                            m_trailer_field_signature(
                                m_unknownSignature(
                                    v_signature
                                )
                            )
                        }
                    );
                } else { // Invalid signature
                    p_securedMessage := m_securedMessage(
                        valueof(v_toBeSignedData.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)
                                    )
                                )
                            )
                        }
                    );
                    p_securedMessage.trailer_fields[0].trailerField.signature_.ecdsaNistP256Signature.sSig := not4b(valueof(p_securedMessage.trailer_fields[0].trailerField.signature_.ecdsaNistP256Signature.sSig));
                }*/ 
                
                return false;/* FIXME To be reviewed true;*/
            } // End of function f_buildGnSecuredMessage_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_signerIdentifierType               Add digest or AT certificate or certificate chain
            * @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_headerInfo
            * @return true on success, false otherwise
            * 
            * @see Draft ETSI TS 103 097 V1.1.14 Clause 7.1  Security profile for CAMs
            */
            function f_buildGnSecuredCam(
                                         out EtsiTs103097Data p_securedMessage,
                                         in ToBeSignedData p_payloadField,
                                         in SignerIdentifier p_signerIdentifierType,
YannGarcia's avatar
YannGarcia committed
                                         in charstring p_certificateName := ""
                                         ) runs on ItsSecurityBaseComponent return boolean {
garciay's avatar
garciay committed
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;

                log(">>> f_buildGnSecuredCam: p_securedMessage= ", p_securedMessage);
                log(">>> f_buildGnSecuredCam: p_payloadField= ", p_payloadField);
                
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                //log("f_buildGnSecuredCam: v_atCertificate = ", v_atCertificate);
                
                // Fill the structure with default values, these values will be updated later
                p_securedMessage := valueof(m_etsiTs103097Data_signed(
                                                                      m_signedData(
                                                                                   sha256,
                                                                                   p_payloadField,
                                                                                   m_signerIdentifier_self,
                                                                                   m_signature_ecdsaNistP256(
                                                                                                             m_ecdsaP256Signature(
                                                                                                                                  m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                  int2oct(0, 32)
                                                                                                                                  )
                                                                                                             )
                                                                                   )
                                                                      ));
                // Prepare mandatory headers
YannGarcia's avatar
YannGarcia committed
                log("f_buildGnSecuredCam: p_signerIdentifierType=", p_signerIdentifierType);
                if (ischosen(p_signerIdentifierType.digest)) { // Add the AT certificate digest
garciay's avatar
garciay committed
                    if (ischosen(v_atCertificate.issuer.sha256AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha256;
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
                                                                                                f_calculateDigestSha256FromCertificate(v_atCertificate)
                                                                                                ));
                    } else if (ischosen(v_atCertificate.issuer.sha384AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha384;
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
                                                                                                f_calculateDigestSha384FromCertificate(v_atCertificate)
                                                                                                        ));
                    }
                }
                if (ispresent(v_atCertificate.signature_)) {
                    if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP256r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1(
                                                                                                            m_ecdsaP256Signature(
                                                                                                                                 m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                 int2oct(0, 32)
                                                                                                                                 )
                                                                                                                   ));
                    } else if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP384r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1(
                                                                                                            m_ecdsaP384Signature(
                                                                                                                                 m_eccP384CurvePoint_x_only(int2oct(0, 48)),
                                                                                                                                 int2oct(0, 48)
                                                                                                                                 )
                                                                                                           ));
YannGarcia's avatar
YannGarcia committed
                    } // else, m_signature_ecdsaNistP256 already chosen by default
garciay's avatar
garciay committed
                }
YannGarcia's avatar
YannGarcia committed
                log("f_buildGnSecuredCam: p_securedMessage = ", p_securedMessage);
garciay's avatar
garciay committed
                
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/);
                
            } // End of function f_buildGnSecuredCam
            
            /**
            * @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_signerIdentifierType         Add digest or AT certificate or certificate chain
garciay's avatar
garciay committed
            * @param p_certificateName              The certificate identifier to be used. Default: TA_CERT_A
            * @param p_protocolVersion              The protocol version to be set. Default: 2
            * @param p_alterIssuerIdentifier        Set to true to alter IssuerIdentifier
garciay's avatar
garciay committed
            * @param p_alterATCertificateSignature  Set to true to alter the AT certificate signature
            * @param p_alterAACertificateSignature  Set to true to alter the AA certificate signature
            * @return true on success, false otherwise
            * 
            * @see Draft ETSI TS 103 097 V1.1.14 Clause 7.1  Security profile for CAMs
            */
            function f_buildGnSecuredCam_Bo(
                                            out EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                            in ToBeSignedData p_payloadField,
                                            in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed
                                            in charstring p_certificateName,
                                            in UInt8 p_protocolVersion,
YannGarcia's avatar
YannGarcia committed
                                            in boolean p_alter_psid,
                                            in boolean p_add_generation_location,
                                            in boolean p_add_expiry_time,
                                            in boolean p_add_p2pcd_learning_request,
                                            in boolean p_add_missing_crl_identifier,
                                            in boolean p_add_encryption_key,
                                            in boolean p_alter_signature_algorithm,
                                            in boolean p_alter_signer_identifier,
                                            in boolean p_alterIssuerIdentifier,
                                            in boolean p_alterATCertificateSignature,
                                            in boolean p_alterAACertificateSignature
                                            ) runs on ItsSecurityBaseComponent return boolean {
garciay's avatar
garciay committed
                
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0));
                var HeaderInfo v_signerInfo;
                 
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                
                // Fill the structure with default values, these values will be updated later
                p_securedMessage := valueof(m_etsiTs103097Data_signed(
                                                                      m_signedData(
                                                                                   sha256,
                                                                                   p_payloadField,
                                                                                   m_signerIdentifier_self,
                                                                                   m_signature_ecdsaNistP256(
                                                                                                             m_ecdsaP256Signature(
                                                                                                                                  m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                  int2oct(0, 32)
                                                                                                                                  )
                                                                                                             )
                                                                                   )
                                                                      ));
                // Prepare mandatory headers
                //log("f_buildGnSecuredCam: p_signerIdentifierType=", p_signerIdentifierType);
YannGarcia's avatar
YannGarcia committed
                if (ischosen(p_signerIdentifierType.digest)) { // Add the AT certificate digest
                    if (ischosen(v_atCertificate.issuer.sha256AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha256;
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
                                                                                                        f_calculateDigestSha256FromCertificate(v_atCertificate)
                                                                                                        ));
                    } else if (ischosen(v_atCertificate.issuer.sha384AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha384;
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
                                                                                                        f_calculateDigestSha384FromCertificate(v_atCertificate)
                                                                                                        ));
                    }
                }
                if (ispresent(v_atCertificate.signature_)) {
                    if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP256r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1(
                                                                                                            m_ecdsaP256Signature(
                                                                                                                                 m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                 int2oct(0, 32)
                                                                                                                                 )
                                                                                                                   ));
                    } else if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP384r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1(
                                                                                                            m_ecdsaP384Signature(
                                                                                                                                 m_eccP384CurvePoint_x_only(int2oct(0, 48)),
                                                                                                                                 int2oct(0, 48)
                                                                                                                                 )
                                                                                                           ));
                                        } // else, m_signature_ecdsaNistP256 already chosen by default
                }
                log("f_buildGnSecuredCam_Bo: p_securedMessage = ", p_securedMessage);

                // Alter protocolVersion
                p_securedMessage.protocolVersion := p_protocolVersion;
YannGarcia's avatar
YannGarcia committed
                // Alter psid
                if (p_alter_psid == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.psid := 99;
                }
                // Add generationLocation
                if (p_add_generation_location == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.generationLocation := valueof(m_threeDLocation(PX_WGSLATITUDE, PX_WGSLONGITUDE, 0));
                }
                if (p_add_expiry_time == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.expiryTime := f_getCurrentTimeUtc() + 3600;
                }
                if (p_add_p2pcd_learning_request == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.p2pcdLearningRequest := 'CAFEDE'O;
YannGarcia's avatar
YannGarcia committed
                }
                if (p_add_missing_crl_identifier == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.missingCrlIdentifier := {
                    cracaId   := 'CAFEDE'O,
                    crlSeries := 0
                  };
YannGarcia's avatar
YannGarcia committed
                }
                if (p_add_encryption_key == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.encryptionKey := valueof(
                                                                                                  m_encryptionKey_public(
                                                                                                                         m_encryptionKey(
                                                                                                                                         -,
                                                                                                                                         m_publicEncryptionKey_eciesNistP256(
                                                                                                                                                                             m_eccP256CurvePoint_x_only(int2oct(5096, 32))
                                                                                                                                                                             ))));
                }
                if (p_alter_signature_algorithm == true) {
                  if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature)) {
                    // Change it in to Brainpool P256r1
                    p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature := valueof(m_ecdsaSignature(
                                                                                                                             p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig,
                                                                                                                             p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig
                                                                                                                             ));
                  } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) {
                    // Change it in to NistP256
                    p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature := valueof(m_ecdsaSignature(
                                                                                                                      p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.rSig,
                                                                                                                      p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig
                                                                                                                      ));
                  } else {
                    var EccP256CurvePoint r_sig;
                    // Change it in to Brainpool P256r1
                    if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.compressed_y_0)) {
                      r_sig := valueof(m_eccP256CurvePoint_compressed_y_0(str2oct(substr(oct2str(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.compressed_y_0), 0, 32 * 2))));
                    } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.compressed_y_1)) {
                      r_sig := valueof(m_eccP256CurvePoint_compressed_y_1(str2oct(substr(oct2str(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.compressed_y_1), 0, 32 * 2))));
                    } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only)) {
                      r_sig :=  valueof(m_eccP256CurvePoint_x_only(str2oct(substr(oct2str(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only), 0, 32 * 2))));
                    } else {
                      // TODO
                      log("f_buildGnSecuredCam_Bo: Unsupported signature variant");
                    }
                    p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature := valueof(m_ecdsaSignature(
                                                                                                                             r_sig,
                                                                                                                             str2oct(substr(oct2str(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.sSig), 0, 32 * 2))
                                                                                                                             ));
                  }
                }
                if (p_alter_signer_identifier == true) {
                  p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_self);
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField);
                /*if (p_alterATCertificateSignature == true) {
garciay's avatar
garciay committed
                    v_atCertificate.signature_.ecdsaNistP256Signature.sSig := not4b(v_atCertificate.signature_.ecdsaNistP256Signature.sSig);
                }
                if (p_alterAACertificateSignature == true) {
                    v_aaCertificate.signature_.ecdsaNistP256Signature.sSig := not4b(v_aaCertificate.signature_.ecdsaNistP256Signature.sSig);
garciay's avatar
garciay committed
                /* FIXME To be reviewed if (p_addMissingHeaders == true) {
                    // Prepare mandatory headers
                    if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificate(
                                    v_atCertificate
                        )));
                    } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
                        ));
                    } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_issuerIdentifier_sha256AndDigest(
                                    f_calculateDigestFromCertificate(v_atCertificate)
                        )));
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_info_its_aid(c_its_aid_CAM))
                    }
garciay's avatar
garciay committed
                
                return f_buildGnSecuredMessage_Bo(p_securedMessage, p_certificateName, p_protocolVersion, p_trailerStatus, p_payloadField, v_mandatoryHeaders, p_headerInfo);*/
garciay's avatar
garciay committed
                
            } // 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_signerIdentifierType       Add digest or AT certificate or certificate chain
             * @param p_threeDLocation       The 3D location
             * @param p_headerInfo         HeaderInfo 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_headerInfo
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredDenm(
                                          out EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                          in ToBeSignedData p_payloadField,
                                          in SignerIdentifier p_signerIdentifierType,
                                          in charstring p_certificateName := ""
                                          ) runs on ItsSecurityBaseComponent return boolean {
garciay's avatar
garciay committed
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                 
                log(">>> f_buildGnSecuredDenm: p_securedMessage= ", p_securedMessage);
                log(">>> f_buildGnSecuredDenm: p_payloadField= ", p_payloadField);
                
garciay's avatar
garciay committed
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                //log("f_buildGnSecuredDenm: v_atCertificate = ", v_atCertificate);
garciay's avatar
garciay committed
                
                p_securedMessage := valueof(m_etsiTs103097Data_signed(
                                                                      m_signedData(
                                                                                   sha256,
                                                                                   p_payloadField,
                                                                                   m_signerIdentifier_self,
                                                                                   m_signature_ecdsaNistP256(
                                                                                                             m_ecdsaP256Signature(
                                                                                                                                  m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                  int2oct(0, 32)
                                                                                                                                  )
                                                                                                             )
                                                                                   )
                                                                      ));
                // Prepare mandatory headers
                log("f_buildGnSecuredDenm: p_signerIdentifierType=", p_signerIdentifierType);
                if (ischosen(p_signerIdentifierType.digest)) { // Add the AT certificate digest
                    if (ischosen(v_atCertificate.issuer.sha256AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha256;
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
                                                                                                f_calculateDigestSha256FromCertificate(v_atCertificate)
                                                                                                ));
                    } else if (ischosen(v_atCertificate.issuer.sha384AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha384;
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
                                                                                                f_calculateDigestSha384FromCertificate(v_atCertificate)
                                                                                                        ));
garciay's avatar
garciay committed
                    }
                }
                if (ispresent(v_atCertificate.signature_)) {
                    if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP256r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1(
                                                                                                            m_ecdsaP256Signature(
                                                                                                                                 m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                 int2oct(0, 32)
                                                                                                                                 )
                                                                                                                   ));
                    } else if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP384r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1(
                                                                                                            m_ecdsaP384Signature(
                                                                                                                                 m_eccP384CurvePoint_x_only(int2oct(0, 48)),
                                                                                                                                 int2oct(0, 48)
                                                                                                                                 )
                                                                                                           ));
                    } // else, m_signature_ecdsaNistP256 already chosen by default
                }
                log("f_buildGnSecuredDenm: p_securedMessage = ", p_securedMessage);
garciay's avatar
garciay committed
                
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/);
            } // 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_signerIdentifierType       Add digest or AT certificate or certificate chain
             * @param p_threeDLocation       The 3D location
             * @param p_headerInfo         HeaderInfo 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_headerInfo
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredDenm_Bo(
                                             out EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                             in ToBeSignedData p_payloadField,
                                             in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed
                                             in charstring p_certificateName,
                                             in UInt8 p_protocolVersion,
                                             in boolean p_alter_psid,
                                             in boolean p_remove_generation_location := true, // Shall be present for DENM
                                             in boolean p_add_expiry_time,
                                             in boolean p_add_p2pcd_learning_request,
                                             in boolean p_add_missing_crl_identifier,
                                             in boolean p_add_encryption_key,
                                             in boolean p_alter_signature_algorithm,
                                             in boolean p_alter_signer_identifier,
                                             in boolean p_alterIssuerIdentifier,
                                             in boolean p_alterATCertificateSignature,
                                             in boolean p_alterAACertificateSignature
                                             ) runs on ItsSecurityBaseComponent return boolean {
garciay's avatar
garciay committed
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0));
                var HeaderInfo v_signerInfo;
                 
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                
                // Fill the structure with default values, these values will be updated later
                p_securedMessage := valueof(m_etsiTs103097Data_signed(
                                                                      m_signedData(
                                                                                   sha256,
                                                                                   p_payloadField,
                                                                                   m_signerIdentifier_self,
                                                                                   m_signature_ecdsaNistP256(
                                                                                                             m_ecdsaP256Signature(
                                                                                                                                  m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                  int2oct(0, 32)
                                                                                                                                  )
                                                                                                             )
                                                                                   )
                                                                      ));
                // Prepare mandatory headers
                //log("f_buildGnSecuredCam: p_signerIdentifierType=", p_signerIdentifierType);
                if (ischosen(p_signerIdentifierType.digest)) { // Add the AT certificate digest
                    if (ischosen(v_atCertificate.issuer.sha256AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha256;
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
                                                                                                        f_calculateDigestSha256FromCertificate(v_atCertificate)
                                                                                                        ));
                    } else if (ischosen(v_atCertificate.issuer.sha384AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha384;
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
                                                                                                        f_calculateDigestSha384FromCertificate(v_atCertificate)
                                                                                                        ));
garciay's avatar
garciay committed
                    }
                }
                if (ispresent(v_atCertificate.signature_)) {
                    if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP256r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1(
                                                                                                            m_ecdsaP256Signature(
                                                                                                                                 m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                 int2oct(0, 32)
                                                                                                                                 )
                                                                                                                   ));
                    } else if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP384r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1(
                                                                                                            m_ecdsaP384Signature(
                                                                                                                                 m_eccP384CurvePoint_x_only(int2oct(0, 48)),
                                                                                                                                 int2oct(0, 48)
                                                                                                                                 )
                                                                                                           ));
                                        } // else, m_signature_ecdsaNistP256 already chosen by default
                }
                log("f_buildGnSecuredDenm_Bo: p_securedMessage = ", p_securedMessage);

                // Alter protocolVersion
                p_securedMessage.protocolVersion := p_protocolVersion;
                // Alter psid
                if (p_alter_psid == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.psid := 99;
                }
                // Remove generationLocation
                if (p_remove_generation_location == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.generationLocation := omit;
                }
                if (p_add_expiry_time == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.expiryTime := f_getCurrentTimeUtc() + 3600;
                }
                if (p_add_p2pcd_learning_request == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.p2pcdLearningRequest := 'CAFEDE'O;
                }
                if (p_add_missing_crl_identifier == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.missingCrlIdentifier := {
                    cracaId   := 'CAFEDE'O,
                    crlSeries := 0
                  };
                }
                if (p_add_encryption_key == true) {
                  p_securedMessage.content.signedData.tbsData.headerInfo.encryptionKey := valueof(
                                                                                                  m_encryptionKey_public(
                                                                                                                         m_encryptionKey(
                                                                                                                                         -,
                                                                                                                                         m_publicEncryptionKey_eciesNistP256(
                                                                                                                                                                             m_eccP256CurvePoint_x_only(int2oct(5096, 32))
                                                                                                                                                                             ))));
                }
                if (p_alter_signature_algorithm == true) {
                  if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature)) {
                    // Change it in to Brainpool P256r1
                    p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature := valueof(m_ecdsaSignature(
                                                                                                                             p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig,
                                                                                                                             p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig
                                                                                                                             ));
                  } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) {
                    // Change it in to NistP256
                    p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature := valueof(m_ecdsaSignature(
                                                                                                                      p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.rSig,
                                                                                                                      p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig
                                                                                                                      ));
                  } else {
                    var EccP256CurvePoint r_sig;
                    // Change it in to Brainpool P256r1
                    if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.compressed_y_0)) {
                      r_sig := valueof(m_eccP256CurvePoint_compressed_y_0(str2oct(substr(oct2str(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.compressed_y_0), 0, 32 * 2))));
                    } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.compressed_y_1)) {
                      r_sig := valueof(m_eccP256CurvePoint_compressed_y_1(str2oct(substr(oct2str(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.compressed_y_1), 0, 32 * 2))));
                    } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only)) {
                      r_sig :=  valueof(m_eccP256CurvePoint_x_only(str2oct(substr(oct2str(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only), 0, 32 * 2))));
                    } else {
                      // TODO
                      log("f_buildGnSecuredCam_Bo: Unsupported signature variant");
garciay's avatar
garciay committed
                    }
                    p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature := valueof(m_ecdsaSignature(
                                                                                                                             r_sig,
                                                                                                                             str2oct(substr(oct2str(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.sSig), 0, 32 * 2))
                                                                                                                             ));
                  }
                }
                if (p_alter_signer_identifier == true) {
                  p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_self);
                }
garciay's avatar
garciay committed
                
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField);
garciay's avatar
garciay committed
            } // End of function f_buildGnSecuredDenm_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_signerIdentifierType       Add digest or AT certificate or certificate chain
            * @param p_threeDLocation       The 3D location
            * @param p_headerInfo         HeaderInfo 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_headerInfo
            * @return true on success, false otherwise
            */
            function f_buildGnSecuredOtherMessage(
                                                  inout EtsiTs103097Data p_securedMessage,
                                                  in ToBeSignedData p_payloadField,
                                                  in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed
                                                  in ThreeDLocation p_threeDLocation,
                                                  in template (omit) HeaderInfo p_headerInfo := omit,
                                                  in charstring p_certificateName := "",
                                                  in boolean p_addMissingHeaders := true
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0));
                var HeaderInfo v_signerInfo;
                 
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                
                // Add additional headers if required
                /* FIXME To be reviewed if (p_addMissingHeaders == true) {
                    // Prepare mandatory headers
                    if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificate(
                                    v_atCertificate
                        )));
                    } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
                        ));
                    } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_issuerIdentifier_sha256AndDigest(
                                    v_atCertificate.cracaId
                        )));
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_info_generation_location(p_threeDLocation))
                    }
                }*/
                
                // Build the secured message and return it
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/);
            } // End of function f_buildGnSecuredOtherMessage
            
            /**
             * @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_signerIdentifierType       Add digest or AT certificate or certificate chain
             * @param p_threeDLocation       The 3D location
             * @param p_headerInfo         HeaderInfo 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_headerInfo
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredOtherMessage_Bo(
                                                     inout EtsiTs103097Data p_securedMessage,
                                                     in UInt8 p_protocolVersion := c_protocol_version,
                                                     in integer p_trailerStatus := 0,
                                                     in ToBeSignedData p_payloadField,
                                                     in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed
                                                     in ThreeDLocation p_threeDLocation,
                                                     in template (omit) HeaderInfo p_headerInfo := omit,
                                                     in charstring p_certificateName := "",
                                                     in boolean p_addMissingHeaders := true
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0));
                var HeaderInfo v_signerInfo;
                
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
                }
                
                // Add additional headers if required
                /* FIXME To be reviewed if (p_addMissingHeaders == true) {
                    // Prepare mandatory headers
                    if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificate(
                                    v_atCertificate
                        )));
                    } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificates(
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
                        ));
                    } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_issuerIdentifier_sha256AndDigest(
                                    v_atCertificate.cracaId
                        )));
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_info_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*/);
            } // 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
             */
            function f_setupIutCertificate(
                                           in charstring p_certificateName
            ) runs on ItsSecurityBaseComponent return HashedId8 {
                // Local variables
                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;
                }
                
                return v_hashedId8;
            } // End of function f_setupIutCertificate
             
            /**
            * @desc Verify the signature of the provided certificate
            * @param p_certificateToBeVerified EtsiTs103097Certificate to be verified
            * @param p_publicKey               Public key to verify the certificate signature
            * @return true on success, false otherwise
            * @verdict
            */
            function f_verifyCertificateSignatureWithPublicKey(
                                                               in template (value) EtsiTs103097Certificate p_certificateToBeVerified,
                                                               in template (value) PublicVerificationKey p_publicVerificationKey
            ) return boolean {
                var ToBeSignedCertificate v_toBeSignedCertificate;
                var octetstring v_enc_msg;
                var octetstring v_signature;
                var octetstring v_issuer;
                
                log(">>> f_verifyCertificateSignatureWithPublicKey: p_certificateToBeVerified=", p_certificateToBeVerified);
                log(">>> f_verifyCertificateSignatureWithPublicKey: p_publicVerificationKey=", p_publicVerificationKey);
                
                // Create ToBeSignedCertificate payload to be signed
                v_toBeSignedCertificate := valueof(p_certificateToBeVerified.toBeSigned);
                log("f_verifyCertificateSignatureWithPublicKey: v_toBeSignedCertificate=", v_toBeSignedCertificate);
                
                v_enc_msg := bit2oct(encvalue(v_toBeSignedCertificate));
                log("f_verifyCertificateSignatureWithPublicKey: v_enc_msg=", v_enc_msg);
                
                // Verify payload
                if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP256r1)) {
                    if (ischosen(p_certificateToBeVerified.issuer.self_)) {
                      v_issuer := int2oct(0, 32);
                    } else {
                      var charstring v_certificate;
                      
                      if (fx_readCertificateFromDigest(valueof(p_certificateToBeVerified.issuer.sha256AndDigest), v_certificate) == false) {
                        log("f_verifyCertificateSignatureWithPublicKey: Invalid issuer: ", p_certificateToBeVerified.issuer.sha256AndDigest);
                        return false;
                      }
                      if (f_getCertificateHash(v_certificate, v_issuer) == false) {
                        log("f_verifyCertificateSignatureWithPublicKey: Invalid certificate: " & v_certificate);
                        return false;
                      }
                    }
                    v_signature := valueof(p_certificateToBeVerified.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only) & valueof(p_certificateToBeVerified.signature_.ecdsaBrainpoolP256r1Signature.sSig);
                    log("f_verifyCertificateSignatureWithPublicKey: v_signedData=", v_signature);
                    if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP256r1.uncompressedP256)) {
                      return f_verifyWithEcdsaBrainpoolp256r1WithSha256_1(
garciay's avatar
garciay committed
                                                                        v_enc_msg, 
                                                                        v_issuer,
                                                                        v_signature,
                                                                        valueof(p_publicVerificationKey.ecdsaBrainpoolP256r1.uncompressedP256.x),
                                                                        valueof(p_publicVerificationKey.ecdsaBrainpoolP256r1.uncompressedP256.y)
                                                                        );
                    } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP256r1.compressed_y_0)) {
                      return f_verifyWithEcdsaBrainpoolp256r1WithSha256(
garciay's avatar
garciay committed
                                                                      v_enc_msg,  
                                                                      v_issuer,
                                                                      v_signature,
                                                                      valueof(p_publicVerificationKey.ecdsaBrainpoolP256r1.compressed_y_0),
                                                                      0 // Latest bit of the Y-coordinate is 0
                                                                      );
                    } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP256r1.compressed_y_1)) {
                      return f_verifyWithEcdsaBrainpoolp256r1WithSha256(
garciay's avatar
garciay committed
                                                                      v_enc_msg, 
                                                                      v_issuer,
                                                                      v_signature,
                                                                      valueof(p_publicVerificationKey.ecdsaBrainpoolP256r1.compressed_y_1),
                                                                      1 // Latest bit of the Y-coordinate is 1
                                                                      );
                    } else {
                      log("f_verifyCertificateSignatureWithPublicKey: Unknown PublicVerificationKey value");
                      return false;
                    }
                } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP384r1)) {
                    if (ischosen(p_certificateToBeVerified.issuer.self_)) {
                      v_issuer := int2oct(0, 48);
                    } else {
                      var charstring v_certificate;
                      
                      if (fx_readCertificateFromDigest(valueof(p_certificateToBeVerified.issuer.sha384AndDigest), v_certificate) == false) {
                        log("f_verifyCertificateSignatureWithPublicKey: Invalid issuer: ", p_certificateToBeVerified.issuer.sha384AndDigest);
                        return false;
                      }
                      if (f_getCertificateHash(v_certificate, v_issuer) == false) {
                        log("f_verifyCertificateSignatureWithPublicKey: Invalid certificate: " & v_certificate);
                        return false;
                      }
                    }
                    v_signature := valueof(p_certificateToBeVerified.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only) & valueof(p_certificateToBeVerified.signature_.ecdsaBrainpoolP384r1Signature.sSig);
                    log("f_verifyCertificateSignatureWithPublicKey: v_signedData=", v_signature);
                    if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP384r1.uncompressedP384)) {
                      return f_verifyWithEcdsaBrainpoolp384r1WithSha384_1(
garciay's avatar
garciay committed
                                                                        v_enc_msg, 
                                                                        v_issuer,
                                                                        v_signature,
                                                                        valueof(p_publicVerificationKey.ecdsaBrainpoolP384r1.uncompressedP384.x),
                                                                        valueof(p_publicVerificationKey.ecdsaBrainpoolP384r1.uncompressedP384.y)
                                                                        );
                    } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP384r1.compressed_y_0)) {
                      return f_verifyWithEcdsaBrainpoolp384r1WithSha384(
garciay's avatar
garciay committed
                                                                      v_enc_msg, 
                                                                      v_issuer,
                                                                      v_signature,
                                                                      valueof(p_publicVerificationKey.ecdsaBrainpoolP384r1.compressed_y_0),
                                                                      0 // Latest bit of the Y-coordinate is 0
                                                                      );
                    } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP384r1.compressed_y_1)) {
                      return f_verifyWithEcdsaBrainpoolp384r1WithSha384(
garciay's avatar
garciay committed
                                                                      v_enc_msg, 
                                                                      v_issuer,
                                                                      v_signature,
                                                                      valueof(p_publicVerificationKey.ecdsaBrainpoolP384r1.compressed_y_1),
                                                                      1 // Latest bit of the Y-coordinate is 1
                                                                      );
                    } else {
                      log("f_verifyCertificateSignatureWithPublicKey: Unknown PublicVerificationKey value");
                      return false;
                    }
                } else if (ischosen(p_publicVerificationKey.ecdsaNistP256)) {
                    if (ischosen(p_certificateToBeVerified.issuer.self_)) {
                      v_issuer := int2oct(0, 32);
                    } else {
                      var charstring v_certificate;
                      
                      if (fx_readCertificateFromDigest(valueof(p_certificateToBeVerified.issuer.sha256AndDigest), v_certificate) == false) {
                        log("f_verifyCertificateSignatureWithPublicKey: Invalid issuer: ", p_certificateToBeVerified.issuer.sha256AndDigest);
                        return false;
                      }
                      if (f_getCertificateHash(v_certificate, v_issuer) == false) {
                        log("f_verifyCertificateSignatureWithPublicKey: Invalid certificate: " & v_certificate);
                        return false;
                      }
                    }
                    v_signature := valueof(p_certificateToBeVerified.signature_.ecdsaNistP256Signature.rSig.x_only) & valueof(p_certificateToBeVerified.signature_.ecdsaNistP256Signature.sSig);
                    log("f_verifyCertificateSignatureWithPublicKey: v_signedData=", v_signature);
                    if (ischosen(p_publicVerificationKey.ecdsaNistP256.uncompressedP256)) {
                      return f_verifyWithEcdsaNistp256WithSha256_1(
                                                                   v_enc_msg, 
                                                                   v_issuer,
                                                                   v_signature,
                                                                   valueof(p_publicVerificationKey.ecdsaNistP256.uncompressedP256.x),
                                                                   valueof(p_publicVerificationKey.ecdsaNistP256.uncompressedP256.y)
                                                                   );
                    } else if (ischosen(p_publicVerificationKey.ecdsaNistP256.compressed_y_0)) {
                      return f_verifyWithEcdsaNistp256WithSha256(
                                                                 v_enc_msg, 
                                                                 v_issuer,
                                                                 v_signature,
                                                                 valueof(p_publicVerificationKey.ecdsaNistP256.compressed_y_0),
                                                                 0 // Latest bit of the Y-coordinate is 0
                                                                 );
                    } else if (ischosen(p_publicVerificationKey.ecdsaNistP256.compressed_y_1)) {
                      return f_verifyWithEcdsaNistp256WithSha256(
                                                                 v_enc_msg, 
                                                                 v_issuer,
                                                                 v_signature,
                                                                 valueof(p_publicVerificationKey.ecdsaNistP256.compressed_y_1),
                                                                 1 // Latest bit of the Y-coordinate is 1
                                                                 );
                    } else {
                      log("f_verifyCertificateSignatureWithPublicKey: Unknown PublicVerificationKey value");
                      return false;
                    }
                }
                
                return false;
            } // End of finction f_verifyCertificateSignatureWithPublicKey
            
            /**
            * @desc Verify the signature of the provided secured message
            * @param p_certificateToBeVerified EtsiTs103097Certificate to be verified
            * @param p_issuingCertificate      Issuing certificate
            * @return true on success, false otherwise
            * @verdict
            */
            function f_verifyCertificateSignatureWithIssuingCertificate(
                                                                        in template (value) EtsiTs103097Certificate p_certificateToBeVerified,
                                                                        in template (value) EtsiTs103097Certificate p_issuingCertificate
            ) return boolean {
                
                // Sanity checks
                if (not(ischosen(p_issuingCertificate.toBeSigned.verifyKeyIndicator.verificationKey))) {
                    return false;
                }
                return f_verifyCertificateSignatureWithPublicKey(
                                                                 p_certificateToBeVerified,
                                                                 p_issuingCertificate.toBeSigned.verifyKeyIndicator.verificationKey
                                                                 );
            } // End of function f_verifyCertificateSignatureWithIssuingCertificate
            
            /**
             * @desc Verify the signature of the provided secured message for ECDSA Nist-P256 algorithm
             * @param p_securedMessage  The message to be verified
             * @param p_publicKey       The ECDSA public key to verify a signature
             * @param p_certificate     EtsiTs103097Certificate to be used to verify the message
             * @return true on success, false otherwise
             * @verdict Unchanged
             */
            function f_verifyGnSecuredMessageSignature_ecdsaNistP256(
                                                                     in template (value) Ieee1609Dot2Data p_securedMessage,
                                                                     in template (value) Oct32 p_certificateIssuer,
                                                                     in template (value) EccP256CurvePoint p_publicKey
            ) return boolean {
                
                // Local variables
                var octetstring v_secPayload;
                var octetstring v_signedData;
                var boolean v_result := false;
                var template (value) ToBeSignedData v_toBeSignedData;
                
                log(">>> f_verifyGnSecuredMessageSignature_ecdsaNistP256: p_securedMessage= ", p_securedMessage);
                log(">>> f_verifyGnSecuredMessageSignature_ecdsaNistP256: p_certificateIssuer= ", p_certificateIssuer);
                log(">>> f_verifyGnSecuredMessageSignature_ecdsaNistP256: p_publicKey= ", p_publicKey);
                
                // Create Ieee1609Dot2Data payload to be signed
                v_toBeSignedData := valueof(p_securedMessage.content.signedData.tbsData);
                log("f_verifyGnSecuredMessageSignature_ecdsaNistP256: v_toBeSignedData=", p_securedMessage.content.signedData.tbsData);
                
                v_secPayload := bit2oct(encvalue(v_toBeSignedData));
                log("f_verifyGnSecuredMessageSignature_ecdsaNistP256: v_secPayload=", v_secPayload);
                
                // Verify payload

                // TODO Check in standard if x-only only
                if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only)) {
                  v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only) & valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig);
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.compressed_y_0)) {
                  v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.compressed_y_0) & valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig);
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.compressed_y_1)) {
                  v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.compressed_y_1) & valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig);