LibItsPki_Functions.ttcn 425 KB
Newer Older
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      v_hmac_key := f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 12));
      log("f_generate_inner_at_request: v_hmac_key= ", v_hmac_key);

      // Generate tag based on the concatenation of verification keys & encryption keys
      if (f_generate_key_tag(p_public_key_compressed, p_compressed_key_mode, p_public_compressed_enc_key, p_compressed_enc_key_mode, v_encoded_tag) == false) {
        log("f_generate_inner_at_request: Failed to generate Key tag");
        return false;
      }
      log("f_generate_inner_at_request: v_encoded_tag= ", v_encoded_tag);
      v_key_tag := substr(
                          fx_hmac_sha256( // TODO Rename and use a wrapper function
                                         v_hmac_key,
                                         v_encoded_tag
                                         ),
                          0,
                          16); // Leftmost 128 bits of the HMAC-SHA256 tag computed previously
      log("f_generate_inner_at_request: v_key_tag= ", v_key_tag);

      // Build the SharedAtRequest
      p_inner_at_request.sharedAtRequest := valueof(
                                                    m_shared_at_request(
                                                                        p_ea_hashed_id8, // eaId identifies the EA certificate shared with EA entity
                                                                        v_key_tag, // Calculated keyTag
                                                                        valueof(
                                                                                m_certificate_subject_attributes( // FIXME Review subjectPermissions
                                                                                                                 v_appPermissions,
                                                                                                                 p_ec_certificate.toBeSigned.certRequestPermissions,
                                                                                                                 -,//{ none_ := NULL },//p_ec_certificate.toBeSigned.id,
                                                                                                                 p_ec_certificate.toBeSigned.validityPeriod,
                                                                                                                 p_ec_certificate.toBeSigned.region,
                                                                                                                 p_ec_certificate.toBeSigned.assuranceLevel
                                                                                                                  ))) // Desired attributes
                                                    );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Calculate the hash of the SharedAtRequest
      v_hash_shared_at_request := f_hashWithSha256(bit2oct(encvalue(p_inner_at_request.sharedAtRequest)));
      log("f_generate_inner_at_request: v_hash_shared_at_request= ", v_hash_shared_at_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Build the ETsiTs103097Data-SignedExternalPayload
      v_tbs := m_toBeSignedData(
                                m_signedDataPayload_ext(v_hash_shared_at_request), // Payload containing extDataHash
                                m_headerInfo_inner_pki_request( // HeaderInfo
                                                               -,
                                                               (f_getCurrentTime()) * 1000) //us
                               );
      log("f_generate_inner_at_request: v_tbs= ", v_tbs);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Calculate the whole certificate SHA
      v_enc_value := encvalue(p_ec_certificate);
      if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP384) or ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1)) {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        v_ec_hash := f_hashWithSha384(bit2oct(v_enc_value));
        v_ec_hashed_id8 := f_hashedId8FromSha384(v_ec_hash);
      } else {
        v_ec_hash := f_hashWithSha256(bit2oct(v_enc_value));
        v_ec_hashed_id8 := f_hashedId8FromSha256(v_ec_hash);
      }
      log("f_generate_inner_at_request: v_ec_hash= ", v_ec_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Signed ToBeSigned payload using the private key of EC certificate obtained from Enrolment request
      // In case of ITS-S privacy, v_signed_at_signature contained the data to be encrypted
      if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1)) {
        v_hashId := sha384;
        v_tbs_signed := f_signWithEcdsaBrainpoolp384r1WithSha384(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
        v_signature := valueof(
                               m_signature_ecdsaBrainpoolP384r1(
                                                                m_ecdsaP384Signature(
                                                                                     m_eccP384CurvePoint_x_only(
                                                                                                                substr(v_tbs_signed, 0, 48)
                                                                                                                ),
                                                                                     substr(v_tbs_signed, 48, 48)
                                                                                     )
                                                                )
                                                        );
      } else if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP384)) {
        v_hashId := sha384;
        v_tbs_signed := f_signWithEcdsaNistp384WithSha384(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
        v_signature := valueof(
                               m_signature_ecdsaNistP384(
                                                         m_ecdsaP384Signature(
                                                                              m_eccP384CurvePoint_x_only(
                                                                                                        substr(v_tbs_signed, 0, 48)
                                                                                                        ),
                                                                              substr(v_tbs_signed, 48, 48)
                                                                              )
                                                        )
                                                        );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        v_hashId := sha256;
        if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1)) {
          v_tbs_signed := f_signWithEcdsaBrainpoolp256r1WithSha256(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
          v_signature := valueof(
                                 m_signature_ecdsaBrainpoolP256r1(
                                                                  m_ecdsaP256Signature(
                                                                                       m_eccP256CurvePoint_x_only(
                                                                                                                  substr(v_tbs_signed, 0, 32)
                                                                                                                  ),
                                                                                       substr(v_tbs_signed, 32, 32)
                                                                                       )
                                                                  )
                                 );
        } else if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256)) {
          v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
          v_signature := valueof(
                                 m_signature_ecdsaNistP256(
                                                           m_ecdsaP256Signature(
                                                                                m_eccP256CurvePoint_x_only(
                                                                                                           substr(v_tbs_signed, 0, 32)
                                                                                                           ),
                                                                                substr(v_tbs_signed, 32, 32)
                                                                                )
                                                           )
                                 );
        } else {
          // Error
          log("f_generate_inner_at_request: Failed to process signature");
          return false;
        }
      }
      v_signed_at_signature := valueof(
                                       m_etsiTs103097Data_signed(
                                                                 m_signedData(
                                                                              v_hashId,
                                                                              v_tbs,
                                                                              m_signerIdentifier_digest(v_ec_hashed_id8), // Signer is the hasheId8 of the EC certificate obtained from Enrolment request
                                                                              v_signature
                                                                              )
                                                                 )
                                       );
      log("f_generate_inner_at_request: v_signed_at_signature= ", v_signed_at_signature);
      log("f_generate_inner_at_request: p_ea_certificate= ", p_ea_certificate);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (PICS_ITS_S_WITH_PRIVACY) { // Build EtsiTs102097Data-Encrypted structure
        var octetstring v_public_enc_key;
        var integer v_compressed_mode;
        var Oct12 v_nonce;
        var Oct16 v_authentication_vector;
        var Oct16 v_aes_sym_key;
        var Oct16 v_encrypted_sym_key;
        var HashedId8 v_recipientId;
        var octetstring v_public_compressed_ephemeral_key;
        var integer v_public_compressed_ephemeral_mode;
        var octetstring v_enc_signed_ec_signature;
        var EncryptedDataEncryptionKey v_encrypted_data_encryption_key;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        // Use EA certificate for the encryption
        if (p_enc_algo == e_nist_p256) {
          if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0)) {
            v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0;
            v_compressed_mode := 0;
          } else if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1)) {
            v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1;
            v_compressed_mode := 1;
          } else {
            log("f_generate_inner_at_request: Wrong NistP256 encryption variant");
            return false;
          }
          v_enc_signed_ec_signature := f_encryptWithEciesNistp256WithSha256(bit2oct(encvalue(v_signed_at_signature)), v_public_enc_key, v_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce);
          if (v_public_compressed_ephemeral_mode == 0) {
            v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_compressed_ephemeral_key));
          } else {
            v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
          }
          v_encrypted_data_encryption_key := valueof(
                                                     m_encryptedDataEncryptionKey_eciesNistP256(
                                                                                                m_evciesP256EncryptedKey(
                                                                                                                         v_eccP256_curve_point,
                                                                                                                         v_encrypted_sym_key,
                                                                                                                         v_authentication_vector
                                                                                                                         )));
        } else if (p_enc_algo == e_brainpool_p256_r1) {
          if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0)) {
            v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0;
            v_compressed_mode := 0;
          } else if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1)) {
            v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1;
            v_compressed_mode := 1;
          } else {
            log("f_generate_inner_at_request: Wrong BrainpoolP256r1 encryption variant");
            return false;
          }
          v_enc_signed_ec_signature := f_encryptWithEciesBrainpoolp256r1WithSha256(bit2oct(encvalue(v_signed_at_signature)), v_public_enc_key, v_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce);
          if (v_public_compressed_ephemeral_mode == 0) {
            v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_compressed_ephemeral_key));
          } else {
            v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
          }
          v_encrypted_data_encryption_key := valueof(
                                                     m_encryptedDataEncryptionKey_eciesBrainpoolP256r1(
                                                                                                       m_evciesP256EncryptedKey(
                                                                                                                                v_eccP256_curve_point,
                                                                                                                                v_encrypted_sym_key,
                                                                                                                                v_authentication_vector
                                                                                                                                )));
        } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else {
          log("f_generate_inner_at_request: Wrong encryption variant");
          return false;
        }
        log("f_generate_inner_at_request: v_encrypted_data_encryption_key= ", v_encrypted_data_encryption_key);
        v_recipientId := p_ea_hashed_id8; // RecipientId is the HashedId8 of the EA certificate
        log("f_generate_inner_at_request: v_recipientId= ", v_recipientId);
        // Fill Certificate template with the public compressed keys (canonical form)
        p_inner_at_request.ecSignature := valueof(
                                                  m_ec_signature(
                                                                 m_etsiTs103097Data_encrypted(
                                                                                              m_encryptedData(
                                                                                                              {
                                                                                                                m_recipientInfo_certRecipInfo(
                                                                                                                                              m_pKRecipientInfo(
                                                                                                                                                                v_recipientId,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                                                v_encrypted_data_encryption_key                                                                                                                                                            ))
                                                                                                                },
                                                                                                              m_symmetricCiphertext_aes128ccm(
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                              m_aesCcmCiphertext(
                                                                                                                                                                 v_nonce,
                                                                                                                                                                 v_enc_signed_ec_signature
                                                                                                                                                                 )
                                                                                                                                              )
                                                                                                              )
                                                                                              )
                                                                 )
                                                  );
      } else if (p_enc_algo == e_sm2_p256) { // FIXME FSCOM

ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else { // Skip the encryption, alowed to be re-identified by the AA
        p_inner_at_request.ecSignature := valueof(m_ec_signature_ext_payload(v_signed_at_signature));
      }
      // Build the InnerAtRequest, EcSignature field is already set
      if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256)) {
        if (p_compressed_key_mode == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_key_x));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_key_x));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaNistP256(v_eccP256_curve_point));
      } else if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1)) {
        if (p_compressed_key_mode == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_key_x));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_key_x));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaBrainpoolP256r1(v_eccP256_curve_point));
      } else {
        var EccP384CurvePoint v_eccP384_curve_point;
        if (p_compressed_key_mode == 0) {
          v_eccP384_curve_point := valueof(m_eccP384CurvePoint_compressed_y_0(v_public_key_x));
        } else {
          v_eccP384_curve_point := valueof(m_eccP384CurvePoint_compressed_y_1(v_public_key_x));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaBrainpoolP384r1(v_eccP384_curve_point));
      }
      if (PX_INCLUDE_ENCRYPTION_KEYS) {
        var template (value) EccP256CurvePoint v_enc_eccP256_curve_point;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        if (p_compressed_enc_key_mode == 0) {
          v_enc_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_0(v_public_enc_key_x);
        } else {
          v_enc_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_1(v_public_enc_key_x);
        }
        if (p_enc_algo == e_nist_p256) {
          v_public_encryption_key := valueof(m_publicEncryptionKey_eciesNistP256(v_enc_eccP256_curve_point));
        } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else {
          v_public_encryption_key := valueof(m_publicEncryptionKey_eciesBrainpoolP256r1(v_enc_eccP256_curve_point));
        }
        p_inner_at_request.publicKeys := valueof( // The freshly generated public verification & encrypition keys to be used for the requested AT certificate
                                                 m_publicKeys(
                                                              v_public_verification_key,
                                                              m_encryptionKey( // FIXME Encryption keys could be optional
                                                                              -,
                                                                              v_public_encryption_key
                                                                              )
                                                              )
                                                  );
      } else {
        p_inner_at_request.publicKeys := valueof( // The freshly generated public verification keys to be used for the requested AT certificate
                                                 m_publicKeys(
                                                              v_public_verification_key
                                                              )
                                                  );
      }
      p_inner_at_request.hmacKey := v_hmac_key;
      log("f_generate_inner_at_request: p_inner_at_request= ", p_inner_at_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_inner_at_request
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_inner_at_request_with_wrong_parameters(
                                                               in Certificate p_aa_certificate,
                                                               in SignAlgorithm p_enc_algo := PX_EC_ALG_FOR_AT,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                               in Oct8 p_aa_hashed_id8,
                                                               in Certificate p_ea_certificate,
                                                               in octetstring p_salt,
                                                               in Oct8 p_ea_hashed_id8,
                                                               in Certificate p_ec_certificate,
                                                               in octetstring p_ec_private_key,
                                                               in boolean p_alter_hmac := false,
                                                               in boolean p_alter_signer_digest := false,
                                                               in template (omit) Time32 p_start := omit,
                                                               in template (omit) Duration p_duration := omit,
                                                               in template (omit) Time64 p_generation_time := omit,
                                                               out octetstring p_private_key,
                                                               out octetstring p_public_key_compressed,
                                                               out integer p_compressed_key_mode,
                                                               out octetstring p_private_enc_key,
                                                               out octetstring p_public_compressed_enc_key,
                                                               out integer p_compressed_enc_key_mode,
                                                               out InnerAtRequest p_inner_at_request
                                                               ) return boolean {
      // Local variables
      var octetstring v_public_key_x;
      var octetstring v_public_key_y;
      var octetstring v_public_enc_key_x;
      var octetstring v_public_enc_key_y;
      var bitstring v_enc_value;
      var octetstring v_ec_hash;
      var PublicVerificationKey v_public_verification_key;
      var BasePublicEncryptionKey v_public_encryption_key;
      var Oct8 v_ec_hashed_id8;
      var octetstring public_enc_key_x;
      var octetstring public_enc_key_y;
      var Oct32 v_hmac_key;
      var PublicVerificationKey v_verification_tag;
      var PublicEncryptionKey v_encryption_tag;
      var octetstring v_encoded_tag;
      var Oct16 v_key_tag;
      var octetstring v_hash_shared_at_request;
      var template (value) ToBeSignedData v_tbs;
      var octetstring v_tbs_signed;
      var Ieee1609Dot2Data v_signed_at_signature;
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var template (value) EccP256CurvePoint v_enc_eccP256_curve_point;
      var HashAlgorithm v_hashId;
      var Signature v_signature;
      var Time32 v_start;
      var Duration v_duration;
      var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
        valueof(m_appPermissions(c_its_aid_CAM, { bitmapSsp := PX_INNER_AT_CERTFICATE_BITMAP_SSP_CAM })),
        valueof(m_appPermissions(c_its_aid_DENM, { bitmapSsp := PX_INNER_AT_CERTFICATE_BITMAP_SSP_DENM }))
        };

      log("f_generate_inner_at_request_with_wrong_parameters: p_enc_algo=", p_enc_algo);

      // Generate verification keys for the certificate to be requested
      if (f_generate_key_pair(p_private_key, v_public_key_x, v_public_key_y, p_public_key_compressed, p_compressed_key_mode) == false) {
        log("f_generate_inner_at_request_with_wrong_parameters: Failed to generate verification key");
        return false;
      }
      log ("f_generate_inner_at_request_with_wrong_parameters: AT verification private key: ", p_private_key);
      log ("f_generate_inner_at_request_with_wrong_parameters: AT verification public compressed key: ", p_public_key_compressed);
      log ("f_generate_inner_at_request_with_wrong_parameters: AT verification public compressed mode: ", p_compressed_key_mode);
      // Generate encryption keys for the certificate to be requested
      if (PX_INCLUDE_ENCRYPTION_KEYS) {
        if (f_generate_key_pair_for_encryption(p_enc_algo, p_private_enc_key, v_public_enc_key_x, v_public_enc_key_y, p_public_compressed_enc_key, p_compressed_enc_key_mode) == false) {
          log("f_generate_inner_at_request_with_wrong_parameters: Failed to generate encryption key");
          return false;
        } else {
          log ("f_generate_inner_at_request_with_wrong_parameters: AT encryption private key: ", p_private_enc_key);
          log ("f_generate_inner_at_request_with_wrong_parameters: AT encryption public compressed key: ", p_public_compressed_enc_key);
          log ("f_generate_inner_at_request_with_wrong_parameters: AT encryption public compressed mode: ", p_compressed_enc_key_mode);
        }
      } else {
        p_private_enc_key := ''O;
        v_public_enc_key_x := ''O;
        v_public_enc_key_y := ''O;
        p_public_compressed_enc_key := ''O;
        p_compressed_enc_key_mode := -1;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Calculate the whole certificate SHA
      v_enc_value := encvalue(p_ec_certificate);
      if (ischosen(p_ec_certificate.issuer.sha256AndDigest)) {
        v_ec_hash := f_hashWithSha256(bit2oct(v_enc_value));
        v_ec_hashed_id8 := f_hashedId8FromSha256(v_ec_hash);
      } else {
        v_ec_hash := f_hashWithSha384(bit2oct(v_enc_value));
        v_ec_hashed_id8 := f_hashedId8FromSha384(v_ec_hash);
      }
      log("f_generate_inner_at_request_with_wrong_parameters: v_ec_hash= ", v_ec_hash);
      log("f_generate_inner_at_request_with_wrong_parameters: v_ec_hashed_id8= ", v_ec_hashed_id8);
      if (p_alter_signer_digest == true) {
        v_ec_hashed_id8 := int2oct((f_getCurrentTimeUtc() * 1000), 8);
        log("f_generate_inner_at_request_with_wrong_parameters: Altered v_ec_hashed_id8= ", v_ec_hashed_id8);
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Generate 32 octets length secret key
      v_hmac_key := f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 12));
      log("f_generate_inner_at_request_with_wrong_parameters: v_hmac_key= ", v_hmac_key);

      // Generate tag based on the concatenation of verification keys & encryption keys
      if (f_generate_key_tag(p_public_key_compressed, p_compressed_key_mode, p_public_compressed_enc_key, p_compressed_enc_key_mode, v_encoded_tag) == false) {
        log("f_generate_inner_at_request_with_wrong_parameters: Failed to generate Key tag");
        return false;
      }
      log("f_generate_inner_at_request_with_wrong_parameters: v_encoded_tag= ", v_encoded_tag);
      // Generate hmac key
      v_key_tag := substr(
                          fx_hmac_sha256( // TODO Rename and use a wrapper function
                                         v_hmac_key,
                                         v_encoded_tag
                                         ),
                          0,
                          16); // Leftmost 128 bits of the HMAC-SHA256 tag computed previously
      log("f_generate_inner_at_request_with_wrong_parameters: v_key_tag= ", v_key_tag);
      if (p_alter_hmac == true) {
        v_hmac_key[0] := 'aa'O;
        v_hmac_key[1] := 'bb'O;
        log("f_generate_inner_at_request_with_wrong_parameters: Altered key_tag= ", v_hmac_key);
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Build the SharedAtRequest
      if (not(ispresent(p_start))) {
        v_start := p_ec_certificate.toBeSigned.validityPeriod.start_;
      } else {
        v_start := valueof(p_start);
        log("f_generate_inner_at_request_with_wrong_parameters: Altered ValidityPeriod.start= ", v_start);
      }
      if (not(ispresent(p_duration))) {
        v_duration := p_ec_certificate.toBeSigned.validityPeriod.duration;
      } else {
        v_duration := valueof(p_duration);
        log("f_generate_inner_at_request_with_wrong_parameters: Altered ValidityPeriod.duration= ", v_duration);
      }
      p_inner_at_request.sharedAtRequest := valueof(
                                                    m_shared_at_request(
                                                                        p_ea_hashed_id8, // eaId identifies the EA certificate shared with EA entity
                                                                        v_key_tag, // Calculated keyTag
                                                                        valueof(
                                                                                m_certificate_subject_attributes(
                                                                                                                 v_appPermissions,
                                                                                                                 p_ec_certificate.toBeSigned.certRequestPermissions,
                                                                                                                 { none_ := NULL },//p_ec_certificate.toBeSigned.id,
                                                                                                                 m_validityPeriod(v_start, v_duration),
                                                                                                                 p_ec_certificate.toBeSigned.region,
                                                                                                                 p_ec_certificate.toBeSigned.assuranceLevel
                                                                                                                 ))) // Desired attributes
                                                    );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Calculate the hash of the SharedAtRequest
      v_hash_shared_at_request := f_hashWithSha256(bit2oct(encvalue(p_inner_at_request.sharedAtRequest)));
      log("f_generate_inner_at_request_with_wrong_parameters: v_hash_shared_at_request= ", v_hash_shared_at_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Build the ETsiTs103097Data-SignedExternalPayload
      if (ispresent(p_generation_time)) {
        v_tbs := m_toBeSignedData(
                                  m_signedDataPayload_ext(v_hash_shared_at_request), // Payload containing extDataHash
                                  m_headerInfo_inner_pki_request( // HeaderInfo
                                                                 -,
                                                                 valueof(p_generation_time) * 1000) //us
                                  );
        log("f_generate_inner_at_request_with_wrong_parameters: Altered generation time: v_tbs= ", v_tbs);
      } else {
        v_tbs := m_toBeSignedData(
                                  m_signedDataPayload_ext(v_hash_shared_at_request), // Payload containing extDataHash
                                  m_headerInfo_inner_pki_request( // HeaderInfo
                                                                 -,
                                                                 f_getCurrentTime() * 1000) //us
                                  );
        log("f_generate_inner_at_request_with_wrong_parameters: v_tbs= ", v_tbs);
      }
      // Signed ToBeSigned payload using the private key of EC certificate obtained from Enrolment request
      // In case of ITS-S privacy, v_signed_at_signature contained the data to be encrypted
      // TODO Simplify with f_signWithEcdsa
      if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1)) {
        v_hashId := sha384;
        v_tbs_signed := f_signWithEcdsaBrainpoolp384r1WithSha384(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
        v_signature := valueof(
                               m_signature_ecdsaBrainpoolP384r1(
                                                                m_ecdsaP384Signature(
                                                                                     m_eccP384CurvePoint_x_only(
                                                                                                                substr(v_tbs_signed, 0, 48)
                                                                                                                ),
                                                                                     substr(v_tbs_signed, 48, 48)
                                                                                     )
                                                                )
                                                        );
      } else {
        v_hashId := sha256;
        if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1)) {
          v_tbs_signed := f_signWithEcdsaBrainpoolp256r1WithSha256(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
          v_signature := valueof(
                                 m_signature_ecdsaBrainpoolP256r1(
                                                                  m_ecdsaP256Signature(
                                                                                       m_eccP256CurvePoint_x_only(
                                                                                                                  substr(v_tbs_signed, 0, 32)
                                                                                                                  ),
                                                                                       substr(v_tbs_signed, 32, 32)
                                                                                       )
                                                                  )
                                 );
        } else if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256)) {
          v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
          v_signature := valueof(
                                 m_signature_ecdsaNistP256(
                                                           m_ecdsaP256Signature(
                                                                                m_eccP256CurvePoint_x_only(
                                                                                                           substr(v_tbs_signed, 0, 32)
                                                                                                           ),
                                                                                substr(v_tbs_signed, 32, 32)
                                                                                )
                                                           )
                                 );
        } else {
          // Error
          log("f_generate_inner_at_request_with_wrong_parameters: Failed to process signature");
          return false;
        }
      }
      v_signed_at_signature := valueof(
                                       m_etsiTs103097Data_signed(
                                                                 m_signedData(
                                                                              v_hashId,
                                                                              v_tbs,
                                                                              m_signerIdentifier_digest(v_ec_hashed_id8), // Signer is the hasheId8 of the EC certificate obtained from Enrolment request
                                                                              v_signature
                                                                              )
                                                                 )
                                       );
      log("f_generate_inner_at_request_with_wrong_parameters: v_signed_at_signature= ", v_signed_at_signature);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (PICS_ITS_S_WITH_PRIVACY) { // Build EtsiTs102097Data-Encrypted structure
        var octetstring v_public_enc_key;
        var integer v_compressed_mode;
        var Oct12 v_nonce;
        var Oct16 v_authentication_vector;
        var Oct16 v_aes_sym_key;
        var Oct16 v_encrypted_sym_key;
        var HashedId8 v_recipientId;
        var octetstring v_public_compressed_ephemeral_key;
        var integer v_public_compressed_ephemeral_mode;
        var octetstring v_enc_signed_ec_signature;
        var EncryptedDataEncryptionKey v_encrypted_data_encryption_key;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        // Use EA certificate for the encryption
        if (p_enc_algo == e_nist_p256) {
          if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0)) {
            v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0;
            v_compressed_mode := 0;
          } else if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1)) {
            v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1;
            v_compressed_mode := 1;
          } else {
            log("f_generate_inner_at_request_with_wrong_parameters: Wrong NistP256 encryption variant");
            return false;
          }
          v_enc_signed_ec_signature := f_encryptWithEciesNistp256WithSha256(bit2oct(encvalue(v_signed_at_signature)), v_public_enc_key, v_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce);
          if (v_public_compressed_ephemeral_mode == 0) {
            v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_compressed_ephemeral_key));
          } else {
            v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
          }
          v_encrypted_data_encryption_key := valueof(
                                                     m_encryptedDataEncryptionKey_eciesNistP256(
                                                                                                m_evciesP256EncryptedKey(
                                                                                                                         v_eccP256_curve_point,
                                                                                                                         v_encrypted_sym_key,
                                                                                                                         v_authentication_vector
                                                                                                                         )));
        } else if (p_enc_algo == e_brainpool_p256_r1) {
          if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0)) {
            v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0;
            v_compressed_mode := 0;
          } else if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1)) {
            v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1;
            v_compressed_mode := 1;
          } else {
            log("f_generate_inner_at_request_with_wrong_parameters: Wrong BrainpoolP256r1 encryption variant");
            return false;
          }
          v_enc_signed_ec_signature := f_encryptWithEciesBrainpoolp256r1WithSha256(bit2oct(encvalue(v_signed_at_signature)), v_public_enc_key, v_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce);
          if (v_public_compressed_ephemeral_mode == 0) {
            v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_compressed_ephemeral_key));
          } else {
            v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
          }
          v_encrypted_data_encryption_key := valueof(
                                                     m_encryptedDataEncryptionKey_eciesBrainpoolP256r1(
                                                                                                       m_evciesP256EncryptedKey(
                                                                                                                                v_eccP256_curve_point,
                                                                                                                                v_encrypted_sym_key,
                                                                                                                                v_authentication_vector
                                                                                                                                )));
        } else if (p_enc_algo == e_sm2_p256) { // FIXME FSCOM

ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else {
          log("f_generate_inner_at_request_with_wrong_parameters: Wrong encryption variant");
          return false;
        }
        log("f_generate_inner_at_request_with_wrong_parameters: v_encrypted_data_encryption_key= ", v_encrypted_data_encryption_key);
        v_recipientId := p_ea_hashed_id8; // RecipientId is the HashedId8 of the EA certificate
        log("f_generate_inner_at_request_with_wrong_parameters: v_recipientId= ", v_recipientId);
        // Fill Certificate template with the public compressed keys (canonical form)
        p_inner_at_request.ecSignature := valueof(
                                                  m_ec_signature(
                                                                 m_etsiTs103097Data_encrypted(
                                                                                              m_encryptedData(
                                                                                                              {
                                                                                                                m_recipientInfo_certRecipInfo(
                                                                                                                                              m_pKRecipientInfo(
                                                                                                                                                                v_recipientId,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                                                v_encrypted_data_encryption_key                                                                                                                                                            ))
                                                                                                                },
                                                                                                              m_symmetricCiphertext_aes128ccm(
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                              m_aesCcmCiphertext(
                                                                                                                                                                 v_nonce,
                                                                                                                                                                 v_enc_signed_ec_signature
                                                                                                                                                                 )
                                                                                                                                              )
                                                                                                              )
                                                                                              )
                                                                 )
                                                  );
      } else { // Skip the encryption, alowed to be re-identified by the AA
        p_inner_at_request.ecSignature := valueof(m_ec_signature_ext_payload(v_signed_at_signature));
      }
      // Build the InnerAtRequest, EcSignature field is already set
      if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256)) {
        if (p_compressed_key_mode == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_key_x));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_key_x));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaNistP256(v_eccP256_curve_point));
      } else if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1)) {
        if (p_compressed_key_mode == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_key_x));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_key_x));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaBrainpoolP256r1(v_eccP256_curve_point));
      } else {
        var EccP384CurvePoint v_eccP384_curve_point;
        if (p_compressed_key_mode == 0) {
          v_eccP384_curve_point := valueof(m_eccP384CurvePoint_compressed_y_0(v_public_key_x));
        } else {
          v_eccP384_curve_point := valueof(m_eccP384CurvePoint_compressed_y_1(v_public_key_x));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaBrainpoolP384r1(v_eccP384_curve_point));
      }
      if (PX_INCLUDE_ENCRYPTION_KEYS) {
        if (p_compressed_enc_key_mode == 0) {
          v_enc_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_0(v_public_enc_key_x);
        } else {
          v_enc_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_1(v_public_enc_key_x);
        }
        if (p_enc_algo == e_nist_p256) {
          v_public_encryption_key := valueof(m_publicEncryptionKey_eciesNistP256(v_enc_eccP256_curve_point));
        } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else {
          v_public_encryption_key := valueof(m_publicEncryptionKey_eciesBrainpoolP256r1(v_enc_eccP256_curve_point));
        }
        p_inner_at_request.publicKeys := valueof( // The freshly generated public verification & encrypition keys to be used for the requested AT certificate
                                                 m_publicKeys(
                                                              v_public_verification_key,
                                                              m_encryptionKey( // FIXME Encryption keys could be optional
                                                                              -,
                                                                              v_public_encryption_key
                                                                              )
                                                              )
                                                  );
      } else {
        p_inner_at_request.publicKeys := valueof( // The freshly generated public verification keys to be used for the requested AT certificate
                                                 m_publicKeys(
                                                              v_public_verification_key
                                                              )
                                                  );
      }
      p_inner_at_request.hmacKey := v_hmac_key;
      log("f_generate_inner_at_request_with_wrong_parameters: p_inner_at_request= ", p_inner_at_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_inner_at_request_with_wrong_parameters
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_verify_inner_at_request_signed_for_pop(
                                                      in EtsiTs102941Data p_etsi_ts_102941_data,
                                                      in template (omit) EtsiTs103097Certificate p_ec_certificate,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                      out InnerAtRequest p_inner_at_request
                                                      ) return boolean {
      var bitstring v_msg_bit;

      log(">>> f_verify_inner_at_request_signed_for_pop: p_etsi_ts_102941_data=", p_etsi_ts_102941_data);
      log(">>> f_verify_inner_at_request_signed_for_pop: p_ec_certificate=", p_ec_certificate);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // 1. Extract content
      p_inner_at_request := p_etsi_ts_102941_data.content.authorizationRequest;

        // 2. Verify the InnerEcRequestSignedForPop signature
        // TODO
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_verify_inner_at_request_signed_for_pop: ", p_inner_at_request);
      return true;
    } // End of function f_verify_inner_at_request_signed_for_pop
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_inner_at_response(
                                          in octetstring p_authorization_request_hash,
                                          in EtsiTs103097Certificate p_certificate,
                                          out InnerAtResponse p_authorization_response
                                          ) return boolean {
      // Local variables
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Build the Proof of Possession InnerEcResponse
      p_authorization_response := valueof(
                                          m_innerAtResponse_ok(
                                                               substr(p_authorization_request_hash, 0, 16),
                                                               p_certificate
                                                               )
                                          );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_inner_at_response
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group inner_at_xxx

  group bfk {

    function f_generate_ee_ra_cert_request(
                                           out octetstring p_caterpillar_private_key,
                                           out octetstring p_caterpillar_public_key_compressed,
                                           out integer p_caterpillar_compressed_mode,
                                           out octetstring p_caterpillar_enc_private_key,
                                           out octetstring p_caterpillar_enc_public_key_compressed,
                                           out integer p_caterpillar_enc_compressed_mode,
                                           out EeRaCertRequest p_ee_ra_cert_request
                                           ) runs on ItsPkiHttp return boolean {
      var octetstring v_public_key_x;
      var octetstring v_public_key_y;
      var EccP256CurvePoint v_ecc_p256_curve_point;
      var EccP256CurvePoint v_ecc_enc_p256_curve_point;
      var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
        valueof(m_appPermissions(36, { bitmapSsp := PX_INNER_EC_CERTFICATE_BITMAP_SSP_CAM })),
        valueof(m_appPermissions(37, { bitmapSsp := PX_INNER_EC_CERTFICATE_BITMAP_SSP_DENM }))
      };
      var PublicVerificationKey v_public_verification_key;
      var template (value) ToBeSignedCertificate v_tbs;
      log (">>> f_generate_ee_ra_cert_request");
      log("f_generate_ee_ra_cert_request: PX_VE_ALG=", PX_VE_ALG);

      // Generate caterpillar signing keys
      if (PX_BFK_TEST_VECTORS) {
        p_caterpillar_private_key := 'D418760F0CB2DCB856BC3C7217AD3AA36DB6742AE1DB655A3D28DF88CBBF84E1'O;
        p_caterpillar_public_key_compressed := 'EE9CC7FBD9EDECEA41F7C8BD258E8D2E988E75BD069ADDCA1E5A38E534AC6818'O;
        p_caterpillar_compressed_mode := 1;
      } else {
        if (f_generate_key_pair(p_caterpillar_private_key, v_public_key_x, v_public_key_y, p_caterpillar_public_key_compressed, p_caterpillar_compressed_mode) == false) {
          log("f_generate_ee_ra_cert_request: Failed to generate caterpillar keys");
          return false;
        }
      }
      log ("f_generate_ee_ra_cert_request: Caterpillar private key: ", p_caterpillar_private_key);
      log ("f_generate_ee_ra_cert_request: Caterpillar public compressed key: ", p_caterpillar_public_key_compressed);
      log ("f_generate_ee_ra_cert_request: Caterpillar public compressed mode: ", p_caterpillar_compressed_mode);
      if (p_caterpillar_compressed_mode == 0) {
        v_ecc_p256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_caterpillar_public_key_compressed));
      } else {
        v_ecc_p256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_caterpillar_public_key_compressed));
      }

      if (PX_EC_ALG_FOR_EC == e_nist_p256) {
        v_public_verification_key := valueof(
                                             m_publicVerificationKey_ecdsaNistP256(
                                                                                   v_ecc_p256_curve_point
                                                                                   ));
      } else if (PX_EC_ALG_FOR_EC == e_nist_p384) { // FIXME FSCOM
        // v_public_verification_key := valueof(
        //                                      m_publicVerificationKey_ecdsaNistP384(
        //                                                                            v_ecc_p384_curve_point
        //                                                                            ));
      } else if (PX_EC_ALG_FOR_EC == e_brainpool_p256_r1) {
        v_public_verification_key := valueof(
                                             m_publicVerificationKey_ecdsaBrainpoolP256r1(
                                                                                          v_ecc_p256_curve_point
                                                                                          ));
      } else if (PX_EC_ALG_FOR_EC == e_brainpool_p384_r1) { // FIXME FSCOM
        // v_public_verification_key := valueof(
        //                                      m_publicVerificationKey_ecdsaBrainpoolP384r1(
        //                                                                                   v_ecc_p384_curve_point
        //                                                                                   ));
      } else if (PX_EC_ALG_FOR_EC == e_sm2_p256) { // FIXME FSCOM
      } else {
        log("f_generate_ee_ra_cert_request: Wrong encryption algorithm, check PX_EC_ALG_FOR_xx");
        return false;
      }

      v_tbs := m_bfk_to_be_signed_certificate(
                                              { none_ := NULL },
                                              v_appPermissions,
                                              m_verificationKeyIndicator_verificationKey(
                                                                                        v_public_verification_key
                                                                                        ),
                                              m_validityPeriod(
                                                              f_getCurrentTime() / 1000,
                                                              m_duration_in_hours(PX_GENERATED_CERTIFICATE_DURATION - 1)
                                                              ),
                                              m_geographicRegion_identifiedRegion(
                                                                                  {
                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_2),
                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_2)
                                                                                    }
                                                                                  ),
                                              PX_GENERATED_CERTIFICATE_SUBJECT_ASSURENCE_LEVEL
                                              );
Yann Garcia's avatar
Yann Garcia committed
      if (PX_BFK_TEST_VECTORS) {
        p_caterpillar_enc_private_key := '4840ed221502d9ab6786bf68fba9f210373bf2215a6709ea59ce8cfd8e09b24d'O;
        p_caterpillar_enc_public_key_compressed := '9a2375d5631ca55a522d03fca8daa95a7978620d6798502b4fe4a006de2f7c19'O;
        p_caterpillar_enc_compressed_mode := 0;
      } else {
        if (f_generate_key_pair_for_encryption(e_nist_p256, p_caterpillar_enc_private_key, v_public_key_x, v_public_key_y, p_caterpillar_enc_public_key_compressed, p_caterpillar_enc_compressed_mode) == false) {
          log("f_generate_ee_ra_cert_request: Failed to generate caterpillar keys");
          return false;
        }
Yann Garcia's avatar
Yann Garcia committed
      log ("f_generate_ee_ra_cert_request: Caterpillar encryption private key: ", p_caterpillar_enc_private_key);
      log ("f_generate_ee_ra_cert_request: Caterpillar encryption public compressed key: ", p_caterpillar_enc_public_key_compressed);
      log ("f_generate_ee_ra_cert_request: Caterpillar encryption public compressed mode: ", p_caterpillar_enc_compressed_mode);
      if (p_caterpillar_enc_compressed_mode == 0) {
        v_ecc_enc_p256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_caterpillar_enc_public_key_compressed));
      } else {
        v_ecc_enc_p256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_caterpillar_enc_public_key_compressed));
      }
      if (PICS_SECPKI_ORIGINAL_BFK_KEY) {
        var Oct16 v_kS;
        f_generate_bkf_signing_key_expension(v_kS);
        log ("f_generate_ee_ra_cert_request: v_kS: ", v_kS);
        var Oct16 v_kE;
        f_generate_bkf_enc_key_expension(v_kE);
        log ("f_generate_ee_ra_cert_request: v_kE: ", v_kE);
        // For Debug purposes, to be removed later
        // log ("f_generate_ee_ra_cert_request: v_signing_expansion_key: ", v_signing_expansion_key);
        // var octetstring v_expanded_caterpillar_private_key;
        // f_bfk_expend_private_key(v_signing_expansion_key, p_caterpillar_private_key, v_expanded_caterpillar_private_key);
        // log ("f_generate_ee_ra_cert_request: v_expanded_caterpillar_private_key: ", v_expanded_caterpillar_private_key);
        // var octetstring v_caterpillar_expended_public_key_compressed;
        // var integer v_caterpillar_expended_compressed_mode;
        // f_bfk_expend_public_key(v_signing_expansion_key, p_caterpillar_public_key_compressed, p_caterpillar_compressed_mode, v_caterpillar_expended_public_key_compressed, v_caterpillar_expended_compressed_mode);
        // log ("f_generate_ee_ra_cert_request: v_caterpillar_expended_public_key_compressed: ", v_caterpillar_expended_public_key_compressed);
        // log ("f_generate_ee_ra_cert_request: v_caterpillar_expended_compressed_mode: ", v_caterpillar_expended_compressed_mode);
        // //v_expanded_caterpillar_private_key[5] := 'FF'O;
        // var boolean v_verif := f_bfk_verify_expended_keys(v_expanded_caterpillar_private_key, v_caterpillar_expended_public_key_compressed, v_caterpillar_expended_compressed_mode);
        // stop;
                                        m_ee_ra_cert_request( 
                                                             f_getCurrentTime() / 1000, 
                                                             explicit, 
                                                             v_tbs,
                                                             m_additional_params_original(
                                                                                          m_butterfly_params_original(
                                                                                                                      m_butterfly_expansion_aes128(
                                                                                                                                                   v_kS
                                                                                                                                                  ),
                                                                                                                      m_encryptionKey(
                                                                                                                                      -,
                                                                                                                                      m_publicEncryptionKey_eciesNistP256(
                                                                                                                                                                          v_ecc_enc_p256_curve_point
                                                                                                                                      )),
                                                                                                                      m_butterfly_expansion_aes128(
                                                                                                                                                   v_kE
                                        )))));
      } else if (PICS_SECPKI_UNIFIED_BFK_KEY) {
        var octetstring v_kS;
        f_generate_bkf_signing_key_expension(v_kS);
        log ("f_generate_ee_ra_cert_request: v_kS: ", v_kS);
                                        m_ee_ra_cert_request( 
                                                             f_getCurrentTime(), 
                                                             explicit, 
                                                             v_tbs,
                                                             m_additional_params_unified(
                                                                                         m_butterfly_expansion_aes128(
                                                                                                                      v_kS
                                        ))));
      } else {
        log("f_generate_ee_ra_cert_request: Wrong configuration, at least one (PICS_SECPKI_ORIGINAL_BFK_KEY, PICS_SECPKI_UNIFIED_BFK_KEY) of shall be set to true");
        return false;
      }
      log("f_generate_ee_ra_cert_request: p_ee_ra_cert_request: ", p_ee_ra_cert_request);

      return true;
    } // End of function f_generate_ee_ra_cert_request

    function f_generate_bfk_batch(
                                   in EeRaCertRequest p_ee_ra_cert_request,
                                   out BfkCertificates p_bfk_batch_certificates, 
                                   out integer p_bfk_batch_counter
                                   ) return boolean {
      log(">>> f_generate_bfk_batch: p_ee_ra_cert_request: ", p_ee_ra_cert_request);

      p_bfk_batch_certificates := {};
      p_bfk_batch_counter := 0;

      if (ischosen(p_ee_ra_cert_request.additionalParams.original)) {
        // Extract caterpillar public key
        var octetstring v_caterpillar_public_key_compressed;
        var integer v_caterpillar_compressed_mode;
        if (ischosen(p_ee_ra_cert_request.tbsCert.verifyKeyIndicator.verificationKey.ecdsaNistP256)) {
          if (ischosen(p_ee_ra_cert_request.tbsCert.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
            v_caterpillar_public_key_compressed := p_ee_ra_cert_request.tbsCert.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0;
            v_caterpillar_compressed_mode := 0;
          } else if (ischosen(p_ee_ra_cert_request.tbsCert.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1)) {
            v_caterpillar_public_key_compressed := p_ee_ra_cert_request.tbsCert.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1;
            v_caterpillar_compressed_mode := 1;
          } else {  
            log("f_generate_bfk_batch: Non canonicalized tbsCert");
            return false;
          }
        }
        // Extract encryprion expension key
        var octetstring v_caterpillar_enc_public_key_compressed;
        var integer v_caterpillar_enc_compressed_mode;
        if (ischosen(p_ee_ra_cert_request.additionalParams.original.encryptionKey.publicKey.eciesNistP256.compressed_y_0)) {
          v_caterpillar_enc_public_key_compressed := p_ee_ra_cert_request.additionalParams.original.encryptionKey.publicKey.eciesNistP256.compressed_y_0;
          v_caterpillar_enc_compressed_mode := 0;
        } else if (ischosen(p_ee_ra_cert_request.additionalParams.original.encryptionKey.publicKey.eciesNistP256.compressed_y_1)) {
          v_caterpillar_enc_public_key_compressed := p_ee_ra_cert_request.additionalParams.original.encryptionKey.publicKey.eciesNistP256.compressed_y_1;
          v_caterpillar_enc_compressed_mode := 1;
        } else {  
          log("f_generate_bfk_batch: Non canonicalized tbsCert");
          return false;
        }
        { // Loop
          // Create an expension key for both signing and encrytion
          var octetstring v_signing_expension_key;
          f_generate_bkf_signing_key_expension(v_signing_expension_key);
          log("f_generate_bfk_batch: v_signing_expension_key: ", v_signing_expension_key);
          var octetstring v_enc_expension_key;
          f_generate_bkf_enc_key_expension(v_enc_expension_key);
          log("f_generate_bfk_batch: v_enc_expension_key: ", v_enc_expension_key);

          var octetstring v_caterpillar_expended_public_key_compressed;
          var integer v_caterpillar_expended_compressed_mode;
          f_bfk_expend_public_key(
                                  v_signing_expension_key,
                                  v_caterpillar_public_key_compressed, v_caterpillar_compressed_mode, 
                                  v_caterpillar_expended_public_key_compressed, v_caterpillar_expended_compressed_mode
                                  );
          log ("f_generate_bfk_batch: v_caterpillar_expended_public_key_compressed: ", v_caterpillar_expended_public_key_compressed);
          log ("f_generate_bfk_batch: v_caterpillar_expended_compressed_mode: ", v_caterpillar_expended_compressed_mode);
          var octetstring v_caterpillar_expended_enc_public_key_compressed;
          var integer v_caterpillar_expended_enc_compressed_mode;
          f_bfk_expend_public_key(
                                  v_enc_expension_key,
                                  v_caterpillar_enc_public_key_compressed, v_caterpillar_enc_compressed_mode, 
                                  v_caterpillar_expended_enc_public_key_compressed, v_caterpillar_expended_enc_compressed_mode
                                  );
          log ("f_generate_bfk_batch: v_caterpillar_enc_public_key_compressed: ", v_caterpillar_enc_public_key_compressed);
          log ("f_generate_bfk_batch: v_caterpillar_expended_enc_compressed_mode: ", v_caterpillar_expended_enc_compressed_mode);

          // The new verirfication key are the new coccon key - ETSI TS 102 941 V2.1.1 Clause 6.2.3.5.4 Butterfly certificate request
          /*var EcdsaNistP256 v_signing_key;
          if (v_caterpillar_expended_compressed_mode == 0) {
            v_signing_key.compressed_y_0 := v_caterpillar_expended_public_key_compressed;
          } else {
            v_signing_key.compressed_y_1 := v_caterpillar_expended_public_key_compressed;
          }
          // The encryption key are the new enc derived key
          var EciesNistP256 v_enc_key;
          if (v_caterpillar_expended_enc_compressed_mode == 0) {
            v_enc_key.compressed_y_0 := v_caterpillar_enc_public_key_compressed;
          } else {
            v_enc_key.compressed_y_1 := v_caterpillar_enc_public_key_compressed;
          }
          // Generate the certificate based on p_ee_ra_cert_request.content.butterflyAuthorizationRequest.tbsCert and enxpended keys
          // TODO Load AA certificate
          var EtsiTs103097Certificate v_cert := m_etsiTs103097Certificate(
                                                                          in template (value) IssuerIdentifier p_issuer,
                                                                          m_toBeSignedCertificate_at(
                                                                                                     p_ee_ra_cert_request.tbsCert.appPermissions,
                                                                                                     m_verificationKeyIndicator_verificationKey(
                                                                                                                                                m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                                                                      v_signing_key
                                                                                                                          )),
                                                                                                     p_ee_ra_cert_request.tbsCert.region,
                                                                                                     p_ee_ra_cert_request.tbsCert.assuranceLevel
                                                                                                     
                                                                                                     m_encryptionKey(
                                                                                                                     -,
                                                                                                                     m_publicEncryptionKey_eciesNistP256(
                                                                                                                                                         v_enc_key
                                                                                                     ))),
                                                                          -,
                                                                          p_ee_ra_cert_request.type_
                                                                          );
          log("f_generate_bfk_batch: AT toBeSigned:", v_cert.toBeSigned);*/
          // Signed certificate with AA certicate
          // Encode certfificate
          // Compute whole-hash SHA256
          // Extract HashedId8
          p_bfk_batch_certificates := {};
          p_bfk_batch_counter := p_bfk_batch_counter + 1;
        } // End of 'for' statement
      } else {
        log("f_generate_bfk_batch: Not implemented yet");
        return false;
      }

      log("<<< f_generate_bfk_batch: p_bfk_batch_certificates: ", p_bfk_batch_certificates);
      log("<<< f_generate_bfk_batch: p_bfk_batch_counter: ", p_bfk_batch_counter);