Skip to content
LibItsSecurity_Functions.ttcn 153 KiB
Newer Older
garciay's avatar
garciay committed
/**
 *  @author   ETSI / STF481 / STF507 / STF517 / STF538
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;
    
    // LibItsCommon
    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
        
        /**
garciay's avatar
garciay committed
         * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature
garciay's avatar
garciay committed
         * @param   p_toBeSignedSecuredMessage    The data to be signed
         * @return  The signature value
         */
        function f_signWithEcdsaNistp256WithSha256(
                                                   in octetstring p_toBeSignedSecuredMessage,
                                                   in Oct32 p_privateKey
        ) return octetstring {
            return fx_signWithEcdsaNistp256WithSha256(
                p_toBeSignedSecuredMessage,
        } // End of function f_signWithEcdsaNistp256WithSha256
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_privateKey                  The private key
garciay's avatar
garciay committed
         * @return  The signature value
         */
        function f_signWithEcdsaBrainpoolp256WithSha256(
                                                        in octetstring p_toBeSignedSecuredMessage,
                                                        in Oct32 p_privateKey
        ) return octetstring {
garciay's avatar
garciay committed
            return fx_signWithEcdsaBrainpoolp256WithSha256(
                p_toBeSignedSecuredMessage,
                p_privateKey
            );
            
        } // End of function f_signWithEcdsaBrainpoolp256WithSha256
        
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_privateKey                  The private key
garciay's avatar
garciay committed
         * @return  The signature value
         */
        function f_signWithEcdsaBrainpoolp384WithSha384(
                                                        in octetstring p_toBeSignedSecuredMessage,
                                                        in Oct48 p_privateKey
        ) return octetstring {
garciay's avatar
garciay committed
            return fx_signWithEcdsaBrainpoolp384WithSha384(
                p_toBeSignedSecuredMessage,
                p_privateKey
            );
            
        } // End of function f_signWithEcdsaBrainpoolp384WithSha384
        
        function f_decrypt(
                           in octetstring         p_encryptPrivateKey,
                           in EtsiTs103097Data    p_encrypedSecuredMessage,
                           out EtsiTs103097Data   p_decrypedSecuredMessage
        ) return boolean {
            if (ischosen(p_encrypedSecuredMessage.content.encryptedData)) {
                var PKRecipientInfo v_pKRecipientInfo;
                var RecipientInfo v_recipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0];
                
                // 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 (ischosen(v_pKRecipientInfo.encKey.eciesNistP256)) {
                  var octetstring v_decryptedSecuredMessage;
                  var SymmetricCiphertext v_ciphertext := p_encrypedSecuredMessage.content.encryptedData.ciphertext;
                  v_decryptedSecuredMessage := f_decryptWithEciesNistp256WithSha256(
                                                                                    v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                    p_encryptPrivateKey,
                                                                                    v_pKRecipientInfo.encKey.eciesNistP256.v.uncompressedP256.x,
                                                                                    v_pKRecipientInfo.encKey.eciesNistP256.v.uncompressedP256.y,
                                                                                    v_pKRecipientInfo.encKey.eciesNistP256.c,
                                                                                    v_pKRecipientInfo.encKey.eciesNistP256.t,
                                                                                    v_ciphertext.aes128ccm.nonce
                                                                                    );
                  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 octetstring v_decryptedSecuredMessage;
                  var SymmetricCiphertext v_ciphertext := p_encrypedSecuredMessage.content.encryptedData.ciphertext;
                  v_decryptedSecuredMessage := f_decryptWithEciesBrainpoolp256WithSha256(
                                                                                         v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                         p_encryptPrivateKey,
                                                                                         v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.uncompressedP256.x,
                                                                                         v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.uncompressedP256.y,
                                                                                         v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.c,
                                                                                         v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.t,
                                                                                         v_ciphertext.aes128ccm.nonce
                                                                                    );
                  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_recipientsPublicKeyX           The Recipient's public encryption key X-coordinate
         * @param   p_recipientsPublicKeyY           The Recipient's public encryption key Y-coordinate
         * @param   p_publicEphemeralKeyX            The generated ephemeral key X-coordinate
         * @param   p_publicEphemeralKeyY            The generated ephemeral key Y-coordinate
         * @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_recipientsPublicKeyX,
                                                      in Oct32 p_recipientsPublicKeyY,
                                                      out Oct32 p_publicEphemeralKeyX,
                                                      out Oct32 p_publicEphemeralKeyY,
                                                      out Oct16 p_encrypted_sym_key,
                                                      out Oct16 p_authentication_vector,
                                                      out Oct12 p_nonce
        ) return octetstring {
          return fx_encryptWithEciesNistp256WithSha256(
                                                       p_toBeEncryptedSecuredMessage,
                                                       p_recipientsPublicKeyX,
                                                       p_recipientsPublicKeyY,
                                                       p_publicEphemeralKeyX,
                                                       p_publicEphemeralKeyY,
                                                       p_encrypted_sym_key,
                                                       p_authentication_vector,
                                                       p_nonce
                                                       );
        } // 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_publicEphemeralKeyX            The generated ephemeral key X-coordinate
         * @param   p_publicEphemeralKeyY            The generated ephemeral key Y-coordinate
         * @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_publicEphemeralKeyX, 
                                                      in Oct32 p_publicEphemeralKeyY,
                                                      in Oct16 p_encrypted_sym_key,
                                                      in Oct16 p_authentication_vector,
                                                      in Oct12 p_nonce
        ) return octetstring {
          return fx_decryptWithEciesNistp256WithSha256(
                                                       p_encryptedSecuredMessage,
                                                       p_privateEncKey,
                                                       p_publicEphemeralKeyX, 
                                                       p_publicEphemeralKeyY,
                                                       p_encrypted_sym_key,
                                                       p_authentication_vector,
                                                       p_nonce
                                                       );
        } // 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_recipientsPublicKeyX           The Recipient's public encryption key X-coordinate
         * @param   p_recipientsPublicKeyY           The Recipient's public encryption key Y-coordinate
         * @param   p_publicEphemeralKeyX            The generated ephemeral key X-coordinate
         * @param   p_publicEphemeralKeyY            The generated ephemeral key Y-coordinate
         * @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_recipientsPublicKeyX,
                                                      in Oct32 p_recipientsPublicKeyY,
                                                      out Oct32 p_publicEphemeralKeyX,
                                                      out Oct32 p_publicEphemeralKeyY,
                                                      out Oct16 p_encrypted_sym_key,
                                                      out Oct16 p_authentication_vector,
                                                      out Oct12 p_nonce
        ) return octetstring {
          return fx_encryptWithEciesBrainpoolp256WithSha256(
                                                       p_toBeEncryptedSecuredMessage,
                                                       p_recipientsPublicKeyX,
                                                       p_recipientsPublicKeyY,
                                                       p_publicEphemeralKeyX,
                                                       p_publicEphemeralKeyY,
                                                       p_encrypted_sym_key,
                                                       p_authentication_vector,
                                                       p_nonce
                                                       );
        } // 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_publicEphemeralKeyX            The generated ephemeral key X-coordinate
         * @param   p_publicEphemeralKeyY            The generated ephemeral key Y-coordinate
         * @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_publicEphemeralKeyX, 
                                                      in Oct32 p_publicEphemeralKeyY,
                                                      in Oct16 p_encrypted_sym_key,
                                                      in Oct16 p_authentication_vector,
                                                      in Oct12 p_nonce
        ) return octetstring {
          return fx_decryptWithEciesBrainpoolp256WithSha256(
                                                       p_encryptedSecuredMessage,
                                                       p_privateEncKey,
                                                       p_publicEphemeralKeyX, 
                                                       p_publicEphemeralKeyY,
                                                       p_encrypted_sym_key,
                                                       p_authentication_vector,
                                                       p_nonce
                                                       );
        } // 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_signature                 The signature
         * @param   p_ecdsaNistp256PublicKeyX   The public key (x coordinate)
         * @param   p_ecdsaNistp256PublicKeyY   The public key (y coordinate)
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaNistp256WithSha256(
garciay's avatar
garciay committed
                                                     in octetstring p_toBeVerifiedData,
                                                     in octetstring p_signature,
                                                     in 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(
                p_toBeVerifiedData,
                p_signature,
                p_ecdsaNistp256PublicKeyX,
                p_ecdsaNistp256PublicKeyY);
        } // End of function f_verifyWithEcdsaNistp256WithSha256
garciay's avatar
garciay committed
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @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(
                                                          in octetstring p_toBeVerifiedData,
                                                          in octetstring 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(
                p_toBeVerifiedData,
                p_signature,
                p_ecdsaBrainpoolp256PublicKeyX,
                p_ecdsaBrainpoolp256PublicKeyY);
        } // End of function f_verifyWithEcdsaBrainpoolp256WithSha256
        
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @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(
                                                          in octetstring p_toBeVerifiedData,
                                                          in octetstring 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(
                p_toBeVerifiedData,
                p_signature,
                p_ecdsaBrainpoolp384PublicKeyX,
                p_ecdsaBrainpoolp384PublicKeyY);
        } // End of function f_verifyWithEcdsaBrainpoolp384WithSha384
        
        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @return  true on success, false otherwise
         */
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
garciay's avatar
garciay committed
                                             ) return boolean {
          return fx_generateKeyPair_nistp256(p_privateKey, p_publicKeyX, p_publicKeyY);
        }
        
        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @return  true on success, false otherwise
         */
        function f_generate_key_pair_brainpoolp256(
garciay's avatar
garciay committed
                                                   out Oct32 p_privateKey,
                                                   out Oct32 p_publicKeyX,
                                                   out Oct32 p_publicKeyY
garciay's avatar
garciay committed
                                                  ) return boolean {
          return fx_generateKeyPair_brainpoolp256(p_privateKey, p_publicKeyX, p_publicKeyY);
        }
        
        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @return  true on success, false otherwise
         */
        function f_generate_key_pair_brainpoolp384(
garciay's avatar
garciay committed
                                                   out Oct48 p_privateKey,
                                                   out Oct48 p_publicKeyX,
                                                   out Oct48 p_publicKeyY
garciay's avatar
garciay committed
                                                  ) return boolean {
          return fx_generateKeyPair_brainpoolp384(p_privateKey, p_publicKeyX, p_publicKeyY);
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 {
                
                // Load certificates if required
garciay's avatar
garciay committed
                if (/*Spirent change*/lengthof(p_certificateName)>0 and (valueof(p_certificateName) != cc_taCert_A)) {
                    if (f_readCertificate(valueof(p_certificateName), p_atCertificate) == false){
                        return false;
                    }
                    if (f_readCertificate(oct2str(p_atCertificate.toBeSigned.cracaId), p_aaCertificate) == false) {
                        return false;
                    }
                } else {
                    p_atCertificate := vc_atCertificate;
                    p_aaCertificate := vc_aaCertificate;
                }
                // Store the certificte to build this message
                vc_lastAtCertificateUsed := p_atCertificate;
                
                return true;
            } // End of function f_prepareCertificates
berge's avatar
berge committed
             * @desc  This function build and sign the SecureMessage part covered by the signature process
             * @param p_securedMessage      The signed  SecureMessage part
             * @param p_payloadField       Payloads to be included in the message
berge's avatar
berge committed
             * @param p_mandatoryHeaders    Mandatory headers for the selected profile 
             * @param p_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
                                             out template (value) EtsiTs103097Data p_securedMessage,
                                             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 Ieee1609Dot2Content v_toBeSignedPayload;
                var Oct32 v_privateKey;
garciay's avatar
garciay committed
                                
                // 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)){
garciay's avatar
garciay committed
                if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature)) {
                    v_signature := f_signWithEcdsaNistp256WithSha256(
                        v_secPayload, 
                        v_privateKey 
                    );
                    p_securedMessage.content.signedData.signature_ := m_signature_ecdsaNistP256(
                                                                                                 m_ecdsaP256Signature(
                                                                                                                      m_eccP256CurvePoint_x_only(substr(v_signature, 0, 32)),
                                                                                                                      substr(v_signature, 32, 32)
                                                                                                                      )
                                                                                                 );
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) {
                    v_signature := f_signWithEcdsaBrainpoolp256WithSha256(
                        v_secPayload, 
                        v_privateKey 
                    );
                    p_securedMessage.content.signedData.signature_ := m_signature_ecdsaBrainpoolP256r1(
                                                                                                       m_ecdsaP256Signature(
                                                                                                                            m_eccP256CurvePoint_x_only(substr(v_signature, 0, 32)),
                                                                                                                            substr(v_signature, 32, 32)
                                                                                                                            )
                                                                                                       );
                } // TODO To be continued
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
                                                out template (value) 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;
filatov's avatar
filatov committed
// FIXME(DF)UNUSED
//                var Oct32 v_hash;
                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
                                         out template (value) EtsiTs103097Data p_securedMessage,
                                         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;
                // Load certificates if required
                if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) {
                    return false;
garciay's avatar
garciay committed
                log("v_atCertificate = ", v_atCertificate);
                
                // Fill sta structure with default values, these values will be updated later
                p_securedMessage := m_etsiTs103097Data_signed(
                                                              m_signedData(
                                                                           sha256,
                                                                           p_payloadField,
                                                                           m_signerIdentifier_self,
                                                                           m_signature_ecdsaNistP256(
                                                                                                     m_ecdsaP256Signature(
                                                                                                                          m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                          int2oct(0, 32)
                                                                                                                          )
                                                                                                     )
                                                                           )
                                                              );
                // Prepare mandatory headers
                if (ischosen(p_signerIdentifierType.certificate)) { // Add the AT certificate
garciay's avatar
garciay committed
                    log("*** " & testcasename() & ": TODO ***");
                    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;
                        p_securedMessage.content.signedData.signer := m_signerIdentifier_digest(
                                                                                                f_calculateDigestSha256FromCertificate(v_atCertificate)
                                                                                               );
                    } else if (ischosen(v_atCertificate.issuer.sha384AndDigest)) {
                        p_securedMessage.content.signedData.hashId := sha384;
                        p_securedMessage.content.signedData.signer := m_signerIdentifier_digest(
                                                                                                f_calculateDigestSha384FromCertificate(v_atCertificate)
                                                                                               );
berge's avatar
berge committed
                    }
garciay's avatar
garciay committed
                } else {
                    log("*** " & testcasename() & ": TODO ***");
                    stop;
garciay's avatar
garciay committed
                }
                if (ispresent(v_atCertificate.signature_)) {
                    if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP256r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := m_signature_ecdsaBrainpoolP256r1(
                                                                                                            m_ecdsaP256Signature(
                                                                                                                                 m_eccP256CurvePoint_x_only(int2oct(0, 32)),
                                                                                                                                 int2oct(0, 32)
                                                                                                                                 )
                                                                                                            );
                    } else if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP384r1Signature)) {
                        p_securedMessage.content.signedData.signature_ := m_signature_ecdsaBrainpoolP384r1(
                                                                                                            m_ecdsaP384Signature(
                                                                                                                                 m_eccP384CurvePoint_x_only(int2oct(0, 48)),
                                                                                                                                 int2oct(0, 48)
                                                                                                                                 )
                                                                                                            );
                                        } // else, m_signature_ecdsaNistP256 already chosen by default
                }
                log("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
                                            out template (value) 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(