LibItsSecurity_Functions.ttcn 194 KB
Newer Older
garciay's avatar
garciay committed
/**
 *  @author   ETSI / STF481 / STF507 / STF517 / STF538 / STF545
garciay's avatar
garciay committed
 *  @version  $URL$
 *            $Id$
 *  @desc     Module containing functions for Security Protocol
garciay's avatar
garciay committed
 *  @copyright   ETSI Copyright Notification
 *               No part may be reproduced except as authorized by written permission.
 *               The copyright and the foregoing restriction extend to reproduction in all media.
 *               All rights reserved.
garciay's avatar
garciay committed
 *
 */
module LibItsSecurity_Functions {
    import from LibCommon_BasicTypesAndValues all;
    // LibIts
    import from IEEE1609dot2BaseTypes language "ASN.1:1997" all;
    import from IEEE1609dot2 language "ASN.1:1997" all;
    import from EtsiTs103097Module language "ASN.1:1997" all;
    
filatov's avatar
filatov committed
    //import from LibItsCommon_Functions all;
    //import from LibItsCommon_TypesAndValues all;
    
    // LibItsSecurity
    import from LibItsSecurity_TypesAndValues all;
    import from LibItsSecurity_Templates all;
    import from LibItsSecurity_Pixits all;
garciay's avatar
garciay committed
    import from LibItsSecurity_Pics all;
    import from LibItsSecurity_TestSystem all;
garciay's avatar
garciay committed
    
    group helpersFunctions {
garciay's avatar
garciay committed
         * @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
garciay's avatar
garciay committed
         * @desc    Produces a 384-bit (48-byte) hash value
         * @param   p_toBeHashedData Data to be used to calculate the hash value
         * @return  The hash value
         */
        function f_hashWithSha384(
                                  in octetstring p_toBeHashedData
        ) return Oct48 {
            return fx_hashWithSha384(p_toBeHashedData);
        } // End of function f_hashWithSha256
        
        /**
Yann Garcia's avatar
Yann Garcia committed
         * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
         * @param   p_toBeSignedSecuredMessage    The data to be signed
         * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_privateKey                  The private key for signature
garciay's avatar
garciay committed
         * @return  The signature value
         */
        function f_signWithEcdsaNistp256WithSha256(
                                                   in octetstring p_toBeSignedSecuredMessage,
                                                   in Oct32 p_certificateIssuer,
        ) return octetstring {
            return fx_signWithEcdsaNistp256WithSha256(
                p_toBeSignedSecuredMessage,
        } // End of function f_signWithEcdsaNistp256WithSha256
garciay's avatar
garciay committed
        /**
Yann Garcia's avatar
Yann Garcia committed
         * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
         * @param   p_toBeSignedSecuredMessage    The data to be signed
         * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_privateKey                  The private key for signature
garciay's avatar
garciay committed
         * @return  The signature value
         */
        function f_signWithEcdsaBrainpoolp256WithSha256(
                                                        in octetstring p_toBeSignedSecuredMessage,
                                                        in Oct32 p_certificateIssuer,
garciay's avatar
garciay committed
                                                        in Oct32 p_privateKey
        ) return octetstring {
garciay's avatar
garciay committed
            return fx_signWithEcdsaBrainpoolp256WithSha256(
                p_toBeSignedSecuredMessage,
garciay's avatar
garciay committed
                p_privateKey
            );
            
        } // End of function f_signWithEcdsaBrainpoolp256WithSha256
        
garciay's avatar
garciay committed
        /**
Yann Garcia's avatar
Yann Garcia committed
         * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
         * @param   p_toBeSignedSecuredMessage    The data to be signed
         * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_privateKey                  The private key for signature
garciay's avatar
garciay committed
         * @return  The signature value
         */
        function f_signWithEcdsaBrainpoolp384WithSha384(
                                                        in octetstring p_toBeSignedSecuredMessage,
                                                        in Oct48 p_certificateIssuer,
garciay's avatar
garciay committed
                                                        in Oct48 p_privateKey
        ) return octetstring {
garciay's avatar
garciay committed
            return fx_signWithEcdsaBrainpoolp384WithSha384(
                p_toBeSignedSecuredMessage,
garciay's avatar
garciay committed
                p_privateKey
            );
            
        } // End of function f_signWithEcdsaBrainpoolp384WithSha384
        
        function f_decrypt(
                           in octetstring         p_encryptPrivateKey,
                           in EtsiTs103097Data    p_encrypedSecuredMessage,
Yann Garcia's avatar
Yann Garcia committed
                           out EtsiTs103097Data   p_decrypedSecuredMessage,
                           out octetstring        p_aes_sym_enc_key
        ) return boolean {
            if (ischosen(p_encrypedSecuredMessage.content.encryptedData)) {
                var PKRecipientInfo v_pKRecipientInfo;
                var RecipientInfo v_recipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0];
            var octetstring v_decryptedSecuredMessage;
                // Check the private encryption key
                if (not(isbound(p_encryptPrivateKey))) {
                  log("*** " & testcasename() & ":ERROR: Failed to load encryption private key ***");
                  return false;
                }
                
                if (ischosen(v_recipientInfo.certRecipInfo)) {
                  v_pKRecipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0].certRecipInfo;
                  // Read the certificate based on the recipientId
                } else if (ischosen(v_recipientInfo.signedDataRecipInfo)) {
                v_pKRecipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0].signedDataRecipInfo;
                  // Read the certificate based on the recipientId
                  log("*** " & testcasename() & ":ERROR: Unsupported RecipientInfo variant ***");
                  return false;
            if (isbound(v_pKRecipientInfo)) {
                if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256)) {
                  var SymmetricCiphertext v_ciphertext := p_encrypedSecuredMessage.content.encryptedData.ciphertext;
                  if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_0)) {
                      v_decryptedSecuredMessage := f_decryptWithEciesNistp256WithSha256(
                                                                                        v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                        p_encryptPrivateKey,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_0,
                                                                                        0,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.c,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.t,
                                                                                        v_ciphertext.aes128ccm.nonce,
Yann Garcia's avatar
Yann Garcia committed
                                                                                        p_salt,
                                                                                        p_aes_sym_enc_key
                                                                                        );
                  } else if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_1)) {
                      v_decryptedSecuredMessage := f_decryptWithEciesNistp256WithSha256(
                                                                                        v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                        p_encryptPrivateKey,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_1,
                                                                                        1,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.c,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.t,
                                                                                        v_ciphertext.aes128ccm.nonce,
Yann Garcia's avatar
Yann Garcia committed
                                                                                        p_salt,
                                                                                        p_aes_sym_enc_key
                                                                                        );
                  } else {
                    log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***");
                    return false;
                  }
                  if (isbound(v_decryptedSecuredMessage)) {
                    var bitstring v_decode := oct2bit(v_decryptedSecuredMessage);
                    if (decvalue(v_decode, p_decrypedSecuredMessage) == 0) {
                      return true;
                    } else {
                      log("*** " & testcasename() & ":ERROR: Faild to decode secured message ***");
                } else if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1)) {
                  var SymmetricCiphertext v_ciphertext := p_encrypedSecuredMessage.content.encryptedData.ciphertext;
                  if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_0)) {
                    v_decryptedSecuredMessage := f_decryptWithEciesBrainpoolp256WithSha256(
                                                                                           v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                           p_encryptPrivateKey,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_0,
                                                                                           0,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.c,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.t,
Yann Garcia's avatar
Yann Garcia committed
                                                                                           v_ciphertext.aes128ccm.nonce,
                                                                                           p_salt,                                                                                                                                                     p_aes_sym_enc_key
                                                                                      );
                  } else if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_1)) {
                    v_decryptedSecuredMessage := f_decryptWithEciesBrainpoolp256WithSha256(
                                                                                           v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                           p_encryptPrivateKey,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_1,
                                                                                           1,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.c,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.t,
Yann Garcia's avatar
Yann Garcia committed
                                                                                           v_ciphertext.aes128ccm.nonce,
                                                                                           p_salt,
                                                                                           p_aes_sym_enc_key
                                                                                      );
                  } else {
                    log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***");
                    return false;
                  }
              } else {
                log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***");
                return false;
              }
              // TODO else, other variants shall be processed here if
            } else {
              log("*** " & testcasename() & ":ERROR: Invalid recipient info ***");
              return false;
            }
                  if (isbound(v_decryptedSecuredMessage)) {
                    var bitstring v_decode := oct2bit(v_decryptedSecuredMessage);
                    if (decvalue(v_decode, p_decrypedSecuredMessage) == 0) {
                      return true;
                    } else {
                      log("*** " & testcasename() & ":ERROR: Faild to decode secured message ***");
            } else {
              log("*** " & testcasename() & ":ERROR: Message not encrypted ***");
        } // End of function f_decrypt
         * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Nist-P256 algorithm
         * @param   p_toBeEncryptedSecuredMessage    The data to be encrypted
         * @param   p_recipientsPublicKeyCompressed  The Recipient's compressed public key
         * @param   p_compressed_mode                 The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
         * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
         * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
         * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
         * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
         * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
         * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
         * @return  The encrypted message
         */
        function f_encryptWithEciesNistp256WithSha256(
                                                      in octetstring p_toBeEncryptedSecuredMessage,
                                                      in Oct32 p_recipientsPublicKeyCompressed,
                                                      in integer p_compressed_mode,
                                                      out Oct32 p_publicEphemeralKeyCompressed,
                                                      out integer p_ephemeralKeyModeCompressed,
                                                      out Oct16 p_aes_sym_key,
                                                      out Oct16 p_encrypted_sym_key,
                                                      out Oct16 p_authentication_vector,
                                                      out Oct12 p_nonce,
                                                      in boolean p_use_hardcoded_values := false
        ) return octetstring {
          return fx_encryptWithEciesNistp256WithSha256(
                                                       p_toBeEncryptedSecuredMessage,
                                                       p_recipientsPublicKeyCompressed,
                                                       p_compressed_mode,
                                                       p_publicEphemeralKeyCompressed,
                                                       p_ephemeralKeyModeCompressed,
                                                       p_aes_sym_key,
                                                       p_encrypted_sym_key,
                                                       p_authentication_vector,
                                                       p_nonce,
                                                       p_use_hardcoded_values
        } // End of function f_encryptWithEciesNistp256WithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Nist-P256 algorithm
         * @param   p_encryptedSecuredMessage    The data to be decrypted
         * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
         * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
         * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
         * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
         * @return  The decrypted message
         * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
         * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
         * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
         */
        function f_decryptWithEciesNistp256WithSha256(
                                                      in octetstring p_encryptedSecuredMessage,
                                                      in Oct32 p_privateEncKey,
                                                      in Oct32 p_publicEphemeralKeyCompressed,
                                                      in integer p_ephemeralKeyModeCompressed,
                                                      in Oct16 p_encrypted_sym_key,
                                                      in Oct16 p_authentication_vector,
Yann Garcia's avatar
Yann Garcia committed
                                                      in Oct32 p_salt,
                                                      out Oct16 p_aes_sym_enc_key
        ) return octetstring {
          return fx_decryptWithEciesNistp256WithSha256(
                                                       p_encryptedSecuredMessage,
                                                       p_privateEncKey,
                                                       p_publicEphemeralKeyCompressed, 
                                                       p_ephemeralKeyModeCompressed,
                                                       p_encrypted_sym_key,
                                                       p_authentication_vector,
Yann Garcia's avatar
Yann Garcia committed
                                                       p_salt,
                                                       p_aes_sym_enc_key
        } // End of function f_decryptWithEcdsaNistp256WithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Brainpool-P256 algorithm
         * @param   p_toBeEncryptedSecuredMessage    The data to be encrypted
         * @param   p_recipientsPublicKeyCompressed  The Recipient's compressed public key
         * @param   p_compressed_mode                 The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
         * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
         * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
         * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
         * @return  The encrypted message
         * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
         * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
         * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
         */
        function f_encryptWithEciesBrainpoolp256WithSha256(
                                                           in octetstring p_toBeEncryptedSecuredMessage,
                                                           in Oct32 p_recipientsPublicKeyCompressed,
                                                           in integer p_compressed_mode,
                                                           in octetstring p_salt,
                                                           out Oct32 p_publicEphemeralKeyCompressed,
                                                           out integer p_ephemeralKeyModeCompressed,
                                                           out Oct16 p_aes_sym_key,
                                                           out Oct16 p_encrypted_sym_key,
                                                           out Oct16 p_authentication_vector,
                                                           out Oct12 p_nonce,
                                                           in boolean p_use_hardcoded_values := false
        ) return octetstring {
          return fx_encryptWithEciesBrainpoolp256WithSha256(
                                                            p_toBeEncryptedSecuredMessage,
                                                            p_recipientsPublicKeyCompressed,
                                                            p_compressed_mode,
                                                            p_publicEphemeralKeyCompressed,
                                                            p_ephemeralKeyModeCompressed,
                                                            p_aes_sym_key,
                                                            p_encrypted_sym_key,
                                                            p_authentication_vector,
                                                            p_nonce,
                                                            p_use_hardcoded_values
        } // End of function f_encryptWithEciesBrainpoolp256WithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Brainpool-P256 algorithm
         * @param   p_encryptedSecuredMessage    The data to be decrypted
         * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
         * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
         * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
         * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
         * @return  The decrypted message
         * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
         * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
         * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
         */
        function f_decryptWithEciesBrainpoolp256WithSha256(
                                                           in octetstring p_encryptedSecuredMessage,
                                                           in Oct32 p_privateEncKey,
                                                           in Oct32 p_publicEphemeralKeyCompressed, 
                                                           in integer p_ephemeralKeyModeCompressed,
                                                           in Oct16 p_encrypted_sym_key,
                                                           in Oct16 p_authentication_vector,
Yann Garcia's avatar
Yann Garcia committed
                                                           in Oct12 p_nonce,
                                                           in Oct32 p_salt,
                                                           out Oct16 p_aes_sym_enc_key
        ) return octetstring {
          return fx_decryptWithEciesBrainpoolp256WithSha256(
                                                            p_encryptedSecuredMessage,
                                                            p_privateEncKey,
                                                            p_publicEphemeralKeyCompressed, 
                                                            p_ephemeralKeyModeCompressed,
                                                            p_encrypted_sym_key,
                                                            p_authentication_vector,
Yann Garcia's avatar
Yann Garcia committed
                                                            p_nonce,
                                                            p_salt,
                                                            p_aes_sym_enc_key
        } // End of function f_decryptWithEcdsaBrainpoolp256WithSha256
        
garciay's avatar
garciay committed
         * @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 HashedId8 value from the hash value
         * @param p_hash The hash value
         * @return The HashedId8 value
         * @verdict
         */
        function f_HashedId8FromSha384( 
                                       in Oct48 p_hash
        ) return HashedId8 {
            return substr(p_hash, lengthof(p_hash) - 8, 8);
        } // End of function f_HashedId8FromSha384
        
garciay's avatar
garciay committed
         * @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
garciay's avatar
garciay committed
         * @desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
garciay's avatar
garciay committed
         * @param   p_signature                 The signature
         * @param   p_ecdsaNistp256PublicKeyCompressed   The compressed public key
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
garciay's avatar
garciay committed
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaNistp256WithSha256(
garciay's avatar
garciay committed
                                                     in octetstring p_toBeVerifiedData,
                                                     in Oct32 p_certificateIssuer,
                                                     in Oct64 p_signature,
                                                     in Oct32 p_ecdsaNistp256PublicKeyCompressed,
                                                     in integer p_compressed_mode
        ) return boolean {
//            log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaNistp256WithSha256: signature", p_signature);
//            log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyCompressed", p_ecdsaNistp256PublicKeyCompressed);
            return fx_verifyWithEcdsaNistp256WithSha256(
                                                        p_toBeVerifiedData,
                                                        p_signature,
                                                        p_ecdsaNistp256PublicKeyCompressed,
                                                        p_compressed_mode
                                                        );
        } // End of function f_verifyWithEcdsaNistp256WithSha256
        
        /**
         * @desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @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_1( // TODO To be removed
                                                       in octetstring p_toBeVerifiedData,
                                                       in Oct32 p_certificateIssuer,
                                                       in Oct64 p_signature,
                                                       in Oct32 p_ecdsaNistp256PublicKeyX,
                                                       in Oct32 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_1(
                p_toBeVerifiedData,
                p_signature,
                p_ecdsaNistp256PublicKeyX,
                p_ecdsaNistp256PublicKeyY);
        } // End of function f_verifyWithEcdsaNistp256WithSha256_1
garciay's avatar
garciay committed
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
garciay's avatar
garciay committed
         * @param   p_signature                 The signature
         * @param   p_ecdsaBrainpoolp256PublicKeyCompressed   The compressed public key
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
garciay's avatar
garciay committed
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaBrainpoolp256WithSha256(
                                                          in octetstring p_toBeVerifiedData,
                                                          in Oct32 p_certificateIssuer,
                                                          in Oct64 p_signature,
                                                          in Oct32 p_ecdsaBrainpoolp256PublicKeyCompressed,
                                                          in integer p_compressed_mode
        ) return boolean {
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: signature", p_signature);
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: ecdsaBrainpoolp256PublicKeyCompressed", p_ecdsaBrainpoolp256PublicKeyCompressed);
            return fx_verifyWithEcdsaBrainpoolp256WithSha256(
                                                             p_toBeVerifiedData,
                                                             p_signature,
                                                             p_ecdsaBrainpoolp256PublicKeyCompressed,
                                                             p_compressed_mode
                                                             );
        } // End of function f_verifyWithEcdsaBrainpoolp256WithSha256
        
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_signature                 The signature
         * @param   p_ecdsaBrainpoolp256PublicKeyX   The public key (x coordinate)
         * @param   p_ecdsaBrainpoolp256PublicKeyY   The public key (y coordinate)
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaBrainpoolp256WithSha256_1( // TODO To be removed
                                                            in octetstring p_toBeVerifiedData,
                                                            in Oct32 p_certificateIssuer,
                                                            in Oct64 p_signature,
                                                            in Oct32 p_ecdsaBrainpoolp256PublicKeyX,
                                                            in Oct32 p_ecdsaBrainpoolp256PublicKeyY
garciay's avatar
garciay committed
        ) return boolean {
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: signature", p_signature);
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: ecdsaBrainpoolp256PublicKeyX", p_ecdsaBrainpoolp256PublicKeyX);
//            log("f_verifyWithEcdsaBrainpoolp256WithSha256: ecdsaBrainpoolp256PublicKeyY", p_ecdsaBrainpoolp256PublicKeyY);
            return fx_verifyWithEcdsaBrainpoolp256WithSha256_1(
garciay's avatar
garciay committed
                p_toBeVerifiedData,
garciay's avatar
garciay committed
                p_signature,
                p_ecdsaBrainpoolp256PublicKeyX,
                p_ecdsaBrainpoolp256PublicKeyY);
        } // End of function f_verifyWithEcdsaBrainpoolp256WithSha256_1
garciay's avatar
garciay committed
        
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
garciay's avatar
garciay committed
         * @param   p_signature                 The signature
         * @param   p_ecdsaBrainpoolp384PublicKeyX   The public key (x coordinate)
         * @param   p_ecdsaBrainpoolp384PublicKeyY   The public key (y coordinate)
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
garciay's avatar
garciay committed
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaBrainpoolp384WithSha384(
                                                          in octetstring p_toBeVerifiedData,
                                                          in Oct48 p_certificateIssuer,
                                                          in Oct96 p_signature,
                                                          in Oct48 p_ecdsaBrainpoolp384PublicKeyCompressed,
                                                          in integer p_compressed_mode
        ) return boolean {
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: signature", p_signature);
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: ecdsaBrainpoolp384PublicKeyCompressed", p_ecdsaBrainpoolp384PublicKeyCompressed);
            return fx_verifyWithEcdsaBrainpoolp384WithSha384(
                                                             p_toBeVerifiedData,
                                                             p_signature,
                                                             p_ecdsaBrainpoolp384PublicKeyCompressed,
                                                             p_compressed_mode
                                                             );
        } // End of function f_verifyWithEcdsaBrainpoolp384WithSha384
        
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_signature                 The signature
         * @param   p_ecdsaBrainpoolp384PublicKeyX   The public key (x coordinate)
         * @param   p_ecdsaBrainpoolp384PublicKeyY   The public key (y coordinate)
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaBrainpoolp384WithSha384_1( // TODO To be removed
                                                            in octetstring p_toBeVerifiedData,
                                                            in Oct48 p_certificateIssuer,
                                                            in Oct96 p_signature,
                                                            in Oct48 p_ecdsaBrainpoolp384PublicKeyX,
                                                            in Oct48 p_ecdsaBrainpoolp384PublicKeyY
garciay's avatar
garciay committed
        ) return boolean {
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: signature", p_signature);
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: ecdsaBrainpoolp384PublicKeyX", p_ecdsaBrainpoolp384PublicKeyX);
//            log("f_verifyWithEcdsaBrainpoolp384WithSha384: ecdsaBrainpoolp384PublicKeyY", p_ecdsaBrainpoolp384PublicKeyY);
            return fx_verifyWithEcdsaBrainpoolp384WithSha384_1(
garciay's avatar
garciay committed
                p_toBeVerifiedData,
garciay's avatar
garciay committed
                p_signature,
                p_ecdsaBrainpoolp384PublicKeyX,
                p_ecdsaBrainpoolp384PublicKeyY);
        } // End of function f_verifyWithEcdsaBrainpoolp384WithSha384_1
        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @param   p_publicKeyCompressed The compressed public keys
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @return  true on success, false otherwise
         */
garciay's avatar
garciay committed
        function f_generate_key_pair_nistp256(
garciay's avatar
garciay committed
                                              out Oct32 p_privateKey,
                                              out Oct32 p_publicKeyX,
                                              out Oct32 p_publicKeyY,
                                              out Oct32 p_publicKeyCompressed,
                                              out integer p_compressed_mode
garciay's avatar
garciay committed
                                             ) return boolean {
          log(">>> f_generate_key_pair_nistp256");
          
          if (PICS_SEC_FIXED_KEYS) { // Debug mode: Use fixed values
           p_privateKey := '43481BC44C073C1432DB6EC4F0EF57062BEA08E4C19F811567325AD1FD1C6577'O;
           p_publicKeyX := '0B5D74B033531C51D17B4F218DD4E39289AE4BF2EE3D7BAB7C07DAF0C14F0317'O;
           p_publicKeyY := '5D49B139A9237832FDE24D77555878CE65D6C2284A1BDA4CE08ABDD4071E0255'O;
           p_publicKeyCompressed := '0B5D74B033531C51D17B4F218DD4E39289AE4BF2EE3D7BAB7C07DAF0C14F0317'O;
           p_compressed_mode := 1;
garciay's avatar
garciay committed

           return true;
         }
          return fx_generateKeyPair_nistp256(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode);
garciay's avatar
garciay committed
        }
        
        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @param   p_publicKeyCompressed The compressed public keys
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
garciay's avatar
garciay committed
         * @return  true on success, false otherwise
         */
        function f_generate_key_pair_brainpoolp256(
garciay's avatar
garciay committed
                                                   out Oct32 p_privateKey,
                                                   out Oct32 p_publicKeyX,
                                                   out Oct32 p_publicKeyY,
                                                   out Oct32 p_publicKeyCompressed,
                                                   out integer p_compressed_mode
garciay's avatar
garciay committed
                                                  ) return boolean {
          log(">>> f_generate_key_pair_brainpoolp256");
          return fx_generateKeyPair_brainpoolp256(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode);
garciay's avatar
garciay committed
        }
        
        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @param   p_publicKeyCompressed The compressed public keys
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
garciay's avatar
garciay committed
         * @return  true on success, false otherwise
         */
        function f_generate_key_pair_brainpoolp384(
garciay's avatar
garciay committed
                                                   out Oct48 p_privateKey,
                                                   out Oct48 p_publicKeyX,
                                                   out Oct48 p_publicKeyY,
                                                   out Oct48 p_publicKeyCompressed,
                                                   out integer p_compressed_mode
garciay's avatar
garciay committed
                                                  ) return boolean {
          return fx_generateKeyPair_brainpoolp384(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode);
garciay's avatar
garciay committed
        /**
        * @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(
                                                  in Certificate p_cert
        ) return HashedId8 {
            var octetstring v_hash;
            
            if (PICS_SEC_SHA256) {
garciay's avatar
garciay committed
                v_hash := f_calculateDigestSha256FromCertificate(p_cert);
            } if (PICS_SEC_SHA384) {
garciay's avatar
garciay committed
                v_hash := f_calculateDigestSha384FromCertificate(p_cert);
            } 
            
            return substr(v_hash, lengthof(v_hash) - 8, 8);
        } // End of function f_calculateDigestFromCertificate
        
        * @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
garciay's avatar
garciay committed
        function f_calculateDigestSha256FromCertificate(
                                                        in EtsiTs103097Certificate 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);
garciay's avatar
garciay committed
        } // End of function f_calculateDigestSha256FromCertificate
        
        function f_calculateDigestSha384FromCertificate(
                                                        in EtsiTs103097Certificate p_cert
        ) return HashedId8 {
            var octetstring v_toBeHashedData;
            var octetstring v_hash;
                        
            v_toBeHashedData := bit2oct(encvalue(p_cert));
            v_hash := f_hashWithSha384(v_toBeHashedData);
            return substr(v_hash, lengthof(v_hash) - 8, 8);
        } // End of function f_calculateDigestSha384FromCertificate
garciay's avatar
garciay committed
        function f_duration2time(
                                 in Duration p_duration
        ) return UInt16 {
            if (ischosen(p_duration.seconds)) {
                return p_duration.seconds;
            } else if (ischosen(p_duration.minutes)) { 
                return p_duration.minutes;
            } else if (ischosen(p_duration.hours)) { 
                return p_duration.hours;
            } else if (ischosen(p_duration.sixtyHours)) {
                return p_duration.sixtyHours;
            } else if (ischosen(p_duration.years)) {
                return p_duration.years;
garciay's avatar
garciay committed
            }
            
            return 0; // Unrechable code
garciay's avatar
garciay committed
        } // 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 EtsiTs103097Certificate p_aaCertificate,
                                           out EtsiTs103097Certificate p_atCertificate
            ) runs on ItsSecurityBaseComponent return boolean {
garciay's avatar
garciay committed
                //log(">>> f_prepareCertificates: ", p_certificateName);
                
                // Load certificates if required
garciay's avatar
garciay committed
                if ((lengthof(p_certificateName) > 0) and (valueof(p_certificateName) != cc_taCert_A)) {
                    var HashedId8 v_digest;
                    var charstring v_cert;
                    
                    if (f_readCertificate(valueof(p_certificateName), p_atCertificate) == false){
garciay's avatar
garciay committed
                        log("f_prepareCertificates: Failed to read certificate ", p_certificateName);
                        return false;
                    }
                    if (ischosen(p_atCertificate.issuer.sha256AndDigest)) {
                        v_digest := p_atCertificate.issuer.sha256AndDigest;
                    } else if (ischosen(p_atCertificate.issuer.sha384AndDigest)) {
                        v_digest := p_atCertificate.issuer.sha384AndDigest;
                    } else {
                        log("f_prepareCertificates: Invalid certificate issuer ", p_atCertificate.issuer);
                        return false;
                    }
garciay's avatar
garciay committed
                    if (f_getCertificateFromDigest(v_digest, p_aaCertificate) == false) {
                        log("f_prepareCertificates: Failed to read certificate issuer ", v_digest);
                        return false;
                    }
                } else {
                    p_atCertificate := vc_atCertificate;
                    p_aaCertificate := vc_aaCertificate;
Yann Garcia's avatar
Yann Garcia committed
                // Store the certificate 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_headerInfo        HeaderInfo to be inserted in the message
berge's avatar
berge committed
             * @param p_securityProfile     Selected security profile
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredMessage(
garciay's avatar
garciay committed
                                             inout EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                             in charstring p_certificateName,
                                             in ToBeSignedData p_payloadField
            ) runs on ItsSecurityBaseComponent return boolean {
                // Local variables
                var octetstring v_secPayload, v_signature;
garciay's avatar
garciay committed
                var ToBeSignedData v_toBeSignedData;
                var octetstring v_certificateIssuer;
                var octetstring v_privateKey;
Yann Garcia's avatar
Yann Garcia committed
                log(">>> f_buildGnSecuredMessage: p_securedMessage=", p_securedMessage);
                log(">>> f_buildGnSecuredMessage: p_payloadField=", p_payloadField);
                // Prepare payload to be signed
garciay's avatar
garciay committed
                v_toBeSignedData := valueof(p_payloadField);
                v_secPayload := bit2oct(encvalue(v_toBeSignedData));
                
                // 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 {
filatov's avatar
filatov committed
                    if(not f_readSigningKey(cc_taCert_A, v_privateKey)){
                f_getCertificateHash(p_certificateName, v_certificateIssuer);
garciay's avatar
garciay committed
                if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature)) {
Yann Garcia's avatar
Yann Garcia committed
                  v_signature := f_signWithEcdsaNistp256WithSha256(
                                                                   v_secPayload,
                                                                   v_certificateIssuer,
                                                                   v_privateKey 
                                                                   );
                  p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaNistP256(
                                                                                                      m_ecdsaP256Signature(
                                                                                                                           m_eccP256CurvePoint_x_only(substr(v_signature, 0, 32)),
                                                                                                                           substr(v_signature, 32, 32)
                                                                                                                           )
                                                                                                      ));
garciay's avatar
garciay committed
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) {
                    v_signature := f_signWithEcdsaBrainpoolp256WithSha256(
Yann Garcia's avatar
Yann Garcia committed
                                                                          v_secPayload,
                                                                          v_certificateIssuer, 
                                                                          v_privateKey 
                                                                          );
garciay's avatar
garciay committed
                    p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1(
Yann Garcia's avatar
Yann Garcia committed
                                                                                                               m_ecdsaP256Signature(
                                                                                                                                    m_eccP256CurvePoint_x_only(substr(v_signature, 0, 32)),
                                                                                                                                    substr(v_signature, 32, 32)
                                                                                                                                    )
                                                                                                               ));
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature)) {
Yann Garcia's avatar
Yann Garcia committed
                  v_signature := f_signWithEcdsaBrainpoolp384WithSha384(
                                                                        v_secPayload,
                                                                        v_certificateIssuer, 
                                                                        v_privateKey 
                                                                        );
                  p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1(
                                                                                                             m_ecdsaP384Signature(
                                                                                                                                  m_eccP384CurvePoint_x_only(substr(v_signature, 0, 32)),
                                                                                                                                  substr(v_signature, 32, 32)
                                                                                                                                  )
                                                                                                             ));
garciay's avatar
garciay committed
                } // TODO To be continued
Yann Garcia's avatar
Yann Garcia committed
                log("<<< f_buildGnSecuredMessage: p_securedMessage=", p_securedMessage);
garciay's avatar
garciay committed
                return true;
            } // 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_headerInfo        HeaderInfo to be inserted in the message
             * @param p_securityProfile     Selected security profile
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredMessage_Bo(
garciay's avatar
garciay committed
                                                inout EtsiTs103097Data 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,
garciay's avatar
garciay committed
                                                in template (value) ToBeSignedData p_payloadField,
                                                in template (value) HeaderInfo p_mandatoryHeaders,
                                                in template (omit) HeaderInfo p_headerInfo := omit
            ) return boolean {
                
                // Local variables
                var octetstring v_secPayload, v_signature;
                var template (value) ToBeSignedData v_toBeSignedData;
                var integer i, j, k, n;
                var HeaderInfo v_headerFields := {};
                var Ieee1609Dot2Content v_toBeSignedPayload;
                var Oct32 v_privateKey;
                var UInt8 v_trailerSize;
                
                // Prepare headers
                if (not(ispresent(p_headerInfo))) {
                    v_headerFields := valueof(p_mandatoryHeaders);
                } else {/* FIXME To be reviewed 
                    // Merge p_headerInfo and v_mandatoryHeaders into v_headerFields
                    i := 0; // index for p_headerInfo
                    j := 0; // index for v_mandatoryHeaders
                    k := 0; // index for v_headerFields
                        
                    // Special processing for signer_info
                    if (lengthof(valueof(p_headerInfo)) > 0 and valueof(p_headerInfo[i].type_) == e_signer_info) {
                        v_headerFields[k] := valueof(p_headerInfo[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_headerInfo); n := n + 1) {
                            if (valueof(p_headerInfo[n].type_) == valueof(p_mandatoryHeaders[j].type_)) {
                                // mandatory header already in p_HeaderFields
                                break;
                            }
                        } // End of 'for' statement
                        if (n >= lengthof(p_headerInfo)) {
                            if (valueof(p_mandatoryHeaders[j].type_) != e_signer_info) {
                                // Add headers from p_headerInfo having lower number than mandatory header
                                for (n := i; n < lengthof(p_headerInfo) and valueof(p_headerInfo[n].type_) < valueof(p_mandatoryHeaders[j].type_); n := n + 1) {
                                    v_headerFields[k] := valueof(p_headerInfo[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_headerInfo); i := i + 1) {
                        // Add headers from p_headerInfo having lower number than mandatory header
                        v_headerFields[k] := valueof(p_headerInfo[i]);
                        k := k + 1;
                    } // End of 'for' statement
                
                // Prepare payload to be signed
                /* FIXME To be reviewed 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_toBeSignedData := m_toBeSignedSecuredMessage_wrong_protocol(
                    v_headerFields,
                    v_toBeSignedPayload,
                    e_signature,
                    p_protocolVersion,
                    v_trailerSize
                );*/
//                log("m_toBeSignedSecuredMessage_wrong_protocol=", v_toBeSignedData);
                /* FIXME To be reviewedv_secPayload := bit2oct(encvalue(v_toBeSignedData));
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 {
filatov's avatar
filatov committed
                    if(not f_readSigningKey(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);
                /* FIXME To be reviewed if (p_trailerStatus == 0) { // No signature
garciay's avatar
garciay committed
                    p_securedMessage := m_securedMessage(
                        valueof(v_toBeSignedData.header_fields),
                        p_payloadField,
                        { }
                    );
                    v_trailerSize := 0;
                } else if (p_trailerStatus == 2) { // Duplicate signature
garciay's avatar
garciay committed
                    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)
                                    )
                                )
                            ) 
                        }
                    );
garciay's avatar
garciay committed
                } else if (p_trailerStatus == 3) { // Signature with reserved algorthm
                    p_securedMessage := m_ieee1609Dot2Data_wrong_protocol(
garciay's avatar
garciay committed
                        p_protocolVersion,
                        valueof(v_toBeSignedData.header_fields),
garciay's avatar
garciay committed
                        p_payloadField,
                        {
                            m_trailer_field_signature(
                                m_unknownSignature(
                                    v_signature
                                )
                            )
                        }
                    );
                } else { // Invalid signature
garciay's avatar
garciay committed
                    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
garciay's avatar
garciay committed
            * @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
garciay's avatar
garciay committed
            * @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
berge's avatar
berge committed
            function f_buildGnSecuredCam(
garciay's avatar
garciay committed
                                         inout EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                         in ToBeSignedData p_payloadField,
                                         in SignerIdentifier p_signerIdentifierType,
                                         in charstring p_certificateName := ""/*,
                                         in boolean p_addMissingHeaders := true*/
            ) runs on ItsSecurityBaseComponent return boolean {
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
Yann Garcia's avatar
Yann Garcia committed

                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;
garciay's avatar
garciay committed
                //log("f_buildGnSecuredCam: v_atCertificate = ", v_atCertificate);
garciay's avatar
garciay committed
                
garciay's avatar
garciay committed
                // Fill the structure with default values, these values will be updated later
                p_securedMessage := valueof(m_etsiTs103097Data_signed(
Yann Garcia's avatar
Yann Garcia committed
                                                                      m_signedData(
                                                                                   sha256,
                                                                                   p_payloadField,
                                                                                   m_signerIdentifier_self,
                                                                                   m_signature_ecdsaNistP256(
                                                                                                             m_ecdsaP256Signature(
                                                                                                                                  m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                  int2oct(0, 32)
                                                                                                                                  )
                                                                                                             )
                                                                                   )
garciay's avatar
garciay committed
                                                                      ));
garciay's avatar
garciay committed
                // Prepare mandatory headers
garciay's avatar
garciay committed
                //log("f_buildGnSecuredCam: p_signerIdentifierType=", p_signerIdentifierType);
garciay's avatar
garciay committed
                if (ischosen(p_signerIdentifierType.certificate)) { // Add the AT certificate
garciay's avatar
garciay committed
                    log("*** " & testcasename() & "f_buildGnSecuredCam: TODO ***");
garciay's avatar
garciay committed
                    stop;
garciay's avatar
garciay committed
                    /* TODO
                     * 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,
garciay's avatar
garciay committed
                                }
                            )
                    ));*/
                } else if (ischosen(p_signerIdentifierType.digest)) { // Add the AT certificate digest
                    if (ischosen(v_atCertificate.issuer.sha256AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha256;
garciay's avatar
garciay committed
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
garciay's avatar
garciay committed
                                                                                                f_calculateDigestSha256FromCertificate(v_atCertificate)
garciay's avatar
garciay committed
                                                                                                ));
garciay's avatar
garciay committed
                    } else if (ischosen(v_atCertificate.issuer.sha384AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha384;
garciay's avatar
garciay committed
                        p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest(
garciay's avatar
garciay committed
                                                                                                f_calculateDigestSha384FromCertificate(v_atCertificate)
garciay's avatar
garciay committed
                                                                                                        ));
berge's avatar
berge committed
                    }
garciay's avatar
garciay committed
                } else {
garciay's avatar
garciay committed
                    log("*** " & testcasename() & "f_buildGnSecuredCam: TODO ***");
garciay's avatar
garciay committed
                    stop;
garciay's avatar
garciay committed
                }
                if (ispresent(v_atCertificate.signature_)) {
                    if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP256r1Signature)) {
garciay's avatar
garciay committed
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1(
garciay's avatar
garciay committed
                                                                                                            m_ecdsaP256Signature(
                                                                                                                                 m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                 int2oct(0, 32)
                                                                                                                                 )
garciay's avatar
garciay committed
                                                                                                                   ));
garciay's avatar
garciay committed
                    } else if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP384r1Signature)) {
garciay's avatar
garciay committed
                        p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1(
garciay's avatar
garciay committed
                                                                                                            m_ecdsaP384Signature(
                                                                                                                                 m_eccP384CurvePoint_x_only(int2oct(0, 48)),
                                                                                                                                 int2oct(0, 48)
                                                                                                                                 )
garciay's avatar
garciay committed
                                                                                                           ));
garciay's avatar
garciay committed
                                        } // else, m_signature_ecdsaNistP256 already chosen by default
                }
garciay's avatar
garciay committed
                //log("f_buildGnSecuredCam: p_securedMessage = ", p_securedMessage);
garciay's avatar
garciay committed
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/);
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_signerIdentifierType               Add digest or AT certificate or certificate chain
garciay's avatar
garciay committed
            * @param p_threeDLocation               The 3D location
            * @param p_headerInfo                 HeaderInfo to be inserted in the message
garciay's avatar
garciay committed
            * @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
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
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(
garciay's avatar
garciay committed
                                            inout EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                            in UInt8 p_protocolVersion := c_protocol_version,
                                            in integer p_trailerStatus := 0,
garciay's avatar
garciay committed
                                            in ToBeSignedData p_payloadField,
                                            in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed
                                            in template (omit) HeaderInfo p_headerInfo := omit,
garciay's avatar
garciay committed
                                            in charstring p_certificateName := "",
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 EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                var HeaderInfo v_mandatoryHeaders := {};
                var HeaderInfo 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_.ecdsaNistP256Signature.sSig := not4b(v_atCertificate.signature_.ecdsaNistP256Signature.sSig);
garciay's avatar
garciay committed
                }
                
                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(
                    } 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(
                    } 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))
                return f_buildGnSecuredMessage_Bo(p_securedMessage, p_certificateName, p_protocolVersion, p_trailerStatus, p_payloadField, v_mandatoryHeaders, p_headerInfo);
                
            } // 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
             */
berge's avatar
berge committed
            function f_buildGnSecuredDenm(
garciay's avatar
garciay committed
                                          inout EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                          in ToBeSignedData p_payloadField,
                                          in SignerIdentifier p_signerIdentifierType,
garciay's avatar
garciay committed
                                          in ThreeDLocation p_threeDLocation,
                                          in template (omit) HeaderInfo p_headerInfo := omit,
garciay's avatar
garciay committed
                                          in charstring p_certificateName := "",
garciay's avatar
garciay committed
                                          in boolean p_addMissingHeaders := true
berge's avatar
berge committed
            ) runs on ItsSecurityBaseComponent return boolean {
berge's avatar
berge committed
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                var HeaderInfo v_mandatoryHeaders := {};
                var HeaderInfo 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
                /* FIXME To be reviewed if (p_addMissingHeaders == true) {
berge's avatar
berge committed
                    // Prepare mandatory headers
                    if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificate(
                    } 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(
berge's avatar
berge committed
                        ));
                    } 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
berge's avatar
berge committed
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_info_generation_location(p_threeDLocation)),
                        valueof(m_header_info_its_aid(c_its_aid_DENM))
berge's avatar
berge committed
                    }
                // Build the secured message and return it
garciay's avatar
garciay committed
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/);
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_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(
garciay's avatar
garciay committed
                                             inout EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                             in UInt8 p_protocolVersion := c_protocol_version,
                                             in integer p_trailerStatus := 0,
garciay's avatar
garciay committed
                                             in ToBeSignedData p_payloadField,
                                             in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed
                                             in ThreeDLocation p_threeDLocation,
                                             in template (omit) HeaderInfo p_headerInfo := omit,
garciay's avatar
garciay committed
                                             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 := {};
                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(
                    } 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(
                    } 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)),
                        valueof(m_header_info_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_headerInfo);
                
            } // 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
            * @param p_signerIdentifierType       Add digest or AT certificate or certificate chain
berge's avatar
berge committed
            * @param p_threeDLocation       The 3D location
            * @param p_headerInfo         HeaderInfo to be inserted in the message
berge's avatar
berge committed
            * @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(
garciay's avatar
garciay committed
                                                  inout EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                                  in ToBeSignedData p_payloadField,
                                                  in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed
garciay's avatar
garciay committed
                                                  in ThreeDLocation p_threeDLocation,
                                                  in template (omit) HeaderInfo p_headerInfo := omit,
garciay's avatar
garciay committed
                                                  in charstring p_certificateName := "",
garciay's avatar
garciay committed
                                                  in boolean p_addMissingHeaders := true
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                var HeaderInfo v_mandatoryHeaders := {};
                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) {
berge's avatar
berge committed
                    // Prepare mandatory headers
                    if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificate(
                    } 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(
berge's avatar
berge committed
                        ));
                    } 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
berge's avatar
berge committed
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_info_generation_location(p_threeDLocation))
berge's avatar
berge committed
                    }
                // Build the secured message and return it
garciay's avatar
garciay committed
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/);
            } // 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_signerIdentifierType       Add digest or AT certificate or certificate chain
garciay's avatar
garciay committed
             * @param p_threeDLocation       The 3D location
             * @param p_headerInfo         HeaderInfo to be inserted in the message
garciay's avatar
garciay committed
             * @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
garciay's avatar
garciay committed
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredOtherMessage_Bo(
garciay's avatar
garciay committed
                                                     inout EtsiTs103097Data p_securedMessage,
garciay's avatar
garciay committed
                                                     in UInt8 p_protocolVersion := c_protocol_version,
garciay's avatar
garciay committed
                                                     in integer p_trailerStatus := 0,
garciay's avatar
garciay committed
                                                     in ToBeSignedData p_payloadField,
                                                     in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed
garciay's avatar
garciay committed
                                                     in ThreeDLocation p_threeDLocation,
                                                     in template (omit) HeaderInfo p_headerInfo := omit,
garciay's avatar
garciay committed
                                                     in charstring p_certificateName := "",
garciay's avatar
garciay committed
                                                     in boolean p_addMissingHeaders := true
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var EtsiTs103097Certificate v_aaCertificate, v_atCertificate;
                var HeaderInfo v_mandatoryHeaders := {};
                var HeaderInfo v_signerInfo;
garciay's avatar
garciay committed
                
                // 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) {
garciay's avatar
garciay committed
                    // Prepare mandatory headers
                    if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate
garciay's avatar
garciay committed
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificate(
garciay's avatar
garciay committed
                                    v_atCertificate
                        )));
                    } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate
garciay's avatar
garciay committed
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_signerIdentifier_certificates(
garciay's avatar
garciay committed
                                    {
                                        v_aaCertificate,
                                        v_atCertificate
                                    }
                                )
                        ));
                    } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
garciay's avatar
garciay committed
                        v_signerInfo := valueof(
                            m_header_info_signer_info(
                                m_issuerIdentifier_sha256AndDigest(
                                    v_atCertificate.cracaId
garciay's avatar
garciay committed
                        )));
                    }
                    v_mandatoryHeaders := {
                        v_signerInfo,
                        valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us
                        valueof(m_header_info_generation_location(p_threeDLocation))
garciay's avatar
garciay committed
                    }
garciay's avatar
garciay committed
                
                // FIXME To be done 
                
                // Build the secured message and return it
garciay's avatar
garciay committed
                return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/);
garciay's avatar
garciay committed
            } // 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
filatov's avatar
filatov committed
// FIXME (DF) UNUSED
//                var EtsiTs103097Certificate v_atCertificate;
garciay's avatar
garciay committed
                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 EtsiTs103097Certificate 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(
                                                               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_verifyWithEcdsaBrainpoolp256WithSha256_1(
                                                                        v_enc_msg, 
                                                                        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_verifyWithEcdsaBrainpoolp256WithSha256(
                                                                      v_enc_msg,  
                                                                      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_verifyWithEcdsaBrainpoolp256WithSha256(
                                                                      v_enc_msg, 
                                                                      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_verifyWithEcdsaBrainpoolp384WithSha384_1(
                                                                        v_enc_msg, 
                                                                        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_verifyWithEcdsaBrainpoolp384WithSha384(
                                                                      v_enc_msg, 
                                                                      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_verifyWithEcdsaBrainpoolp384WithSha384(
                                                                      v_enc_msg, 
                                                                      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_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_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_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;
            } // 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
                // 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
                v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only) & valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig);
                log("f_verifyGnSecuredMessageSignature_ecdsaNistP256: v_signedData=", v_signedData);
                if (ischosen(p_publicKey.uncompressedP256)) {
                    v_result := f_verifyWithEcdsaNistp256WithSha256_1(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.uncompressedP256.x),
                        valueof(p_publicKey.uncompressedP256.y)
                    );
                } else if (ischosen(p_publicKey.compressed_y_0)) {
                    v_result := f_verifyWithEcdsaNistp256WithSha256(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.compressed_y_0),
                        0
                    );
                } else if (ischosen(p_publicKey.compressed_y_1)) {
                    v_result := f_verifyWithEcdsaNistp256WithSha256(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.compressed_y_1),
                        1
                    );
                }
                
                log("f_verifyGnSecuredMessageSignature_ecdsaNistP256: v_result=", v_result);
                return v_result;
            } // End of function f_verifyGnSecuredMessageSignature_ecdsaNistP256
            
            /**
             * @desc Verify the signature of the provided secured message for ECDSA Brainpool-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_ecdsaBrainpoolP256r1(
                                                                            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_ecdsaBrainpoolP256r1: p_securedMessage= ", p_securedMessage);
                log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: p_certificateIssuer= ", p_certificateIssuer);
                log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: p_publicKey= ", p_publicKey);
                // Create Ieee1609Dot2Data payload to be signed
                v_toBeSignedData := valueof(p_securedMessage.content.signedData.tbsData);
                log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: v_toBeSignedData=", p_securedMessage.content.signedData.tbsData);
                
                v_secPayload := bit2oct(encvalue(v_toBeSignedData));
                log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: v_secPayload=", v_secPayload);
                
                // Verify payload
                v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only) & valueof(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig);
                log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: v_signedData=", v_signedData);
                if (ischosen(p_publicKey.uncompressedP256)) {
                    v_result := f_verifyWithEcdsaBrainpoolp256WithSha256_1(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.uncompressedP256.x),
                        valueof(p_publicKey.uncompressedP256.y)
                    );
                } else if (ischosen(p_publicKey.compressed_y_0)) {
                    v_result := f_verifyWithEcdsaBrainpoolp256WithSha256(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.compressed_y_0),
                        0
                    );
                } else if (ischosen(p_publicKey.compressed_y_1)) {
                    v_result := f_verifyWithEcdsaBrainpoolp256WithSha256(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.compressed_y_1),
                        1
                    );
                }
                
                log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: v_result=", v_result);
                return v_result;
            } // End of function f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1
            
            /**
             * @desc Verify the signature of the provided secured message for ECDSA Brainpool-P384 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_ecdsaBrainpoolP384r1(
                                                                            in template (value) Ieee1609Dot2Data p_securedMessage,
                                                                            in template (value) Oct48 p_certificateIssuer,
                                                                            in template (value) EccP384CurvePoint 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_ecdsaBrainpoolP384r1: p_securedMessage= ", p_securedMessage);
                log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: p_certificateIssuer= ", p_certificateIssuer);
                log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: p_publicKey= ", p_publicKey);
                
                // Create Ieee1609Dot2Data payload to be signed
                v_toBeSignedData := valueof(p_securedMessage.content.signedData.tbsData);
                log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: v_toBeSignedData=", p_securedMessage.content.signedData.tbsData);
                v_secPayload := bit2oct(encvalue(v_toBeSignedData));
                log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: v_secPayload=", v_secPayload);
                
                // Verify payload
                v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only) & valueof(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.sSig);
                log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: v_signedData=", v_signedData);
                if (ischosen(p_publicKey.uncompressedP384)) {
                    v_result := f_verifyWithEcdsaBrainpoolp384WithSha384_1(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.uncompressedP384.x),
                        valueof(p_publicKey.uncompressedP384.y)
                    );
                } else if (ischosen(p_publicKey.compressed_y_0)) {
                    v_result := f_verifyWithEcdsaBrainpoolp384WithSha384(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.compressed_y_0),
                        0
                    );
                } else if (ischosen(p_publicKey.compressed_y_1)) {
                    v_result := f_verifyWithEcdsaBrainpoolp384WithSha384(
                        v_secPayload, 
                        valueof(p_certificateIssuer),
                        v_signedData,
                        valueof(p_publicKey.compressed_y_1),
                        1
                    );
                }
                log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: v_result=", v_result);
                return v_result;
            } // End of function f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1
            * @desc Verify the signature of the provided secured message
            * @param p_securedMessage
            * @param p_certificate     EtsiTs103097Certificate to be used to verify the message
            * @return true on success, false otherwise
            * @verdict
            */
            function f_verifyGnSecuredMessageSignatureWithCertificate(
                                                                      in template (value) Ieee1609Dot2Data p_securedMessage,
Yann Garcia's avatar
Yann Garcia committed
                                                                      in template (value) charstring p_certificate_id,
                                                                      in template (value) EtsiTs103097Certificate p_certificate
                var octetstring v_issuer;
Yann Garcia's avatar
Yann Garcia committed
                var EtsiTs103097Certificate v_certificate;
                
                log(">>> f_verifyGnSecuredMessageSignatureWithCertificate: p_securedMessage=", p_securedMessage);
                log(">>> f_verifyGnSecuredMessageSignatureWithCertificate: p_certificate_id=", p_certificate_id);
                log(">>> f_verifyGnSecuredMessageSignatureWithCertificate: p_certificate=", p_certificate);
Yann Garcia's avatar
Yann Garcia committed
                if (f_getCertificateHash(valueof(p_certificate_id), v_issuer) == false) {
                  log("f_verifyCertificateSignatureWithPublicKey: Invalid certificate id: " & p_certificate_id);
                  return false;
                }
                if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) {
                  return f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1(p_securedMessage, v_issuer, p_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1);
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature)) {
                  return f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1(p_securedMessage, v_issuer, p_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1);
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature)) {
                  return f_verifyGnSecuredMessageSignature_ecdsaNistP256(p_securedMessage, v_issuer, p_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256);
                return false;
            } // End of function f_verifyGnSecuredOtherMessageWithDeviceCertificate
        } // End of group deviceSignatureHelpers
filatov's avatar
filatov committed
        group messageGetters {
            * @desc    return Ieee1609Dot2Data header field of given type or null if none
            * @param   p_msg the Ieee1609Dot2Data
            * @param   p_type header field type
            * @return  HeaderInfo of given type if any or null
garciay's avatar
garciay committed
            function f_getMsgHeaderInfo(
garciay's avatar
garciay committed
                                        in template(omit) Ieee1609Dot2Data p_securedMessage,
                                        out HeaderInfo p_return
garciay's avatar
garciay committed
                var integer v_length;
                var Ieee1609Dot2Data v_securedMessage;
garciay's avatar
garciay committed
                
garciay's avatar
garciay committed
                if (not isvalue(p_securedMessage)) {
                    testcase.stop(__SCOPE__ & " can not handle omitted secured message values");
                }
                v_securedMessage := valueof(p_securedMessage);
garciay's avatar
garciay committed
                if (ispresent(v_securedMessage.content.signedData)) {
                    p_return := v_securedMessage.content.signedData.tbsData.headerInfo;
                    return true;
                }

                log("f_getMsgHeaderField: return false");
            * @desc    return SignerIdentifier Ieee1609Dot2Data field
            function f_getMsgSignerIdentifier (
garciay's avatar
garciay committed
                                               in template(omit) Ieee1609Dot2Data p_securedMessage,
                                               out SignerIdentifier p_signerIdentifier
garciay's avatar
garciay committed
                if (not isvalue(p_securedMessage)) {
                    testcase.stop(__SCOPE__ & " can not handle omitted secured message values");
                }
                
                if (ischosen(p_securedMessage.content.signedData)) {
garciay's avatar
garciay committed
                    p_signerIdentifier := valueof(p_securedMessage.content.signedData.signer);
                    return true;
                }
                log("f_getMsgSignerIdentifier: return false");
garciay's avatar
garciay committed
            
garciay's avatar
garciay committed
        } // End of group messageGetters
filatov's avatar
filatov committed
        
        group certificateGetters {
             * @desc Set the generation location as defined in Draft ETSI TS 103 097 V1.1.14 Clause 7.2 Security profile for DENMs
             * @param p_latitude    The latitude value of the ITS-S position
             * @param p_longitude   The longitude value of the ITS-S position
             * @param p_elevation   The elevation value of the ITS-S position
             * @verdict Unchanged
             */
            function f_setGenerationLocation(
                                             in SecLatitude p_latitude,
                                             in SecLongitude p_longitude,
                                             in SecElevation p_elevation := 0
            ) runs on ItsSecurityBaseComponent {
                vc_location := {
                    p_latitude,
                    p_longitude,
                    p_elevation
                }
            } // End of function f_setGenerationLocation
            * @desc    Load in memory cache the certificates available
            * @param   p_configId      A configuration identifier
            * @remark  This method SHALL be call before any usage of certificates
            * @return  true on success, false otherwise
            */
            function f_loadCertificates(
garciay's avatar
garciay committed
                                        in charstring p_configId
            ) runs on ItsSecurityBaseComponent return boolean {
                // Setup certificates memory cache
garciay's avatar
garciay committed
                if (fx_loadCertificates(PX_CERTIFICATE_POOL_PATH, p_configId) == true) {
                  // Setup security component variables
                  if (f_readCertificate(cc_taCert_A, vc_atCertificate) == true) {
garciay's avatar
garciay committed
                    var HashedId8 v_issuer;
                    log("Issuer: ", vc_atCertificate.issuer);
                    if (ischosen(vc_atCertificate.issuer.sha256AndDigest)) {
                      v_issuer := vc_atCertificate.issuer.sha256AndDigest;
                    } else if (ischosen(vc_atCertificate.issuer.sha384AndDigest)) {
                      v_issuer := vc_atCertificate.issuer.sha384AndDigest;
                    } else {
                      log("AT certificate cannot be issued by CA");
                      return false;
                    }
                    log("Selected issuer: ", v_issuer);
                    if (f_getCertificateFromDigest(v_issuer, vc_aaCertificate)) {
                      if (f_readSigningKey(cc_taCert_A, vc_signingPrivateKey) == true) {
                        f_readEncryptingKey(cc_taCert_A, vc_encryptPrivateKey);
                        return true;
                      }
                      log("f_loadCertificates: Failed to load signing key for ", cc_taCert_A);
                    } else {
                      log("f_loadCertificates: Failed to load AA certificate for ", cc_taCert_A);
                    }
                  } else {
                    log("f_loadCertificates: Failed to load AT certificate for ", cc_taCert_A);
                  }
garciay's avatar
garciay committed
                } else {
                  log("f_loadCertificates: Failed to load certificates from ", PX_CERTIFICATE_POOL_PATH);
garciay's avatar
garciay committed
                }
                return false;
            } // End of function f_loadCertificates
            
            /**
            * @desc    Unload from memory cache the certificates available
            * @return  true on success, false otherwise
            */
            function f_unloadCertificates() runs on ItsSecurityBaseComponent return boolean {
                // Reset security component variables
                vc_signingPrivateKey := ''O;
                vc_encryptPrivateKey := ''O;
                // Clear certificates memory cache
                return fx_unloadCertificates();
            } // End of function f_unloadCertificates
             * @desc    Read the specified certificate
             * @param   p_certificate_id the certificate identifier
             * @param   p_certificate   the expected certificate
             * @return  true on success, false otherwise
             */
            function f_readCertificate(
                                       in charstring p_certificate_id,
                                       out EtsiTs103097Certificate p_certificate
                var octetstring v_certificate;
                
                if (fx_readCertificate(p_certificate_id, v_certificate) == true) {
garciay's avatar
garciay committed
                    var bitstring v_oct2bit;
                    var integer v_result;
                    
                    v_oct2bit := oct2bit(v_certificate);
                    v_result := decvalue(v_oct2bit, p_certificate);
                    if (v_result == 0) {
                        return true;
                    }
                }
                
                log("f_readCertificate: Failed to retrieve ", p_certificate_id);
                return false;
            } // End of function f_readCertificate
             * @desc    Read the specified certificate
             * @param   p_certificate_id the certificate identifier
             * @param   p_digest        the digest of the certificate
             * @return  true on success, false otherwise
             */
            function f_getCertificateDigest(
                                            in charstring p_certificate_id,
garciay's avatar
garciay committed
                                            out HashedId8 p_digest
                if (not fx_readCertificateDigest(p_certificate_id, p_digest)){
                    log("f_getCertificateDigest: Failed to retrieve digest for ", p_certificate_id);
                    return false;
                }
                return true;
            } // End of function f_getCertificateDigest
            /**
             * @desc    Read the whole-hash of the certificate
             * @param   p_certificate_id the certificate identifier
             * @param   p_hash          the whole-hash of the certificate
             * @return  true on success, false otherwise
             */
            function f_getCertificateHash(
                                            in charstring p_certificate_id,
                                            out octetstring p_hash
            ) return boolean {
                if (not fx_readCertificateHash(p_certificate_id, p_hash)){
                    log("f_getCertificateHash: Failed to retrieve digest for ", p_certificate_id);
                    return false;
                }
                return true;
            } // End of function f_getCertificateHash
            
            function f_getCertificateFromDigest(
                                                in HashedId8 p_digest, 
                                                out EtsiTs103097Certificate p_certificate
                var charstring v_certificate_id;
                if (not(fx_readCertificateFromDigest(p_digest, v_certificate_id))) {
                    log("f_getCertificateFromDigest: Failed to retrieve digest for ", p_digest);
                    return false;
                }
                if (not(f_readCertificate(v_certificate_id, p_certificate))) {
                    log("f_getCertificateFromDigest: Failed to retrieve digest for ", v_certificate_id);
                    return false;
                }
                return true;
            } // End of function f_getCertificateFromDigest
            
Yann Garcia's avatar
Yann Garcia committed
            function f_getCertificateFromHashedId3(
                                                   in HashedId3 p_digest, 
                                                   out EtsiTs103097Certificate p_certificate
            ) return boolean {
                var charstring v_certificate_id;
                if (not(fx_readCertificateFromHashedId3(p_digest, v_certificate_id))) {
                    log("f_getCertificateFromHashedId3: Failed to retrieve digest for ", p_digest);
                    return false;
                }
                if (not(f_readCertificate(v_certificate_id, p_certificate))) {
                    log("f_getCertificateFromHashedId3: Failed to retrieve digest for ", v_certificate_id);
                    return false;
                }
                return true;
            } // End of function f_getCertificateFromHashedId3
            
            * @desc    Read the signing private key for the specified certificate
            * @param   p_keysId            the keys identifier
            * @param   p_signingPrivateKey the signing private key
            * @return  true on success, false otherwise
            */
            function f_readSigningKey(
                                       in charstring p_keysId,
                                       out Oct32 p_signingPrivateKey
                return fx_readSigningKey(p_keysId, p_signingPrivateKey);
            } // End of function f_readSigningKey
            
            /**
            * @desc    Read the encrypting private keys for the specified certificate
            * @param   p_keysId            the keys identifier
            * @param   p_encryptPrivateKey the encrypt private key
            * @return  true on success, false otherwise
            */
            function f_readEncryptingKey(
garciay's avatar
garciay committed
                                         in charstring p_keysId,
                                         out Oct32 p_encryptPrivateKey
                return fx_readEncryptingKey(p_keysId, p_encryptPrivateKey);
            } // End of function f_readEncryptingKey
            function f_getCertificateValidityRestriction(
                                                         in template (value) EtsiTs103097Certificate p_cert,
garciay's avatar
garciay committed
                                                         out template (value) ValidityPeriod p_validityPeriod,
                                                         out template (omit) GeographicRegion p_geographicRegion
garciay's avatar
garciay committed
                p_validityPeriod := valueof(p_cert.toBeSigned.validityPeriod);
                if (ispresent(p_cert.toBeSigned.region)) {
                    p_geographicRegion := valueof(p_cert.toBeSigned.region);
                } else {
                    p_geographicRegion := omit;
                }
garciay's avatar
garciay committed
                return true;
            } // End of function f_getCertificateValidityRestriction
filatov's avatar
filatov committed
            
        }// End of group certificateGetters
garciay's avatar
garciay committed
        group certificatesCaching {
            
            function f_createCertificatesCaching(
                                                 in SequenceOfCertificate p_certificates, 
garciay's avatar
garciay committed
                                                 out CertificatesCaching p_certificatesCaching
            ) return boolean {
                p_certificatesCaching := { };
                for (var integer v_counter := 0; v_counter < lengthof(p_certificates); v_counter := v_counter + 1) {
                    var CertificatesCachingItem v_item;
                    v_item.certificate := p_certificates[v_counter];
garciay's avatar
garciay committed
                    v_item.hashedId8 := f_calculateDigestSha256FromCertificate(v_item.certificate);
garciay's avatar
garciay committed
                    p_certificatesCaching[v_counter] := v_item;
                } // End of 'for' statement
                
                return true;
            }
            
            function f_getCertificateFromCaching(
                                                 in CertificatesCaching p_certificatesCaching, 
                                                 in HashedId8 p_hashedId8, 
                                                 out EtsiTs103097Certificate p_certificate
garciay's avatar
garciay committed
            ) return boolean {
                for (var integer v_counter := 0; v_counter < lengthof(p_certificatesCaching); v_counter := v_counter + 1) { 
                    if (match(p_certificatesCaching[v_counter].hashedId8, p_hashedId8) == true) {
                        p_certificate := p_certificatesCaching[v_counter].certificate;
                        return true;
                    }
                } // End of 'for' statement
                
                return false;
            }
            
            function f_getCertificatesCachingItem(
                                                  in CertificatesCaching p_certificatesCaching, 
                                                  in UInt8 p_index, 
                                                  out EtsiTs103097Certificate p_certificate
garciay's avatar
garciay committed
            ) return boolean {
                if (lengthof(p_certificatesCaching) < p_index) {
                    p_certificate := p_certificatesCaching[p_index].certificate;
                    return true;
                }
                
                return false;
            }
            
            function f_getCertificatesCachingItemSize(
                                                      in CertificatesCaching p_certificatesCaching
            ) return UInt8 {
                return lengthof(p_certificatesCaching);
            }
            
        }// End of group certificatesCaching
        
        
    } // End of group helpersFunctions

    group externalFunctions {
        
        group signing {
            
            /**
garciay's avatar
garciay committed
             * @desc    Produces a 256-bit (32-byte) hash value
             * @param   p_toBeHashedData Data to be used to calculate the hash value
             * @return  The hash value
             */
            external function fx_hashWithSha256(in octetstring p_toBeHashedData) return Oct32;
garciay's avatar
garciay committed
             * @desc    Produces a 384-bit (48-byte) hash value
             * @param   p_toBeHashedData Data to be used to calculate the hash value
             * @return  The hash value
             */
            external function fx_hashWithSha384(in octetstring p_toBeHashedData) return Oct48;
garciay's avatar
garciay committed
            
Yann Garcia's avatar
Yann Garcia committed
            external function fx_hmac_sha256(in octetstring p_k, in octetstring p_m) return octetstring;
Yann Garcia's avatar
Yann Garcia committed
             * @desc    This function validates AES128 CCM encryption based on IEEE Std 1609.2-20XX Annex D.6.1 AES-CCM-128
             * @param[in] The symmetric AES 128 encryption key 
             * @param[in] The initial vector (aka nonce)
             * @param[in] The raw payload
             * @return  The encrypted payload
Yann Garcia's avatar
Yann Garcia committed
            external function fx_encrypt_aes_128_ccm_test(in octetstring p_k, in octetstring p_n, in octetstring p_pt) return octetstring;
Yann Garcia's avatar
Yann Garcia committed
             * @desc    TThis function validates AES128 CCM encryption based on AES-GCM-256
             * @param[in] The symmetric AES 128 encryption key 
             * @param[in] The initial vector (aka nonce)
             * @param[in] The raw payload
             * @return  The encrypted payload
Yann Garcia's avatar
Yann Garcia committed
            external function fx_encrypt_aes_128_gcm_test(in octetstring p_k, in octetstring p_n, in octetstring p_pt) return octetstring;
Yann Garcia's avatar
Yann Garcia committed
             * @desc    This function validates AES128 CCM decryption based on IEEE Std 1609.2-20XX Annex D.6.1 AES-CCM-128
             * @param[in] The symmetric AES 128 encryption key 
             * @param[in] The initial vector (aka nonce)
             * @param[in] The cyphered payload
             * @return  The raw payload
Yann Garcia's avatar
Yann Garcia committed
            external function fx_decrypt_aes_128_ccm_test(in octetstring p_k, in octetstring p_n, in octetstring p_pt) return octetstring;
             * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Nist-P256 algorithm
             * @param   p_toBeEncryptedSecuredMessage    The data to be encrypted
             * @param   p_recipientsPublicKeyCompressed  The Recipient's compressed public key
             * @param   p_compressed_mode                 The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
             * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
             * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
             * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
             * @return  The encrypted message
            external function fx_encryptWithEciesNistp256WithSha256(in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_recipientsPublicKeyCompressed, in integer p_compressed_mode, in octetstring p_salt, out Oct32 p_publicEphemeralKeyCompressed, out integer p_ephemeralKeyModeCompressed, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce, in boolean p_use_hardcoded_values := false) return octetstring;
            external function fx_test_encryptWithEciesNistp256WithSha256(in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_privateEphemeralKey, in Oct32 p_recipientPublicKeyX, in Oct32 p_recipientPublicKeyY, in octetstring p_salt, out Oct32 p_publicEphemeralKeyX, out Oct32 p_publicEphemeralKeyY, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce) return octetstring;
             * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Nist-P256 algorithm
             * @param   p_encryptedSecuredMessage    The data to be decrypted
             * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
             * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
             * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
             * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
             * @return  The decrypted message
Yann Garcia's avatar
Yann Garcia committed
            external function fx_decryptWithEciesNistp256WithSha256(in octetstring p_encryptedSecuredMessage, in Oct32 p_privateEncKey, in Oct32 p_publicEphemeralKeyCompressed, in integer p_ephemeralKeyModeCompressed, in Oct16 p_encrypted_sym_key, in Oct16 p_authentication_vector, in Oct12 p_nonce, in Oct32 p_salt, out Oct16 p_aes_sym_enc_key) return octetstring;
            /**
             * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Brainpool-P256 algorithm
             * @param   p_toBeEncryptedSecuredMessage    The data to be encrypted
             * @param   p_recipientsPublicKeyCompressed  The Recipient's compressed public key
             * @param   p_compressed_mode                 The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
             * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
             * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
             * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
             * @return  The encrypted message
             */
            external function fx_encryptWithEciesBrainpoolp256WithSha256(in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_recipientsPublicKeyCompressed, in integer p_compressed_mode, in octetstring p_salt, out Oct32 p_publicEphemeralKeyCompressed, out integer p_ephemeralKeyModeCompressed, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce, in boolean p_use_hardcoded_values := false) return octetstring;
            
            external function fx_test_encryptWithEciesBrainpoolp256WithSha256(in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_privateEphemeralKey, in Oct32 p_recipientPublicKeyX, in Oct32 p_recipientPublicKeyY, in octetstring p_salt, out Oct32 p_publicEphemeralKeyX, out Oct32 p_publicEphemeralKeyY, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce) return octetstring;
            
            /**
             * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Brainpool-P256 algorithm
             * @param   p_encryptedSecuredMessage    The data to be decrypted
             * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
             * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
             * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
             * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
             * @return  The decrypted message
             */
Yann Garcia's avatar
Yann Garcia committed
            external function fx_decryptWithEciesBrainpoolp256WithSha256(in octetstring p_encryptedSecuredMessage, in Oct32 p_privateEncKey, in Oct32 p_publicEphemeralKeyCompressed, in integer p_ephemeralKeyModeCompressed, in Oct16 p_encrypted_sym_key, in Oct16 p_authentication_vector, in Oct12 p_nonce, in Oct32 p_salt, out Oct16 p_aes_sym_enc_key) return octetstring;
garciay's avatar
garciay committed
            /**
             * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature
             * @param   p_toBeSignedSecuredMessage  The data to be signed
             * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
             * @param   p_privateKey                The private key
             * @return  The signature value
             */
            external function fx_signWithEcdsaNistp256WithSha256(in octetstring p_toBeSignedSecuredMessage, in Oct32 p_certificateIssuer, in Oct32 p_privateKey) return octetstring;
Yann Garcia's avatar
Yann Garcia committed
            external function fx_test_signWithEcdsaNistp256WithSha256(in octetstring p_toBeSignedSecuredMessage, in Oct32 p_privateKey) return octetstring;
            /**
             * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature
             * @param   p_toBeSignedSecuredMessage    The data to be signed
             * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
             * @param   p_privateKey                  The private key for signature
garciay's avatar
garciay committed
             * @return  The signature value
             */
            external function fx_signWithEcdsaBrainpoolp256WithSha256(in octetstring p_toBeSignedSecuredMessage, in Oct32 p_certificateIssuer, in Oct32 p_privateKey) return octetstring;
garciay's avatar
garciay committed
            
            /**
             * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature
             * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
             * @param   p_privateKey                  The private key for signature
garciay's avatar
garciay committed
             * @return  The signature value
             */
            external function fx_signWithEcdsaBrainpoolp384WithSha384(in octetstring p_toBeSignedSecuredMessage, in Oct48 p_certificateIssuer, in Oct48 p_privateKey) return octetstring;
            /**
             * @desc    Verify the signature of the specified data
             * @param   p_toBeVerifiedData          The data to be verified
             * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
             * @param   p_signature                 The signature
             * @param   p_ecdsaNistp256PublicKeyCompressed   The compressed public key
             * @param   p_compressed_mode            The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @return  true on success, false otherwise
             */
            external function fx_verifyWithEcdsaNistp256WithSha256(in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in octetstring p_signature, in Oct32 p_ecdsaNistp256PublicKeyCompressed, in integer p_compressed_mode) return boolean;
            external function fx_test_verifyWithEcdsaNistp256WithSha256(in octetstring p_toBeVerifiedData, in octetstring p_signature, in Oct32 p_ecdsaNistp256PublicKeyCompressed, in integer p_compressed_mode) return boolean;
garciay's avatar
garciay committed
             * @desc    Verify the signature of the specified data
             * @param   p_toBeVerifiedData          The data to be verified
             * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
garciay's avatar
garciay committed
             * @param   p_signature                 The signature
             * @param   p_ecdsaNistp256PublicKeyX   The public key (x coordinate)
             * @param   p_ecdsaNistp256PublicKeyY   The public key (y coordinate)
             * @return  true on success, false otherwise
             */
            external function fx_verifyWithEcdsaNistp256WithSha256_1(in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaNistp256PublicKeyX, in Oct32 p_ecdsaNistp256PublicKeyY) return boolean;
            
            /**
             * @desc    Verify the signature of the specified data
             * @param   p_toBeVerifiedData          The data to be verified
             * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
             * @param   p_signature                 The signature
             * @param   p_ecdsaBrainpoolp256PublicKeyCompressed   The compressed public key
             * @param   p_compressed_mode            The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @return  true on success, false otherwise
             */
            external function fx_verifyWithEcdsaBrainpoolp256WithSha256(in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaBrainpoolp256PublicKeyCompressed, in integer p_compressed_mode) return boolean;
garciay's avatar
garciay committed
            
            /**
             * @desc    Verify the signature of the specified data
             * @param   p_toBeVerifiedData          The data to be verified
             * @param   p_certificateIssuer         The certificate issuer
garciay's avatar
garciay committed
             * @param   p_signature                 The signature
             * @param   p_ecdsaBrainpoolp256PublicKeyX   The public key (x coordinate)
             * @param   p_ecdsaBrainpoolp256PublicKeyY   The public key (y coordinate)
             * @return  true on success, false otherwise
             */
            external function fx_verifyWithEcdsaBrainpoolp256WithSha256_1(in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaBrainpoolp256PublicKeyX, in Oct32 p_ecdsaBrainpoolp256PublicKeyY) return boolean;
            
            /**
             * @desc    Verify the signature of the specified data
             * @param   p_toBeVerifiedData          The data to be verified
             * @param   p_certificateIssuer         The certificate issuer
             * @param   p_signature                 The signature
             * @param   p_ecdsaBrainpoolp384PublicKeyCompressed   The compressed public key
             * @param   p_compressed_mode            The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
             * @return  true on success, false otherwise
             */
            external function fx_verifyWithEcdsaBrainpoolp384WithSha384(in octetstring p_toBeVerifiedData, in Oct48 p_certificateIssuer, in Oct96 p_signature, in Oct48 p_ecdsaBrainpoolp384PublicKeyCompressed, in integer p_compressed_mode) return boolean;
garciay's avatar
garciay committed
            
            /**
             * @desc    Verify the signature of the specified data
             * @param   p_toBeVerifiedData          The data to be verified
             * @param   p_certificateIssuer         The hash of the canonical certificate issuer
garciay's avatar
garciay committed
             * @param   p_signature                 The signature
             * @param   p_ecdsaBrainpoolp384PublicKeyX   The public key (x coordinate)
             * @param   p_ecdsaBrainpoolp384PublicKeyY   The public key (y coordinate)
garciay's avatar
garciay committed
             * @return  true on success, false otherwise
             */
            external function fx_verifyWithEcdsaBrainpoolp384WithSha384_1(in octetstring p_toBeVerifiedData, in Oct48 p_certificateIssuer, in Oct96 p_signature, in Oct48 p_ecdsaBrainpoolp384PublicKeyX, in Oct48 p_ecdsaBrainpoolp384PublicKeyY) return boolean;
garciay's avatar
garciay committed
             * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
             *          This function should not be used by the ATS
             * @param   p_privateKey    The new private key value
             * @param   p_publicKeyX    The new public key value (x coordinate)
             * @param   p_publicKeyX    The new public key value (y coordinate)
             * @param   p_publicKeyCompressed The compressed public keys
             * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
garciay's avatar
garciay committed
             * @return  true on success, false otherwise
             */
            external function fx_generateKeyPair_nistp256(out Oct32 p_privateKey, out Oct32 p_publicKeyX, out Oct32 p_publicKeyY, out Oct32 p_publicKeyCompressed, out integer p_compressed_mode) return boolean;
garciay's avatar
garciay committed
            
            /**
             * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
             *          This function should not be used by the ATS
             * @param   p_privateKey    The new private key value
             * @param   p_publicKeyX    The new public key value (x coordinate)
             * @param   p_publicKeyX    The new public key value (y coordinate)
             * @param   p_publicKeyCompressed The compressed public keys
             * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
garciay's avatar
garciay committed
             * @return  true on success, false otherwise
             */
            external function fx_generateKeyPair_brainpoolp256(out Oct32 p_privateKey, out Oct32 p_publicKeyX, out Oct32 p_publicKeyY, out Oct32 p_publicKeyCompressed, out integer p_compressed_mode) return boolean;
garciay's avatar
garciay committed
            
            /**
             * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
             *          This function should not be used by the ATS
             * @param   p_privateKey    The new private key value
             * @param   p_publicKeyX    The new public key value (x coordinate)
             * @param   p_publicKeyX    The new public key value (y coordinate)
             * @param   p_publicKeyCompressed The compressed public keys
             * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
garciay's avatar
garciay committed
             * @return  true on success, false otherwise
             */
            external function fx_generateKeyPair_brainpoolp384(out Oct48 p_privateKey, out Oct48 p_publicKeyX, out Oct48 p_publicKeyY, out Oct48 p_publicKeyCompressed, out integer p_compressed_mode) return boolean;
            
        } // End of group signing
        group encryption {
            
        } // End of group encryption
        group certificatesLoader {
            
            /**
            * @desc    Load in memory cache the certificates available in the specified directory
            * @param   p_rootDirectory Root directory to access to the certificates identified by the certificate ID
            * @param   p_configId      A configuration identifier
            * @remark  This method SHALL be call before any usage of certificates
            * @return  true on success, false otherwise
            */
            external function fx_loadCertificates(in charstring p_rootDirectory, in charstring p_configId) return boolean;
garciay's avatar
garciay committed
            external function fx_store_certificate(in charstring p_cert_id, in octetstring p_cert, in octetstring p_private_key, in octetstring p_public_key_x, in octetstring p_public_key_y, in octetstring p_public_key_compressed, in integer p_public_key_compressed_mode, in octetstring p_hash, in octetstring p_hashid8, in octetstring p_issuer, in template (omit) octetstring p_private_enc_key, in template (omit) octetstring p_public_enc_key_x, in template (omit) octetstring p_public_enc_key_y, in template (omit) octetstring p_public_enc_compressed_key, in template (omit) integer p_public_enc_key_compressed_mode) return boolean;
             * @desc    Unload from memory cache the certificates
             * @return  true on success, false otherwise
             */
            external function fx_unloadCertificates() return boolean;
             * @desc    Read the specified certificate
             * @param   p_certificate_id the certificate identifier
             * @param   p_certificate   the expected certificate
             * @return  true on success, false otherwise
             */
            external function fx_readCertificate(in charstring p_certificate_id, out octetstring p_certificate) return boolean;
             * @desc    Read the specified certificate digest
             * @param   p_certificate_id the certificate identifier
             * @param   p_digest   the expected certificate
             * @return  true on success, false otherwise
             */
            external function fx_readCertificateDigest(in charstring p_certificate_id, out HashedId8 p_digest) return boolean;
            /**
             * @desc    Read the whole-hash of the specified certificate
             * @param   p_certificate_id the certificate identifier
             * @param   p_hash          the whole-hash of the certificate
             * @return  true on success, false otherwise
             */
            external function fx_readCertificateHash(in charstring p_certificate_id, out octetstring p_hash) return boolean;
            external function fx_readCertificateFromDigest(in HashedId8 p_digest, out charstring p_certificate_id) return boolean;
Yann Garcia's avatar
Yann Garcia committed
            
            external function fx_readCertificateFromHashedId3(in HashedId3 p_digest, out charstring p_certificate_id) return boolean;
             * @desc    Read the private keys for the specified certificate
             * @param   p_keysId            the keys identifier
             * @param   p_signingPrivateKey the signing private key
             * @return  true on success, false otherwise
             */

            external function fx_readSigningKey(in charstring p_keysId, out Oct32 p_signingPrivateKey) return boolean;

            /**
            * @desc    Read the private keys for the specified certificate
            * @param   p_keysId            the keys identifier
            * @param   p_encryptPrivateKey the encrypt private key
            * @return  true on success, false otherwise
            */

            external function fx_readEncryptingKey(in charstring p_keysId, out Oct32 p_encryptingPrivateKey) return boolean;

        } // End of group certificatesLoader
        
        group geodesic {
            
            /**
            * @desc    Check that given polygon doesn't have neither self-intersections nor holes.
            * @param   p_region   Polygonal Region
            * @return  true on success, false otherwise
            * @verdict Unchanged
            */
garciay's avatar
garciay committed
            external function fx_isValidPolygonalRegion(in PolygonalRegion p_region) return boolean;
            * @desc Check if a polygonal region is inside another one
            * @param p_parent  The main polygonal region
            * @param p_region  The polygonal region to be included
            * @return true on success, false otherwise
            * @verdict Unchanged
            */
garciay's avatar
garciay committed
            external function fx_isPolygonalRegionInside(in PolygonalRegion p_parent, in PolygonalRegion p_region) return boolean;
            * @desc Check that the location is inside a circular region
            * @param p_region      The circular region to consider
            * @param p_location    The device location
            * @return true on success, false otherwise
            * @verdict Unchanged
            */
garciay's avatar
garciay committed
            external function fx_isLocationInsideCircularRegion(in CircularRegion p_region, in ThreeDLocation p_location) return boolean;
            * @desc Check that the location is inside a rectangular region
            * @param p_region      The rectangular region to consider
            * @param p_location    The device location
            * @return true on success, false otherwise
            * @verdict Unchanged
            */
            external function fx_isLocationInsideRectangularRegion(in SequenceOfRectangularRegion p_region, in ThreeDLocation p_location) return boolean;
            * @desc Check that the location is inside a polygonal region
            * @param p_region      The polygonal region to consider
            * @param p_location    The device location
            * @return true on success, false otherwise
            * @verdict Unchanged
            */
            external function fx_isLocationInsidePolygonalRegion(in PolygonalRegion p_region, in ThreeDLocation p_location) return boolean;
            * @desc Check if the location is inside an identified region
            * @param p_region      The identified region to consider
            * @param p_location    The device location
            * @return true on success, false otherwise
            * @verdict Unchanged
            */
garciay's avatar
garciay committed
            external function fx_isLocationInsideIdentifiedRegion(in IdentifiedRegion p_region, in ThreeDLocation p_location) return boolean;
garciay's avatar
garciay committed
            /**
            * @desc Check if the location is inside an undefined region
            * @param p_region      The identified region to consider
            * @param p_location    The device location
            * @return true on success, false otherwise
            * @verdict Unchanged
            */
            external function fx_isLocationInsideOtherRegion(in octetstring p_region, in ThreeDLocation p_location) return boolean; 
garciay's avatar
garciay committed
            
            /**
             * @desc    Check that p_circular_region_1 circular region is included into p_circular_region_2 circular region
             * @param   p_circular_region_1    Circular region 1
             * @param   p_circular_region_2    Circular region 2
             *
             * @return  true on success, false otherwise
             */
            external function fx_areCirclesInside(in CircularRegion p_circular_region_1, in CircularRegion p_circular_region_2) return boolean;
            
            /**
             * @desc    Check that p_rectanglar_region_1 rectangular region is included into p_rectanglar_region_2 rectangular region
             * @param   p_rectanglar_region_1    Rectangular region 1
             * @param   p_rectanglar_region_2    Rectangular region 2
             *
             * @return  true on success, false otherwise
             */
            external function fx_areRectanglesInside(in SequenceOfRectangularRegion p_rectanglar_region_1, in SequenceOfRectangularRegion p_rectanglar_region_2) return boolean;
garciay's avatar
garciay committed
            
            /**
             * @desc    Check that p_polygonal_region_1 polygonal region is included into p_polygonal_region_2 polygonal region
             * @param   p_polygonal_region_1    Polygonal region 1
             * @param   p_polygonal_region_2    Polygonal region 2
             *
             * @return  true on success, false otherwise
             */
            external function fx_arePolygonsInside(in PolygonalRegion p_polygonal_region_1, in PolygonalRegion p_polygonal_region_2) return boolean;
            
            * @desc Convert a spacial coordinate from DMS to Dms
            * @param p_degrees The degrees (D)
            * @param p_minutes The minutes (M)
            * @param p_seconds The seconds (S)
            * @param p_latlon  The latitude/longitude: (N|S|E|W)
            * @return The decimal coordinate on success, 0.0, otherwise
            * @verdict Unchanged
            */
            external function fx_dms2dd(in Int p_degrees, in Int p_minutes, in float p_seconds, in Oct1 p_latlon) return float;
        } // End of group geodesic
        
    } // End of group externalFunctions
    
filatov's avatar
filatov committed
    group geometryFunctions {
        
garciay's avatar
garciay committed
        function f_checkRegionValidityRestiction(
                                                 in EtsiTs103097Certificate p_cert, 
                                                 in EtsiTs103097Certificate p_cert_issuer
garciay's avatar
garciay committed
        ) return boolean {
            var ValidityPeriod v_cert_region, v_cert_issuer_region;
garciay's avatar
garciay committed
            var boolean v_cert_issuer_region_result;
            
            /* FIXME To be reviewed v_cert_issuer_region_result := f_getCertificateValidityRestriction(p_cert_issuer, e_region, v_cert_issuer_region);
garciay's avatar
garciay committed
            if (f_getCertificateValidityRestriction(p_cert, e_region, v_cert_region) == false) {
                if (v_cert_issuer_region_result == true) {
garciay's avatar
garciay committed
                    if (v_cert_issuer_region.validity.region.region_type != e_none) {
garciay's avatar
garciay committed
                        return false;
                    }
                }
            } else if (
                        (v_cert_issuer_region_result == true) and 
garciay's avatar
garciay committed
                        (v_cert_issuer_region.validity.region.region_type != e_none)
garciay's avatar
garciay committed
            ) {
garciay's avatar
garciay committed
                if (v_cert_region.validity.region.region_type == e_circle) {
                    if (v_cert_issuer_region.validity.region.region_type == e_circle) {
garciay's avatar
garciay committed
                        // Check v_cert_region 'circle' is inside v_cert_issuer_region 'circle'
                        if (f_areCirclesInside(v_cert_region.validity.region.region.circular_region, v_cert_issuer_region.validity.region.region.circular_region) == false) {
                            log("*** " & testcasename() & ": FAIL: Issuer and issuing certificates circle area does not match ***");
                            return false;
                        }
                    }
garciay's avatar
garciay committed
                } else if (v_cert_region.validity.region.region_type == e_rectangle) {
                    if (v_cert_issuer_region.validity.region.region_type == e_rectangle) {
garciay's avatar
garciay committed
                        // Check v_cert_region 'rectangle' is inside v_cert_issuer_region 'rectangle'
                        if (f_areRectanglesInside(v_cert_region.validity.region.region.rectangular_region, v_cert_issuer_region.validity.region.region.rectangular_region) == false) {
                            log("*** " & testcasename() & ": FAIL: Issuer and issuing certificates rectangle area does not match ***");
                            return false;
                        }
                    }
garciay's avatar
garciay committed
                } else if (v_cert_region.validity.region.region_type == e_polygon) {
                    if (v_cert_issuer_region.validity.region.region_type == e_polygon) {
garciay's avatar
garciay committed
                        // Check v_cert_region 'polygon' is inside v_cert_issuer_region 'polygon'
                        if (f_arePolygonsInside(v_cert_region.validity.region.region.polygonal_region, v_cert_issuer_region.validity.region.region.polygonal_region) == false) {
                            log("*** " & testcasename() & ": FAIL: Issuer and issuing certificates polygon area does not match ***");
                            return false;
                        }
                    }
garciay's avatar
garciay committed
                } else if (v_cert_region.validity.region.region_type == e_id) {
garciay's avatar
garciay committed
                    // Check id_region
                    if (not match (v_cert_region.validity.region, mw_geographicRegion_identified(mw_identifiedRegion_iso3166_any))) { 
                        log("*** " & testcasename() & ": FAIL: Identified region is not conformed to ISO 3166-1 ***");
                        return false;
                    }
                    if (not match (v_cert_region.validity.region, mw_geographicRegion_identified(mw_identifiedRegion_un_stats_any))) {
                        log("*** " & testcasename() & ": FAIL: Identified region is not conformed to United Nations Statistics Division ***");
                        return false;
                    }
                    // Check region_dictionary
                    if (not match (v_cert_region.validity.region.region.id_region.region_dictionary, v_cert_issuer_region.validity.region.region.id_region.region_dictionary)) {
                        log("*** " & testcasename() & ": FAIL: Issuer and issuing 'region_dictionary' field does not match ***");
                        return false;
                    }
                    // Check region_identifier
                    if (not match (v_cert_region.validity.region.region.id_region.region_identifier, v_cert_issuer_region.validity.region.region.id_region.region_identifier)) {
                        log("*** " & testcasename() & ": FAIL: Issuer and issuing 'region_identifier' field does not match ***");
                        return false;
                    }
                    // Check local_region
                    if (
                        (not match (v_cert_issuer_region.validity.region.region.id_region.local_region, v_cert_region.validity.region.region.id_region.local_region)) or 
                        (not match (v_cert_issuer_region.validity.region.region.id_region.local_region, 0))
                    ) {
                        log("*** " & testcasename() & ": FAIL: Issuer and issuing 'local_region' field does not match ***");
                        return false;
garciay's avatar
garciay committed
                    }
                }
garciay's avatar
garciay committed
            
            return true;
        } // End of function f_checkRegionValidityRestiction
        
filatov's avatar
filatov committed
        /**
garciay's avatar
garciay committed
         * @desc    Check that p_circular_region_1 circular region is included into p_circular_region_2 circular region
         * @param   p_circular_region_1    Circular region 1
         * @param   p_circular_region_2    Circular region 2
         *
         * @return  true on success, false otherwise
         */
        function f_areCirclesInside(
                                    in CircularRegion p_circular_region_1, 
                                    in CircularRegion p_circular_region_2
        ) return boolean {
            return fx_areCirclesInside(p_circular_region_1, p_circular_region_2);
        }
        
        /**
         * @desc    Check that p_rectanglar_region_1 rectangular region is included into p_rectanglar_region_2 rectangular region
         * @param   p_rectanglar_region_1    Rectangular region 1
         * @param   p_rectanglar_region_2    Rectangular region 2
         *
         * @return  true on success, false otherwise
         */
        function f_areRectanglesInside(
                                       in SequenceOfRectangularRegion p_rectanglar_region_1, 
                                       in SequenceOfRectangularRegion p_rectanglar_region_2
garciay's avatar
garciay committed
        ) return boolean {
            return fx_areRectanglesInside(p_rectanglar_region_1, p_rectanglar_region_2);
        }
        
        /**
         * @desc    Check that p_polygonal_region_1 polygonal region is included into p_polygonal_region_2 polygonal region
         * @param   p_polygonal_region_1    Polygonal region 1
         * @param   p_polygonal_region_2    Polygonal region 2
         *
         * @return  true on success, false otherwise
         */
        function f_arePolygonsInside(
                                     in PolygonalRegion p_polygonal_region_1, 
                                     in PolygonalRegion p_polygonal_region_2
        ) return boolean {
            return fx_arePolygonsInside(p_polygonal_region_1, p_polygonal_region_2);
        }
        
        /**
         * @desc    Check that given location is valid
         * @param   p_location    location to be checked
         * @return  true on success, false otherwise
         */
        function f_isValidTwoDLocation(
garciay's avatar
garciay committed
                                       in template (value) TwoDLocation p_location
filatov's avatar
filatov committed
        ) return boolean {
//FIXME RGY Titan doesn't support dot notation after valueof at the moment
//                (valueof(p_location).longitude != c_maxLongitude + 1) and
//                (valueof(p_location).latitude != c_maxLatitude + 1);
                (valueof(p_location.longitude) != c_maxLongitude + 1) and
                (valueof(p_location.latitude) != c_maxLatitude + 1);
        } // End of function f_isValidTwoDLocation
filatov's avatar
filatov committed
        /**
garciay's avatar
garciay committed
         * @desc    Check that two given rectanlular regions are intersected
         *          Note: Regions must be normalized(northWest.latitude >= southEast.latitude)
garciay's avatar
garciay committed
         * @param   p_r1    Region 1
         * @param   p_r2    Region 2
         *
         * @return  true on success, false otherwise
         */
        function f_isRectangularRegionsIntersected(
garciay's avatar
garciay committed
                                                   in template (value) RectangularRegion p_r1,
                                                   in template (value) RectangularRegion p_r2
        ) return boolean {
garciay's avatar
garciay committed
            return not (
//FIXME RGY Titan doesn't support dot notation after valueof at the moment
//                valueof(p_r2).northWest.longitude > valueof(p_r1).southEast.longitude or 
//                valueof(p_r2).southEast.longitude < valueof(p_r1).northWest.longitude or 
//                valueof(p_r2).southEast.latitude  > valueof(p_r1).northWest.latitude or 
//                valueof(p_r2).northWest.latitude  < valueof(p_r1).southEast.latitude
                valueof(p_r2.northWest.longitude) > valueof(p_r1.southEast.longitude) or 
                valueof(p_r2.southEast.longitude) < valueof(p_r1.northWest.longitude) or 
                valueof(p_r2.southEast.latitude)  > valueof(p_r1.northWest.latitude) or 
                valueof(p_r2.northWest.latitude)  < valueof(p_r1.southEast.latitude)
garciay's avatar
garciay committed
            );
        } // End of function f_isRectangularRegionsIntersected
filatov's avatar
filatov committed
        
garciay's avatar
garciay committed
        function f_isContinuousRectangularRegions(
                                                  in template (value) SequenceOfRectangularRegion p_region
filatov's avatar
filatov committed
        ) return boolean {
            var integer v_i, v_j;
            var boolean v_found;
            
            for (v_i := 0; v_i < lengthof(p_region); v_i := v_i + 1) {
                var PolygonalRegion v_region_base;
                f_convertRectangularRegionIntoPolygonalRegion(valueof(p_region[v_i]), v_region_base);
                v_found := false;
                for (v_j := 0; v_j < lengthof(p_region); v_j := v_j + 1) {
                    if (v_j != v_i) {
                        var PolygonalRegion v_region;
                        f_convertRectangularRegionIntoPolygonalRegion(valueof(p_region[v_j]), v_region);
                        if (f_isPolygonalRegionInside(v_region, v_region_base) == true) {
                            v_found := true;
                        }
                    }
                } // End of 'for' statement
                if (v_found == false) {
                    return false;
                }
            } // End of 'for' statement
            
filatov's avatar
filatov committed
            return true;
        } // End of function f_isContinuousRectangularRegions
         * @desc Check if a polygonal region is inside another one
garciay's avatar
garciay committed
         * @param p_parent  The main polygonal region
         * @param p_region  The polygonal region to be included
         * @return true on success, false otherwise
         * @verdict Unchanged
         */
        function f_isRectangularRegionsInside(
                                              in template (value) SequenceOfRectangularRegion p_parent,
                                              in template (value) SequenceOfRectangularRegion p_region
        ) return boolean {
            var integer v_i, v_j;
            
            for (v_i := 0; v_i < lengthof(p_parent); v_i := v_i + 1) {
                var PolygonalRegion v_region_parent, v_region;
                f_convertRectangularRegionIntoPolygonalRegion(valueof(p_parent[v_i]), v_region_parent);
                for (v_j := 0; v_j < lengthof(p_parent); v_j := v_j + 1) {
                    f_convertRectangularRegionIntoPolygonalRegion(valueof(p_region[v_j]), v_region);
                    if (f_isPolygonalRegionInside(v_region, v_region_parent) == true) {
                        return true;
                    }
                } // End of 'for' statement
            } // End of 'for' statement
            
            return false;
        } // End of function f_isRectangularRegionsInside
        /**
         * @desc Convert a rectangular region into a polygonal region
         * @param p_region The rectangular regions to convert
         * @return 
         * @verdict 
         */
        function f_convertRectangularRegionIntoPolygonalRegion(
                                                               in template (value) RectangularRegion p_rectangular_region,
                                                               out PolygonalRegion p_region
        ) return boolean {
            
            // Convert rectangular regions to polygons and check polygons
            p_region[0] := valueof(p_rectangular_region.northWest);
                valueof(p_rectangular_region.northWest.latitude) + valueof(p_rectangular_region.southEast.latitude),
                valueof(p_rectangular_region.northWest.longitude)
            p_region[2] := valueof(p_rectangular_region.southEast);
                valueof(p_rectangular_region.northWest.latitude),
                valueof(p_rectangular_region.northWest.longitude) + valueof(p_rectangular_region.southEast.longitude) 
            };
            log("f_convertRectangularRegionIntoPolygonalRegion: DEBUG: Northwest location is invalid in rect ", p_region);
            
            return true;
        } // End of function 
        
garciay's avatar
garciay committed
         * @desc    Check that given polygon doesn't have neither self-intersections nor holes.
         * @param   p_region   Polygonal Region
         * @return  true on success, false otherwise
         * @verdict Unchanged
         */
        function f_isValidPolygonalRegion(
garciay's avatar
garciay committed
                                          in template (value) PolygonalRegion p_region
filatov's avatar
filatov committed
        ) return boolean {
            // Sanity check
            if (not isbound(p_region) or (lengthof(p_region) == 0)) {
                return false;
            }
            
garciay's avatar
garciay committed
            return fx_isValidPolygonalRegion(valueof(p_region));
        } // End of function f_isValidPolygonalRegion
         * @desc Check if a polygonal region is inside another one
garciay's avatar
garciay committed
         * @param p_parent  The main polygonal region
         * @param p_region  The polygonal region to be included
         * @return true on success, false otherwise
         * @verdict Unchanged
         */
        function f_isPolygonalRegionInside(
garciay's avatar
garciay committed
                                           in template (value) PolygonalRegion p_parent,
                                           in template (value) PolygonalRegion p_region
filatov's avatar
filatov committed
        ) return boolean {
            // Sanity check
            if (not isbound(p_parent) or not isbound(p_region) or (lengthof(p_parent) == 0) or (lengthof(p_region) == 0)) {
                return false;
            }
            
            return fx_isPolygonalRegionInside(valueof(p_parent), valueof(p_region));
        } // End of function f_isPolygonalRegionInside
garciay's avatar
garciay committed
        
garciay's avatar
garciay committed
         * @desc
         */
        function f_isIdentifiedRegionInside(
garciay's avatar
garciay committed
                                            in template (value) UInt16 p_parent,
                                            in template (value) UInt16 p_region
        ) return boolean {
garciay's avatar
garciay committed
            return valueof(p_parent) == valueof(p_region);
        } // End of function f_isIdentifiedRegionInside
garciay's avatar
garciay committed
        
garciay's avatar
garciay committed
         * @desc Check that the location is inside a region
         * @param p_region      The region to consider
         * @param p_location    The device location
         * @return true on success, false otherwise
         * @verdict Unchanged
         */
        function f_isLocationInsideRegion(
garciay's avatar
garciay committed
                                          in template (value) GeographicRegion p_region,
                                          in template (value) ThreeDLocation p_location
        ) return boolean {
            var boolean v_ret := false;
            if (ischosen(p_region.circularRegion)) {
                v_ret := f_isLocationInsideCircularRegion(valueof(p_region.circularRegion), p_location);
            } else if (ischosen(p_region.rectangularRegion)) {
                v_ret := f_isLocationInsideRectangularRegion(valueof(p_region.rectangularRegion), p_location);
            } else if (ischosen(p_region.polygonalRegion)) {
                v_ret := f_isLocationInsidePolygonalRegion(valueof(p_region.polygonalRegion), p_location);
            } else if (ischosen(p_region.identifiedRegion)) {
                for (var integer v_i := 0; v_i < lengthof(p_region.identifiedRegion); v_i := v_i + 1) {
                    if (f_isLocationInsideIdentifiedRegion(valueof(p_region.identifiedRegion[v_i]), p_location) == true) {
                        v_ret := true;
                        break;
                    }
                } // End of 'for' statement
        } // End of function f_isLocationInsideRegion
        
        /**
        * @desc Check that the location is inside a circular region
        * @param p_region      The circular region to consider
        * @param p_location    The device location
        * @return true on success, false otherwise
        * @verdict Unchanged
        */
garciay's avatar
garciay committed
        function f_isLocationInsideCircularRegion(
                                                  in template (value) CircularRegion p_region,
                                                  in template (value) ThreeDLocation p_location
        ) return boolean {
            // Sanity check
            if (not isbound(p_region) or not isbound(p_location)) {
                return false;
            }
            
garciay's avatar
garciay committed
            return fx_isLocationInsideCircularRegion(valueof(p_region), valueof(p_location));
        } // End of function f_isLocationInsideCircularRegion
        
        /**
        * @desc Check that the location is inside a rectangular region
        * @param p_region      The rectangular region to consider
        * @param p_location    The device location
        * @return true on success, false otherwise
        * @verdict Unchanged
        */
        function f_isLocationInsideRectangularRegion(
                                                     in template (value) SequenceOfRectangularRegion p_region,
garciay's avatar
garciay committed
                                                     in template (value) ThreeDLocation p_location
        ) return boolean {
            // Sanity check
            if (not isbound(p_region) or not isbound(p_location) or (lengthof(p_region) == 0)) {
                return false;
            }
garciay's avatar
garciay committed
//            log("f_isLocationInsideRectangularRegion: p_polygonalArea: ", p_region);
//            log("f_isLocationInsideRectangularRegion: p_location: ", p_location);
garciay's avatar
garciay committed
            return fx_isLocationInsideRectangularRegion(valueof(p_region), valueof(p_location));
        } // End of function f_isLocationInsideRectangularRegion
        
        /**
        * @desc Check that the location is inside a polygonal region
        * @param p_region      The polygonal region to consider
        * @param p_location    The device location
        * @return true on success, false otherwise
        * @verdict Unchanged
        */
        function f_isLocationInsidePolygonalRegion(
garciay's avatar
garciay committed
                                                   in template (value) PolygonalRegion  p_region,
                                                   in template (value) ThreeDLocation p_location
        ) return boolean {
            // Sanity check
            if (not isbound(p_region) or not isbound(p_location) or (lengthof(p_region) == 0)) {
                return false;
            }
//            log("f_isLocationInsidePolygonalRegion: p_polygonalArea: ", p_region, " - ", valueof(p_region));
//            log("f_isLocationInsidePolygonalRegion: p_location: ", p_location, " - ", valueof(p_location));
garciay's avatar
garciay committed
            return fx_isLocationInsidePolygonalRegion(valueof(p_region), valueof(p_location));
        } // End of function f_isLocationInsidePolygonalRegion
        
        /**
        * @desc Check if the location is inside an identified region
        * @param p_region      The identified region to consider
        * @param p_location    The device location
        * @return true on success, false otherwise
        * @verdict Unchanged
        */
        function f_isLocationInsideIdentifiedRegion(
garciay's avatar
garciay committed
                                                    in template (value) IdentifiedRegion p_region,
                                                    in template (value) ThreeDLocation p_location
        ) return boolean {
            // Sanity check
            if (not isbound(p_region) or not isbound(p_location)) {
                return false;
            }
            
garciay's avatar
garciay committed
            return fx_isLocationInsideIdentifiedRegion(valueof(p_region), valueof(p_location));
        } // End of function f_isLocationInsideIdentifiedRegion
        
        /**
        * @desc Check if the location is inside an undefined region
        * @param p_region      The identified region to consider
        * @param p_location    The device location
        * @return true on success, false otherwise
        * @verdict Unchanged
        */
        function f_isLocationInsideOtherRegion(
garciay's avatar
garciay committed
                                               in template (value) octetstring p_region,
                                               in template (value) ThreeDLocation p_location
        ) return boolean {
garciay's avatar
garciay committed
            // Sanity check
            if (valueof(p_region) == ''O) {
                return false;
            }
            
            return fx_isLocationInsideOtherRegion(valueof(p_region), valueof(p_location)); 
        } // End of function f_isLocationInsideOtherRegion
        
        * @desc Convert a spacial coordinate from DMS to Dms
        * @param p_degrees The degrees (D)
        * @param p_minutes The minutes (M)
        * @param p_seconds The seconds (S)
        * @param p_latlon  The latitude/longitude: (N|S|E|W)
        * @return The decimal coordinate on success, 0.0, otherwise
        * @verdict Unchanged
        */
        function f_dms2dd(
garciay's avatar
garciay committed
                          in integer p_degrees,
                          in integer p_minutes,
                          in float p_seconds,
                          in charstring p_latlon
        ) return float {
            var Oct1 v_latlon;
            
            // Sanity checks
            if (lengthof(p_latlon) != 1) {
                return 0.0;
            } else if ((p_latlon != "N") and (p_latlon != "S") and (p_latlon != "E") and (p_latlon != "W")) {
                return 0.0;
            }
            v_latlon := char2oct(p_latlon);
            return fx_dms2dd(p_degrees, p_minutes, p_seconds, v_latlon);
        } // End of function f_dms2dd
        
        /**
        * @desc Convert the latitude from float to int
        * @param p_latitude The latitude to be converted. Significand length shall be 7 digits length
        * @return The converted latitude
        * @verdict Unchanged
        */
garciay's avatar
garciay committed
        function f_ddlat2int(
                             in float p_latitude
        ) return SecLatitude {
            return float2int(p_latitude * 10000000.0); // Significand length shall be 7 digits length
        }
        
        /**
        * @desc Convert the longitude from float to int
        * @param p_longitude The longitude to be converted. Significand length shall be 6 digits length
        * @return The converted longitude
        * @verdict Unchanged
        */
garciay's avatar
garciay committed
        function f_ddlon2int(
                             in float p_longitude
        ) return SecLongitude {
            return float2int(p_longitude * 1000000.0); // Significand length shall be 6 digits length
        }
        
    } // End of group geometryFunctions
filatov's avatar
filatov committed
    
} // End of module LibItsSecurity_Functions