Rev

Rev 3271 | Go to most recent revision | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | Download | SVN | Bug Tracker

module TestCodec_ChainOfCertificates {
 
  // 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;
 
  // LibItsGeoNetworking
  import from LibItsGeoNetworking_EncdecDeclarations all;
  import from LibItsGeoNetworking_TypesAndValues all;
  import from LibItsGeoNetworking_Templates 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
   * @member enc_cert   The whole-certificate encoding value
   * @member hashedid8  The whole-certificate hashedid8 value
   */

  type record sec_info {
    EtsiTs103097Certificate   cert,
    octetstring               enc_cert,
    Oct32                     private_key,
    Oct32                     public_key_x,
    Oct32                     public_key_y,
    Oct32                     public_key_compressed,
    Oct32                     hash,
    integer                   compressed_mode,
    HashedId8                 hashedid8,
    HashedId8                 issuer
  }
     
  type record chain_sec_info {
    sec_info ca,
    sec_info aa,
    sec_info at
  }

  testcase tc_full_check_certificate_1() runs on TCType system TCType {
    var chain_sec_info v_chain_sec_info;
    var bitstring v_enc_msg := ''B;
    var template (value) GnNonSecuredPacket v_gnNonSecuredPacket;
    var template (value) EtsiTs103097Data v_secured_data;
    var template (value) GeoNetworkingPdu v_gnSecuredPacket;
    var octetstring v_publicKeyCompressed;
    var integer v_publicKeyCompressedMode;
   
    // Generate CA certificate
    v_chain_sec_info.ca.cert := f_create_ca_certificate_nistP256_1(v_chain_sec_info.ca);
    v_enc_msg := encvalue(v_chain_sec_info.ca.cert); // Encode the whole certificate
    v_chain_sec_info.ca.enc_cert := bit2oct(v_enc_msg);
    v_chain_sec_info.ca.hash := f_hashWithSha256(v_chain_sec_info.ca.enc_cert); // Compute the hash
    v_chain_sec_info.ca.hashedid8 := f_HashedId8FromSha256(v_chain_sec_info.ca.hash);
    v_chain_sec_info.ca.issuer := v_chain_sec_info.ca.hashedid8; // CA certificate: hashedid8 == issuer
    // Verify signature of CA certificate by itself
    v_enc_msg := encvalue(v_chain_sec_info.ca.cert.toBeSigned);
    if (ischosen(v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
      v_publicKeyCompressed := v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0;
      v_publicKeyCompressedMode := 0;
    } else {
      v_publicKeyCompressed := v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1;
      v_publicKeyCompressedMode := 1;
    }
    if (f_verifyWithEcdsaNistp256WithSha256(
                                            bit2oct(v_enc_msg),
                                            int2oct(0, 32),
                                            v_chain_sec_info.ca.cert.signature_.ecdsaNistP256Signature.rSig.x_only & v_chain_sec_info.ca.cert.signature_.ecdsaNistP256Signature.sSig,
                                            v_publicKeyCompressed,
                                            v_publicKeyCompressedMode
                                            ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass);
      log("Root keys: ", v_chain_sec_info.ca.cert);
    }
   
    // Generate AA certificate
    v_chain_sec_info.aa.cert := f_create_aa_certificate_nistP256_1(v_chain_sec_info.ca, v_chain_sec_info.aa);
    v_enc_msg := encvalue(v_chain_sec_info.aa.cert); // Encode the whole certificate
    v_chain_sec_info.aa.enc_cert := bit2oct(v_enc_msg);
    v_chain_sec_info.aa.hash := f_hashWithSha256(v_chain_sec_info.aa.enc_cert); // Compute the hash
    v_chain_sec_info.aa.hashedid8 := f_HashedId8FromSha256(v_chain_sec_info.aa.enc_cert);
    v_chain_sec_info.aa.issuer := v_chain_sec_info.ca.hashedid8;
    // Verify signature of AA certificate by CA certificate
    v_enc_msg := encvalue(v_chain_sec_info.aa.cert.toBeSigned);
    if (ischosen(v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
      v_publicKeyCompressed := v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0;
      v_publicKeyCompressedMode := 0;
    } else {
      v_publicKeyCompressed := v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1;
      v_publicKeyCompressedMode := 1;
    }
    if (f_verifyWithEcdsaNistp256WithSha256(
                                            bit2oct(v_enc_msg),
                                            v_chain_sec_info.ca.hash,
                                            v_chain_sec_info.aa.cert.signature_.ecdsaNistP256Signature.rSig.x_only & v_chain_sec_info.aa.cert.signature_.ecdsaNistP256Signature.sSig,
                                            v_publicKeyCompressed,
                                            v_publicKeyCompressedMode
                                            ) == false) {
      setverdict(fail);
    } else {
      v_enc_msg := encvalue(v_chain_sec_info.aa.cert);
      log("AA keys: ", v_chain_sec_info.aa.cert);
      setverdict(pass)
    }

    // Generate AT certificate
    v_chain_sec_info.at.cert := f_create_at_certificate_nistP256_1(v_chain_sec_info.aa, v_chain_sec_info.at);
    v_enc_msg := encvalue(v_chain_sec_info.at.cert); // Encode the whole certificate
    v_chain_sec_info.at.enc_cert := bit2oct(v_enc_msg);
    v_chain_sec_info.at.hash := f_hashWithSha256(v_chain_sec_info.at.enc_cert); // Compute the hash
    v_chain_sec_info.at.hashedid8 := f_HashedId8FromSha256(v_chain_sec_info.at.hash);
    v_chain_sec_info.at.issuer := v_chain_sec_info.aa.hashedid8;
    // Verify signature of AT certificate by AA certificate
    v_enc_msg := encvalue(v_chain_sec_info.at.cert.toBeSigned);
    if (ischosen(v_chain_sec_info.aa.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
      v_publicKeyCompressed := v_chain_sec_info.aa.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0;
      v_publicKeyCompressedMode := 0;
    } else {
      v_publicKeyCompressed := v_chain_sec_info.aa.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1;
      v_publicKeyCompressedMode := 1;
    }
    if (f_verifyWithEcdsaNistp256WithSha256(
                                            bit2oct(v_enc_msg),
                                            v_chain_sec_info.aa.hash,
                                            v_chain_sec_info.at.cert.signature_.ecdsaNistP256Signature.rSig.x_only & v_chain_sec_info.at.cert.signature_.ecdsaNistP256Signature.sSig,
                                            v_publicKeyCompressed,
                                            v_publicKeyCompressedMode
                                            ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass);
      v_enc_msg := encvalue(v_chain_sec_info.at.cert);
      log("AT keys: ", v_chain_sec_info.at.cert);
    }

    log("tc_full_check_certificate_1: Final chain = ", v_chain_sec_info);
   
    // Store Private key in binary format
    fx_loadCertificates("/home/vagrant/tmp/Yann", "");
    fx_store_certificate("CERT_TEST_A_ROOT", v_chain_sec_info.ca.enc_cert, v_chain_sec_info.ca.private_key, v_chain_sec_info.ca.public_key_x, v_chain_sec_info.ca.public_key_y, v_chain_sec_info.ca.public_key_compressed, v_chain_sec_info.ca.compressed_mode, v_chain_sec_info.ca.hashedid8, v_chain_sec_info.ca.issuer, omit, omit, omit, omit, omit);
    fx_store_certificate("CERT_TS_A_AA", v_chain_sec_info.aa.enc_cert, v_chain_sec_info.aa.private_key, v_chain_sec_info.aa.public_key_x, v_chain_sec_info.aa.public_key_y, v_chain_sec_info.aa.public_key_compressed, v_chain_sec_info.aa.compressed_mode, v_chain_sec_info.aa.hashedid8, v_chain_sec_info.aa.issuer, omit, omit, omit, omit, omit);
    fx_store_certificate("CERT_TS_A_AT", v_chain_sec_info.at.enc_cert, v_chain_sec_info.at.private_key, v_chain_sec_info.at.public_key_x, v_chain_sec_info.at.public_key_y, v_chain_sec_info.at.public_key_compressed, v_chain_sec_info.at.compressed_mode, v_chain_sec_info.at.hashedid8, v_chain_sec_info.at.issuer, omit, omit, omit, omit, omit);
   
    // Create a basic GeoNetworking message
  v_gnNonSecuredPacket := m_geoNwShbPacket(
                                           LongPosVector: {
                                           gnAddr := {
                                             typeOfAddress := e_manual,
                                             stationType := e_roadSideUnit,
                                             stationCountryCode := 33,
                                             mid := 'a4fedecabeef'O
                                           },
                                            timestamp_ := 123456,
                                             latitude := 4856,
                                             longitude := 675,
                                             pai := '1'B,
                                             speed := 55,
                                             heading := 9876
                                             }
                                           );
    // Build the secured message and sign it
    v_secured_data := f_build_and_sign_secured_message_nistP256_1(v_gnNonSecuredPacket, v_chain_sec_info.at);

    // Verify signature of secured messagee by AT certificate
    v_enc_msg := encvalue(valueof(v_secured_data.content.signedData.tbsData));
    if (ischosen(v_chain_sec_info.at.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
      v_publicKeyCompressed := v_chain_sec_info.at.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0;
      v_publicKeyCompressedMode := 0;
    } else {
      v_publicKeyCompressed := v_chain_sec_info.at.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1;
      v_publicKeyCompressedMode := 1;
    }
    if (f_verifyWithEcdsaNistp256WithSha256(
                                            bit2oct(v_enc_msg),
                                            v_chain_sec_info.at.hash,
                                            valueof(v_secured_data.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only) & valueof(v_secured_data.content.signedData.signature_.ecdsaNistP256Signature.sSig),
                                            v_publicKeyCompressed,
                                            v_publicKeyCompressedMode
                                            ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
    }

    // Finalyse the GeoNetworking message
   
    // TODO Create a chain of certificates
   
    // TODO Add encryption support
   
  } // End of testcase tc_full_check_certificate_1
 
  testcase tc_full_check_certificate_2() runs on TCType system TCType {
    var chain_sec_info v_chain_sec_info;
    var bitstring v_enc_msg := ''B;
    var template (value) GnNonSecuredPacket v_gnNonSecuredPacket;
    var template (value) EtsiTs103097Data v_secured_data;
    var template (value) GeoNetworkingPdu v_gnSecuredPacket;
    var octetstring v_publicKeyCompressed;
    var integer v_publicKeyCompressedMode;
   
    // Generate CA certificate
    v_chain_sec_info.ca.cert := f_create_ca_certificate_brainpoolP256_1(v_chain_sec_info.ca);
    v_enc_msg := encvalue(v_chain_sec_info.ca.cert); // Endcode the whole certificate
    v_chain_sec_info.ca.enc_cert := bit2oct(v_enc_msg);
    v_chain_sec_info.ca.hash := f_hashWithSha256(v_chain_sec_info.ca.enc_cert); // Compute the hash
    v_chain_sec_info.ca.hashedid8 := f_HashedId8FromSha256(v_chain_sec_info.ca.hash);
    v_chain_sec_info.ca.issuer := v_chain_sec_info.ca.hashedid8; // CA certificate: hashedid8 == issuer
    // Verify signature of CA certificate by itself
    v_enc_msg := encvalue(v_chain_sec_info.ca.cert.toBeSigned);
    if (ischosen(v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0)) {
      v_publicKeyCompressed := v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0;
      v_publicKeyCompressedMode := 0;
    } else {
      v_publicKeyCompressed := v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_1;
      v_publicKeyCompressedMode := 1;
    }
    if (f_verifyWithEcdsaBrainpoolp256WithSha256(
                                                 bit2oct(v_enc_msg),
                                                 int2oct(0, 32),
                                                 v_chain_sec_info.ca.cert.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only & v_chain_sec_info.ca.cert.signature_.ecdsaBrainpoolP256r1Signature.sSig,
                                                 v_publicKeyCompressed,
                                                 v_publicKeyCompressedMode
                                                 ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
    }
   
    // Generate AA certificate
    v_chain_sec_info.aa.cert := f_create_aa_certificate_brainpoolP256_1(v_chain_sec_info.ca, v_chain_sec_info.aa);
    v_enc_msg := encvalue(v_chain_sec_info.aa.cert); // Encode the whole certificate
    v_chain_sec_info.aa.enc_cert := bit2oct(v_enc_msg);
    v_chain_sec_info.aa.hash := f_hashWithSha256(v_chain_sec_info.aa.enc_cert); // Compute the hash
    v_chain_sec_info.aa.hashedid8 := f_HashedId8FromSha256(v_chain_sec_info.aa.hash);
    v_chain_sec_info.aa.issuer := v_chain_sec_info.ca.hashedid8;
    // Verify signature of AA certificate by CA certificate
    v_enc_msg := encvalue(v_chain_sec_info.aa.cert.toBeSigned);
    if (ischosen(v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0)) {
      v_publicKeyCompressed := v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0;
      v_publicKeyCompressedMode := 0;
    } else {
      v_publicKeyCompressed := v_chain_sec_info.ca.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_1;
      v_publicKeyCompressedMode := 1;
    }
    if (f_verifyWithEcdsaBrainpoolp256WithSha256(
                                                 bit2oct(v_enc_msg),
                                                 v_chain_sec_info.ca.hash,
                                                 v_chain_sec_info.aa.cert.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only & v_chain_sec_info.aa.cert.signature_.ecdsaBrainpoolP256r1Signature.sSig,
                                                 v_publicKeyCompressed,
                                                 v_publicKeyCompressedMode
                                                ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass)
    }

    // Generate AT certificate
    v_chain_sec_info.at.cert := f_create_at_certificate_brainpoolP256_1(v_chain_sec_info.aa, v_chain_sec_info.at);
    v_enc_msg := encvalue(v_chain_sec_info.at.cert); // Encode the whole certificate
    v_chain_sec_info.at.enc_cert := bit2oct(v_enc_msg);
    v_chain_sec_info.at.hash := f_hashWithSha256(v_chain_sec_info.at.enc_cert); // Compute the hash
    v_chain_sec_info.at.hashedid8 := f_HashedId8FromSha256(v_chain_sec_info.at.hash);
    v_chain_sec_info.at.issuer := v_chain_sec_info.aa.hashedid8;
    // Verify signature of AT certificate by AA certificate
    v_enc_msg := encvalue(v_chain_sec_info.at.cert.toBeSigned);
    if (ischosen(v_chain_sec_info.aa.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0)) {
      v_publicKeyCompressed := v_chain_sec_info.aa.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0;
      v_publicKeyCompressedMode := 0;
    } else {
      v_publicKeyCompressed := v_chain_sec_info.aa.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_1;
      v_publicKeyCompressedMode := 1;
    }
    if (f_verifyWithEcdsaBrainpoolp256WithSha256(
                                                 bit2oct(v_enc_msg),
                                                 v_chain_sec_info.aa.hash,
                                                 v_chain_sec_info.at.cert.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only & v_chain_sec_info.at.cert.signature_.ecdsaBrainpoolP256r1Signature.sSig,
                                                 v_publicKeyCompressed,
                                                 v_publicKeyCompressedMode
                                                ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass);
    }

    log("tc_full_check_certificate_2: Final chain = ", v_chain_sec_info);
   
    // Store Private key in binary format
    fx_loadCertificates("/home/vagrant/tmp/Yann", "");
    fx_store_certificate("CERT_TEST_B_ROOT", v_chain_sec_info.ca.enc_cert, v_chain_sec_info.ca.private_key, v_chain_sec_info.ca.public_key_x, v_chain_sec_info.ca.public_key_y, v_chain_sec_info.ca.public_key_compressed, v_chain_sec_info.ca.compressed_mode, v_chain_sec_info.ca.hashedid8, v_chain_sec_info.ca.issuer, omit, omit, omit, omit, omit);
    fx_store_certificate("CERT_TS_B_AA", v_chain_sec_info.aa.enc_cert, v_chain_sec_info.aa.private_key, v_chain_sec_info.aa.public_key_x, v_chain_sec_info.aa.public_key_y, v_chain_sec_info.aa.public_key_compressed, v_chain_sec_info.aa.compressed_mode, v_chain_sec_info.aa.hashedid8, v_chain_sec_info.aa.issuer, omit, omit, omit, omit, omit);
    fx_store_certificate("CERT_TS_B_AT", v_chain_sec_info.at.enc_cert, v_chain_sec_info.at.private_key, v_chain_sec_info.at.public_key_x, v_chain_sec_info.at.public_key_y, v_chain_sec_info.at.public_key_compressed, v_chain_sec_info.at.compressed_mode, v_chain_sec_info.at.hashedid8, v_chain_sec_info.at.issuer, omit, omit, omit, omit, omit);
   
    // Create a basic GeoNetworking message
  v_gnNonSecuredPacket := m_geoNwShbPacket(
                                           LongPosVector: {
                                           gnAddr := {
                                             typeOfAddress := e_manual,
                                             stationType := e_roadSideUnit,
                                             stationCountryCode := 33,
                                             mid := 'a4fedecabeef'O
                                           },
                                             timestamp_ := 123456,
                                             latitude := 4856,
                                             longitude := 675,
                                             pai := '1'B,
                                             speed := 55,
                                             heading := 9876
                                             }
                                           );
    // Build the secured message and sign it
    v_secured_data := f_build_and_sign_secured_message_brainpoolP256_1(v_gnNonSecuredPacket, v_chain_sec_info.at);

    // Verify signature of secured message by AT certificate
    v_enc_msg := encvalue(valueof(v_secured_data.content.signedData.tbsData));
    if (ischosen(v_chain_sec_info.at.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0)) {
      v_publicKeyCompressed := v_chain_sec_info.at.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0;
      v_publicKeyCompressedMode := 0;
    } else {
      v_publicKeyCompressed := v_chain_sec_info.at.cert.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_1;
      v_publicKeyCompressedMode := 1;
    }
    if (f_verifyWithEcdsaBrainpoolp256WithSha256(
                                                 bit2oct(v_enc_msg),
                                                 v_chain_sec_info.at.hash,
                                                 valueof(v_secured_data.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only) & valueof(v_secured_data.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig),
                                                 v_publicKeyCompressed,
                                                 v_publicKeyCompressedMode
                                                 ) == false) {
      setverdict(fail);
    } else {
      setverdict(pass);
    }

    // Finalyse the GeoNetworking message
   
    // TODO Create a chain of certificates
   
    // TODO Add encryption support
  } // End of testcase tc_full_check_certificate_2
 
  /**
   * @desc Function to generate a CA certificate / NistP256
   * @see ETSI TS 103 097 V1.3.1 7.2.3 Root CA certificates
   */

  function f_create_ca_certificate_nistP256_1(
                                              out sec_info p_ca_sec_info
  ) runs on TCType return EtsiTs103097Certificate {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var charstring v_certId := "STF538 NistP256 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 })),
      valueof(m_appPermissions(38, { 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 HashedId8 v_sha256AndDigest;
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_enc_msg := ''B;
    var EccP256CurvePoint v_eccPoint;
     
    // Generate Private/Public keys
    f_generate_key_pair_nistp256(p_ca_sec_info.private_key, p_ca_sec_info.public_key_x, p_ca_sec_info.public_key_y, p_ca_sec_info.public_key_compressed, p_ca_sec_info.compressed_mode);
    if (p_ca_sec_info.compressed_mode == 0) {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_0(p_ca_sec_info.public_key_compressed));
    } else {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_1(p_ca_sec_info.public_key_compressed));
    }
    // 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(
                                                                                                                                               v_eccPoint
                                                                                                                                               )),
                                                              m_validityPeriod(
                                                                               17469212,
                                                                               m_duration_years(10)
                                                                              )
                                                             )
                                      );
    // Encode it ==> Get octetstring
  v_enc_msg := encvalue(valueof(v_cert.toBeSigned));
    // Sign the certificate using ECDSA/SHA-256 (NIST p-256)
  v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_enc_msg), int2oct(0, 32), p_ca_sec_info.private_key);
  v_cert.signature_ := m_signature_ecdsaNistP256(
                                                 m_ecdsaP256Signature(
                                                                      m_eccP256CurvePoint_x_only(
                                                                                                 substr(v_sig, 0, 32)
                                                                                                 ),
                                                                      substr(v_sig, 32, 32)
                                                                      )
                                                );
    log("f_create_ca_certificate_nistP256_1: Signed template ", valueof(v_cert));
   
    // Final CA certificate
    return valueof(v_cert);
  } // End of function f_create_ca_certificate_nistP256_1
 
  /**
   * @desc Function to generate a CA certificate / BrainpoolP256
   * @see ETSI TS 103 097 V1.3.1 Clause 77.2.3 Root CA certificates
   */

  function f_create_ca_certificate_brainpoolP256_1(
                                                   out sec_info p_ca_sec_info
  ) runs on TCType return EtsiTs103097Certificate {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var charstring v_certId := "STF538 BrainpoolP256 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 })),
      valueof(m_appPermissions(38, { 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 HashedId8 v_sha256AndDigest;
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_enc_msg := ''B;
    var EccP256CurvePoint v_eccPoint;
     
    // Generate Private/Public keys
    f_generate_key_pair_brainpoolp256(p_ca_sec_info.private_key, p_ca_sec_info.public_key_x, p_ca_sec_info.public_key_y, p_ca_sec_info.public_key_compressed, p_ca_sec_info.compressed_mode);
    if (p_ca_sec_info.compressed_mode == 0) {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_0(p_ca_sec_info.public_key_compressed));
    } else {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_1(p_ca_sec_info.public_key_compressed));
    }
    // 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_ecdsaBrainpoolP256r1(
                                                                                                                                                      v_eccPoint
                                                                                                                                                      )),
                                                              m_validityPeriod(
                                                                               17469212,
                                                                               m_duration_years(10)
                                                                              )
                                                             )
                                      );
    // Encode it ==> Get octetstring
  v_enc_msg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (BRAINPOOL P-256)
  v_sig := f_signWithEcdsaBrainpoolp256WithSha256(bit2oct(v_enc_msg), int2oct(0, 32), p_ca_sec_info.private_key);
  v_cert.signature_ := m_signature_ecdsaBrainpoolP256r1(
                                                        m_ecdsaP256Signature(
                                                                             m_eccP256CurvePoint_x_only(
                                                                                                        substr(v_sig, 0, 32)
                                                                                                        ),
                                                                             substr(v_sig, 32, 32)
                                                                            )
                                                      );
    log("f_create_ca_certificate_brainpoolP256_1: Signed template ", valueof(v_cert));
   
    // Final CA certificate
    return valueof(v_cert);
  } // End of function f_create_ca_certificate_brainpoolP256_1
 
  /**
   * @desc AA certificate / NistP256
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Enrollment certificate
   */

  function f_create_aa_certificate_nistP256_1(
                                              in sec_info p_ca_sec_info,
                                              out sec_info p_aa_sec_info
  ) runs on TCType return EtsiTs103097Certificate {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var charstring v_certId := "STF538 NistP256 AA Certificate"; // ETSI TS 103 097 V1.3.1 Clause 7.2.2 Enrolment credential #5
    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 })),
      valueof(m_appPermissions(38, { bitmapSsp := '830001'O }))
    };
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_enc_msg := ''B;
    var EccP256CurvePoint v_eccPoint;
     
    // Generate Private/Public keys
    f_generate_key_pair_nistp256(p_aa_sec_info.private_key, p_aa_sec_info.public_key_x, p_aa_sec_info.public_key_y, p_aa_sec_info.public_key_compressed, p_aa_sec_info.compressed_mode);
    if (p_aa_sec_info.compressed_mode == 0) {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_0(p_aa_sec_info.public_key_compressed));
    } else {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_1(p_aa_sec_info.public_key_compressed));
    }
    // Fill Certificate template with the public key
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_sha256AndDigest(p_ca_sec_info.hashedid8),
                                      m_toBeSignedCertificate_aa(
                                                                 { name := v_certId },
                                                                 v_appPermissions,
                                                                 m_verificationKeyIndicator_verificationKey(
                                                                                                            m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                                  v_eccPoint
                                                                                                                                                  )),
                                                                 m_validityPeriod(
                                                                                  17469212,
                                                                                  m_duration_years(10)
                                                                                  ),
                                                                 m_geographicRegion_identifiedRegion(
                                                                                                     {
                                                                                                       m_identifiedRegion_country_only(12),
                                                                                                       m_identifiedRegion_country_only(34)
                                                                                                       }
                                                                                                     )
                                                                 )
                                      );
    // Encode it ==> Get octetstring
  v_enc_msg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (NIST P-256)
  v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_enc_msg), p_ca_sec_info.hash, p_ca_sec_info.private_key);
  v_cert.signature_ := m_signature_ecdsaNistP256(
                                                 m_ecdsaP256Signature(
                                                                      m_eccP256CurvePoint_x_only(
                                                                                                 substr(v_sig, 0, 32)
                                                                                                 ),
                                                                      substr(v_sig, 32, 32)
                                                                      )
                                                );
    log("f_create_aa_certificate_nistP256_1: Signed template ", valueof(v_cert));
   
    // Final AA certificate
    return valueof(v_cert);
  } // End of function f_create_aa_certificate_nistP256_1

  /**
   * @desc AA certificate / BrainpoolP256
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Enrollment certificate
   */

  function f_create_aa_certificate_brainpoolP256_1(
                                                   in sec_info p_ca_sec_info,
                                                   out sec_info p_aa_sec_info
  ) runs on TCType return EtsiTs103097Certificate {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var charstring v_certId := "STF538 BrainpoolP256 AA Certificate"; // ETSI TS 103 097 V1.3.1 Clause 7.2.2 Enrolment credential #5
    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 })),
      valueof(m_appPermissions(38, { bitmapSsp := '830001'O }))
    };
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_enc_msg := ''B;
    var EccP256CurvePoint v_eccPoint;
     
    // Generate Private/Public keys
    f_generate_key_pair_brainpoolp256(p_aa_sec_info.private_key, p_aa_sec_info.public_key_x, p_aa_sec_info.public_key_y, p_aa_sec_info.public_key_compressed, p_aa_sec_info.compressed_mode);
    if (p_aa_sec_info.compressed_mode == 0) {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_0(p_aa_sec_info.public_key_compressed));
    } else {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_1(p_aa_sec_info.public_key_compressed));
    }
    // Fill Certificate template with the public key
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_sha256AndDigest(p_ca_sec_info.hashedid8),
                                      m_toBeSignedCertificate_aa(
                                                                 { name := v_certId },
                                                                 v_appPermissions,
                                                                 m_verificationKeyIndicator_verificationKey(
                                                                                                            m_publicVerificationKey_ecdsaBrainpoolP256r1(
                                                                                                                                                         v_eccPoint
                                                                                                                                                         )),
                                                                 m_validityPeriod(
                                                                                  17469212,
                                                                                  m_duration_years(10)
                                                                                  ),
                                                                 m_geographicRegion_identifiedRegion(
                                                                                                     {
                                                                                                       m_identifiedRegion_country_only(12),
                                                                                                       m_identifiedRegion_country_only(34)
                                                                                                       }
                                                                                                     )
                                                                 )
                                      );
    // Encode it ==> Get octetstring
  v_enc_msg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (BRAINPOOL P-256)
  v_sig := f_signWithEcdsaBrainpoolp256WithSha256(bit2oct(v_enc_msg), p_ca_sec_info.hash, p_ca_sec_info.private_key);
  v_cert.signature_ := m_signature_ecdsaBrainpoolP256r1(
                                                        m_ecdsaP256Signature(
                                                                             m_eccP256CurvePoint_x_only(
                                                                                                        substr(v_sig, 0, 32)
                                                                                                        ),
                                                                             substr(v_sig, 32, 32)
                                                                            )
                                                );
    log("f_create_aa_certificate_brainpoolP256_1: Signed template ", valueof(v_cert));
   
    // Final AA certificate
    return valueof(v_cert);
  } // End of function f_create_aa_certificate_brainpoolP256_1

  /**
   * @desc AT certificate / NistP256
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets
   */

  function f_create_at_certificate_nistP256_1(
                                              in sec_info p_aa_sec_info,
                                              out sec_info p_at_sec_info
  ) runs on TCType return EtsiTs103097Certificate {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var charstring v_certId := "STF538 NistP256 AT Certificate"; // 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 })),
      valueof(m_appPermissions(38, { bitmapSsp := '830001'O }))
    };
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_enc_msg := ''B;
    var EccP256CurvePoint v_eccPoint;
     
    // Generate Private/Public keys
    f_generate_key_pair_nistp256(p_at_sec_info.private_key, p_at_sec_info.public_key_x, p_at_sec_info.public_key_y, p_at_sec_info.public_key_compressed, p_at_sec_info.compressed_mode);
    if (p_at_sec_info.compressed_mode == 0) {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_0(p_at_sec_info.public_key_compressed));
    } else {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_1(p_at_sec_info.public_key_compressed));
    }
    // Fill Certificate template with the public key
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_sha256AndDigest(p_aa_sec_info.hashedid8),
                                      m_toBeSignedCertificate_aa(
                                                                 { name := v_certId },
                                                                 v_appPermissions,
                                                                 m_verificationKeyIndicator_verificationKey(
                                                                                                            m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                                  v_eccPoint
                                                                                                                                                  )),
                                                                 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_enc_msg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (NIST P-256)
  v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_enc_msg), p_aa_sec_info.hash, p_aa_sec_info.private_key);
  v_cert.signature_ := m_signature_ecdsaNistP256(
                                                 m_ecdsaP256Signature(
                                                                      m_eccP256CurvePoint_x_only(
                                                                                                 substr(v_sig, 0, 32)
                                                                                                 ),
                                                                      substr(v_sig, 32, 32)
                                                                     )
                                                );
    log("f_create_at_certificate_nistP256_1: Signed template ", valueof(v_cert));
   
    // Final AT certificate
    return valueof(v_cert);
  } // End of function f_create_at_certificate_nistP256_1

  /**
   * @desc AT certificate / BrainpoolP256
   * @see ETSI TS 103 097 V1.3.1 Clause 7.2.1 Authorization tickets
   */

  function f_create_at_certificate_brainpoolP256_1(
                                                   in sec_info p_aa_sec_info,
                                                   out sec_info p_at_sec_info
  ) runs on TCType return EtsiTs103097Certificate {
    var template (value) EtsiTs103097Certificate v_cert; // ETSI TS 103 097 V1.3.1 Clause 6 Bullet 1
    var charstring v_certId := "STF538 BrainpoolP256 AT Certificate"; // 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 })),
      valueof(m_appPermissions(38, { bitmapSsp := '830001'O }))
    };
    var Oct32 v_sig := int2oct(0, 32);
    var bitstring v_enc_msg := ''B;
    var EccP256CurvePoint v_eccPoint;
     
    // Generate Private/Public keys
    f_generate_key_pair_brainpoolp256(p_at_sec_info.private_key, p_at_sec_info.public_key_x, p_at_sec_info.public_key_y, p_at_sec_info.public_key_compressed, p_at_sec_info.compressed_mode);
    if (p_at_sec_info.compressed_mode == 0) {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_0(p_at_sec_info.public_key_compressed));
    } else {
      v_eccPoint := valueof(m_eccP256CurvePoint_compressed_y_1(p_at_sec_info.public_key_compressed));
    }
    // Fill Certificate template with the public key
  v_cert := m_etsiTs103097Certificate(
                                      m_issuerIdentifier_sha256AndDigest(p_aa_sec_info.hashedid8),
                                      m_toBeSignedCertificate_aa(
                                                                 { name := v_certId },
                                                                 v_appPermissions,
                                                                 m_verificationKeyIndicator_verificationKey(
                                                                                                            m_publicVerificationKey_ecdsaBrainpoolP256r1(
                                                                                                                                                         v_eccPoint
                                                                                                                                                         )),
                                                                 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_enc_msg := encvalue(v_cert.toBeSigned);
    // Sign the certificate using ECDSA/SHA-256 (BRAINPOOL P-256)
  v_sig := f_signWithEcdsaBrainpoolp256WithSha256(bit2oct(v_enc_msg), p_aa_sec_info.hash, p_aa_sec_info.private_key);
  v_cert.signature_ := m_signature_ecdsaBrainpoolP256r1(
                                                        m_ecdsaP256Signature(
                                                                             m_eccP256CurvePoint_x_only(
                                                                                                        substr(v_sig, 0, 32)
                                                                                                        ),
                                                                             substr(v_sig, 32, 32)
                                                                             )
                                                       );
    log("f_create_at_certificate_brainpoolP256_1: Signed template ", valueof(v_cert));
   
    // Final AT certificate
    return valueof(v_cert);
  } // End of function f_create_at_certificate_brainpoolP256_1

  function f_build_and_sign_secured_message_nistP256_1(
                                                       in template (value) GnNonSecuredPacket p_gnNonSecuredPacket,
                                                       in sec_info p_at_sec_info
  ) runs on TCType return EtsiTs103097Data {
    var octetstring v_raw_payload_to_be_signed;
    var template (value) ToBeSignedData v_toBeSignedData;
    var Oct32 v_sig := '0000000000000000000000000000000000000000000000000000000000000000'O;
    var EtsiTs103097Data v_secured_data;

    // Build the message to be signed
    v_raw_payload_to_be_signed := bit2oct(encvalue(p_gnNonSecuredPacket));
  v_toBeSignedData := m_toBeSignedData(
                                       m_signedDataPayload(
                                                           m_etsiTs103097Data_unsecured(v_raw_payload_to_be_signed)
                                                           ),
                                       m_headerInfo_gn(
                                                       -,
                                                       12345
                                                       )
                                       );
    // Signed it
  v_raw_payload_to_be_signed := bit2oct(encvalue(v_toBeSignedData));
  v_sig := f_signWithEcdsaNistp256WithSha256(v_raw_payload_to_be_signed, p_at_sec_info.hash, p_at_sec_info.private_key);
    // Finalize the secured message
  v_secured_data := valueof(
                            m_etsiTs103097Data_signed(
                                                      m_signedData(
                                                                   sha256,
                                                                   v_toBeSignedData,
                                                                   { digest := p_at_sec_info.hashedid8 },
                                                                   m_signature_ecdsaNistP256(
                                                                                             m_ecdsaP256Signature(
                                                                                                                  m_eccP256CurvePoint_x_only(
                                                                                                                                             substr(v_sig, 0, 32)
                                                                                                                                             ),
                                                                                                                  substr(v_sig, 32, 32)
                                                                                                                  )
                                                                                             )
                                                                   )
                                                      )
                            );
    log("f_build_and_sign_secured_message_nistP256_1: v_secured_data = ", v_secured_data);
   
    return v_secured_data;
  } // End of function f_build_and_sign_secured_message_nistP256_1
 
  function f_build_and_sign_secured_message_brainpoolP256_1(
                                                            in template (value) GnNonSecuredPacket p_gnNonSecuredPacket,
                                                            in sec_info p_at_sec_info
  ) runs on TCType return EtsiTs103097Data {
    var octetstring v_raw_payload_to_be_signed;
    var template (value) ToBeSignedData v_toBeSignedData;
    var Oct32 v_sig := '0000000000000000000000000000000000000000000000000000000000000000'O;
    var template (value) EtsiTs103097Data v_secured_data;

    // Build the message to be signed
    v_raw_payload_to_be_signed := bit2oct(encvalue(p_gnNonSecuredPacket));
  v_toBeSignedData := m_toBeSignedData(
                                       m_signedDataPayload(
                                                           m_etsiTs103097Data_unsecured(v_raw_payload_to_be_signed)
                                                           ),
                                       m_headerInfo_gn(
                                                       -,
                                                       12345
                                                       )
                                       );
    // Signed it
  v_raw_payload_to_be_signed := bit2oct(encvalue(v_toBeSignedData));
  v_sig := f_signWithEcdsaBrainpoolp256WithSha256(v_raw_payload_to_be_signed, p_at_sec_info.hash, p_at_sec_info.private_key);
    // Finalize the secured message
  v_secured_data := m_etsiTs103097Data_signed(
                                              m_signedData(
                                                           sha256,
                                                           v_toBeSignedData,
                                                           { digest := p_at_sec_info.hashedid8 },
                                                           m_signature_ecdsaBrainpoolP256r1(
                                                                                            m_ecdsaP256Signature(
                                                                                                                 m_eccP256CurvePoint_x_only(
                                                                                                                                            substr(v_sig, 0, 32)
                                                                                                                                            ),
                                                                                                                 substr(v_sig, 32, 32)
                                                                                                                 )
                                                                                            )
                                                           )
                                              );
    log("f_build_and_sign_secured_message_brainpoolP256_1: v_secured_data = ", v_secured_data);
   
    return valueof(v_secured_data);
  } // End of function f_build_and_sign_secured_message_brainpoolP256_1
 
} // End of module TestCodec_ChainOfCertificates