/*
 * @author
 *     
 * @version
 *     1.0
 * @desc
 *     
 * @remark
 *     
 * @see
 *     
 */ 
module TestCodec_Certificates {
  
  // LibCommon
  import from LibCommon_BasicTypesAndValues all;
  import from LibCommon_DataStrings 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;
  
  // LibItsSecurity
  import from LibItsSecurity_EncdecDeclarations all;
  import from LibItsSecurity_TypesAndValues all;
  import from LibItsSecurity_Templates all;
  import from LibItsSecurity_Functions all;
  import from LibItsSecurity_Pixits all;
  
  // TestCodec
  import from TestCodec_TestAndSystem all;
  
  /**
   * @desc Root certificate / NistP256
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets
   */
  testcase tc_root_certificate_sha256_1() runs on TCType system TCType {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var EtsiTs103097Certificate v_cert_dec; 
    var charstring v_certId := "STF538 Root Certificate";
    var HashAlgorithm v_self := sha256; // ETSI TS 103 097 V1.3.1 Clause 7.2.3 Root CA certificates Bullet 1
    var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
      valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), 
      valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) 
    };
    var SequenceOfPsidSspRange v_certIssuePermissions := { // ETSI TS 103 097 V1.3.1 Clause 7.2.3 Root CA certificates Bullet 3
      valueof(m_psidSspRange(1)) 
    };
    var Oct32 v_private_key := int2oct(0, 32);
    var Oct32 v_publicKeyX := int2oct(0, 32);
    var Oct32 v_publicKeyY := int2oct(0, 32);
    var HashedId8 v_sha256AndDigest;
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_encMsg := ''B;
      
    // Generate Private/Public keys
    f_generate_key_pair_nistp256(v_private_key, v_publicKeyX, v_publicKeyY);
    // Fill Certificate template with the public key      
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_self(v_self),
                                      m_toBeSignedCertificate_ca(
                                                              { name := v_certId },
                                                              v_appPermissions,
                                                              { 
                                                                m_psidGroupPermissions(
                                                                                       m_subjectPermissions_explicit(
                                                                                                                     v_certIssuePermissions
                                                                                                                     ))
                                                                },
                                                              m_verificationKeyIndicator_verificationKey( 
                                                                                                         m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                               m_eccP256CurvePoint_uncompressed(
                                                                                                                                                                                v_publicKeyX,
                                                                                                                                                                                v_publicKeyY
                                                                                                                                                                                ))),
                                                              m_validityPeriod(
                                                                               17469212,
                                                                               m_duration_years(10)
                                                                               )
                                                              )
                                      );
    // Encode it ==> Get octetstring
    log("Encode template ", valueof(v_cert.toBeSigned));
  v_encMsg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (NIST p-256)
  v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_encMsg), v_private_key);
    log("v_sig = ", v_sig);
  v_cert.signature_ := m_signature_ecdsaNistP256(
                                                 m_ecdsaP256Signature(
                                                                      m_eccP256CurvePoint_x_only(
                                                                                                 substr(v_sig, 0, 32)
                                                                                                 ),
                                                                      substr(v_sig, 32, 32)
                                                                      )
                                                 );
    // Final certificate
  v_encMsg := encvalue(v_cert);
    setverdict(pass, "Encoding passed.");
    // Decode and check signature
    if (decvalue(v_encMsg, v_cert_dec) != 0) {
      setverdict(fail);
      stop;
    }
  v_encMsg := encvalue(v_cert_dec.toBeSigned);
    if (f_verifyWithEcdsaNistp256WithSha256(
                                            bit2oct(v_encMsg), 
                                            v_cert_dec.signature_.ecdsaNistP256Signature.rSig.x_only & v_cert_dec.signature_.ecdsaNistP256Signature.sSig,
                                            v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.uncompressedP256.x,
                                            v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.uncompressedP256.y
                                            ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
      }
    
  } // End of testcase tc_root_certificate_sha256_1
   
  /**
   * @desc Root certificate / BrainpoolP256
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets
   */
  testcase tc_root_certificate_sha256_2() runs on TCType system TCType {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var EtsiTs103097Certificate v_cert_dec; 
    var charstring v_certId := "STF538 Root Certificate";
    var HashAlgorithm v_self := sha256; // ETSI TS 103 097 V1.3.1 Clause 7.2.3 Root CA certificates Bullet 1
    var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
      valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), 
      valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) 
    };
    var SequenceOfPsidSspRange v_certIssuePermissions := { // ETSI TS 103 097 V1.3.1 Clause 7.2.3 Root CA certificates Bullet 3
      valueof(m_psidSspRange(1)) 
    };
    var Oct32 v_private_key := int2oct(0, 32);
    var Oct32 v_publicKeyX := int2oct(0, 32);
    var Oct32 v_publicKeyY := int2oct(0, 32);
    var HashedId8 v_sha256AndDigest;
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_encMsg := ''B;
      
    // Generate Private/Public keys
    f_generate_key_pair_brainpoolp256(v_private_key, v_publicKeyX, v_publicKeyY);
    // Fill Certificate template with the public key      
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_self(v_self),
                                      m_toBeSignedCertificate_ca(
                                                              { name := v_certId },
                                                              v_appPermissions,
                                                              { 
                                                                m_psidGroupPermissions(
                                                                                       m_subjectPermissions_explicit(
                                                                                                                     v_certIssuePermissions
                                                                                                                     ))
                                                                },
                                                              m_verificationKeyIndicator_verificationKey( 
                                                                                                         m_publicVerificationKey_ecdsaBrainpoolP256(
                                                                                                                                                    m_eccP256CurvePoint_uncompressed(
                                                                                                                                                                                     v_publicKeyX,
                                                                                                                                                                                     v_publicKeyY
                                                                                                                                                                                     ))),
                                                              m_validityPeriod(
                                                                               17469212,
                                                                               m_duration_years(10)
                                                                               )
                                                                 )
                                      );
    // Encode it ==> Get octetstring
    log("Encode template ", valueof(v_cert.toBeSigned));
  v_encMsg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (NIST p-256)
  v_sig := f_signWithEcdsaBrainpoolp256WithSha256(bit2oct(v_encMsg), v_private_key);
  v_cert.signature_ := m_signature_ecdsaBrainpoolP256r1(
                                                        m_ecdsaP256Signature(
                                                                             m_eccP256CurvePoint_x_only(
                                                                                                        substr(v_sig, 0, 32)
                                                                                                        ),
                                                                             substr(v_sig, 32, 32)
                                                                             )
                                                        );
    // Final certificate
  v_encMsg := encvalue(v_cert);
    setverdict(pass, "Encoding passed.");
    // Decode and check signature
    if (decvalue(v_encMsg, v_cert_dec) != 0) {
      setverdict(fail);
      stop;
    }
    v_encMsg := encvalue(v_cert_dec.toBeSigned);
    if (f_verifyWithEcdsaBrainpoolp256WithSha256(
                                                 bit2oct(v_encMsg), 
                                                 v_cert_dec.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only & v_cert_dec.signature_.ecdsaBrainpoolP256r1Signature.sSig,
                                                 v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.uncompressedP256.x,
                                                 v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.uncompressedP256.y
                                                 ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
      }
    
  } // End of testcase tc_root_certificate_sha256_2
   
  /**
   * @desc Root certificate / BrainpoolP284
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets
   */
  testcase tc_root_certificate_sha384_1() runs on TCType system TCType {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var EtsiTs103097Certificate v_cert_dec; 
    var charstring v_certId := "STF538 Root Certificate";
    var HashAlgorithm v_self := sha384; // ETSI TS 103 097 V1.3.1 Clause 7.2.3 Root CA certificates Bullet 1
    var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
      valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), 
      valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) 
    };
    var SequenceOfPsidSspRange v_certIssuePermissions := { // ETSI TS 103 097 V1.3.1 Clause 7.2.3 Root CA certificates Bullet 3
      valueof(m_psidSspRange(1)) 
    };
    var Oct48 v_private_key := int2oct(0, 48);
    var Oct48 v_publicKeyX := int2oct(0, 48);
    var Oct48 v_publicKeyY := int2oct(0, 48);
    var HashedId8 v_sha256AndDigest;
    var Oct48 v_sig := int2oct(0, 48);
    var bitstring v_encMsg := ''B;
      
    // Generate Private/Public keys
    f_generate_key_pair_brainpoolp384(v_private_key, v_publicKeyX, v_publicKeyY);
    // Fill Certificate template with the public key      
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_self(v_self),
                                      m_toBeSignedCertificate_ca(
                                                                  { name := v_certId },
                                                                  v_appPermissions,
                                                                  { 
                                                                    m_psidGroupPermissions(
                                                                                           m_subjectPermissions_explicit(
                                                                                                                         v_certIssuePermissions
                                                                                                                         ))
                                                                    },
                                                                  m_verificationKeyIndicator_verificationKey(
                                                                                                             m_publicVerificationKey_ecdsaBrainpoolP384(
                                                                                                                                                        m_eccP384CurvePoint_uncompressed(
                                                                                                                                                                                         v_publicKeyX,
                                                                                                                                                                                         v_publicKeyY
                                                                                                                                                                                        ))),
                                                                  m_validityPeriod(
                                                                                   17469212,
                                                                                   m_duration_years(10)
                                                                                   )
                                                                 )
                                      );
  // Encode it ==> Get octetstring
    log("Encode template ", valueof(v_cert.toBeSigned));
  v_encMsg := encvalue(v_cert.toBeSigned);
    // Sign the certificate
  v_sig := f_signWithEcdsaBrainpoolp384WithSha384(bit2oct(v_encMsg), v_private_key);
  v_cert.signature_ := m_signature_ecdsaBrainpoolP384r1(
                                                        m_ecdsaP384Signature(
                                                                             m_eccP384CurvePoint_x_only(
                                                                                                        substr(v_sig, 0, 48)
                                                                                                        ),
                                                                             substr(v_sig, 48, 48)
                                                                             )
                                                        );
    // Final certificate
  v_encMsg := encvalue(v_cert);
    setverdict(pass, "Encoding passed.");
    // Decode and check signature
    if (decvalue(v_encMsg, v_cert_dec) != 0) {
      setverdict(fail);
      stop;
    }
    v_encMsg := encvalue(v_cert_dec.toBeSigned);
    if (f_verifyWithEcdsaBrainpoolp384WithSha384(
                                                 bit2oct(v_encMsg), 
                                                 v_cert_dec.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only & v_cert_dec.signature_.ecdsaNistP256Signature.sSig,
                                                 v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.uncompressedP384.x,
                                                 v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.uncompressedP384.y
                                                 ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
    }

  } // End of testcase tc_root_certificate_sha384_1
   
  /**
   * @desc EA certificate / NistP256
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets
   */
  testcase tc_ea_certificate_sha256_1() runs on TCType system TCType {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var EtsiTs103097Certificate v_cert_dec; 
    var charstring v_certId := "STF538 EA Certificate"; // ETSI TS 103 097 V1.3.1 Clause 7.2.2 Enrolment credential #5
    var HashedId8 v_sha256AndDigest := f_HashedId8FromSha256(f_hashWithSha256('616263'O)); // ETSI TS 103 097 V1.3.1 Clause 7.2.2 Enrolment credential #2
    var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
      valueof(m_appPermissions(36, { bitmapSsp := 'FF0001'O })), 
      valueof(m_appPermissions(37, { bitmapSsp := 'FF0001'O })) 
    };
    var Oct32 v_private_key := int2oct(0, 32);
    var Oct32 v_publicKeyX := int2oct(0, 32);
    var Oct32 v_publicKeyY := int2oct(0, 32);
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_encMsg := ''B;
      
    // Generate Private/Public keys
    f_generate_key_pair_nistp256(v_private_key, v_publicKeyX, v_publicKeyY);
    // Fill Certificate template with the public key      
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_sha256AndDigest(v_sha256AndDigest),
                                      m_toBeSignedCertificate_ea(
                                                                 { name := v_certId },
                                                                 v_appPermissions,
                                                                 m_verificationKeyIndicator_verificationKey(
                                                                                                            m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                                  m_eccP256CurvePoint_uncompressed(
                                                                                                                                                                                   v_publicKeyX,
                                                                                                                                                                                   v_publicKeyY
                                                                                                                                                                                   ))),
                                                                 m_validityPeriod(
                                                                                  17469212,
                                                                                  m_duration_years(10)
                                                                                  ),
                                                                 m_geographicRegion_identifiedRegion(
                                                                                                     {
                                                                                                       m_identifiedRegion_country_only(12), 
                                                                                                       m_identifiedRegion_country_only(34)
                                                                                                     }
                                                                                                     )
                                                                 )
                                      );
    // Encode it ==> Get octetstring
    log("Encode template ", valueof(v_cert));
  v_encMsg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (NIST p-256)
  v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_encMsg), v_private_key);
  v_cert.signature_ := m_signature_ecdsaNistP256(
                                                 m_ecdsaP256Signature(
                                                                      m_eccP256CurvePoint_x_only(
                                                                                                 substr(v_sig, 0, 32)
                                                                                                 ),
                                                                      substr(v_sig, 32, 32)
                                                                      )
                                                 );
    // Final certificate
  v_encMsg := encvalue(v_cert);
      
    setverdict(pass, "Encoding passed.");
    // Decode and check signature
    if (decvalue(v_encMsg, v_cert_dec) != 0) {
      setverdict(fail);
      stop;
    }
    v_encMsg := encvalue(v_cert_dec.toBeSigned);
    if (f_verifyWithEcdsaNistp256WithSha256(
                                            bit2oct(v_encMsg), 
                                            v_cert_dec.signature_.ecdsaNistP256Signature.rSig.x_only & v_cert_dec.signature_.ecdsaNistP256Signature.sSig,
                                            v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.uncompressedP256.x,
                                            v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.uncompressedP256.y
                                           ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
    }

  } // End of testcase tc_ea_certificate_sha256_1
   
  /**
   * @desc Authorisation Ticket certificate
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets
   */
  testcase tc_at_certificate_sha256_1() runs on TCType system TCType {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var EtsiTs103097Certificate v_cert_dec; 
    var HashedId8 v_sha256AndDigest := f_HashedId8FromSha256(f_hashWithSha256('616263'O)); // ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets #2
    var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
      valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), 
      valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) 
    };
    var Oct32 v_private_key := int2oct(0, 32);
    var Oct32 v_publicKeyX := int2oct(0, 32);
    var Oct32 v_publicKeyY := int2oct(0, 32);
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_encMsg := ''B;

    if (f_generate_key_pair_nistp256(v_private_key, v_publicKeyX, v_publicKeyY) == false) {
      setverdict(fail);
      stop;
    }

  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_sha256AndDigest(v_sha256AndDigest),
                                      m_toBeSignedCertificate_at(
                                                                 v_appPermissions,
                                                                 m_verificationKeyIndicator_verificationKey(
                                                                                                            m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                                  m_eccP256CurvePoint_uncompressed(
                                                                                                                                                                                   v_publicKeyX,
                                                                                                                                                                                   v_publicKeyY
                                                                                                                                                                                   ))),
                                                                 m_validityPeriod(
                                                                                  17469212,
                                                                                  m_duration_years(10)
                                                                                  ),
                                                                 m_geographicRegion_identifiedRegion(
                                                                                                     {
                                                                                                       m_identifiedRegion_country_only(12), 
                                                                                                       m_identifiedRegion_country_only(34)
                                                                                                       }
                                                                                                     )
                                                                )
                                     );
    // Encode it ==> Get octetstring
    log("Encode template ", valueof(v_cert.toBeSigned));
  v_encMsg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (NIST p-256)
  v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_encMsg), v_private_key);
    log("v_sig = ", v_sig);
  v_cert.signature_ := m_signature_ecdsaNistP256(
                                                 m_ecdsaP256Signature(
                                                                      m_eccP256CurvePoint_x_only(
                                                                                                 substr(v_sig, 0, 32)
                                                                                                 ),
                                                                      substr(v_sig, 32, 32)
                                                                     )
                                                );
    // Final certificate
    v_encMsg := TestEtsiTs103097Certificate(v_cert, false);
    // Decode and check signature
    if (decvalue(v_encMsg, v_cert_dec) != 0) {
      setverdict(fail);
      stop;
    }
    v_encMsg := encvalue(v_cert_dec.toBeSigned);
    if (f_verifyWithEcdsaNistp256WithSha256(
                                            bit2oct(v_encMsg), 
                                            v_cert_dec.signature_.ecdsaNistP256Signature.rSig.x_only & v_cert_dec.signature_.ecdsaNistP256Signature.sSig,
                                            v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.uncompressedP256.x,
                                            v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.uncompressedP256.y
                                           ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
    }

  } // End of testcase tc_at_certificate_sha256_1
   
  /**
   * @desc Authorisation Ticket certificate
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets
   */
  testcase tc_at_certificate_sha256_2() runs on TCType system TCType {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var EtsiTs103097Certificate v_cert_dec; 
    var HashedId8 v_sha256AndDigest := f_HashedId8FromSha256(f_hashWithSha256('616263'O)); // ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets #2
    var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
      valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), 
      valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) 
    };
    var SequenceOfPsidSspRange v_certRequestPermissions := { 
      valueof(m_psidSspRange(2)) 
    };
    var Oct32 v_private_key := int2oct(0, 32);
    var Oct32 v_publicKeyX := int2oct(0, 32);
    var Oct32 v_publicKeyY := int2oct(0, 32);
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_encMsg := ''B;

    if (f_generate_key_pair_brainpoolp256(v_private_key, v_publicKeyX, v_publicKeyY) == false) {
      setverdict(fail);
      stop;
    }

  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_sha256AndDigest(v_sha256AndDigest),
                                      m_toBeSignedCertificate_at(
                                                                 v_appPermissions,
                                                                 m_verificationKeyIndicator_verificationKey(
                                                                                                            m_publicVerificationKey_ecdsaBrainpoolP256(
                                                                                                                                                       m_eccP256CurvePoint_uncompressed(
                                                                                                                                                                                        v_publicKeyX,
                                                                                                                                                                                        v_publicKeyY
                                                                                                                                                                                        ))),
                                                                 m_validityPeriod(
                                                                                  17469212,
                                                                                  m_duration_years(10)
                                                                                  )
                                                                )
                                     );
    // Encode it ==> Get octetstring
    log("Encode template ", valueof(v_cert.toBeSigned));
  v_encMsg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (BP p-256)
  v_sig := f_signWithEcdsaBrainpoolp256WithSha256(bit2oct(v_encMsg), v_private_key);

  v_cert.signature_ := m_signature_ecdsaBrainpoolP256r1(
                                                        m_ecdsaP256Signature(
                                                                             m_eccP256CurvePoint_x_only(
                                                                                                        substr(v_sig, 0, 32)
                                                                                                       ),
                                                                             substr(v_sig, 32, 32)
                                                                            )
                                                       );
    // Final certificate
  v_encMsg := TestEtsiTs103097Certificate(v_cert, false);
    // Decode and check signature
    if (decvalue(v_encMsg, v_cert_dec) != 0) {
      setverdict(fail);
      stop;
    }
    v_encMsg := encvalue(v_cert_dec.toBeSigned);
    if (f_verifyWithEcdsaBrainpoolp256WithSha256(
                                                 bit2oct(v_encMsg), 
                                                 v_cert_dec.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only & v_cert_dec.signature_.ecdsaBrainpoolP256r1Signature.sSig,
                                                 v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.uncompressedP256.x,
                                                 v_cert_dec.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.uncompressedP256.y
                                           ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
    }

  } // End of testcase tc_at_certificate_sha256_2
   
  testcase tc_certificate_asn1c_1() runs on TCType system TCType {
    var template (value) EtsiTs103097Certificate v_cert;
    var charstring v_certId := "vehicle-test.example.com";
    var HashAlgorithm v_self := sha256;
    var HashedId3 v_cracaId := '5E6F5B'O;
    var CrlSeries v_crlSeries := 2;
    var Oct32 v_private_key := int2oct(0, 32);
    var Oct32 v_publicKeyX := int2oct(0, 32);
    var Oct32 v_publicKeyY := int2oct(0, 32);
    var HashedId8 v_sha256AndDigest;
    var Oct32 v_sig := int2oct(0, 32);
    var octetstring v_exp_enc_msg := '80030080AF232618BE5E6F5558811876656869636C652D746573742E6578616D706C652E636F6D5E6F5B0002010A8F1C86000A83010280000C80002201018001238104038300010102E08101020100C0E0800102800123818002010081010101000080808208C3C070B040C040108033070D0501CE0C0A0806017B00F030D203EA04BE0903808008B2030104020A0D010C0105C0F80BB1460239348D17405C1A845151D40612002617CF4E6B25097F03F502AD0C6F2F125974700D31A60FD1EF12040E4D8231AB'O;
      
    // Generate Private/Public keys
    f_generate_key_pair_nistp256(v_private_key, v_publicKeyX, v_publicKeyY);
    // Fill Certificate template with the public key      
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_sha256AndDigest('AF232618BE5E6F55'O),
                                      m_toBeSignedCertificate_ca(
                                                              { name := v_certId },
                                                              { valueof(m_appPermissions(35, { bitmapSsp := '830001'O })) },
                                                              { 
                                                                m_psidGroupPermissions(
                                                                                       m_subjectPermissions_all,
                                                                                       2, 
                                                                                       0, 
                                                                                       oct2bit('C0'O)
                                                                                       ),
                                                                m_psidGroupPermissions(
                                                                                       m_subjectPermissions_explicit(
                                                                                                                     {
                                                                                                                       valueof(m_psidSspRange(35)),
                                                                                                                       valueof(m_psidSspRange(256))
                                                                                                                       }
                                                                                                                     ))
                                                              },
                                                              m_verificationKeyIndicator_verificationKey( 
                                                                                                         m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                               m_eccP256CurvePoint_compressed_y_0(
                                                                                                                                                                                  '08C3C070B040C040108033070D0501CE0C0A0806017B00F030D203EA04BE0903'O
                                                                                                                                                                                  ))),
                                                              m_validityPeriod(
                                                                               17469212,
                                                                               m_duration_years(10)
                                                                               ),
                                                              m_geographicRegion_identifiedRegion(
                                                                                                  {
                                                                                                    m_identifiedRegion_country_only(12), 
                                                                                                    m_identifiedRegion_country_only(34)
                                                                                                    }
                                                                                                  )
                                                              ),
                                      m_signature_ecdsaNistP256(
                                                                m_ecdsaP256Signature(
                                                                                     m_eccP256CurvePoint_x_only(
                                                                                                                '08B2030104020A0D010C0105C0F80BB1460239348D17405C1A845151D4061200'O
                                                                                                                ),
                                                                                     '2617CF4E6B25097F03F502AD0C6F2F125974700D31A60FD1EF12040E4D8231AB'O
                                                                                     )
                                                                )
                                     );
      v_cert.toBeSigned.cracaId := v_cracaId;
      v_cert.toBeSigned.crlSeries := v_crlSeries;

    TestEtsiTs103097Certificate(v_cert, true, oct2bit(v_exp_enc_msg));
    
  } // End of testcase tc_certificate_asn1c_1
   
  group encdec_functions {
        
    function TestEtsiTs103097Certificate(
                                         in template (value) EtsiTs103097Certificate p_cert,
                                         in boolean p_decode := true, 
                                         in template (omit) bitstring p_expEncMsg := omit 
                                         ) runs on TCType return bitstring {
      var bitstring v_encMsg;
      var template (omit) TestRecord v_tr := { bs := p_expEncMsg };
      var EtsiTs103097Certificate v_decMsg;
      var integer v_res := 0;
    
      // Encode template
      log("Encode template ", valueof(p_cert));
    v_encMsg := encvalue(p_cert);
      log("Encoded message:  ", bit2oct(v_encMsg));
      // Check result
      if (not isbound(v_encMsg)) {
        setverdict(fail, "Encoding failed!");
        stop;
      }
      if (ispresent(v_tr.bs)) {
        if (not match(v_encMsg, p_expEncMsg)) {
          log("Expected message: ", bit2oct(valueof(p_expEncMsg)));
          setverdict(fail, "Encoding failed, not the expected result!");
          stop;
        }
      }
      setverdict(pass, "Encoding passed.");
    
      // Check decoding
      if (p_decode == true) {
      v_res := decvalue(v_encMsg, v_decMsg);
        log("Decoded message: ", v_decMsg);
        select (v_res) {
        case (0) {
          if(match(v_decMsg, p_cert)) {
            setverdict(pass);
          } else {
            setverdict(fail);
          }
        }
        case (1) {
          setverdict(fail, "Decoding failed.");
        }
        case (2) {
          setverdict(fail, "Not enough bits.");
        }
        }
      }
      return v_encMsg;
    }
  } // End of group encdec_functions
   
  control {
    execute(tc_root_certificate_sha256_1());
    execute(tc_root_certificate_sha256_2());
    execute(tc_root_certificate_sha384_1());
    execute(tc_ea_certificate_sha256_1());
    execute(tc_at_certificate_sha256_1());
    execute(tc_at_certificate_sha256_2());
    execute(tc_certificate_asn1c_1());
  }
   
} // End of module TestCodec_Certificates 
