LibItsPki_Functions.ttcn 425 KB
Newer Older
ASN.1 Documenter's avatar
ASN.1 Documenter committed
/**
 *  @author   ETSI / STF544
 *  @version  $Url$
 *            $Id$
 *  @desc     Module containing functions for ITS PKI ATS
 *  @copyright   ETSI Copyright Notification
 *               No part may be reproduced except as authorized by written permission.
 *               The copyright and the foregoing restriction extend to reproduction in all media.
 *               All rights reserved.
 *
 */
module LibItsPki_Functions {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  // LibCommon
  import from LibCommon_Time all;
  import from LibCommon_VerdictControl all;
  import from LibCommon_Sync all;
  import from LibCommon_BasicTypesAndValues all;
  import from LibCommon_DataStrings all;
  // LibHelpers
  import from LibHelpers_Functions all;

ASN.1 Documenter's avatar
ASN.1 Documenter committed
  // LibIts
  import from Ieee1609Dot2BaseTypes language "ASN.1:1997" all;
  import from Ieee1609Dot2 language "ASN.1:1997" all;
  import from EtsiTs102941BaseTypes language "ASN.1:1997" all;
  import from EtsiTs102941TypesEnrolment language "ASN.1:1997" all;
  import from EtsiTs102941TypesAuthorization language "ASN.1:1997" all;
  import from EtsiTs102941TypesAuthorizationValidation language "ASN.1:1997" all;
  import from EtsiTs102941MessagesCa language "ASN.1:1997" all;
  import from EtsiTs102941TrustLists language "ASN.1:1997" all;
  import from EtsiTs103097Module language "ASN.1:1997" all;
  import from Ieee1609Dot2Dot1EeRaInterface language "ASN.1:1997" all;
  import from Ieee1609Dot2Dot1AcaRaInterface language "ASN.1:1997" all;
  import from Ieee1609Dot2Dot1Acpc language "ASN.1:1997" all;
  import from ETSI_ITS_CDD language "ASN.1:1997" all;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  import from CAM_PDU_Descriptions language "ASN.1:1997" all;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  // LibItsCommon
  import from LibItsCommon_TypesAndValues all;
  import from LibItsCommon_Functions all;
  import from LibItsCommon_ASN1_NamedNumbers all;
  import from LibItsCommon_Pixits all;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  // LibItsGeoNetworking
  import from LibItsGeoNetworking_TypesAndValues all;
  import from LibItsGeoNetworking_TestSystem all;
  import from LibItsGeoNetworking_Pixits all;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  // LibItsSecurity
  import from LibItsSecurity_TypesAndValues all;
  import from LibItsSecurity_Templates all;
  import from LibItsSecurity_Functions all;
  import from LibItsSecurity_Pics all;
  import from LibItsSecurity_Pixits all;
  import from LibItsSecurity_TestSystem all;
  // LibHttp
  import from LibHttp_TypesAndValues all;
  import from LibHttp_Templates all;
  import from LibHttp_Functions all;
  import from LibHttp_TestSystem all;
  import from LibHttp_Pics all;

  // LibHttp
  import from LibHttp_BinaryTemplates all;

ASN.1 Documenter's avatar
ASN.1 Documenter committed
  // LibItsPki
  import from LibItsPki_TypesAndValues all;
  import from LibItsPki_Templates all;
  import from LibItsPki_Pics all;
  import from LibItsPki_Pixits all;
  import from LibItsPki_TestSystem all;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  group pkiConfigurationFunctions {

    function f_cfMtcUp01(
                         out ItsPkiItss p_itss,
                         out ItsPkiHttp p_pki
                         ) runs on ItsMtc {
      p_itss := ItsPkiItss.create("ITS-S") alive;
      p_pki := ItsPkiHttp.create("PKI") alive;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      connect(self:syncPort, mtc:syncPort);
      connect(p_itss:syncPort, self:syncPort);
      connect(p_pki:syncPort, self:syncPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      connect(p_pki:infoPort, p_itss:infoPort);
    } // End of function f_cfMtcUp01
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_cfMtcUp02(
                         out ItsPkiHttp p_itss,
                         out ItsPkiHttp p_ea
                         ) runs on ServerSyncComp {
      p_itss := ItsPkiItss.create("ITS-S") alive;
      p_ea := ItsPkiHttp.create("EA") alive;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      connect(self:syncPort, mtc:syncPort);
      connect(p_itss:syncPort, self:syncPort);
      connect(p_ea:syncPort, self:syncPort);
    } // End of function f_cfMtcUp02
    function f_cfMtcUp03(
                         out ItsPkiHttp p_itss,
                         out ItsPkiHttp p_tlm
                         ) runs on ServerSyncComp {
      p_itss := ItsPkiItss.create("ITS-S") alive;
      p_tlm := ItsPkiHttp.create("TLM") alive;
      connect(self:syncPort, mtc:syncPort);
      connect(p_itss:syncPort, self:syncPort);
      connect(p_tlm:syncPort, self:syncPort);
    } // End of function f_cfMtcUp03
    function f_cfMtcUp04(
                         out ItsPkiHttp p_itss,
                         out ItsPkiHttp p_dc
                         ) runs on ServerSyncComp {
      p_itss := ItsPkiItss.create("ITS-S") alive;
      p_dc := ItsPkiHttp.create("DC") alive;
      connect(self:syncPort, mtc:syncPort);
      connect(p_itss:syncPort, self:syncPort);
      connect(p_dc:syncPort, self:syncPort);
    } // End of function f_cfMtcUp04
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Setups default configuration
     * @param   p_certificate_id The certificate identifier the TA shall use in case of secured IUT
     */
    function f_cfHttpUp(
                        in charstring p_ea_certificate_id := "CERT_TS_A_EA", // TODO Use a constant
                        in charstring p_aa_certificate_id := "CERT_TS_A_AA"
                        ) runs on ItsPkiHttp system ItsPkiHttpSystem {

      if (PICS_MULTIPLE_END_POINT == false) {
        map(self:httpPort, system:httpPort);
      } else {
        map(self:httpEcPort, system:httpEcPort);
        map(self:httpAtVPort, system:httpAtVPort);
        map(self:httpAtPort, system:httpAtPort);
      }
      f_connect4SelfOrClientSync();

      f_initialiseSecuredMode(p_ea_certificate_id, p_aa_certificate_id); // TODO To be removed???

      // TODO Duplicate code, use a function
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Setup EA certificate shared with PKI EA entity
      f_readCertificate(p_ea_certificate_id, vc_eaCertificate);
      f_readSigningKey(p_ea_certificate_id, vc_eaPrivateKey); // TODO To be removed
      f_readEncryptingKey(p_ea_certificate_id, vc_eaPrivateEncKey);
      f_getCertificateDigest(p_ea_certificate_id, vc_eaHashedId8);
      f_getCertificateHash(p_ea_certificate_id, vc_eaWholeHash);
      f_getCertificateHash256(p_ea_certificate_id, vc_eaWholeHash256);
      log("f_cfHttpUp: vc_eaPrivateKey= ", vc_eaPrivateKey);
      log("f_cfHttpUp: vc_eaPrivateEncKey= ", vc_eaPrivateEncKey);
      log("f_cfHttpUp: vc_eaHashedId8= ", vc_eaHashedId8);
      log("f_cfHttpUp: vc_eaWholeHash= ", vc_eaWholeHash);
      log("f_cfHttpUp: vc_eaWholeHash256= ", vc_eaWholeHash256);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Setup AA certificate shared with PKI AA entity
      f_readCertificate(p_aa_certificate_id, vc_aaCertificate);
      f_readSigningKey(p_aa_certificate_id, vc_aaPrivateKey); // Required for AuthorizationValidation request
      f_readEncryptingKey(p_aa_certificate_id, vc_aaPrivateEncKey);
      f_getCertificateDigest(p_aa_certificate_id, vc_aaHashedId8);
      f_getCertificateHash(p_aa_certificate_id, vc_aaWholeHash);
      f_getCertificateHash256(p_aa_certificate_id, vc_aaWholeHash256);
      log("f_cfHttpUp: vc_aaPrivateKey= ", vc_aaPrivateKey);
      log("f_cfHttpUp: vc_aaPrivateEncKey= ", vc_aaPrivateEncKey);
      log("f_cfHttpUp: vc_aaHashedId8= ", vc_aaHashedId8);
      log("f_cfHttpUp: vc_aaWholeHash= ", vc_aaWholeHash);
      log("f_cfHttpUp: vc_aaWholeHash256= ", vc_aaWholeHash256);

      // Storage of enrolment keys in case of re-enrolment
      vc_ec_keys_counter := 0;
      vc_ec_counter := 0;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      vc_ec_private_keys := {};
      vc_ec_public_compressed_key := {};
      vc_ec_compressed_modes := {};
      vc_ec_hashed_id8 := {};
      vc_ec_certificates := {};

      if (PICS_MULTIPLE_END_POINT == false) {
        activate(a_default_pki_http());
      } else {
        activate(a_default_pki_http_ec());
        activate(a_default_pki_http_atv());
        activate(a_default_pki_http_at());
      }
    } // End of function f_cfHttpUp
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Setups default configuration
     */
    function f_cfHttpUp_ca() runs on ItsPkiHttp system ItsPkiHttpSystem { // FIXME Rename into f_cfHttpUp_rca_dc
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      if (PICS_MULTIPLE_END_POINT == false) {
        map(self:httpPort, system:httpPort);
      } else {
        map(self:httpCaPort, system:httpCaPort);
      }
      f_connect4SelfOrClientSync();

      f_initialiseSecuredMode();

      if (PICS_MULTIPLE_END_POINT == false) {
        activate(a_default_pki_http());
      } else {
        activate(a_default_pki_http_ca());
      }
    } // End of function f_cfHttpUp_ca
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Setups default configuration
     */
    function f_cfHttpUp_tlm() runs on ItsPkiHttp system ItsPkiHttpSystem { // FIXME Rename into f_cfHttpUp_cpoc
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      if (PICS_MULTIPLE_END_POINT == false) {
        map(self:httpPort, system:httpPort);
      } else {
        map(self:httpTlmPort, system:httpTlmPort);
      }
      f_connect4SelfOrClientSync();

      f_initialiseSecuredMode();

      if (PICS_MULTIPLE_END_POINT == false) {
        activate(a_default_pki_http());
      } else {
        activate(a_default_pki_http_tlm());
      }
    } // End of function f_cfHttpUp_tlm
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Setups default configuration
     * @param   p_certificate_id The certificate identifier the TA shall use in case of secured IUT
     */
    function f_cfHttpUp_itss(
                             in charstring p_ea_certificate_id := "CERT_TS_A_EA", // TODO Use a constant
                             in charstring p_aa_certificate_id := "CERT_TS_A_AA"
                             ) runs on ItsPkiHttp system ItsPkiHttpSystem {

      if (PICS_MULTIPLE_END_POINT == false) {
        map(self:httpPort, system:httpPort);
      } else {
        map(self:httpEcPort, system:httpEcPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        map(self:httpAtPort, system:httpAtPort);
      }

      f_initialiseSecuredMode(p_ea_certificate_id, p_aa_certificate_id); // TODO To be removed???

      // TODO Duplicate code, use a function
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Setup EA certificate shared with PKI EA entity
      f_readCertificate(p_ea_certificate_id, vc_eaCertificate);
      f_readSigningKey(p_ea_certificate_id, vc_eaPrivateKey); // TODO To be removed
      f_readEncryptingKey(p_ea_certificate_id, vc_eaPrivateEncKey);
      f_getCertificateDigest(p_ea_certificate_id, vc_eaHashedId8);
      f_getCertificateHash(p_ea_certificate_id, vc_eaWholeHash);
      f_getCertificateHash256(p_ea_certificate_id, vc_eaWholeHash256);
      log("f_cfHttpUp_itss: vc_eaPrivateKey= ", vc_eaPrivateKey);
      log("f_cfHttpUp_itss: vc_eaPrivateEncKey= ", vc_eaPrivateEncKey);
      log("f_cfHttpUp_itss: vc_eaHashedId8= ", vc_eaHashedId8);
      log("f_cfHttpUp_itss: vc_eaWholeHash= ", vc_eaWholeHash);
      log("f_cfHttpUp: vc_eaWholeHash256= ", vc_eaWholeHash256);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Setup AA certificate shared with PKI AA entity
      f_readCertificate(p_aa_certificate_id, vc_aaCertificate);
      f_readSigningKey(p_aa_certificate_id, vc_aaPrivateKey); // Required for AuthorizationValidation request
      f_readEncryptingKey(p_aa_certificate_id, vc_aaPrivateEncKey);
      f_getCertificateDigest(p_aa_certificate_id, vc_aaHashedId8);
      f_getCertificateHash(p_aa_certificate_id, vc_aaWholeHash);
      f_getCertificateHash256(p_aa_certificate_id, vc_aaWholeHash256);
      log("f_cfHttpUp_itss: vc_aaPrivateKey= ", vc_aaPrivateKey);
      log("f_cfHttpUp_itss: vc_aaPrivateEncKey= ", vc_aaPrivateEncKey);
      log("f_cfHttpUp_itss: vc_aaHashedId8= ", vc_aaHashedId8);
      log("f_cfHttpUp_itss: vc_aaWholeHash= ", vc_aaWholeHash);
      log("f_cfHttpUp: vc_eaWholeHash256= ", vc_aaWholeHash256);

      // Storage of enrolment keys in case of re-enrolment
      vc_ec_keys_counter := 0;
      vc_ec_counter := 0;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      vc_ec_private_keys := {};
      vc_ec_public_compressed_key := {};
      vc_ec_compressed_modes := {};
      vc_ec_hashed_id8 := {};
      vc_ec_certificates := {};

      if (PICS_MULTIPLE_END_POINT == false) {
        activate(a_default_pki_http());
      } else {
        activate(a_default_pki_http_at());
      }
    } // End of function f_cfHttpUp_itss
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Setups default configuration
     * @param   p_certificate_id The certificate identifier the TA shall use in case of secured IUT
     */
    function f_cfHttpUp_ea(
                           in charstring p_ea_certificate_id := "CERT_TS_A_EA", // TODO Use a constant
                           in charstring p_aa_certificate_id := "CERT_TS_A_AA"
                           ) runs on ItsPkiHttp system ItsPkiHttpSystem {
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      if (PICS_MULTIPLE_END_POINT == false) {
        map(self:httpPort, system:httpPort);
      } else {
        map(self:httpAtVPort, system:httpAtVPort);
      }

      f_initialiseSecuredMode(p_ea_certificate_id, p_aa_certificate_id); // TODO To be removed???

      // TODO Duplicate code, use a function
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Setup EA certificate shared with PKI EA entity
      f_readCertificate(p_ea_certificate_id, vc_eaCertificate);
      f_readSigningKey(p_ea_certificate_id, vc_eaPrivateKey); // TODO To be removed
      f_readEncryptingKey(p_ea_certificate_id, vc_eaPrivateEncKey);
      f_getCertificateDigest(p_ea_certificate_id, vc_eaHashedId8);
      f_getCertificateHash(p_ea_certificate_id, vc_eaWholeHash);
      f_getCertificateHash256(p_aa_certificate_id, vc_eaWholeHash256);
      log("f_cfHttpUp_ea: vc_eaPrivateKey= ", vc_eaPrivateKey);
      log("f_cfHttpUp_ea: vc_eaPrivateEncKey= ", vc_eaPrivateEncKey);
      log("f_cfHttpUp_ea: vc_eaHashedId8= ", vc_eaHashedId8);
      log("f_cfHttpUp_ea: vc_eaWholeHash= ", vc_eaWholeHash);
      log("f_cfHttpUp: vc_aaWholeHash256= ", vc_eaWholeHash256);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Setup AA certificate shared with PKI AA entity
      f_readCertificate(p_aa_certificate_id, vc_aaCertificate);
      f_readSigningKey(p_aa_certificate_id, vc_aaPrivateKey); // Required for AuthorizationValidation request
      f_readEncryptingKey(p_aa_certificate_id, vc_aaPrivateEncKey);
      f_getCertificateDigest(p_aa_certificate_id, vc_aaHashedId8);
      f_getCertificateHash(p_aa_certificate_id, vc_aaWholeHash);
      f_getCertificateHash256(p_aa_certificate_id, vc_aaWholeHash256);
      log("f_cfHttpUp_ea: vc_aaPrivateKey= ", vc_aaPrivateKey);
      log("f_cfHttpUp_ea: vc_aaPrivateEncKey= ", vc_aaPrivateEncKey);
      log("f_cfHttpUp_ea: vc_aaHashedId8= ", vc_aaHashedId8);
      log("f_cfHttpUp_ea: vc_aaWholeHash= ", vc_aaWholeHash);
      log("f_cfHttpUp: vc_aaWholeHash256= ", vc_aaWholeHash256);

      // Storage of enrolment keys in case of re-enrolment
      vc_ec_keys_counter := 0;
      vc_ec_counter := 0;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      vc_ec_private_keys := {};
      vc_ec_public_compressed_key := {};
      vc_ec_compressed_modes := {};
      vc_ec_hashed_id8 := {};
      vc_ec_certificates := {};

      if (PICS_MULTIPLE_END_POINT == false) {
        activate(a_default_pki_http());
      } else {
        activate(a_default_pki_http_atv());
        activate(a_default_pki_http_at());
      }
    } // End of function f_cfHttpUp_ea
    function f_cfUp_itss() runs on ItsPkiItss system ItsPkiItssSystem {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      map(self:geoNetworkingPort, system:geoNetworkingPort);
      map(self:utPort, system:utPort);
      //map(self:acPort, system:acPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      f_initializeState();
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // activate(a_default_pki()); TOTO Defualt from geoNet
    } // End of function f_cfUp_itss

    /**
     * @desc    Deletes default configuration 
     */
    function f_cfMtcDown01(
                           inout ItsPkiItss p_itss,
                           inout ItsPkiHttp p_pki
                           ) runs on ItsMtc {
      disconnect(self:syncPort, mtc:syncPort);
      disconnect(p_itss:syncPort, self:syncPort);
      disconnect(p_pki:syncPort, self:syncPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      disconnect(p_pki:infoPort, p_itss:infoPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      p_itss.done;
      p_pki.done;
    }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_cfMtcDown02(
                           inout ItsPkiHttp p_itss,
                           inout ItsPkiHttp p_ea
                           ) runs on ServerSyncComp {
      disconnect(self:syncPort, mtc:syncPort);
      disconnect(p_itss:syncPort, self:syncPort);
      disconnect(p_ea:syncPort, self:syncPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      p_itss.done;
      p_ea.done;
    }
    function f_cfMtcDown03(
                           inout ItsPkiHttp p_itss,
                           inout ItsPkiHttp p_tlm
                           ) runs on ServerSyncComp {
      disconnect(self:syncPort, mtc:syncPort);
      disconnect(p_itss:syncPort, self:syncPort);
      disconnect(p_tlm:syncPort, self:syncPort);
    function f_cfMtcDown04(
                           inout ItsPkiHttp p_itss,
                           inout ItsPkiHttp p_dc
                           ) runs on ServerSyncComp {
      disconnect(self:syncPort, mtc:syncPort);
      disconnect(p_itss:syncPort, self:syncPort);
      disconnect(p_dc:syncPort, self:syncPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Deletes default configuration 
     */
    function f_cfHttpDown() runs on ItsPkiHttp {
      if (PICS_MULTIPLE_END_POINT == false) {
        unmap(self:httpPort, system:httpPort);
      } else {
        unmap(self:httpEcPort, system:httpEcPort);
        unmap(self:httpAtVPort, system:httpAtVPort);
        unmap(self:httpAtPort, system:httpAtPort);
      }
      f_disconnect4SelfOrClientSync();
      f_uninitialiseSecuredMode();
    } // End of function f_cfHttpDown
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Deletes default configuration 
     */
    function f_cfHttpDown_ca() runs on ItsPkiHttp {
      if (PICS_MULTIPLE_END_POINT == false) {
        unmap(self:httpPort, system:httpPort);
      } else {
        unmap(self:httpCaPort, system:httpCaPort);
      }
      f_disconnect4SelfOrClientSync();
      f_uninitialiseSecuredMode();
    } // End of function f_cfHttpDown_ca
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Deletes default configuration 
     */
    function f_cfHttpDown_tlm() runs on ItsPkiHttp {
      if (PICS_MULTIPLE_END_POINT == false) {
        unmap(self:httpPort, system:httpPort);
      } else {
        unmap(self:httpTlmPort, system:httpTlmPort);
      }
      f_disconnect4SelfOrClientSync();
      f_uninitialiseSecuredMode();
    } // End of function f_cfHttpDown_tlm
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Deletes default configuration 
     */
    function f_cfHttpDown_itss() runs on ItsPkiHttp {
      if (PICS_MULTIPLE_END_POINT == false) {
        unmap(self:httpPort, system:httpPort);
      } else {
        unmap(self:httpEcPort, system:httpEcPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        unmap(self:httpAtPort, system:httpAtPort);
      }
      f_disconnect4SelfOrClientSync();
      f_uninitialiseSecuredMode();
    } // End of function f_cfHttpDown_itss
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Deletes default configuration 
     */
    function f_cfHttpDown_ea() runs on ItsPkiHttp {
      if (PICS_MULTIPLE_END_POINT == false) {
        unmap(self:httpPort, system:httpPort);
      } else {
        unmap(self:httpAtVPort, system:httpAtVPort);
      }
      f_disconnect4SelfOrClientSync();
      f_uninitialiseSecuredMode();
    } // End of function f_cfHttpDown_ea
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc    Deletes default configuration 
     */
    function f_cfDown_itss() runs on ItsPkiItss system ItsPkiItssSystem {
      unmap(self:geoNetworkingPort, system:geoNetworkingPort);
      unmap(self:utPort, system:utPort);
      //unmap(self:acPort, system:acPort);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_cfDown
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc Initialise secure mode if required
     */
    function f_initialiseSecuredMode(
                                     in charstring p_certificate_id  := "CERT_TS_A_EA", // TODO Use a constant
                                     in charstring p_peerCertificateId := "CERT_IUT_A_EA"
                                     ) runs on ItsSecurityBaseComponent {
      if(not(f_loadCertificates(PX_IUT_SEC_CONFIG_NAME))) {
        log("*** INFO: TEST CASE NOW STOPPING ITSELF! ***");
        setverdict(inconc);
        stop;
      }
    } // End of function f_initialiseSecuredMode()
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_uninitialiseSecuredMode() runs on ItsSecurityBaseComponent {
      f_unloadCertificates();
    } // End of function f_uninitialiseSecuredMode()
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_initializeState() runs on ItsPkiItss {
      var Oct8 v_hashedId8ToBeUsed;

      log(">>> f_initializeState: vc_hashedId8ToBeUsed= ", vc_hashedId8ToBeUsed);
      v_hashedId8ToBeUsed := f_setupIutCertificate(vc_hashedId8ToBeUsed);
      log("f_initializeState: v_hashedId8ToBeUsed= ", v_hashedId8ToBeUsed);

      f_utInitializeIut(UtPkiInitialize: { v_hashedId8ToBeUsed } );

      f_sleep(PX_NEIGHBOUR_DISCOVERY_DELAY);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      //      f_acLoadScenario(p_scenario);
      //      f_acStartScenario();
    }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of pkiConfigurationFunctions

  group ut_port {

    function f_utInitializeIut(template (value) UtPkiInitialize p_init) runs on ItsPkiItss {
      utPort.send(p_init);
      tc_wait.start;
      alt {
        [] utPort.receive(UtPkiResults: { utPkiInitializeResult := true }) {
          tc_wait.stop;
          log("*** f_utInitializeIut: INFO: IUT initialized ***");
        }
        [] utPort.receive {
          tc_wait.stop;
          log("*** f_utInitializeIut: INFO: IUT could not be initialized ***");
          f_selfOrClientSyncAndVerdict("error", e_error);
        }
        [] tc_wait.timeout {
          log("*** f_utInitializeIut: INFO: IUT could not be initialized in time ***");
          f_selfOrClientSyncAndVerdict("error", e_timeout);
        }
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_utInitializeIut
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_sendUtTriggerEnrolmentRequestPrimitive(
                                                      in octetstring p_canonical_id := ''O,
                                                      in Oct1 p_enc_algorithm := '00'O,
                                                      in octetstring p_private_key := ''O,
                                                      in octetstring p_public_key_compressed := ''O,
                                                      in integer p_compressed_mode := 0
                                                      ) runs on ItsPkiItss {
      var TriggerEnrolmentRequest v_ut_trigger_enrolment_request;
      var octetstring v_compressed_public_key;

      if (p_compressed_mode == 2) { // TODO v_compressed_public_key := int2oct(p_compressed_mode, 1) & p_public_key_compressed?
        v_compressed_public_key := '02'O & p_public_key_compressed;
      } else {
        v_compressed_public_key := '03'O & p_public_key_compressed;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      v_ut_trigger_enrolment_request := { p_canonical_id, p_enc_algorithm, p_private_key, v_compressed_public_key };
      utPort.send(UtPkiTrigger: { triggerEnrolmentRequest := v_ut_trigger_enrolment_request });
      tc_ac.start;
      alt {
        [] utPort.receive(UtPkiResults: { utPkiTriggerResult := true }) {
          tc_ac.stop;
        }
        [] utPort.receive(UtPkiResults: { utPkiTriggerResult := false }) {
          tc_ac.stop;
          log("*** f_sendUtTriggerEnrolmentRequestPrimitive: ERROR: Received unexpected message ***");
          f_selfOrClientSyncAndVerdict("error", e_error);
        }
        [] utPort.receive {
          log("*** f_sendUtTriggerEnrolmentRequestPrimitive: INFO: Some message received in UT Port ***");
          repeat;
        }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        [] tc_ac.timeout {
          log("*** f_sendAcPkiPrimitive: ERROR: Timeout while waiting for adapter control event result ***");
          f_selfOrClientSyncAndVerdict("error", e_timeout);
        }
      } // End of 'alt' statement
    } // End of function f_sendUtTriggerEnrolmentRequestPrimitive
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_sendUtTriggerAuthorizationRequestPrimitive(
                                                          in octetstring p_canonical_id := ''O,
                                                          in Oct1 p_enc_algorithm := '00'O,
                                                          in octetstring p_private_key := ''O,
                                                          in octetstring p_public_key_compressed := ''O,
                                                          in integer p_compressed_mode := 0
                                                          ) runs on ItsPkiItss {
      var TriggerAuthorizationRequest v_ut_trigger_enrolment_request;
      var octetstring v_compressed_public_key;

      if (p_compressed_mode == 2) { // TODO v_compressed_public_key := int2oct(p_compressed_mode, 1) & p_public_key_compressed?
        v_compressed_public_key := '02'O & p_public_key_compressed;
      } else {
        v_compressed_public_key := '03'O & p_public_key_compressed;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      v_ut_trigger_enrolment_request := { p_canonical_id, p_enc_algorithm, p_private_key, v_compressed_public_key };
      utPort.send(UtPkiTrigger: { triggerAuthorizationRequest := v_ut_trigger_enrolment_request });
      tc_ac.start;
      alt {
        [] utPort.receive(UtPkiResults: { utPkiTriggerResult := true }) {
          tc_ac.stop;
        }
        [] utPort.receive(UtPkiResults: { utPkiTriggerResult := false }) {
          tc_ac.stop;
          log("*** f_sendUtTriggerAuthorizationRequestPrimitive: ERROR: Received unexpected message ***");
          f_selfOrClientSyncAndVerdict("error", e_error);
        }
        [] utPort.receive(UtPkiTriggerInd:?) {
          log("*** f_sendUtTriggerAuthorizationRequestPrimitive: INFO: Received UtPkiTriggerInd message ***");
          repeat;
        }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        [] tc_ac.timeout {
          log("*** f_sendAcPkiPrimitive: ERROR: Timeout while waiting for adapter control event result ***");
          f_selfOrClientSyncAndVerdict("error", e_timeout);
        }
      } // End of 'alt' statement
    } // End of function f_sendUtTriggerAuthorizationRequestPrimitive
    function f_sendUtTriggerUpdateEctl(template (value) charstring p_ectl_uri) runs on ItsPkiItss {
      utPort.send(UtPkiTrigger: { triggerUpdateEctl := { ectl_uri := p_ectl_uri } });
      tc_wait.start;
      alt {
        [] utPort.receive(UtPkiResults: { utPkiTriggerResult := true }) {
          tc_wait.stop;
          log("*** f_sendUtTriggerUpdateEctl: INFO: IUT has updated ECTL ***");
        }
        [] utPort.receive {
          tc_wait.stop;
          log("*** f_sendUtTriggerUpdateEctl: INFO: IUT could not update ECTL ***");
          f_selfOrClientSyncAndVerdict("error", e_error);
        }
        [] tc_wait.timeout {
          log("*** f_sendUtTriggerUpdateEctl: INFO: IUT could not update ECTL in time ***");
          f_selfOrClientSyncAndVerdict("error", e_timeout);
        }
      }
    } // End of function f_sendUtTriggerUpdateEctl
    function f_sendUtTriggerRequestForTlmCtl(template (value) charstring p_tlm_ctl_uri) runs on ItsPkiItss {
      utPort.send(UtPkiTrigger: { triggerRequestForTlmCtl := { tlm_ctl_uri := p_tlm_ctl_uri } });
      tc_wait.start;
      alt {
        [] utPort.receive(UtPkiResults: { utPkiTriggerResult := true }) {
          tc_wait.stop;
          log("*** f_sendUtTriggerRequestForTlmCtl: INFO: IUT has updated ECTL ***");
        }
        [] utPort.receive {
          tc_wait.stop;
          log("*** f_sendUtTriggerRequestForTlmCtl: INFO: IUT could not update ECTL ***");
          f_selfOrClientSyncAndVerdict("error", e_error);
        }
        [] tc_wait.timeout {
          log("*** f_sendUtTriggerRequestForTlmCtl: INFO: IUT could not update ECTL in time ***");
          f_selfOrClientSyncAndVerdict("error", e_timeout);
        }
      }
    } // End of function f_sendUtTriggerRequestForTlmCtl
    function f_sendUtTriggerRequestForRcaCtl(template (value) charstring p_tlm_ctl_uri) runs on ItsPkiItss {
      utPort.send(UtPkiTrigger: { triggerRequestForRcaCtl := { tlm_ctl_uri := p_tlm_ctl_uri } });
      tc_wait.start;
      alt {
        [] utPort.receive(UtPkiResults: { utPkiTriggerResult := true }) {
          tc_wait.stop;
          log("*** f_sendUtTriggerRequestForRcaCtl: INFO: IUT has updated ECTL ***");
        }
        [] utPort.receive {
          tc_wait.stop;
          log("*** f_sendUtTriggerRequestForRcaCtl: INFO: IUT could not update ECTL ***");
          f_selfOrClientSyncAndVerdict("error", e_error);
        }
        [] tc_wait.timeout {
          log("*** f_sendUtTriggerRequestForRcaCtl: INFO: IUT could not update ECTL in time ***");
          f_selfOrClientSyncAndVerdict("error", e_timeout);
        }
      }
    } // End of function f_sendUtTriggerRequestForRcaCtl
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group ut_port

  group helpers {

    function f_decode_EccP256CurvePoint(
                                        in octetstring buf,
                                        out EccP256CurvePoint p
    ) runs on ItsPkiHttp return boolean  {
        var integer ptype := oct2int(buf[0] and4b '7F'O);
        if(lengthof(buf) == 33){
          if (ptype == 0)       {p.x_only := substr(buf, 1, 32);}
          else if (ptype == 2)  {p.compressed_y_0 := substr(buf, 1, 32);}
          else if (ptype == 3)  {p.compressed_y_1 := substr(buf, 1, 32);}
          else {
            log("f_decode_EccP256CurvePoint: unsupported value for point type ", ptype);
            return false;
          }
        }else if(lengthof(buf) == 65){
          if (ptype == 4) {
            p.uncompressedP256.x := substr(buf, 1, 32);
            p.uncompressedP256.y := substr(buf, 33, 32);
          }else{
            log("f_decode_EccP256CurvePoint: unsupported value for point type ", ptype);
            return false;
          }
        }else{
          log("f_decode_EccP256CurvePoint: wrong buffer length ", lengthof(buf));
          return false;
        }
        return true;
    }

    function f_decode_EccP384CurvePoint(
                                        in octetstring buf,
                                        out EccP384CurvePoint p
    ) runs on ItsPkiHttp return boolean  {
        var integer ptype := oct2int(buf[0] and4b '7F'O);
        if(lengthof(buf) == 49){
          if (ptype == 0)       {p.x_only := substr(buf, 1, 48);}
          else if (ptype == 2)  {p.compressed_y_0 := substr(buf, 1, 48);}
          else if (ptype == 3)  {p.compressed_y_1 := substr(buf, 1, 48);}
          else {
            log("f_decode_EccP384CurvePoint: unsupported value for point type ", ptype);
            return false;
          }
        }else if(lengthof(buf) == 97){
          if (ptype == 4) {
            p.uncompressedP384.x := substr(buf, 1, 48);
            p.uncompressedP384.y := substr(buf, 49, 48);
          }else{
            log("f_decode_EccP256CurvePoint: unsupported value for point type ", ptype);
            return false;
          }
        }else{
          log("f_decode_EccP256CurvePoint: wrong buffer length ",lengthof(buf));
          return false;
        }
        return true;
    }

    function f_get_canonical_itss_key(
                                      out PublicVerificationKey p_key
                                      ) runs on ItsPkiHttp return boolean {
      log("f_get_canonical_itss_key: PX_VE_ALG=", PX_VE_ALG);
      if (PX_VE_ALG == e_nist_p256) {
        return f_decode_EccP256CurvePoint(PICS_ITS_S_SIGN_NISTP256_PUBLIC_KEY, p_key.ecdsaNistP256);
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        return f_decode_EccP256CurvePoint(PICS_ITS_S_SIGN_BRAINPOOLP256r1_PUBLIC_KEY, p_key.ecdsaNistP256);
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        return f_decode_EccP384CurvePoint(PICS_ITS_S_SIGN_BRAINPOOLP384r1_PUBLIC_KEY, p_key.ecdsaNistP256);
      }
      return false;
    }

ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_key_pair(
                                 out octetstring p_private_key,
                                 out octetstring p_public_key_x,
                                 out octetstring p_public_key_y,
                                 out octetstring p_public_key_compressed,
                                 out integer p_compressed_mode
                                 ) return boolean {
      log(">>> f_generate_key_pair: PX_VE_ALG=", PX_VE_ALG);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (PX_VE_ALG == e_nist_p256) {
        f_generate_key_pair_nistp256(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        f_generate_key_pair_brainpoolp256r1(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
      } else if (PX_VE_ALG == e_sm2_p256) {
        f_generate_key_pair_sm2p256(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        f_generate_key_pair_brainpoolp384r1(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
      } else if (PX_VE_ALG == e_nist_p384) {
        f_generate_key_pair_nistp384(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        // error
        return false;
      }

      log("<<< f_generate_key_pair: p_compressed_mode=", p_compressed_mode);
      return true;
    }

    function f_generate_key_pair_for_encryption(
                                                in SignAlgorithm p_algorithm,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                out octetstring p_private_key,
                                                out octetstring p_public_key_x,
                                                out octetstring p_public_key_y,
                                                out octetstring p_public_key_compressed,
                                                out integer p_compressed_mode
                                                ) return boolean {
      if (p_algorithm == e_nist_p256) {
        f_generate_key_pair_nistp256(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
      } else if (p_algorithm == e_brainpool_p256_r1) {
        f_generate_key_pair_brainpoolp256r1(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
      } else if (p_algorithm == e_sm2_p256) {
        f_generate_key_pair_sm2p256(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        // error
        return false;
      }

      return true;
    } // End of function f_generate_key_pair_for_encryption

    function f_http_restart(
                            in charstring p_content_text
                            ) runs on ItsPkiHttp {
      if (not(PICS_MULTIPLE_END_POINT)) {
        log("f_http_restart: restart httpPort");
        httpPort.stop;
        httpPort.start;
      } else {
        log("f_http_restart: restart httpPort with contentType ", p_content_text);
        select(p_content_text){
          case ("inner_ec_request"){
            httpEcPort.stop;
            httpEcPort.start;
          }
          case ("inner_atv_request"){
            httpAtVPort.stop;
            httpAtVPort.start;
          }
        }
      }
    } // End of function f_http_restart
ASN.1 Documenter's avatar
ASN.1 Documenter committed

    function f_http_send(
                         in Headers p_headers,
                         in template (value) HttpMessage p_http_message
                         ) runs on ItsPkiHttp {
      log(">>> f_http_send: ", p_http_message);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (not(PICS_MULTIPLE_END_POINT)) {
        httpPort.send(p_http_message);
      } else {
        var charstring_list v_content_text;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        f_get_header(p_headers, c_header_content_text, v_content_text);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        if (not(isvalue(v_content_text))) {
          log("f_http_send: Failed to send message: header not found: ", c_header_content_text);
          return;
        }
        if (v_content_text == { "inner_ec_request" }) {
          log("f_http_send: Send on EC end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_EC }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpEcPort.send(p_http_message);
        } else if (v_content_text == { "inner_atv_request" }) {
          log("f_http_send: Send on ATV end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_ATV }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpAtVPort.send(p_http_message);
        } else if (v_content_text == { "inner_atv_response" }) {
          log("f_http_send: Send on ATV end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_ATV }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpAtVPort.send(p_http_message);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else if (v_content_text == { "inner_at_request" }) {
          log("f_http_send: Send on AT end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_AT }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpAtPort.send(p_http_message);
        } else if (v_content_text == { "bfk_auth_request" }) {
          log("f_http_send: Send on EC end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_EC }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpEcPort.send(p_http_message);
        } else if (v_content_text == { "bfk_cert_request" }) {
          log("f_http_send: Send on AT end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_AT }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpEcPort.send(p_http_message);
        } else if (v_content_text == { "bfk_at_download_request" }) {
          log("f_http_send: Send on EC end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_EC }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpEcPort.send(p_http_message);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else if (v_content_text == { "ca_request" }) {
          log("f_http_send: Send on CA end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_CA }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpCaPort.send(p_http_message);
        } else if (v_content_text == { "ca_response" }) {
          log("f_http_send: Send on CA end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_CA }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpCaPort.send(p_http_message);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else if (v_content_text == { "tlm_request" }) {
          log("f_http_send: Send on TLM end point");
          f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_TLM }, p_headers);
          if (ischosen(p_http_message.request)) {
            p_http_message.request.header := p_headers;
          } else {
            p_http_message.response.header := p_headers;
          }
          httpTlmPort.send(p_http_message);
        } else {
          log("f_http_send: Invalid header value: ", v_content_text);
        }
      }
    } // End of function f_http_send

    function f_generate_key_tag(
                                in octetstring p_public_key_compressed,
                                in integer p_compressed_key_mode,
                                in octetstring p_public_compressed_enc_key,
                                in integer p_compressed_enc_key_mode,
                                out octetstring p_encoded_tag
                                ) return boolean {
      // Local variables
      var PublicVerificationKey v_verification_tag;
      var PublicEncryptionKey v_encryption_tag;

      log(">>> f_generate_key_tag: p_public_key_compressed=", p_public_key_compressed);
      log(">>> f_generate_key_tag: p_public_compressed_enc_key=", p_public_compressed_enc_key);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (PX_VE_ALG == e_nist_p256) {
        if (p_compressed_key_mode == 0) {
          v_verification_tag.ecdsaNistP256.compressed_y_0 := p_public_key_compressed;
        } else {
          v_verification_tag.ecdsaNistP256.compressed_y_1 := p_public_key_compressed;
        }
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        if (p_compressed_key_mode == 0) {
          v_verification_tag.ecdsaBrainpoolP256r1.compressed_y_0 := p_public_key_compressed;
        } else {
          v_verification_tag.ecdsaBrainpoolP256r1.compressed_y_1 := p_public_key_compressed;
        }
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        if (p_compressed_key_mode == 0) {
          v_verification_tag.ecdsaBrainpoolP384r1.compressed_y_0 := p_public_key_compressed;
        } else {
          v_verification_tag.ecdsaBrainpoolP384r1.compressed_y_1 := p_public_key_compressed;
        }
      } else if (PX_VE_ALG == e_nist_p384) {
        if (p_compressed_key_mode == 0) {
          v_verification_tag.ecdsaNistP384.compressed_y_0 := p_public_key_compressed;
        } else {
          v_verification_tag.ecdsaNistP384.compressed_y_1 := p_public_key_compressed;
        }
      } else if (PX_VE_ALG == e_sm2_p256) {
        if (p_compressed_key_mode == 0) {
          v_verification_tag.ecsigSm2.compressed_y_0 := p_public_key_compressed;
        } else {
          v_verification_tag.ecsigSm2.compressed_y_1 := p_public_key_compressed;
        }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        log("f_generate_key_tag: Failed to generate HMAC tag");
        return false;
      }
      log("f_generate_key_tag: v_verification_tag= ", v_verification_tag);
      p_encoded_tag := bit2oct(encvalue(v_verification_tag));
      if (PX_INCLUDE_ENCRYPTION_KEYS) {
        v_encryption_tag.supportedSymmAlg := aes128Ccm;
        if (PX_EC_ALG_FOR_EC_SIGN == e_nist_p256) {
          if (p_compressed_enc_key_mode == 0) {
            v_encryption_tag.publicKey.eciesNistP256.compressed_y_0 := p_public_compressed_enc_key;
          } else {
            v_encryption_tag.publicKey.eciesNistP256.compressed_y_1 := p_public_compressed_enc_key;
          }
        } else if (PX_EC_ALG_FOR_EC_SIGN == e_brainpool_p256_r1) {
          if (p_compressed_enc_key_mode == 0) {
            v_encryption_tag.publicKey.eciesBrainpoolP256r1.compressed_y_0 := p_public_compressed_enc_key;
          } else {
            v_encryption_tag.publicKey.eciesBrainpoolP256r1.compressed_y_1 := p_public_compressed_enc_key;
          }
        } else if (PX_EC_ALG_FOR_EC_SIGN == e_sm2_p256) { // FIXME FSCOM
          if (p_compressed_enc_key_mode == 0) {
            v_encryption_tag.publicKey.ecencSm2.compressed_y_0 := p_public_compressed_enc_key;
          } else {
            v_encryption_tag.publicKey.ecencSm2.compressed_y_1 := p_public_compressed_enc_key;
          }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else {
          log("f_generate_key_tag: Failed to generate HMAC tag (enc)");
          return false;
        }
        log("f_generate_key_tag: v_encryption_tag= ", v_encryption_tag);
        p_encoded_tag := p_encoded_tag & bit2oct(encvalue(v_encryption_tag));
      }

      return true;
    } // End of function f_generate_key_tag
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group helpers

  group http { // TODO Split into EnnerEc, Authorization, AuthorizationValidation and bfk
ASN.1 Documenter's avatar
ASN.1 Documenter committed

    function f_http_build_inner_ec_request( // TODO Cleanup parameters
                                           out octetstring p_private_key,
                                           out octetstring p_public_key_compressed,
                                           out integer p_compressed_mode,
                                           out Oct16 p_aes_sym_key,
                                           out Oct16 p_encrypted_sym_key,
                                           out Oct16 p_authentication_vector,
                                           out Oct12 p_nonce,
                                           out octetstring p_salt,
                                           out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                           out Oct32 p_request_hash
                                           ) runs on ItsPkiHttp {
      var InnerEcRequest v_inner_ec_request;
      var Ieee1609Dot2Data v_inner_ec_request_signed_for_pop;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var boolean v_result;

      log(">>> f_http_build_inner_ec_request");
      log ("f_http_build_inner_ec_request: vc_ec_keys_counter: ", vc_ec_keys_counter);
      log ("f_http_build_inner_ec_request: vc_ec_private_keys: ", vc_ec_private_keys);
      log ("f_http_build_inner_ec_request: vc_ec_counter: ", vc_ec_counter);

ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (f_generate_inner_ec_request(p_private_key, p_public_key_compressed, p_compressed_mode, v_inner_ec_request) == false) {
        log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequest ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log ("f_http_build_inner_ec_request: ==> EC verification private key: ", p_private_key);
      log ("f_http_build_inner_ec_request: ==> EC verification public compressed key: ", p_public_key_compressed);
      log ("f_http_build_inner_ec_request: ==> EC verification public compressed mode: ", p_compressed_mode);
      // Store enrolment keys for re-enrolment
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      vc_ec_private_keys[vc_ec_keys_counter] := p_private_key;
      vc_ec_public_compressed_key[vc_ec_keys_counter] := p_public_key_compressed;
      vc_ec_compressed_modes[vc_ec_keys_counter] := p_compressed_mode;
      vc_ec_keys_counter := vc_ec_keys_counter + 1;
      // Generate InnerEcRequestSignedForPoP
      if (f_generate_inner_ec_request_signed_for_pop(p_private_key, v_inner_ec_request, v_inner_ec_request_signed_for_pop) == false) {
        log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log("f_http_build_inner_ec_request: v_inner_ec_request_signed_for_pop= ", v_inner_ec_request_signed_for_pop);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Secure InnerEcRequestSignedForPoP message
      if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_inner_ec_request: ERROR: Non canonical EA certificate ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log("f_http_build_inner_ec_request: Public encryption key: ", v_public_enc_key);
      log("f_http_build_inner_ec_request: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_eaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      log("f_http_build_inner_ec_request: vc_ec_keys_counter: ", vc_ec_keys_counter);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if ((PICS_SECPKI_REENROLMENT == false) or (vc_ec_keys_counter == 1)) { // This is the first enrolment, we used Factory keys
        var octetstring v_private_key;
        if (PX_VE_ALG == e_nist_p256) {
          v_private_key := PICS_ITS_S_SIGN_NITSP256_PRIVATE_KEY;
        } else if (PX_VE_ALG == e_brainpool_p256_r1) {
          v_private_key := PICS_ITS_S_SIGN_BRAINPOOLP256r1_PRIVATE_KEY;
        } else if (PX_VE_ALG == e_sm2_p256) {
          v_private_key := PICS_ITS_S_SIGN_SM2P256_PRIVATE_KEY;
        } else if (PX_VE_ALG == e_nist_p384) {
          v_private_key := PICS_ITS_S_SIGN_NISTP384_PRIVATE_KEY;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        } else {
          v_private_key := PICS_ITS_S_SIGN_BRAINPOOLP384r1_PRIVATE_KEY;
        }
        v_result := f_build_pki_secured_request_message_signed_with_pop(v_private_key, valueof(m_signerIdentifier_self), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop))), PX_EC_ALG_FOR_EC, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
      } else { // We use last valid EC certificate
        // TODO Retrieve EC certificate from the first enrolment instead of PX
        log("f_http_build_inner_ec_request: v_ec_private_key: ", vc_ec_private_keys[vc_ec_keys_counter - 1]);
        log("f_http_build_inner_ec_request: v_ec_public_compressed_key: ", vc_ec_public_compressed_key[vc_ec_keys_counter - 1]);
        log("f_http_build_inner_ec_request: v_ec_compressed_modes: ", vc_ec_compressed_modes[vc_ec_keys_counter - 1]);
        log("f_http_build_inner_ec_request: v_ec_hashed_id8: ", vc_ec_hashed_id8[vc_ec_keys_counter - 1]);
        v_result := f_build_pki_secured_request_message_signed_with_pop(vc_ec_private_keys[vc_ec_keys_counter - 1], valueof(m_signerIdentifier_digest(vc_ec_hashed_id8[vc_ec_keys_counter - 1])), vc_ec_hashed_id8[vc_ec_keys_counter - 1]/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop))), PX_EC_ALG_FOR_EC, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      if (v_result == false) {
        log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      } else {
        log("f_http_build_inner_ec_request: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
        log("f_http_build_inner_ec_request: p_request_hash= ", p_request_hash);
      }
    } // End of function f_http_build_inner_ec_request

    function f_http_build_inner_ec_request_with_wrong_parameters( // TODO Cleanup parameters
                                                                 in SequenceOfPsidSsp p_appPermissions,
                                                                 in octetstring p_canonical_id := PICS_ITS_S_CANONICAL_ID,
                                                                 in Time32 p_start,
                                                                 in Duration p_duration,
                                                                 in boolean p_alter_private_key := false,
                                                                 out octetstring p_private_key,
                                                                 out octetstring p_public_key_compressed,
                                                                 out integer p_compressed_mode,
                                                                 out Oct16 p_aes_sym_key,
                                                                 out Oct16 p_encrypted_sym_key,
                                                                 out Oct16 p_authentication_vector,
                                                                 out Oct12 p_nonce,
                                                                 out octetstring p_salt,
                                                                 out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                                 out Oct32 p_request_hash
                                                                 ) runs on ItsPkiHttp {
      var InnerEcRequest v_inner_ec_request;
      var Ieee1609Dot2Data v_inner_ec_request_signed_for_pop;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var boolean v_result;

      log(">>> f_http_build_inner_ec_request_with_wrong_parameters");
      if (f_generate_inner_ec_request_with_wrong_parameters(p_appPermissions, p_canonical_id, p_start, p_duration, p_alter_private_key, p_private_key, p_public_key_compressed, p_compressed_mode, v_inner_ec_request) == false) {
        log("*** f_http_build_inner_ec_request_with_wrong_parameters: ERROR: Failed to generate InnerEcRequest ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log ("f_http_build_inner_ec_request_with_wrong_parameters: ==> EC verification private key: ", p_private_key);
      log ("f_http_build_inner_ec_request_with_wrong_parameters: ==> EC verification public compressed key: ", p_public_key_compressed);
      log ("f_http_build_inner_ec_request_with_wrong_parameters: ==> EC verification public compressed mode: ", p_compressed_mode);
      // Generate InnerEcRequestSignedForPoP
      if (f_generate_inner_ec_request_signed_for_pop(p_private_key, v_inner_ec_request, v_inner_ec_request_signed_for_pop) == false) {
        log("*** f_http_build_inner_ec_request_with_wrong_parameters: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log("f_http_build_inner_ec_request_with_wrong_parameters: v_inner_ec_request_signed_for_pop= ", v_inner_ec_request_signed_for_pop);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Secure InnerEcRequestSignedForPoP message
      if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_inner_ec_request_with_wrong_parameters: ERROR: Non canonical EA certificate ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log("f_http_build_inner_ec_request_with_wrong_parameters: Public encryption key: ", v_public_enc_key);
      log("f_http_build_inner_ec_request_with_wrong_parameters: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_eaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      var octetstring v_private_key;
      if (PX_VE_ALG == e_nist_p256) {
        v_private_key := PICS_ITS_S_SIGN_NITSP256_PRIVATE_KEY;
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        v_private_key := PICS_ITS_S_SIGN_BRAINPOOLP256r1_PRIVATE_KEY;
      } else if (PX_VE_ALG == e_sm2_p256) {
        v_private_key := PICS_ITS_S_SIGN_SM2P256_PRIVATE_KEY;
      } else if (PX_VE_ALG == e_nist_p384) {
        v_private_key := PICS_ITS_S_SIGN_NISTP384_PRIVATE_KEY;
      } else {
        v_private_key := PICS_ITS_S_SIGN_BRAINPOOLP384r1_PRIVATE_KEY;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      v_result := f_build_pki_secured_request_message_signed_with_pop(v_private_key, valueof(m_signerIdentifier_self), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop))), PX_EC_ALG_FOR_EC, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (v_result == false) {
        log("*** f_http_build_inner_ec_request_with_wrong_parameters: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      } else {
        log("f_http_build_inner_ec_request_with_wrong_parameters: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
        log("f_http_build_inner_ec_request_with_wrong_parameters: p_request_hash= ", p_request_hash);
      }
    } // End of function f_http_build_inner_ec_request_with_wrong_parameters

    function f_http_build_invalid_enrolment_request(
                                                    out octetstring p_private_key,
                                                    out octetstring p_public_key_compressed,
                                                    out integer p_compressed_mode,
                                                    out Oct16 p_aes_sym_key,
                                                    out Oct16 p_encrypted_sym_key,
                                                    out Oct16 p_authentication_vector,
                                                    out Oct12 p_nonce,
                                                    out octetstring p_salt,
                                                    out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                    out Oct32 p_request_hash
                                                    ) runs on ItsPkiHttp {
      var InnerEcRequest v_inner_ec_request;
      var Ieee1609Dot2Data v_inner_ec_request_signed_for_pop;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var boolean v_ret_code;
      var octetstring v_private_key;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (f_generate_inner_ec_request(p_private_key, p_public_key_compressed, p_compressed_mode, v_inner_ec_request) == false) {
        log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequest ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log ("f_http_build_invalid_enrolment_request: EC verification private key: ", p_private_key);
      log ("f_http_build_invalid_enrolment_request: EC verification public compressed key: ", p_public_key_compressed);
      log ("f_http_build_invalid_enrolment_request: EC verification public compressed mode: ", p_compressed_mode);
      // Generate InnerEcRequestSignedForPoP
      if (f_generate_inner_ec_request_signed_for_pop(p_private_key, v_inner_ec_request, v_inner_ec_request_signed_for_pop) == false) {
        log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log("f_http_build_invalid_enrolment_request: v_inner_ec_request_signed_for_pop= ", v_inner_ec_request_signed_for_pop);
      // Modify signature to get an error
      if (ischosen(v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaNistP256Signature)) {
        v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaNistP256Signature.sSig[1] := bit2oct('10101010'B xor4b oct2bit(v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaNistP256Signature.sSig[1]));
      } else if (ischosen(v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) {
        v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig[1] := bit2oct('10101010'B xor4b oct2bit(v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig[1]));
      } else {
        v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.sSig[1] := bit2oct('10101010'B xor4b oct2bit(v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.sSig[1]));
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Secure InnerEcRequestSignedForPoP message
      if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_invalid_enrolment_request: ERROR: Non canonical EA certificate ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log("*** f_http_build_invalid_enrolment_request: Public encryption key: ", v_public_enc_key);
      log("*** f_http_build_invalid_enrolment_request: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_eaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      if (PX_VE_ALG == e_nist_p256) {
        v_private_key := PICS_ITS_S_SIGN_NITSP256_PRIVATE_KEY;
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        v_private_key := PICS_ITS_S_SIGN_BRAINPOOLP256r1_PRIVATE_KEY;
      } else if (PX_VE_ALG == e_sm2_p256) {
        v_private_key := PICS_ITS_S_SIGN_SM2P256_PRIVATE_KEY;
      } else if (PX_VE_ALG == e_nist_p384) {
        v_private_key := PICS_ITS_S_SIGN_NISTP384_PRIVATE_KEY;
      } else {
        v_private_key := PICS_ITS_S_SIGN_BRAINPOOLP384r1_PRIVATE_KEY;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      v_ret_code := f_build_pki_secured_request_message_signed_with_pop(v_private_key, valueof(m_signerIdentifier_self), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop))), PX_EC_ALG_FOR_EC, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (v_ret_code == false) {
        log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log("*** f_http_build_invalid_enrolment_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data = ", p_ieee1609dot2_signed_and_encrypted_data);
    } // End of function f_http_build_invalid_enrolment_request

    function f_http_build_inner_ec_response(
                                            in template (omit) InnerEcRequest p_inner_ec_request := omit,
                                            in EnrolmentResponseCode p_responseCode := ok,
                                            in Oct16 p_request_hash,
                                            in octetstring p_private_key := ''O,
                                            in octetstring p_digest := ''O,
                                            in Oct16 p_aes_sym_key,
                                            out EtsiTs103097Certificate p_ec_certificate,
                                            out HashedId8 p_ec_certificate_hashed_id8,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                            out InnerEcResponse p_inner_ec_response,
                                            out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
                                            ) return boolean {
      // Local variables
      var bitstring v_msg_bit;
      var octetstring v_msg;
      var Oct12 v_nonce;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var boolean p_result := false;

      log(">>> f_http_build_inner_ec_response: p_inner_ec_request= ", p_inner_ec_request);
      log(">>> f_http_build_inner_ec_response: p_responseCode= ", p_responseCode);
      log(">>> f_http_build_inner_ec_response: p_request_hash= ", p_request_hash);
      log(">>> f_http_build_inner_ec_response: p_private_key= ", p_private_key);
      log(">>> f_http_build_inner_ec_response: p_digest= ", p_digest);
      log(">>> f_http_build_inner_ec_response: p_aes_sym_key= ", p_aes_sym_key);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Check expectred response
      if (p_responseCode != ok) {
        p_inner_ec_response := valueof(
                                       m_innerEcResponse_ko(
                                                            p_request_hash,
                                                            p_responseCode
                                                            )
                                       );
        p_result := true;
      } else {
        // Generate the certificate
        if (f_generate_ec_certificate_for_inner_ec_response(valueof(p_inner_ec_request), p_private_key, p_digest, p_ec_certificate, p_ec_certificate_hashed_id8) == false) {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
          log("f_http_build_inner_ec_response: Failed to generate the certificate");
          p_inner_ec_response := valueof(
                                         m_innerEcResponse_ko(
                                                              p_request_hash,
                                                              incompleterequest
                                                              )
                                         );
        } else {
          p_inner_ec_response := valueof(
                                         m_innerEcResponse_ok(
                                                              p_request_hash,
                                                              p_ec_certificate
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                              )
                                         );
        }
      }

      // Secure the response
      log("f_http_build_inner_ec_response: p_inner_ec_response= ", p_inner_ec_response);
      v_msg := bit2oct(encvalue(m_etsiTs102941Data_inner_ec_response(p_inner_ec_response)));
      v_nonce := substr(f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 16)), 0, 12); // Random value
      // TODO Consider  Sha384: m_signerIdentifier_digest(f_hashedId8FromSha384(p_digest))
      if (f_build_pki_secured_response_message(p_private_key,
                                               valueof(m_signerIdentifier_digest(f_hashedId8FromSha256(p_digest))),//  in SignerIdentifier p_signer_identifier,
                                               v_msg,
                                               p_aes_sym_key,
                                               v_nonce,
                                               p_ieee1609dot2_signed_and_encrypted_data
                                               ) == false) {
        log("f_http_build_inner_ec_response: Failed to generate the certificate");
        p_inner_ec_response := valueof(
                                       m_innerEcResponse_ko(
                                                            p_request_hash,
                                                            deniedrequest
                                                            )
                                       );
      } else {
        p_result := true;
      }

      return p_result;
    } // End of function f_http_build_inner_ec_response
    function f_http_build_error_ec_response(
                                            in EnrolmentResponseCode p_responseCode := ok,
                                            in Oct16 p_request_hash,
                                            in octetstring p_private_key := ''O,
                                            in octetstring p_digest := ''O,
                                            in Oct16 p_aes_sym_key,
                                            out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
                                            ) return boolean {
      // Local variables
      var octetstring v_msg;
      var Oct12 v_nonce;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var boolean p_result := false;
      var InnerEcResponse v_inner_ec_response;

      // Check expectred response
      if (p_responseCode == ok) {
        return false;
      }
      v_inner_ec_response := valueof(
                                      m_innerEcResponse_ko(
                                                          p_request_hash,
                                                          p_responseCode
                                                          )
                                      );
      // Secure the response
      log("f_http_build_error_ec_response: p_inner_ec_response= ", v_inner_ec_response);
      v_msg := bit2oct(encvalue(m_etsiTs102941Data_inner_ec_response(v_inner_ec_response)));
      v_nonce := substr(f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 16)), 0, 12); // Random value
      // TODO Consider  Sha384: m_signerIdentifier_digest(f_hashedId8FromSha384(p_digest))
      if (f_build_pki_secured_response_message(p_private_key,
                                               valueof(m_signerIdentifier_digest(f_hashedId8FromSha256(p_digest))),//  in SignerIdentifier p_signer_identifier,
                                               v_msg,
                                               p_aes_sym_key,
                                               v_nonce,
                                               p_ieee1609dot2_signed_and_encrypted_data
                                               ) == false) {
        log("f_http_build_inner_ec_response: Failed to generate the certificate");
        return false;
      }
      return true;
    } // End of function f_http_build_error_ec_response

ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_http_build_authorization_request(
                                                in Certificate p_ec_certificate, // Enrolment credentials certificate
                                                in octetstring p_ec_private_key,
                                                out octetstring p_private_key,
                                                out octetstring p_public_key_compressed,
                                                out integer p_compressed_key_mode,
                                                out octetstring p_private_enc_key,
                                                out octetstring p_public_compressed_enc_key,
                                                out integer p_compressed_enc_key_mode,
                                                out Oct16 p_aes_sym_key,
                                                out Oct16 p_encrypted_sym_key,
                                                out Oct16 p_authentication_vector,
                                                out Oct12 p_nonce,
                                                out octetstring p_salt,
                                                out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                out Oct32 p_request_hash
                                                ) runs on ItsPkiHttp return boolean {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Local variables
      var octetstring v_public_key_x;
      var octetstring v_public_key_y;
      var octetstring v_public_enc_key_x;
      var octetstring v_public_enc_key_y;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var InnerAtRequest v_inner_at_request;
      var Ieee1609Dot2Data v_inner_at_request_data;
      var InnerAtRequest v_authorization_request;
      var bitstring v_authorization_request_msg;

      // Generate the InnerAtRequest
      if (f_generate_inner_at_request(vc_aaCertificate, -, vc_aaHashedId8, vc_eaCertificate, vc_eaWholeHash/*salt*/, vc_eaHashedId8, p_ec_certificate, p_ec_private_key, p_private_key, p_public_key_compressed, p_compressed_key_mode, p_private_enc_key, p_public_compressed_enc_key, p_compressed_enc_key_mode, v_inner_at_request) == false) {
        log("*** f_http_build_authorization_request: ERROR: Failed to generate AuthorizationRequest ***");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("f_http_build_authorization_request: v_inner_at_request= ", v_inner_at_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Secure InnerAtRequest message
      if (f_extract_enc_key(vc_aaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_authorization_request: ERROR: Non canonical AA certificate ***");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("*** f_http_build_authorization_request: Public encryption key: ", v_public_enc_key);
      log("*** f_http_build_authorization_request: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_aaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      log("*** f_http_build_authorization_request: p_salt: ", p_salt);
      if (PICS_PKI_AUTH_POP) {
        if(f_build_pki_secured_request_message_signed_with_pop(p_private_key, valueof(m_signerIdentifier_self), vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_inner_at_request))), PX_EC_ALG_FOR_AT, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
          log("*** f_http_build_authorization_request: ERROR: Failed to generate Authorization Request ***");
          return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
      } else { // Only encryption of EtsiTs102941Data/InnerAtRequest
        log("*** f_http_build_authorization_request: POP signature not applied");
        if(f_build_pki_secured_request_message_for_authorization(vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_inner_at_request))), PX_EC_ALG_FOR_AT, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
          log("*** f_http_build_authorization_request: ERROR: Failed to generate Authorization Request ***");
          return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
      }
      log("<<< f_http_build_authorization_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
      log("<<< f_http_build_authorization_request: DEBUG: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_http_build_authorization_request

    function f_http_build_authorization_request_with_wrong_private_key(
                                                                       in Certificate p_ec_certificate, // Enrolment credentials certificate
                                                                       in octetstring p_ec_private_key,
                                                                       out octetstring p_private_key,
                                                                       out octetstring p_public_key_compressed,
                                                                       out integer p_compressed_key_mode,
                                                                       out octetstring p_private_enc_key,
                                                                       out octetstring p_public_compressed_enc_key,
                                                                       out integer p_compressed_enc_key_mode,
                                                                       out Oct16 p_aes_sym_key,
                                                                       out Oct16 p_encrypted_sym_key,
                                                                       out Oct16 p_authentication_vector,
                                                                       out Oct12 p_nonce,
                                                                       out octetstring p_salt,
                                                                       out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                                       out Oct32 p_request_hash
                                                                       ) runs on ItsPkiHttp return boolean {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Local variables
      var octetstring v_public_key_x;
      var octetstring v_public_key_y;
      var octetstring v_public_enc_key_x;
      var octetstring v_public_enc_key_y;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var InnerAtRequest v_inner_at_request;
      var Ieee1609Dot2Data v_inner_at_request_data;
      var InnerAtRequest v_authorization_request;
      var bitstring v_authorization_request_msg;

      // Generate the InnerAtRequest
      if (f_generate_inner_at_request(vc_aaCertificate, -, vc_aaHashedId8, vc_eaCertificate, vc_eaWholeHash/*salt*/, vc_eaHashedId8, p_ec_certificate, p_ec_private_key, p_private_key, p_public_key_compressed, p_compressed_key_mode, p_private_enc_key, p_public_compressed_enc_key, p_compressed_enc_key_mode, v_inner_at_request) == false) {
        log("*** f_http_build_authorization_request_with_wrong_private_key: ERROR: Failed to generate AuthorizationRequest ***");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("f_http_build_authorization_request_with_wrong_private_key: v_inner_at_request= ", v_inner_at_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Secure InnerAtRequest message
      /***
          Use the wrong private key
      ***/
      if (f_extract_enc_key(vc_eaCertificate/*Insted of vc_aaCertificate/*/, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_authorization_request_with_wrong_private_key: ERROR: Non canonical EA certificate ***");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("*** f_http_build_authorization_request_with_wrong_private_key: Public encryption key: ", v_public_enc_key);
      log("*** f_http_build_authorization_request_with_wrong_private_key: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_aaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      log("*** f_http_build_authorization_request_with_wrong_private_key: p_salt: ", p_salt);
      if (PICS_PKI_AUTH_POP) {
        if(f_build_pki_secured_request_message_signed_with_pop(p_private_key, valueof(m_signerIdentifier_self), vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_inner_at_request))), PX_EC_ALG_FOR_AT, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
          log("*** f_http_build_authorization_request_with_wrong_private_key: ERROR: Failed to generate Authorization Request ***");
          return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
      } else { // Only encryption of EtsiTs102941Data/InnerAtRequest
        log("*** f_http_build_authorization_request_with_wrong_private_key: POP signature not applied");
        if(f_build_pki_secured_request_message_for_authorization(vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_inner_at_request))), PX_EC_ALG_FOR_AT, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
          log("*** f_http_build_authorization_request_with_wrong_private_key: ERROR: Failed to generate Authorization Request ***");
          return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
      }
      log("*** f_http_build_authorization_request_with_wrong_private_key: DEBUG: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
      log("*** f_http_build_authorization_request_with_wrong_private_key: DEBUG: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_http_build_authorization_request_with_wrong_private_key

    function f_http_build_authorization_request_with_wrong_parameters(
                                                                      in Certificate p_ec_certificate, // Enrolment credentials certificate
                                                                      in octetstring p_ec_private_key,
                                                                      in boolean p_alter_pop_signature := false,
                                                                      in boolean p_alter_hmac := false,
                                                                      in boolean p_alter_signer_digest := false,
                                                                      in boolean p_alter_pks_recipient := false,
                                                                      in boolean p_alter_enc_key := false,
                                                                      in boolean p_alter_ea_id := false,
                                                                      in template (omit) Time32 p_start := omit,
                                                                      in template (omit) Duration p_duration := omit,
                                                                      in template (omit) Time64 p_generation_time := omit,
                                                                      out octetstring p_private_key,
                                                                      out octetstring p_public_key_compressed,
                                                                      out integer p_compressed_key_mode,
                                                                      out octetstring p_private_enc_key,
                                                                      out octetstring p_public_compressed_enc_key,
                                                                      out integer p_compressed_enc_key_mode,
                                                                      out Oct16 p_aes_sym_key,
                                                                      out Oct16 p_encrypted_sym_key,
                                                                      out Oct16 p_authentication_vector,
                                                                      out Oct12 p_nonce,
                                                                      out octetstring p_salt,
                                                                      out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                                      out Oct32 p_request_hash
                                                                      ) runs on ItsPkiHttp return boolean {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Local variables
      var octetstring v_public_key_x;
      var octetstring v_public_key_y;
      var octetstring v_public_enc_key_x;
      var octetstring v_public_enc_key_y;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var InnerAtRequest v_inner_at_request;
      var Ieee1609Dot2Data v_inner_at_request_data;
      var InnerAtRequest v_authorization_request;
      var bitstring v_authorization_request_msg;
      var boolean v_ret_code;

      // Generate the InnerAtRequest
      if (p_alter_ea_id == true) {
        var HashedId8 v_ea_hashed_id8 := vc_eaHashedId8;
        v_ea_hashed_id8[0] := 'bb'O;
        v_ea_hashed_id8[1] := 'cc'O;
        log("f_http_build_authorization_request_with_wrong_parameters: Altered eaId= ", v_ea_hashed_id8);
        v_ret_code := f_generate_inner_at_request(vc_aaCertificate, -, vc_aaHashedId8, vc_eaCertificate, vc_eaWholeHash/*salt*/, v_ea_hashed_id8, p_ec_certificate, p_ec_private_key, p_private_key, p_public_key_compressed, p_compressed_key_mode, p_private_enc_key, p_public_compressed_enc_key, p_compressed_enc_key_mode, v_inner_at_request);
      } else {
        v_ret_code := f_generate_inner_at_request_with_wrong_parameters(vc_aaCertificate, -, vc_aaHashedId8, vc_eaCertificate, vc_eaWholeHash/*salt*/, vc_eaHashedId8, p_ec_certificate, p_ec_private_key, p_alter_hmac, p_alter_signer_digest, p_start, p_duration, p_generation_time, p_private_key, p_public_key_compressed, p_compressed_key_mode, p_private_enc_key, p_public_compressed_enc_key, p_compressed_enc_key_mode, v_inner_at_request);
      }
      if (v_ret_code == false) {
        log("*** f_http_build_authorization_request_with_wrong_parameters: ERROR: Failed to generate AuthorizationRequest ***");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("f_http_build_authorization_request_with_wrong_parameters: v_inner_at_request= ", v_inner_at_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Secure InnerAtRequest message
      if (f_extract_enc_key(vc_aaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_authorization_request_with_wrong_parameters: ERROR: Non canonical AA certificate ***");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("*** f_http_build_authorization_request_with_wrong_parameters: Public encryption key: ", v_public_enc_key);
      log("*** f_http_build_authorization_request_with_wrong_parameters: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_aaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      log("*** f_http_build_authorization_request_with_wrong_parameters: p_salt: ", p_salt);
      if (PICS_PKI_AUTH_POP) {
        if(f_build_pki_secured_request_message_signed_with_pop(p_private_key, valueof(m_signerIdentifier_self), vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_inner_at_request))), PX_EC_ALG_FOR_AT, p_alter_pop_signature, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
          log("*** f_http_build_authorization_request_with_wrong_parameters: ERROR: Failed to generate Authorization Request ***");
          return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
      } else { // Only encryption of EtsiTs102941Data/InnerAtRequest
        log("*** f_http_build_authorization_request_with_wrong_parameters: POP signature not applied");
        if(f_build_pki_secured_request_message_for_authorization(vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_inner_at_request))), PX_EC_ALG_FOR_AT, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
          log("*** f_http_build_authorization_request_with_wrong_parameters: ERROR: Failed to generate Authorization Request ***");
          return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
      }
      log("*** f_http_build_authorization_request_with_wrong_parameters: DEBUG: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
      if (p_alter_enc_key == true) {
        /***
            Alter encryption key to prevent decryption
         ***/
        if (ischosen(p_ieee1609dot2_signed_and_encrypted_data.content.encryptedData.recipients[0].certRecipInfo.encKey.eciesNistP256)) {
          p_ieee1609dot2_signed_and_encrypted_data.content.encryptedData.recipients[0].certRecipInfo.encKey.eciesNistP256.c[1] := 'aa'O;
          p_ieee1609dot2_signed_and_encrypted_data.content.encryptedData.recipients[0].certRecipInfo.encKey.eciesNistP256.c[2] := 'bb'O;
        } else {
          p_ieee1609dot2_signed_and_encrypted_data.content.encryptedData.recipients[0].certRecipInfo.encKey.eciesBrainpoolP256r1.c[1] := 'aa'O;
          p_ieee1609dot2_signed_and_encrypted_data.content.encryptedData.recipients[0].certRecipInfo.encKey.eciesBrainpoolP256r1.c[2] := 'bb'O;
        }
        log("*** f_http_build_authorization_request_with_wrong_parameters: DEBUG: Altered enc key= ", p_ieee1609dot2_signed_and_encrypted_data);
      }
      if (p_alter_pks_recipient == true) {
        p_ieee1609dot2_signed_and_encrypted_data.content.encryptedData.recipients[0].pskRecipInfo := int2oct(314259265, 8); // NOT equal to the HashedId8 of the certificate CERT_AA
        log("*** f_http_build_authorization_request_with_wrong_parameters: DEBUG: Altered pskRecipInfo= ", p_ieee1609dot2_signed_and_encrypted_data);
      }
      log("*** f_http_build_authorization_request_with_wrong_parameters: DEBUG: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_http_build_authorization_request_with_wrong_parameters

    function f_http_build_authorization_response(
                                                 in template (omit) InnerAtRequest p_inner_at_request := omit,
                                                 in AuthorizationResponseCode p_responseCode := ok,
                                                 in Oct16 p_request_hash,
                                                 in octetstring p_private_key := ''O,
                                                 in octetstring p_digest := ''O,
                                                 in Oct16 p_aes_sym_key,
                                                 out InnerAtResponse p_inner_at_response,
                                                 out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
                                                 ) return boolean {
      // Local variables
      var bitstring v_msg_bit;
      var octetstring v_msg;
      var Oct12 v_nonce;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var EtsiTs103097Certificate v_at_certificate;
      var boolean v_result := false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      log(">>> f_http_build_authorization_response: p_inner_at_request= ", p_inner_at_request);
      log(">>> f_http_build_authorization_response: p_responseCode= ", p_responseCode);
      log(">>> f_http_build_authorization_response: p_request_hash= ", p_request_hash);
      log(">>> f_http_build_authorization_response: p_private_key= ", p_private_key);
      log(">>> f_http_build_authorization_response: p_digest= ", p_digest);
      log(">>> f_http_build_authorization_response: p_aes_sym_key= ", p_aes_sym_key);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Check expectred response
      if (p_responseCode != ok) {
        p_inner_at_response := valueof(
                                       m_innerAtResponse_ko(
                                                            p_request_hash,
                                                            p_responseCode
                                                            )
                                       );
        v_result := true;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        // Generate the certificate
        if (f_generate_at_certificate_for_inner_at_response(valueof(p_inner_at_request), p_private_key, p_digest, v_at_certificate) == false) {
          log("f_http_build_authorization_response: Failed to generate the certificate");
          p_inner_at_response := valueof(
                                         m_innerAtResponse_ko(
                                                              p_request_hash,
                                                              its_aa_incompleterequest
                                                              )
                                         );
        } else {
          p_inner_at_response := valueof(
                                         m_innerAtResponse_ok(
                                                              p_request_hash,
                                                              v_at_certificate
                                                              )
                                         );
        }
      }

      // Secure the response
      log("f_http_build_authorization_response: p_inner_at_response= ", p_inner_at_response);
      v_msg := bit2oct(encvalue(m_etsiTs102941Data_inner_at_response(p_inner_at_response)));
      v_nonce := substr(f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 16)), 0, 12); // Random value
      // TODO Consider  Sha384: m_signerIdentifier_digest(f_hashedId8FromSha384(p_digest))
      if (f_build_pki_secured_response_message(p_private_key,
                                               valueof(m_signerIdentifier_digest(f_hashedId8FromSha256(p_digest))),//  in SignerIdentifier p_signer_identifier,
                                               v_msg,
                                               p_aes_sym_key,
                                               v_nonce,
                                               p_ieee1609dot2_signed_and_encrypted_data
                                               ) == false) {
        log("f_http_build_authorization_response: Failed to generate the certificate");
        p_inner_at_response := valueof(
                                       m_innerAtResponse_ko(
                                                            p_request_hash,
                                                            its_aa_deniedpermissions
                                                            )
                                       );
      } else {
        v_result := true;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }

      log("<<< f_http_build_authorization_response: v_result= ", v_result);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_http_build_authorization_response: p_inner_at_response= ", p_inner_at_response);
      return v_result;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_http_build_authorization_response
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_http_build_authorization_validation_request(
                                                           in InnerAtRequest p_inner_at_request,
                                                           in octetstring p_public_key_compressed,
                                                           in integer p_compressed_key_mode,
                                                           in octetstring p_private_enc_key,
                                                           in octetstring p_public_compressed_enc_key,
                                                           in integer p_compressed_enc_key_mode,
                                                           out Oct16 p_aes_sym_key,
                                                           out Oct16 p_encrypted_sym_key,
                                                           out Oct16 p_authentication_vector,
                                                           out Oct12 p_nonce,
                                                           out octetstring p_salt,
                                                           out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                           out Oct32 p_request_hash
                                                           ) runs on ItsPkiHttp return boolean {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Local variables
      var AuthorizationValidationRequest v_authorization_validation_request;
      var bitstring v_authorization_validation_request_msg;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;

      log(">>> f_http_build_authorization_validation_request");

      // Copy the sharedAtRequest component from the InnerAtRequest received in the AuthorizationRequestMessage
      v_authorization_validation_request.sharedAtRequest := p_inner_at_request.sharedAtRequest;
      // Copy the ecSignature component from the InnerAtRequest received in the AuthorizationRequestMessage or AuthorizationRequestMessageWithPop
      v_authorization_validation_request.ecSignature := p_inner_at_request.ecSignature;
      // Secure the InnerAtRequest message
      if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("f_http_build_authorization_validation_request: Non canonical EA certificate");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("f_http_build_authorization_validation_request: Public encryption key: ", v_public_enc_key);
      log("f_http_build_authorization_validation_request: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_eaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      log("f_http_build_authorization_validation_request: vc_aaHashedId8: ", vc_aaHashedId8);
      log("f_http_build_authorization_validation_request: p_salt: ", p_salt);
      if(f_build_pki_secured_request_message_signed_with_pop(vc_aaPrivateKey, valueof(m_signerIdentifier_digest(vc_aaHashedId8)), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_validation_request(v_authorization_validation_request))), PX_EC_ALG_FOR_ATV, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
        log("f_http_build_authorization_validation_request: Failed to generate Authorization Request");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("f_http_build_authorization_validation_request: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
      log("f_http_build_authorization_validation_request: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_http_build_authorization_validation_request

    function f_http_build_invalid_authorization_validation_request(
                                                                   in InnerAtRequest p_inner_at_request,
                                                                   in octetstring p_public_key_compressed,
                                                                   in integer p_compressed_key_mode,
                                                                   in octetstring p_private_enc_key,
                                                                   in octetstring p_public_compressed_enc_key,
                                                                   in integer p_compressed_enc_key_mode,
                                                                   out Oct16 p_aes_sym_key,
                                                                   out Oct16 p_encrypted_sym_key,
                                                                   out Oct16 p_authentication_vector,
                                                                   out Oct12 p_nonce,
                                                                   out octetstring p_salt,
                                                                   out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                                   out Oct32 p_request_hash
                                                                   ) runs on ItsPkiHttp return boolean {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Local variables
      var AuthorizationValidationRequest v_authorization_validation_request;
      var bitstring v_authorization_validation_request_msg;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;

      log(">>> f_http_build_invalid_authorization_validation_request");

      // Copy the sharedAtRequest component from the InnerAtRequest received in the AuthorizationRequestMessage
      v_authorization_validation_request.sharedAtRequest := p_inner_at_request.sharedAtRequest;
      // Copy the ecSignature component from the InnerAtRequest received in the AuthorizationRequestMessage or AuthorizationRequestMessageWithPop
      v_authorization_validation_request.ecSignature := p_inner_at_request.ecSignature;
      // Secure the InnerAtRequest message
      if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("f_http_build_invalid_authorization_validation_request: Non canonical EA certificate");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("f_http_build_invalid_authorization_validation_request: Public encryption key: ", v_public_enc_key);
      log("f_http_build_invalid_authorization_validation_request: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_eaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      log("f_http_build_invalid_authorization_validation_request: vc_aaHashedId8: ", vc_aaHashedId8);
      log("f_http_build_invalid_authorization_validation_request: p_salt: ", p_salt);
      if(f_build_pki_secured_request_message_signed_with_pop(vc_aaPrivateKey, valueof(m_signerIdentifier_digest(vc_aaHashedId8)),
                                                             vc_eaHashedId8/*recipientId*/, v_public_enc_key,
                                                             v_compressed_enc_key_mode, p_salt,
                                                             bit2oct(encvalue(m_etsiTs102941Data_authorization_validation_request(v_authorization_validation_request))),
                                                             PX_EC_ALG_FOR_ATV, true, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("f_http_build_invalid_authorization_validation_request: Failed to generate Authorization Request");
        return false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("f_http_build_invalid_authorization_validation_request: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
      log("f_http_build_invalid_authorization_validation_request: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_http_build_invalid_authorization_validation_request

    function f_http_build_authorization_validation_response(
                                                            in SharedAtRequest p_shared_at_request,
                                                            in AuthorizationValidationResponseCode p_responseCode := ok,
                                                            in Oct16 p_request_hash,
                                                            in octetstring p_private_key := ''O,
                                                            in octetstring p_digest := ''O,
                                                            in Oct16 p_aes_sym_key,
                                                            out AuthorizationValidationResponse p_authorization_validation_response,
                                                            out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
                                                            ) return boolean {
      // Local variables
      var bitstring v_msg_bit;
      var octetstring v_msg;
      var Oct12 v_nonce;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var boolean v_result := false;
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      log(">>> f_http_build_authorization_validation_response: p_shared_at_request= ", p_shared_at_request);
      log(">>> f_http_build_authorization_validation_response: p_responseCode= ", p_responseCode);
      log(">>> f_http_build_authorization_validation_response: p_request_hash= ", p_request_hash);
      log(">>> f_http_build_authorization_validation_response: p_private_key= ", p_private_key);
      log(">>> f_http_build_authorization_validation_response: p_digest= ", p_digest);
      log(">>> f_http_build_authorization_validation_response: p_aes_sym_key= ", p_aes_sym_key);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Check expectred response
      if (p_responseCode != ok) {
        p_authorization_validation_response := valueof(
                                                       m_authorizationValidationResponse_ko(
                                                                                            p_request_hash,
                                                                                            p_responseCode
                                                                                            )
                                                       );
        v_result := true;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        p_authorization_validation_response := valueof(m_authorizationValidationResponse_ok(
                                                                                            p_request_hash,
                                                                                            p_shared_at_request.requestedSubjectAttributes
                                                                                            )
                                                        );
      }
      log("f_http_build_authorization_validation_response: p_authorization_validation_response= ", p_authorization_validation_response);
      // Encapsulte authorization validation response into EtsiTs102941Data
      v_msg := bit2oct(encvalue(m_etsiTs102941Data_authorization_validation_response(p_authorization_validation_response)));
      // Secure the response
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      v_nonce := substr(f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 16)), 0, 12); // Random value
      if (f_build_pki_secured_response_message(p_private_key,
                                               valueof(m_signerIdentifier_digest(f_hashedId8FromSha256(p_digest))),//  in SignerIdentifier p_signer_identifier,
                                               v_msg,
                                               p_aes_sym_key,
                                               v_nonce,
                                               p_ieee1609dot2_signed_and_encrypted_data
                                               ) == false) {
        log("f_http_build_authorization_validation_response: Failed to generate the certificate");
        p_authorization_validation_response := valueof(
                                                       m_authorizationValidationResponse_ko(
                                                                                            p_request_hash,
                                                                                            deniedpermissions
                                                                                            )
                                                       );
      } else {
        v_result := true;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("<<< f_http_build_authorization_validation_response: v_result= ", v_result);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_http_build_authorization_validation_response: p_authorization_validation_response= ", p_authorization_validation_response);
      return v_result;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function f_http_build_authorization_validation_response

    function f_http_build_butterfly_authorization_request_message( // TODO Cleanup parameters
                                                                  in Oct32 p_private_key_ec,
                                                                  in HashedId8 p_ec_cert_hashed_id8,
                                                                  out octetstring p_caterpillar_private_key,
                                                                  out octetstring p_caterpillar_public_key_compressed,
                                                                  out integer p_caterpillar_compressed_mode,
                                                                  out octetstring p_caterpillar_enc_private_key,
                                                                  out octetstring p_caterpillar_enc_public_key_compressed,
                                                                  out integer p_caterpillar_enc_compressed_mode,
                                                                  out Oct16 p_aes_sym_key,
                                                                  out Oct16 p_encrypted_sym_key,
                                                                  out Oct16 p_authentication_vector,
                                                                  out Oct12 p_nonce,
                                                                  out octetstring p_salt,
                                                                  out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                                  out Oct32 p_request_hash,
                                                                  out EeRaCertRequest p_ee_ra_cert_request
                                                                  ) runs on ItsPkiHttp return boolean {

      var Ieee1609Dot2Data v_ee_ra_cert_request_signed;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var boolean v_result;

      log(">>> f_http_build_butterfly_authorization_request_message: p_private_key_ec: ", p_private_key_ec);
      log(">>> f_http_build_butterfly_authorization_request_message: p_ec_cert_hashed_id8: ", p_ec_cert_hashed_id8);

      // Generate EeRaCertRequest
      if (f_generate_ee_ra_cert_request(p_caterpillar_private_key, p_caterpillar_public_key_compressed, p_caterpillar_compressed_mode, p_caterpillar_enc_private_key, p_caterpillar_enc_public_key_compressed, p_caterpillar_enc_compressed_mode, p_ee_ra_cert_request) == false) {
        log("*** f_http_build_butterfly_authorization_request_message: ERROR: Failed to generate InnerEcRequest ***");
        return false;
      }
      log ("f_http_build_butterfly_authorization_request_message: p_ee_ra_cert_request: ", p_ee_ra_cert_request);

      // Secure EeRaCertRequest
      if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_butterfly_authorization_request_message: ERROR: Non canonical EA certificate ***");
        return false;
      }
      log("f_http_build_butterfly_authorization_request_message: Public encryption key: ", v_public_enc_key);
      log("f_http_build_butterfly_authorization_request_message: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_eaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      v_result := f_build_pki_secured_request_message_signed_with_pop(p_private_key_ec, valueof(m_signerIdentifier_digest(p_ec_cert_hashed_id8)), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_ee_ra_cert_request(p_ee_ra_cert_request))), PX_EC_ALG_FOR_EC, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
      if (v_result == false) {
        log("*** f_http_build_butterfly_authorization_request_message: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        return false;
      } else {
        log("f_http_build_butterfly_authorization_request_message: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
        log("f_http_build_butterfly_authorization_request_message: p_request_hash= ", p_request_hash);
      }
    } // End of function f_http_build_butterfly_authorization_request_message

    function f_http_build_butterfly_authorization_response_message(
                                                                   in EeRaCertRequest p_ee_ra_cert_request,
                                                                   in HashedId8 p_request_hash,
                                                                   in octetstring p_private_key := ''O,
                                                                   in octetstring p_digest := ''O,
                                                                   in Oct16 p_aes_sym_key,
                                                                   out RaEeCertInfo p_ra_ee_cert_info,
                                                                   out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
                                                                   ) runs on ItsPkiHttp return boolean {
      var bitstring v_msg_bit;
      var octetstring v_msg;
      var Oct12 v_nonce;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var boolean v_result := false;

      log(">>> f_http_build_butterfly_authorization_response_message: p_ee_ra_cert_request= ", p_ee_ra_cert_request);
      log(">>> f_http_build_butterfly_authorization_response_message: p_request_hash= ", p_request_hash);
      log(">>> f_http_build_butterfly_authorization_response_message: p_private_key= ", p_private_key);
      log(">>> f_http_build_butterfly_authorization_response_message: p_digest= ", p_digest);
      log(">>> f_http_build_butterfly_authorization_response_message: p_aes_sym_key= ", p_aes_sym_key);


      // Generate EeRaCertRequest
      if (f_generate_ra_ee_cert_info(p_ee_ra_cert_request, p_request_hash, p_ra_ee_cert_info) == false) {
        log("*** f_http_build_butterfly_authorization_response_message: ERROR: Failed to generate InnerEcRequest ***");
        return v_result;
      }
      log ("f_http_build_butterfly_authorization_response_message: p_ra_ee_cert_info: ", p_ra_ee_cert_info);

      // Secure the response
      v_msg := bit2oct(encvalue(m_etsiTs102941Data_ra_ee_cert_info(p_ra_ee_cert_info)));
      v_nonce := substr(f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 16)), 0, 12); // Random value
      // TODO Consider  Sha384: m_signerIdentifier_digest(f_hashedId8FromSha384(p_digest))
      if (f_build_pki_secured_response_message(p_private_key,
                                               valueof(m_signerIdentifier_digest(f_hashedId8FromSha256(p_digest))),//  in SignerIdentifier p_signer_identifier,
                                               v_msg,
                                               p_aes_sym_key,
                                               v_nonce,
                                               p_ieee1609dot2_signed_and_encrypted_data
                                               ) == false) {
        log("f_http_build_butterfly_authorization_response_message: Failed to generate the certificate");
        return v_result;
      } else {
        v_result := true;
      }

      log("<<< f_http_build_butterfly_authorization_response_message: v_result= ", v_result);
      return v_result;
    } // End of function f_http_build_butterfly_authorization_response_message

    function f_http_build_butterfly_cert_request(
                                                 in EeRaCertRequest p_ee_ra_cert_request,
                                                 in octetstring p_private_key := ''O,
                                                 out Oct16 p_aes_sym_key,
                                                 out Oct16 p_encrypted_sym_key,
                                                 out Oct16 p_authentication_vector,
                                                 out Oct12 p_nonce,
                                                 out octetstring p_salt,
                                                 out RaAcaCertRequest p_ra_aca_cert_request,
                                                 out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                 out Oct32 p_request_hash
                                                 ) runs on ItsPkiHttp return boolean {
      // Local variables
      var Ieee1609Dot2Data v_ra_aca_cert_request_signed;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var boolean v_result;

      log(">>> f_http_build_butterfly_cert_request: p_ee_ra_cert_request= ", p_ee_ra_cert_request);
      log(">>> f_http_build_butterfly_cert_request: p_private_key= ", p_private_key);

      p_ra_aca_cert_request := valueof(
                                        m_ra_aca_cert_request(
                                                              p_ee_ra_cert_request.generationTime,
                                                              p_ee_ra_cert_request.type_,
                                                              '00000000'B, // FIXME What does it mean? ETSI TS 102 941 V2.1.1 (2021-10) Figure 27 Bullet 1 dash #3
                                                              p_ee_ra_cert_request.tbsCert,
                                                              -,
                                                              omit // FIXME Shall be the cocoon key that shall be derived by the EA ETSI TS 102 941 V2.1.1 (2021-10) Figure 27 Bullet 1 dash #4
                                        ));
      log("f_http_build_butterfly_cert_request: p_ra_aca_cert_request= ", p_ra_aca_cert_request);

      // Secure RaAcaCertRequest
      if (f_extract_enc_key(vc_aaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_butterfly_cert_request: ERROR: Non canonical EA certificate ***");
        return false;
      }
      log("f_http_build_butterfly_cert_request: Public encryption key: ", v_public_enc_key);
      log("f_http_build_butterfly_cert_request: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_eaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.
      v_result := f_build_pki_secured_request_message_signed_with_pop(vc_eaPrivateKey, valueof(m_signerIdentifier_self), vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_ra_aca_cert_request(p_ra_aca_cert_request))), PX_EC_ALG_FOR_EC, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
      if (v_result == false) {
        log("*** f_http_build_butterfly_cert_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        return false;
      } else {
        log("f_http_build_butterfly_cert_request: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
        log("f_http_build_butterfly_cert_request: p_request_hash= ", p_request_hash);
      }

      return true;
    } // End of function f_http_build_butterfly_cert_request

    function f_http_build_butterfly_cert_response(
                                                  in HashedId8 p_request_hash,
                                                  in octetstring p_private_key := ''O,
                                                  in octetstring p_digest := ''O,
                                                  in Oct16 p_aes_sym_key,
                                                  out AcaRaCertResponse p_aca_ra_cert_response,
                                                  out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
      // Local variables
      var bitstring v_msg_bit;
      var octetstring v_msg;
      var Oct12 v_nonce;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var boolean v_result := false;

      log(">>> f_http_build_butterfly_cert_response: p_request_hash= ", p_request_hash);
      log(">>> f_http_build_butterfly_cert_response: p_private_key= ", p_private_key);
      log(">>> f_http_build_butterfly_cert_response: p_digest= ", p_digest);
      log(">>> f_http_build_butterfly_cert_response: p_aes_sym_key= ", p_aes_sym_key);

      p_aca_ra_cert_response := valueof(
                                        m_ra_aca_cert_response(
                                                               f_getCurrentTimeUtc(),
                                                               p_request_hash,
                                                               m_aca_response_plain(m_etsiTs103097Data_unsecured(''O)) // FIXME FSCOM
                                        ));

      // Secure the response
      log("f_http_build_butterfly_cert_response: p_aca_ra_cert_response= ", p_aca_ra_cert_response);
      v_msg := bit2oct(encvalue(m_etsiTs102941Data_aca_ra_cert_response(p_aca_ra_cert_response)));
      v_nonce := substr(f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 16)), 0, 12); // Random value
      // TODO Consider  Sha384: m_signerIdentifier_digest(f_hashedId8FromSha384(p_digest))
      if (f_build_pki_secured_response_message(p_private_key,
                                               valueof(m_signerIdentifier_digest(f_hashedId8FromSha256(p_digest))),//  in SignerIdentifier p_signer_identifier,
                                               v_msg,
                                               p_aes_sym_key,
                                               v_nonce,
                                               p_ieee1609dot2_signed_and_encrypted_data
                                               ) == false) {
        log("f_http_build_butterfly_cert_response: Failed to generate the certificate");
      } else {
        v_result := true;
      }

      log("<<< f_http_build_butterfly_cert_response: v_result= ", v_result);
      log("<<< f_http_build_butterfly_cert_response: p_aca_ra_cert_response= ", p_aca_ra_cert_response);
      return v_result;

    } // End of function f_http_build_butterfly_cert_response

    function f_http_build_butterfly_at_download_request_message(
                                                                in charstring p_filename,
                                                                out Oct16 p_aes_sym_key,
                                                                out Oct16 p_encrypted_sym_key,
                                                                out Oct16 p_authentication_vector,
                                                                out Oct12 p_nonce,
                                                                out octetstring p_salt,
                                                                out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                                out Oct32 p_request_hash
                                                                ) runs on ItsPkiHttp return boolean {
      var EeRaDownloadRequest v_ee_ra_download_request;
      var Ieee1609Dot2Data v_ee_ra_download_request_signed;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var octetstring v_private_key;
      var boolean v_result;

      log(">>> f_http_build_butterfly_at_download_request_message: p_filename: ", p_filename);

      // Generate EeRaDownloadRequest
      if (f_generate_ee_ra_download_request(p_filename, v_ee_ra_download_request) == false) {
        log("*** f_http_build_butterfly_at_download_request_message: ERROR: Failed to generate InnerEcRequest ***");
        return false;
      }
      log ("f_http_build_butterfly_at_download_request_message: v_ee_ra_download_request: ", v_ee_ra_download_request);

      // Secure EeRaDownloadRequest
      if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
        log("*** f_http_build_butterfly_at_download_request_message: ERROR: Non canonical EA certificate ***");
        return false;
      }
      log("f_http_build_butterfly_at_download_request_message: Public encryption key: ", v_public_enc_key);
      log("f_http_build_butterfly_at_download_request_message: Public encryption key comp: ", v_compressed_enc_key_mode);
      p_salt := vc_eaWholeHash256; // IEEE 1609.2: If the encryption key was obtained from a certificate c, P1 is SHA-256 (c), where c is the COER encoding of the certificate, canonicalized per 6.4.3.

      log("f_http_build_butterfly_at_download_request_message: vc_ec_keys_counter: ", vc_ec_keys_counter);
      log("f_http_build_butterfly_at_download_request_message: vc_ec_private_keys: ", vc_ec_private_keys);
      log("f_http_build_butterfly_at_download_request_message: vc_ec_cert_hashed_id8: ", vc_ec_hashed_id8);
      v_result := f_build_pki_secured_request_message_signed_with_pop(vc_ec_private_keys[vc_ec_keys_counter - 1], valueof(m_signerIdentifier_digest(vc_ec_hashed_id8[vc_ec_keys_counter - 1])), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_ee_ra_download_request(v_ee_ra_download_request))), PX_EC_ALG_FOR_EC, -, p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
      if (v_result == false) {
        log("*** f_http_build_butterfly_at_download_request_message: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        return false;
      } else {
        log("f_http_build_butterfly_at_download_request_message: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
        log("f_http_build_butterfly_at_download_request_message: p_request_hash= ", p_request_hash);
      }
    } // End of function f_http_build_butterfly_at_download_request_message

ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_http_build_dc_request( // TODO Cleanup parameters
                                     in charstring p_ea_certificate_id,
                                     in charstring p_aa_certificate_id,
                                     in charstring p_rca_certificate_id,
                                     out octetstring p_private_key,
                                     out octetstring p_public_key_compressed,
                                     out integer p_compressed_mode,
                                     out Oct16 p_aes_sym_key,
                                     out Oct16 p_encrypted_sym_key,
                                     out Oct16 p_authentication_vector,
                                     out Oct12 p_nonce,
                                     out octetstring p_salt,
                                     out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                     out Oct32 p_request_hash
                                     ) runs on ItsPkiHttp {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    } // End of function 
  } // End of group http

  group generate_certificates {

    function f_generate_ec_certificate(
                                       out octetstring p_private_key,
                                       out Certificate p_ec_certificate
                                       ) return boolean {
      var octetstring v_public_key_x;
      var octetstring v_public_key_y;
      var octetstring p_public_key_compressed;
      var integer p_compressed_mode;
      var EccP256CurvePoint v_ecc_p256_curve_point;
      var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
        valueof(m_appPermissions(36, { bitmapSsp := PX_INNER_EC_CERTFICATE_BITMAP_SSP_CAM })),
        valueof(m_appPermissions(37, { bitmapSsp := PX_INNER_EC_CERTFICATE_BITMAP_SSP_DENM }))
      };
      var template (value) EtsiTs103097Certificate v_cert;
      var bitstring v_tbs;
      var Oct32 v_sig;
      var bitstring v_enc_msg;
      var PublicVerificationKey v_public_verification_key;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log(">>> f_generate_ec_certificate");
      log("f_generate_ec_certificate: PX_EC_ALG_FOR_EC=", PX_EC_ALG_FOR_EC);
      log("f_generate_ec_certificate: PX_VE_ALG=", PX_VE_ALG);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Generate verification keys for the certificate
      if (f_generate_key_pair(p_private_key, v_public_key_x, v_public_key_y, p_public_key_compressed, p_compressed_mode) == false) {
        log("f_generate_ec_certificate: Failed to generate verification key");
        return false;
      }
      if (p_compressed_mode == 0) {
        v_ecc_p256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_public_key_compressed));
      } else {
        v_ecc_p256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_public_key_compressed));
      }

      if (PX_EC_ALG_FOR_EC == e_nist_p256) {
        v_public_verification_key := valueof(
                                             m_publicVerificationKey_ecdsaNistP256(
                                                                                   v_ecc_p256_curve_point
                                                                                   ));
      } else if (PX_EC_ALG_FOR_EC == e_nist_p384) { // FIXME FSCOM
        // v_public_verification_key := valueof(
        //                                      m_publicVerificationKey_ecdsaNistP384(
        //                                                                            v_ecc_p384_curve_point
        //                                                                            ));
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (PX_EC_ALG_FOR_EC == e_brainpool_p256_r1) {
        v_public_verification_key := valueof(
                                             m_publicVerificationKey_ecdsaBrainpoolP256r1(
                                                                                          v_ecc_p256_curve_point
                                                                                          ));
      } else if (PX_EC_ALG_FOR_EC == e_brainpool_p384_r1) { // FIXME FSCOM
        // v_public_verification_key := valueof(
        //                                      m_publicVerificationKey_ecdsaBrainpoolP384r1(
        //                                                                                   v_ecc_p384_curve_point
        //                                                                                   ));
      } else if (PX_EC_ALG_FOR_EC == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        log("f_generate_ec_certificate: Wrong encryption algorithm, check PX_EC_ALG_FOR_xx");
        return false;
      }
      v_cert := m_etsiTs103097Certificate(
                                          m_issuerIdentifier_sha256AndDigest(f_hashedId8FromSha256(f_hashWithSha256('616263'O))),
                                          m_toBeSignedCertificate_at(
                                                                     v_appPermissions,
                                                                     m_verificationKeyIndicator_verificationKey(
                                                                                                                v_public_verification_key
                                                                                                                ),
                                                                     m_validityPeriod(
                                                                                      f_getCurrentTime() / 1000,
                                                                                      m_duration_in_hours(PX_GENERATED_CERTIFICATE_DURATION)
                                                                                      ),
                                                                     m_geographicRegion_identifiedRegion(
                                                                                                         {
                                                                                                           m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_2),
                                                                                                           m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_2)
                                                                                                           }
                                                                                                         ),
                                                                     PX_GENERATED_CERTIFICATE_SUBJECT_ASSURENCE_LEVEL
                                                                     )
                                          );
      // Encode it ==> Get octetstring
      v_tbs := encvalue(v_cert.toBeSigned);
      // Sign the certificate
      v_sig := f_signWithEcdsa(bit2oct(v_tbs), int2oct(11, 32), p_private_key);
      if (PX_VE_ALG == e_nist_p256) {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        v_cert.signature_ := m_signature_ecdsaNistP256(
                                                       m_ecdsaP256Signature(
                                                                            m_eccP256CurvePoint_x_only(
                                                                                                       substr(v_sig, 0, 32)
                                                                                                       ),
                                                                            substr(v_sig, 32, 32)
                                                                            )
                                                       );
      } else if (PX_VE_ALG == e_brainpool_p256_r1) { // FIXME FSCOM
        v_cert.signature_ := m_signature_ecdsaBrainpoolP256r1(
                                                              m_ecdsaP256Signature(
                                                                                    m_eccP256CurvePoint_x_only(
                                                                                                              substr(v_sig, 0, 32)
                                                                                                              ),
                                                                                    substr(v_sig, 32, 32)
                                                                                    )
                                                              );
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
      } else if (PX_VE_ALG == e_nist_p384) {
        v_cert.signature_ := m_signature_ecdsaNistP384(
                                                       m_ecdsaP384Signature(
                                                                            m_eccP384CurvePoint_x_only(
                                                                                                       substr(v_sig, 0, 48)
                                                                                                       ),
                                                                             substr(v_sig, 48, 48)
                                                                             )
                                                        );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        v_cert.signature_ := m_signature_ecdsaBrainpoolP384r1(
                                                              m_ecdsaP384Signature(
                                                                                   m_eccP384CurvePoint_x_only(
                                                                                                              substr(v_sig, 0, 48)
                                                                                                              ),
                                                                                   substr(v_sig, 48, 48)
                                                                                   )
                                                              );
      }
      log("f_generate_ec_certificate: v_cert= ", v_cert);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      p_ec_certificate := valueof(v_cert);
      return true;
    } // End of function f_generate_ec_certificate
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_ec_certificate_for_inner_ec_response(
                                                             in InnerEcRequest p_inner_ec_request,
                                                             in octetstring p_private_key,
                                                             in octetstring p_digest,
                                                             out EtsiTs103097Certificate p_ec_certificate,
                                                             out HashedId8 p_ec_certificate_hashed_id8
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                             ) return boolean {
      var CertificateId v_certificate_id;
      var EtsiTs103097Certificate v_cert;
      var IssuerIdentifier v_issuer;
      var bitstring v_tbs;
      var octetstring v_sig;
      var ValidityPeriod v_valPeriod;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log(">>> f_generate_ec_certificate_for_inner_ec_response: p_inner_ec_request: ", p_inner_ec_request);
      log(">>> f_generate_ec_certificate_for_inner_ec_response: p_digest: ", p_digest);

      v_issuer := valueof(m_issuerIdentifier_sha256AndDigest(f_hashedId8FromSha256(p_digest))); // TODO Check sha256/384 f_hashedId8FromSha384
      if (not(ispresent(p_inner_ec_request.requestedSubjectAttributes.id))) {
        v_certificate_id := { none_ := NULL };
      } else {
        v_certificate_id := p_inner_ec_request.requestedSubjectAttributes.id;
      }
      if (ispresent(p_inner_ec_request.requestedSubjectAttributes.validityPeriod)) {
        v_valPeriod := p_inner_ec_request.requestedSubjectAttributes.validityPeriod;
      } else {
        v_valPeriod := valueof(m_validityPeriod(f_getCurrentTime() / 1000, m_duration_in_hours(24)));
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      v_cert := valueof(
                        m_etsiTs103097Certificate(
                                                  v_issuer,
                                                  m_toBeSignedCertificate_ec(
                                                                             v_certificate_id,
                                                                             p_inner_ec_request.requestedSubjectAttributes.appPermissions,
                                                                             m_verificationKeyIndicator_verificationKey(
                                                                                                                        p_inner_ec_request.publicKeys.verificationKey
                                                                                                                        ),
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                             p_inner_ec_request.requestedSubjectAttributes.region,
                                                                             p_inner_ec_request.requestedSubjectAttributes.assuranceLevel,
                                                                             p_inner_ec_request.publicKeys.encryptionKey
                                                                             )
                                                  )
                        );
      // Encode it ==> Get octetstring
      v_tbs := encvalue(v_cert.toBeSigned);
      // Sign the certificate
      v_sig := f_signWithEcdsa(bit2oct(v_tbs), p_digest, p_private_key);
      if (PX_VE_ALG == e_nist_p256) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaNistP256(
                                                               m_ecdsaP256Signature(
                                                                                    m_eccP256CurvePoint_x_only(
                                                                                                               substr(v_sig, 0, 32)
                                                                                                               ),
                                                                                    substr(v_sig, 32, 32)
                                                                                    )
                                                               )
                                     );
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaBrainpoolP256r1(
                                                                      m_ecdsaP256Signature(
                                                                                           m_eccP256CurvePoint_x_only(
                                                                                                                      substr(v_sig, 0, 32)
                                                                                                                      ),
                                                                                           substr(v_sig, 32, 32)
                                                                                           )
                                                                      )
                                     );
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaBrainpoolP384r1(
                                                                      m_ecdsaP384Signature(
                                                                                           m_eccP384CurvePoint_x_only(
                                                                                                                      substr(v_sig, 0, 48)
                                                                                                                      ),
                                                                                           substr(v_sig, 48, 48)
                                                                                           )
                                                                      )
                                     );
      } else if (PX_VE_ALG == e_nist_p384) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaNistP384(
                                                               m_ecdsaP384Signature(
                                                                                    m_eccP384CurvePoint_x_only(
                                                                                                               substr(v_sig, 0, 48)
                                                                                                               ),
                                                                                    substr(v_sig, 48, 48)
                                                                                    )
                                                                )
                                     );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      p_ec_certificate := valueof(v_cert);

      // Encode it and calculate HashedId8
      v_tbs := encvalue(p_ec_certificate);
      p_ec_certificate_hashed_id8 := f_hashedId8FromSha256(f_hashWithSha256(bit2oct(v_tbs)));
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("f_generate_ec_certificate_for_inner_ec_response: p_ec_certificate= ", p_ec_certificate);
      log("f_generate_ec_certificate_for_inner_ec_response: p_ec_certificate_hashed_id8= ", p_ec_certificate_hashed_id8);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_ec_certificate_for_inner_ec_response
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_at_certificate_for_inner_at_response(
                                                             in InnerAtRequest p_inner_at_request,
                                                             in octetstring p_private_key,
                                                             in octetstring p_digest,
                                                             out EtsiTs103097Certificate p_at_certificate
                                                             ) return boolean {
      var EtsiTs103097Certificate v_cert;
      var IssuerIdentifier v_issuer;
      var bitstring v_tbs;
      var octetstring v_sig;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      v_issuer := valueof(m_issuerIdentifier_sha256AndDigest(f_hashedId8FromSha256(p_digest))); // TODO Check sha256/384 f_hashedId8FromSha384
      v_cert := valueof(
                        m_etsiTs103097Certificate(
                                                  v_issuer,
                                                  m_toBeSignedCertificate_at(
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.appPermissions,
                                                                             m_verificationKeyIndicator_verificationKey(
                                                                                                                        p_inner_at_request.publicKeys.verificationKey
                                                                                                                        ),
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.validityPeriod,
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.region,
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.assuranceLevel,
                                                                             p_inner_at_request.publicKeys.encryptionKey
                                                                             )
                                                  )
                        );
      // Encode it ==> Get octetstring
      v_tbs := encvalue(v_cert.toBeSigned);
      // Sign the certificate
      v_sig := f_signWithEcdsa(bit2oct(v_tbs), p_digest, p_private_key);
      log("f_generate_at_certificate_for_inner_at_response: PX_VE_ALG=", PX_VE_ALG);
      if (PX_VE_ALG == e_nist_p256) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaNistP256(
                                                               m_ecdsaP256Signature(
                                                                                    m_eccP256CurvePoint_x_only(
                                                                                                               substr(v_sig, 0, 32)
                                                                                                               ),
                                                                                    substr(v_sig, 32, 32)
                                                                                    )
                                                               )
                                     );
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaBrainpoolP256r1(
                                                                      m_ecdsaP256Signature(
                                                                                           m_eccP256CurvePoint_x_only(
                                                                                                                      substr(v_sig, 0, 32)
                                                                                                                      ),
                                                                                           substr(v_sig, 32, 32)
                                                                                           )
                                                                      )
                                     );
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaBrainpoolP384r1(
                                                                      m_ecdsaP384Signature(
                                                                                           m_eccP384CurvePoint_x_only(
                                                                                                                      substr(v_sig, 0, 48)
                                                                                                                      ),
                                                                                           substr(v_sig, 48, 48)
                                                                                           )
                                                                      )
                                     );
      } else if (PX_VE_ALG == e_nist_p384) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaNistP384(
                                                               m_ecdsaP384Signature(
                                                                                    m_eccP384CurvePoint_x_only(
                                                                                                              substr(v_sig, 0, 48)
                                                                                                              ),
                                                                                    substr(v_sig, 48, 48)
                                                                                    )
                                                              )
                                     );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      p_at_certificate := valueof(v_cert);
      log("f_generate_at_certificate_for_inner_at_response: p_at_certificate= ", p_at_certificate);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_at_certificate_for_inner_at_response
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_at_certificate_for_authorization_response(
                                                                  in InnerAtRequest p_inner_at_request,
                                                                  in octetstring p_private_key,
                                                                  in octetstring p_digest,
                                                                  out EtsiTs103097Certificate p_at_certificate
                                                                  ) return boolean {
      var EtsiTs103097Certificate v_cert;
      var IssuerIdentifier v_issuer;
      var bitstring v_tbs;
      var octetstring v_sig;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log(">>> f_generate_at_certificate_for_authorization_response");

      v_issuer := valueof(m_issuerIdentifier_sha256AndDigest(f_hashedId8FromSha256(p_digest))); // TODO Check sha256/384 f_hashedId8FromSha384
      v_cert := valueof(
                        m_etsiTs103097Certificate(
                                                  v_issuer,
                                                  m_toBeSignedCertificate_ec(
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.id,
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.appPermissions,
                                                                             m_verificationKeyIndicator_verificationKey(
                                                                                                                        p_inner_at_request.publicKeys.verificationKey
                                                                                                                        ),
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.validityPeriod,
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.region,
                                                                             p_inner_at_request.sharedAtRequest.requestedSubjectAttributes.assuranceLevel,
                                                                             p_inner_at_request.publicKeys.encryptionKey
                                                                             )
                                                  )
                        );
      // Encode it ==> Get octetstring
      v_tbs := encvalue(v_cert.toBeSigned);
      // Sign the certificate
      v_sig := f_signWithEcdsa(bit2oct(v_tbs), p_digest, p_private_key);
      if (PX_VE_ALG == e_nist_p256) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaNistP256(
                                                               m_ecdsaP256Signature(
                                                                                    m_eccP256CurvePoint_x_only(
                                                                                                               substr(v_sig, 0, 32)
                                                                                                               ),
                                                                                    substr(v_sig, 32, 32)
                                                                                    )
                                                               )
                                     );
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaBrainpoolP256r1(
                                                                      m_ecdsaP256Signature(
                                                                                           m_eccP256CurvePoint_x_only(
                                                                                                                      substr(v_sig, 0, 32)
                                                                                                                      ),
                                                                                           substr(v_sig, 32, 32)
                                                                                           )
                                                                      )
                                     );
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaBrainpoolP384r1(
                                                                      m_ecdsaP384Signature(
                                                                                           m_eccP384CurvePoint_x_only(
                                                                                                                      substr(v_sig, 0, 48)
                                                                                                                      ),
                                                                                           substr(v_sig, 48, 48)
                                                                                           )
                                                                      )
                                     );
      } else if (PX_VE_ALG == e_nist_p384) {
        v_cert.signature_ := valueof(
                                     m_signature_ecdsaNistP384(
                                                               m_ecdsaP384Signature(
                                                                                    m_eccP384CurvePoint_x_only(
                                                                                                              substr(v_sig, 0, 48)
                                                                                                              ),
                                                                                    substr(v_sig, 48, 48)
                                                                                    )
                                                              )
                                     );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      p_at_certificate := valueof(v_cert);
      log("f_generate_at_certificate_for_authorization_response: p_at_certificate= ", p_at_certificate);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_at_certificate_for_authorization_response
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group generate_certificates 
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  group inner_ec_xxx {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_inner_ec_request(
                                         out octetstring p_private_key,
                                         out octetstring p_public_key_compressed,
                                         out integer p_compressed_mode,
                                         out InnerEcRequest p_inner_ec_request
                                         ) runs on ItsPkiHttp return boolean {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Local variables
      var Oct32 v_public_key_x;
      var Oct32 v_public_key_y;
      var PublicVerificationKey v_public_verification_key;

      log (">>> f_generate_inner_ec_request");
      log("f_generate_inner_ec_request: PX_VE_ALG=", PX_VE_ALG);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Generate keys for the certificate to be requested
      if (f_generate_key_pair(p_private_key, v_public_key_x, v_public_key_y, p_public_key_compressed, p_compressed_mode) == false) {
        log ("f_generate_inner_ec_request: failed to generate keys");
        return false;
      }
      // Build the Proof of Possession InnerEcRequest
      if (PX_VE_ALG == e_nist_p256) {
        var EccP256CurvePoint v_eccP256_curve_point;
        if (p_compressed_mode == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_public_key_compressed));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_public_key_compressed));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaNistP256(v_eccP256_curve_point));
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        var EccP256CurvePoint v_eccP256_curve_point;
        if (p_compressed_mode == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_public_key_compressed));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_public_key_compressed));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaBrainpoolP256r1(v_eccP256_curve_point));
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        var EccP384CurvePoint v_eccP384_curve_point;
        if (p_compressed_mode == 0) {
          v_eccP384_curve_point := valueof(m_eccP384CurvePoint_compressed_y_0(p_public_key_compressed));
        } else {
          v_eccP384_curve_point := valueof(m_eccP384CurvePoint_compressed_y_1(p_public_key_compressed));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaBrainpoolP384r1(v_eccP384_curve_point));
      }
      if (PICS_EC_SUBJECT_ATTRIBUT_ID) {
        p_inner_ec_request := valueof(
                                      m_innerEcRequest(
                                                       PICS_ITS_S_CANONICAL_ID,
                                                       m_publicKeys(
                                                                    v_public_verification_key
                                                                    ),
                                                       m_certificateSubjectAttributes_id_name(
                                                                                              oct2char(PICS_ITS_S_CANONICAL_ID) & int2str(f_getCurrentTime()), // ETSI TS  103 097 Clause 7.2.2 Enrolment credential 
                                                                                              { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
                                                                                                valueof(m_appPermissions(c_its_aid_SCR, { bitmapSsp := PX_INNER_EC_CERTFICATE_BITMAP_SSP_SCR }))
                                                                                                },
                                                                                              m_validityPeriod(
                                                                                                               f_getCurrentTime() / 1000,
                                                                                                               m_duration_in_hours(PX_GENERATED_CERTIFICATE_DURATION)
                                                                                                               ),
                                                                                              m_geographicRegion_identifiedRegion(
                                                                                                                                  {
                                                                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_1),
                                                                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_2)
                                                                                                                                    }
                                                                                                                                  ),
                                                                                              PX_GENERATED_CERTIFICATE_SUBJECT_ASSURENCE_LEVEL
                                                                                              )
                                                       )
                                      );
      } else {
        p_inner_ec_request := valueof(
                                      m_innerEcRequest(
                                                       PICS_ITS_S_CANONICAL_ID,
                                                       m_publicKeys(
                                                                    v_public_verification_key
                                                                    ),
                                                       m_certificateSubjectAttributes_id_omit( // ETSI TS  103 097 Clause 7.2.2 Enrolment credential 
                                                                                              { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
                                                                                                valueof(m_appPermissions(c_its_aid_SCR, { bitmapSsp := PX_INNER_EC_CERTFICATE_BITMAP_SSP_SCR }))
                                                                                                },
                                                                                              m_validityPeriod(
                                                                                                               f_getCurrentTime() / 1000,
                                                                                                               m_duration_in_hours(PX_GENERATED_CERTIFICATE_DURATION)
                                                                                                               ),
                                                                                              m_geographicRegion_identifiedRegion(
                                                                                                                                  {
                                                                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_1),
                                                                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_2)
                                                                                                                                    }
                                                                                                                                  ),
                                                                                              PX_GENERATED_CERTIFICATE_SUBJECT_ASSURENCE_LEVEL
                                                                                              )
                                                       )
                                      );
      }
      // Remove geographical region (ETAS)
      if (not(PICS_EC_SUBJECT_ATTRIBUT_REGION)) {
        p_inner_ec_request.requestedSubjectAttributes.region := omit;
      }
      log("f_generate_inner_ec_request: PICS_SECPKI_REENROLMENT: ", PICS_SECPKI_REENROLMENT);
      log("f_generate_inner_ec_request: vc_ec_keys_counter: ", vc_ec_keys_counter);
      if (PICS_SECPKI_REENROLMENT and (vc_ec_keys_counter > 0)) { // This is a re-enrolment, the identifier of its current valid Enrolment Credential
        log("f_generate_inner_ec_request: This is a re-enrolment: vc_ec_keys_counter= ", vc_ec_keys_counter);
        log("f_generate_inner_ec_request: This is a re-enrolment: vc_ec_hashed_id8[vc_ec_keys_counter - 1]= ", vc_ec_hashed_id8[vc_ec_keys_counter - 1]);
        p_inner_ec_request.itsId := vc_ec_hashed_id8[vc_ec_keys_counter - 1];
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_generate_inner_ec_request: ", p_inner_ec_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_inner_ec_request
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_inner_ec_request_with_wrong_parameters(
                                                               in SequenceOfPsidSsp p_appPermissions,
                                                               in octetstring p_canonical_id := PICS_ITS_S_CANONICAL_ID,
                                                               in Time32 p_start,
                                                               in Duration p_duration,
                                                               in boolean p_alter_private_key := false,
                                                               out octetstring p_private_key,
                                                               out octetstring p_public_key_compressed,
                                                               out integer p_compressed_mode,
                                                               out InnerEcRequest p_inner_ec_request
                                                               ) runs on ItsPkiHttp return boolean {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Local variables
      var Oct32 v_public_key_x;
      var Oct32 v_public_key_y;
      var octetstring v_private_key;
      var octetstring v_public_key_compressed;
      var integer v_compressed_mode;
      var PublicVerificationKey v_public_verification_key;

      log (">>> f_generate_inner_ec_request_with_wrong_parameters");
      // Generate keys for the certificate to be requested
      if (f_generate_key_pair(p_private_key, v_public_key_x, v_public_key_y, p_public_key_compressed, p_compressed_mode) == false) {
        log ("f_generate_inner_ec_request_with_wrong_parameters: failed to generate keys");
        return false;
      }
      if (p_alter_private_key == false) {
        v_private_key := p_private_key;
        v_public_key_compressed := p_public_key_compressed;
        v_compressed_mode := p_compressed_mode;
      } else {
        log ("f_generate_inner_ec_request_with_wrong_parameters: Alter verify private key");
        if (f_generate_key_pair(v_private_key, v_public_key_x, v_public_key_y, v_public_key_compressed, v_compressed_mode) == false) {
          log ("f_generate_inner_ec_request_with_wrong_parameters: failed to generate keys");
          return false;
        }
      }
      // Build the Proof of Possession InnerEcRequest
      log("f_generate_inner_ec_request_with_wrong_parameters: PX_VE_ALG=", PX_VE_ALG);
      if (PX_VE_ALG == e_nist_p256) {
        var EccP256CurvePoint v_eccP256_curve_point;
        if (v_compressed_mode == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_key_compressed));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_key_compressed));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaNistP256(v_eccP256_curve_point));
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        var EccP256CurvePoint v_eccP256_curve_point;
        if (v_compressed_mode == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_key_compressed));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_key_compressed));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaBrainpoolP256r1(v_eccP256_curve_point));
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else {
        var EccP384CurvePoint v_eccP384_curve_point;
        if (v_compressed_mode == 0) {
          v_eccP384_curve_point := valueof(m_eccP384CurvePoint_compressed_y_0(v_public_key_compressed));
        } else {
          v_eccP384_curve_point := valueof(m_eccP384CurvePoint_compressed_y_1(v_public_key_compressed));
        }
        v_public_verification_key := valueof(m_publicVerificationKey_ecdsaBrainpoolP384r1(v_eccP384_curve_point));
      }
      if (PICS_EC_SUBJECT_ATTRIBUT_ID) {
        p_inner_ec_request := valueof(
                                      m_innerEcRequest(
                                                      p_canonical_id,
                                                      m_publicKeys(
                                                                    v_public_verification_key
                                                                    ),
                                                      m_certificateSubjectAttributes_id_name(
                                                                                              oct2char(PICS_ITS_S_CANONICAL_ID),
                                                                                              p_appPermissions, // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
                                                                                              m_validityPeriod(
                                                                                                              p_start,
                                                                                                              p_duration
                                                                                                              ),
                                                                                              m_geographicRegion_identifiedRegion(
                                                                                                                                  {
                                                                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_1),
                                                                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_2)
                                                                                                                                    }
                                                                                                                                  ),
                                                                                              PX_GENERATED_CERTIFICATE_SUBJECT_ASSURENCE_LEVEL
                                                                                              )
                                                      )
                                      );
      } else {
        p_inner_ec_request := valueof(
                                      m_innerEcRequest(
                                                      p_canonical_id,
                                                      m_publicKeys(
                                                                    v_public_verification_key
                                                                    ),
                                                      m_certificateSubjectAttributes_id_omit( // ETSI TS  103 097 Clause 7.2.2 Enrolment credential 
                                                                                              p_appPermissions, // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
                                                                                              m_validityPeriod(
                                                                                                              p_start,
                                                                                                              p_duration
                                                                                                              ),
                                                                                              m_geographicRegion_identifiedRegion(
                                                                                                                                  {
                                                                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_1),
                                                                                                                                    m_identifiedRegion_country_only(PX_GENERATED_CERTIFICATE_REGION_COUNTRY_2)
                                                                                                                                    }
                                                                                                                                  ),
                                                                                              PX_GENERATED_CERTIFICATE_SUBJECT_ASSURENCE_LEVEL
                                                                                              )
                                                      )
                                      );
      }// Remove geographical region (ETAS)
      if (not(PICS_EC_SUBJECT_ATTRIBUT_REGION)) {
        p_inner_ec_request.requestedSubjectAttributes.region := omit;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("f_generate_inner_ec_request_with_wrong_parameters: ", p_inner_ec_request);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_inner_ec_request_with_wrong_parameters
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_inner_ec_request_signed_for_pop(
                                                        in octetstring p_private_key,
                                                        in InnerEcRequest p_inner_ec_request,
                                                        out Ieee1609Dot2Data p_inner_ec_request_signed_for_pop
    ) runs on ItsPkiHttp return boolean {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Local variables
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var octetstring v_encoded_inner_ec_request;
      var template (value) ToBeSignedData v_tbs;
      var octetstring v_tbs_signed;
      var Signature v_signature;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Encode it
      log("f_generate_inner_ec_request_signed_for_pop: encode ", p_inner_ec_request);
      v_encoded_inner_ec_request := bit2oct(encvalue(p_inner_ec_request));
      // Signed the encoded InnerEcRequestSignedForPop
      v_tbs := m_toBeSignedData(
                                m_signedDataPayload(
                                                    m_etsiTs103097Data_unsecured(
                                                                                 v_encoded_inner_ec_request
                                                                                 )
                                                   ),
                                m_headerInfo_inner_pki_request(
                                                               -,
                                                               (f_getCurrentTime() * 1000) //us
                                                               )
                               );
      // Signed the encoded InnerEcRequestSignedForPop
      log("f_generate_inner_ec_request_signed_for_pop: tbs= ", v_tbs);
      log("f_generate_inner_ec_request_signed_for_pop: tbs= ", bit2oct(encvalue(v_tbs)));
      v_tbs_signed := f_signWithEcdsa(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key);
      // Finalyse signed InnerEcRequestSignedForPop
      if (PX_VE_ALG == e_nist_p256) {
        v_signature := valueof(
                               m_signature_ecdsaNistP256(
                                                         m_ecdsaP256Signature(
                                                                              m_eccP256CurvePoint_x_only(
                                                                                                         substr(v_tbs_signed, 0, 32)
                                                                                                         ),
                                                                              substr(v_tbs_signed, 32, 32)
                                                                              )
                                                         )
                               );
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        v_signature := valueof(
                               m_signature_ecdsaBrainpoolP256r1(
                                                                m_ecdsaP256Signature(
                                                                                     m_eccP256CurvePoint_x_only(
                                                                                                                substr(v_tbs_signed, 0, 32)
                                                                                                                ),
                                                                                     substr(v_tbs_signed, 32, 32)
                                                                                     )
                                                                )
                               );
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        v_signature := valueof(
                               m_signature_ecdsaBrainpoolP384r1(
                                                                m_ecdsaP384Signature(
                                                                                     m_eccP384CurvePoint_x_only(
                                                                                                                substr(v_tbs_signed, 0, 48)
                                                                                                                ),
                                                                                     substr(v_tbs_signed, 48, 48)
                                                                                     )
                                                                )
                               );
      } else if (PX_VE_ALG == e_nist_p384) {
        v_signature := valueof(
                               m_signature_ecdsaNistP384(
                                                         m_ecdsaP384Signature(
                                                                              m_eccP384CurvePoint_x_only(
                                                                                                        substr(v_tbs_signed, 0, 48)
                                                                                                        ),
                                                                              substr(v_tbs_signed, 48, 48)
                                                                              )
                                                        )
                               );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("f_generate_inner_ec_request_signed_for_pop: v_signature= ", v_signature);
      p_inner_ec_request_signed_for_pop := valueof(
                                                   m_etsiTs103097Data_signed(
                                                                             m_signedData(
                                                                                          sha256,
                                                                                          v_tbs,
                                                                                          m_signerIdentifier_self,
                                                                                          v_signature
                                                                                          )
                                                                             )
                                                   );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_generate_inner_ec_request_signed_for_pop: p_inner_ec_request_signed_for_pop= ", p_inner_ec_request_signed_for_pop);
      return true;
    } // End of function f_generate_inner_ec_request_signed_for_pop

    function f_verify_inner_ec_request_signed_for_pop(
                                                      in EtsiTs102941Data p_etsi_ts_102941_data,
                                                      out InnerEcRequest p_inner_ec_request
                                                      ) return boolean {
      var bitstring v_msg_bit;

      log(">>> f_verify_inner_ec_request_signed_for_pop: ", p_etsi_ts_102941_data);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // 1. Decode content
      v_msg_bit := oct2bit(p_etsi_ts_102941_data.content.enrolmentRequest.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_msg_bit, p_inner_ec_request) != 0) {
        log("f_verify_inner_ec_request_signed_for_pop: Failed to decode InnerEcRequest");
        return false;
      } else {
        log("f_verify_inner_ec_request_signed_for_pop: v_inner_ec_request= ", p_inner_ec_request);

        // 2. Verify the InnerEcRequestSignedForPop signature
        // TODO
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_verify_inner_ec_request_signed_for_pop
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_generate_inner_ec_response(
                                          in octetstring p_inner_ec_request_hash,
                                          in EtsiTs103097Certificate p_certificate,
                                          out InnerEcResponse p_inner_ec_response
                                         ) return boolean {
      // Local variables
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Build the Proof of Possession InnerEcResponse
      p_inner_ec_response := valueof(
                                     m_innerEcResponse_ok(
                                                          substr(p_inner_ec_request_hash, 0, 16),
                                                          p_certificate
                                                          )
                                     );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_generate_inner_ec_response
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group inner_ec_xxx

  group inner_at_xxx {

    function f_generate_inner_at_request(
                                         in Certificate p_aa_certificate,
                                         in SignAlgorithm p_enc_algo := PX_EC_ALG_FOR_EC_SIGN,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                         in Oct8 p_aa_hashed_id8,
                                         in Certificate p_ea_certificate,
                                         in octetstring p_salt,
                                         in Oct8 p_ea_hashed_id8,
                                         in Certificate p_ec_certificate,
                                         in octetstring p_ec_private_key,
                                         out octetstring p_private_key,
                                         out octetstring p_public_key_compressed,
                                         out integer p_compressed_key_mode,
                                         out octetstring p_private_enc_key,
                                         out octetstring p_public_compressed_enc_key,
                                         out integer p_compressed_enc_key_mode,
                                         out InnerAtRequest p_inner_at_request
                                         ) return boolean {
      // Local variables
      var octetstring v_public_key_x;
      var octetstring v_public_key_y;
      var octetstring v_public_enc_key_x;
      var octetstring v_public_enc_key_y;
      var bitstring v_enc_value;
      var octetstring v_ec_hash;
      var PublicVerificationKey v_public_verification_key;
      var BasePublicEncryptionKey v_public_encryption_key;
      var Oct8 v_ec_hashed_id8;
      var octetstring public_enc_key_x;
      var octetstring public_enc_key_y;
      var Oct32 v_hmac_key;
      var PublicVerificationKey v_verification_tag;
      var PublicEncryptionKey v_encryption_tag;
      var octetstring v_encoded_tag;
      var Oct16 v_key_tag;
      var octetstring v_hash_shared_at_request;
      var template (value) ToBeSignedData v_tbs;
      var octetstring v_tbs_signed;
      var Ieee1609Dot2Data v_signed_at_signature;
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var HashAlgorithm v_hashId;
      var Signature v_signature;
      var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
        valueof(m_appPermissions(c_its_aid_CAM, { bitmapSsp := PX_INNER_AT_CERTFICATE_BITMAP_SSP_CAM })),
        valueof(m_appPermissions(c_its_aid_DENM, { bitmapSsp := PX_INNER_AT_CERTFICATE_BITMAP_SSP_DENM }))
      };

      log(">>> f_generate_inner_at_request: p_enc_algo=", p_enc_algo);

      // Generate verification keys for the certificate to be requested
      if (f_generate_key_pair(p_private_key, v_public_key_x, v_public_key_y, p_public_key_compressed, p_compressed_key_mode) == false) {
        log("f_generate_inner_at_request: Failed to generate verification key");
        return false;
      }
      log ("f_generate_inner_at_request: AT verification private key: ", p_private_key);
      log ("f_generate_inner_at_request: AT verification public compressed key: ", p_public_key_compressed);
      log ("f_generate_inner_at_request: AT verification public compressed mode: ", p_compressed_key_mode);
      // Generate encryption keys for the certificate to be requested
      if (PX_INCLUDE_ENCRYPTION_KEYS) {
        if (f_generate_key_pair_for_encryption(p_enc_algo, p_private_enc_key, v_public_enc_key_x, v_public_enc_key_y, p_public_compressed_enc_key, p_compressed_enc_key_mode) == false) {
          log("f_generate_inner_at_request: Failed to generate encryption key");
          return false;
        } else {
          log ("f_generate_inner_at_request: AT encryption private key: ", p_private_enc_key);
          log ("f_generate_inner_at_request: AT encryption public compressed key: ", p_public_compressed_enc_key);
          log ("f_generate_inner_at_request: AT encryption public compressed mode: ", p_compressed_enc_key_mode);
        }
      } else {
        p_private_enc_key := ''O;
        v_public_enc_key_x := ''O;
        v_public_enc_key_y := ''O;
        p_public_compressed_enc_key := ''O;
        p_compressed_enc_key_mode := -1;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Generate 32 octets length secret key
      v_hmac_key := f_hashWithSha256(int2oct((f_getCurrentTimeUtc() * 1000), 12));
      log("f_generate_inner_at_request: v_hmac_key= ", v_hmac_key);

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

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

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

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

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

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

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

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

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

  group bfk {

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

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

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

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

      return true;
    } // End of function f_generate_ee_ra_cert_request

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

      p_bfk_batch_certificates := {};
      p_bfk_batch_counter := 0;

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

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

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

      log("<<< f_generate_bfk_batch: p_bfk_batch_certificates: ", p_bfk_batch_certificates);
      log("<<< f_generate_bfk_batch: p_bfk_batch_counter: ", p_bfk_batch_counter);
      return true;
    } // End of function f_generate_bfk_batch

    function f_generate_ra_ee_cert_info(
                                        in EeRaCertRequest p_ee_ra_cert_request,
                                        in HashedId8 p_requestHash,
                                        out RaEeCertInfo p_ra_ee_cert_info
                                        ) runs on ItsPkiHttp return boolean {
      log(">>> f_generate_ra_ee_cert_info: p_ee_ra_cert_request: ", p_ee_ra_cert_request);

      var UInt32 v_current_time := f_getCurrentTimeUtc() / 1000; // In seconds
      var UInt32 v_dl_time := v_current_time + 60; // Current time + one minute

      // Build Batch of certificates
      f_generate_bfk_batch(p_ee_ra_cert_request, vc_bfk_batch_certificates, vc_bfk_batch_counter);

      // Build the response
      p_ra_ee_cert_info := valueof(
                                   m_ra_ee_cert_info(
                                                     v_current_time,
                                                     vc_bfk_batch_counter,
                                                     p_requestHash,
                                                     v_dl_time
                                   ));
      log("<<< f_generate_ra_ee_cert_info: p_ra_ee_cert_info: ", p_ra_ee_cert_info);

      return true;
    } // End of function f_generate_ra_ee_cert_info

    function f_generate_ee_ra_download_request(
                                               in charstring p_filename,
                                               out EeRaDownloadRequest p_ee_ra_download_request
                                               ) runs on ItsPkiHttp return boolean {
      var UInt32 v_current_time := f_getCurrentTime() / 1000; // In seconds
      p_ee_ra_download_request := valueof(m_ee_ra_download_request(v_current_time, p_filename));
      log("f_generate_ee_ra_download_request: p_ee_ra_download_request: ", p_ee_ra_download_request);

      return true
    } // End of function f_generate_ee_ra_download_request

  } // End of group bfk

ASN.1 Documenter's avatar
ASN.1 Documenter committed
  group dc {

    function f_build_dc(
                        in charstring p_rca_certificate_id,
                        out EtsiTs103097Certificate p_rca_certificate
                        ) {
      log(">>> f_build_dc");

      // Load certificate
      f_readCertificate(p_rca_certificate_id, p_rca_certificate);
    }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_verify_rca_ctl_response_message(
                                               in EtsiTs103097Data p_etsi_ts_103097_signed_data,
                                               in boolean p_check_security := true,
                                               out ToBeSignedRcaCtl p_to_be_signed_rca_ctl
                                               ) return boolean {
      var bitstring v_etsi_ts_102941_data_msg;
      var bitstring v_tbs;
      var Certificate v_certificate;
      var charstring v_certificate_id;
      var octetstring v_issuer;
      var EtsiTs102941Data v_etsi_ts_102941_data;

      log(">>> f_verify_rca_ctl_response_message: p_etsi_ts_103097_signed_data= ", p_etsi_ts_103097_signed_data);

      // 1. Verify signature
      log("f_verify_rca_ctl_response_message: p_etsi_ts_103097_signed_data.content.signedData.tbsData= ", p_etsi_ts_103097_signed_data.content.signedData.tbsData);
      v_tbs := encvalue(p_etsi_ts_103097_signed_data.content.signedData.tbsData);
      if (ispresent(p_etsi_ts_103097_signed_data.content.signedData.signer.digest)) {
        if (f_getCertificateFromDigest(p_etsi_ts_103097_signed_data.content.signedData.signer.digest, v_certificate, v_certificate_id) == false) {
          log("f_verify_rca_ctl_response_message: Failed to retrieve certificate from ", p_etsi_ts_103097_signed_data.content.signedData.signer.digest);
          if (p_check_security == true) {
            return false;
          }
        }
        log("f_verify_rca_ctl_response_message (1): v_certificate: ", v_certificate);
        f_getCertificateHash(v_certificate_id, v_issuer);
      } else {
        v_certificate := p_etsi_ts_103097_signed_data.content.signedData.signer.certificate[0];
        log("f_verify_rca_ctl_response_message (2): v_certificate: ", v_certificate);
        if (ispresent(v_certificate.issuer.sha256AndDigest)) {
          v_issuer := v_certificate.issuer.sha256AndDigest;
        } if (ispresent(v_certificate.issuer.sha384AndDigest)) {
          v_issuer := v_certificate.issuer.sha384AndDigest;
        } else { // self_
          if (v_certificate.issuer.self_ == sha256) {
            v_issuer := int2oct(0, 32);
          } else {
            v_issuer := int2oct(0, 48);
          }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
      }
      if (f_verifyEcdsa(bit2oct(v_tbs), v_issuer, p_etsi_ts_103097_signed_data.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
        log("f_verify_rca_ctl_response_message: Failed to verify signature");
        if (p_check_security == true) {
          return false;
        }
      }
      v_etsi_ts_102941_data_msg := oct2bit(p_etsi_ts_103097_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_etsi_ts_102941_data_msg, v_etsi_ts_102941_data) != 0) {
        log("f_verify_rca_ctl_response_message: Failed to decode EtsiTs102941Data");
        return false;
      } else {
        log("f_verify_rca_ctl_response_message: v_etsi_ts_102941_data= ", v_etsi_ts_102941_data);
        log("f_verify_pki_response_message: RcaCertificateTrustListMessage matching= ", match(v_etsi_ts_102941_data, mw_etsiTs102941Data_to_be_signed_rca_ctl));
        if (match(v_etsi_ts_102941_data, mw_etsiTs102941Data_to_be_signed_rca_ctl) == false) {
          log("f_verify_rca_ctl_response_message: Failed to decode certificateTrustListRca");
          return false;
        } else {
          var Time32 v_time := (f_getCurrentTime()/* - 1072915200000*/) / 1000;
          p_to_be_signed_rca_ctl := v_etsi_ts_102941_data.content.certificateTrustListRca;
          log("f_verify_rca_ctl_response_message: p_to_be_signed_rca_ctl= ", p_to_be_signed_rca_ctl);
          if (p_to_be_signed_rca_ctl.nextUpdate <= v_time) {
            log("f_verify_rca_ctl_response_message: Invalid nextUpdate value: compared values=", p_to_be_signed_rca_ctl.nextUpdate, "/", v_time);
            return false;
          }
          // TODO Verify RCA certificate & signature
        }
      }

      return true;
    }

    function f_verify_rca_crl_response_message(
                                               in EtsiTs103097Data p_etsi_ts_103097_signed_data,
                                               in boolean p_check_security := true,
                                               out ToBeSignedCrl p_to_be_signed_crl
                                               ) return boolean {
      var bitstring v_etsi_ts_102941_data_msg;
      var bitstring v_tbs;
      var Certificate v_certificate;
      var charstring v_certificate_id;
      var octetstring v_issuer;
      var EtsiTs102941Data v_etsi_ts_102941_data;

      log(">>> f_verify_rca_crl_response_message: p_etsi_ts_103097_signed_data= ", p_etsi_ts_103097_signed_data);

      // 1. Verify signature
      log("f_verify_rca_crl_response_message: p_etsi_ts_103097_signed_data.content.signedData.tbsData= ", p_etsi_ts_103097_signed_data.content.signedData.tbsData);
      v_tbs := encvalue(p_etsi_ts_103097_signed_data.content.signedData.tbsData);
      if (f_getCertificateFromDigest(p_etsi_ts_103097_signed_data.content.signedData.signer.digest, v_certificate, v_certificate_id) == false) {
        log("f_verify_rca_crl_response_message: Failed to retrieve certificate from ", p_etsi_ts_103097_signed_data.content.signedData.signer.digest);
        if (p_check_security == true) {
          return false;
        }
      }
      f_getCertificateHash(v_certificate_id, v_issuer);
      if (f_verifyEcdsa(bit2oct(v_tbs), v_issuer, p_etsi_ts_103097_signed_data.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
        log("f_verify_rca_crl_response_message: Failed to verify signature");
        if (p_check_security == true) {
          return false;
        }
      }
      v_etsi_ts_102941_data_msg := oct2bit(p_etsi_ts_103097_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_etsi_ts_102941_data_msg, v_etsi_ts_102941_data) != 0) {
        log("f_verify_rca_crl_response_message: Failed to decode EtsiTs102941Data");
        return false;
      } else {
        log("f_verify_rca_crl_response_message: v_etsi_ts_102941_data= ", v_etsi_ts_102941_data);
        log("f_verify_pki_response_message: CertificateRevocationList matching= ", match(v_etsi_ts_102941_data, mw_etsiTs102941Data_to_be_signed_crl));
        if (match(v_etsi_ts_102941_data, mw_etsiTs102941Data_to_be_signed_crl) == false) {
          log("f_verify_rca_crl_response_message: Failed to decode certificateRevocationList");
          return false;
        } else {
          var Time32 v_time := (f_getCurrentTime()/* - 1072915200000*/) / 1000;
          p_to_be_signed_crl := v_etsi_ts_102941_data.content.certificateRevocationList;
          log("f_verify_rca_crl_response_message: p_to_be_signed_crl= ", p_to_be_signed_crl);
          if (p_to_be_signed_crl.thisUpdate >= v_time) {
            log("f_verify_rca_crl_response_message: Invalid thisUpdate value");
            return false;
          }
          if (p_to_be_signed_crl.nextUpdate <= v_time) {
            log("f_verify_rca_crl_response_message: Invalid nextUpdate value");
            return false;
          }
          // TODO Verify RCA certificate & signature
        }
      }

      return true;
    }

    /**
     * @desc this function is used to retrieve the root certificate from SubCA entity
     * @param p_certificate The root certificate
     * @return 0 on success, -1 otherwise
     */
    function f_get_root_ca_certificate(
                                       in charstring p_iut_certificate := "CERT_IUT_A_CA",
                                       in boolean p_explicit_type := false,
                                       out Certificate p_certificate
                                       ) runs on ItsPkiHttp return integer {
      var Headers v_headers;
      var HttpMessage v_response;
      var octetstring v_os;
      var bitstring v_msg_bit;
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      log(">>> f_get_root_ca_certificate");
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      // Get root certificate
      f_cfHttpUp_ca();
      f_init_default_headers_list(PICS_HEADER_CTL_CONTENT_TYPE, "ca_request", v_headers);
      // Test Body
      f_http_send(
                  v_headers,
                  m_http_request(
                                  m_http_request_get(
                                                    PICS_HTTP_GET_URI_DC,
                                                    v_headers
                                                    )));
      tc_ac.start;
      alt {
        [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(
                                                        mw_http_response(
                                                                          mw_http_response_ok(
                                                                                              mw_http_message_body_binary(
                                                                                                                          mw_binary_body_ieee1609dot2_certificate
                                                                                                                          )))) -> value v_response {
          tc_ac.stop;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
        [PICS_MULTIPLE_END_POINT] httpCaPort.receive(
                                                      mw_http_response(
                                                                      mw_http_response_ok(
                                                                                          mw_http_message_body_binary(
                                                                                                                      mw_binary_body_ieee1609dot2_certificate
                                                                                                                      )))) -> value v_response {
          tc_ac.stop;
        }
        [] tc_ac.timeout {
        }
      } // End of 'alt' statement
      f_cfHttpDown_ca();
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      if (not(isvalue(v_response))) {
        log("f_get_root_ca_certificate: fail to get certificate");
        return -1;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
      log("v_response.response.body.binary_body.ieee1609dot2_certificate: ", v_response.response.body.binary_body.ieee1609dot2_certificate);
      p_certificate := v_response.response.body.binary_body.ieee1609dot2_certificate;
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      log("<<< f_get_root_ca_certificate: ", p_certificate);
      return 0;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    }

    function f_verify_rca_certificate(
                                      in charstring p_authorized_certificate := "CERT_IUT_A_RCA",//"CERT_IUT_A_RCA",
                                      in Certificate p_certificate,
                                      in boolean p_check_implicit := false,
                                      in boolean p_check_reconstruction_value := false,
                                      in boolean p_check_no_signature := false,
                                      in boolean p_check_region_restriction := false,
                                      in boolean p_check_signature_content := false,
                                      in boolean p_check_app_permissions := false,
                                      in boolean p_check_app_ssps := false,
                                      in boolean p_check_app_validity_period := false
                                      ) return boolean {
      var CertificateType v_type_ := explicit;
      var template Signature v_signature_ := ?;
      var template IssuerIdentifier v_issuer := ?;
      var template PublicVerificationKey v_public_verification_key := ?;
ASN.1 Documenter's avatar
ASN.1 Documenter committed

      log(">>> f_verify_rca_certificate: p_authorized_certificate= ", p_authorized_certificate);
      log(">>> f_verify_rca_certificate: p_certificate= ", p_certificate);

      if (p_check_implicit == true) {
        v_type_ := implicit;
      }
      if (p_check_no_signature == true) {
        v_signature_ := omit;
      }
      if (match(p_certificate, mw_etsiTs103097Certificate(-, -, v_signature_, v_type_)) == false) {
        log("f_verify_rca_certificate: version/explicit mismatch");
        return false;
      }
      if (p_check_reconstruction_value == false) {
        if (match(p_certificate, mw_etsiTs103097Certificate(
                                                            -,
                                                            mw_toBeSignedCertificate_ca(
                                                                                        (mw_certificateId_none, mw_certificateId_name),
                                                                                        -,
                                                                                        -,
                                                                                        mw_verificationKeyIndicator_verificationKey
                                                                                        ),
                                                            v_signature_
                                                            )) == false) {
          log("f_verify_rca_certificate: verificationKey mismatch");
          return false;
        }
        if (p_check_signature_content) {
          var template PublicVerificationKey v_publicVerificationKey;
          if (PICS_SEC_SHA256) {
            v_signature_ := mw_signature_ecdsaNistP256;
            v_issuer := (mw_issuerIdentifier_self(sha256), mw_issuerIdentifier_sha256AndDigest);
            v_public_verification_key := mw_publicVerificationKey_ecdsaNistP256;
          } else if (PICS_SEC_BRAINPOOL_P256R1) {
            v_signature_ := mw_signature_ecdsaBrainpoolP256r1;
            v_issuer := (mw_issuerIdentifier_self(sha256), mw_issuerIdentifier_sha256AndDigest);
            v_public_verification_key := mw_publicVerificationKey_ecdsaBrainpoolP256r1;
          } else if (PICS_SEC_BRAINPOOL_P384R1) {
            v_signature_ := mw_signature_ecdsaBrainpoolP384r1;
            v_issuer := (mw_issuerIdentifier_self(sha384), mw_issuerIdentifier_sha384AndDigest);
            v_public_verification_key := mw_publicVerificationKey_ecdsaBrainpoolP384r1;
          }
          if (match(p_certificate, mw_etsiTs103097Certificate(
                                                              v_issuer,
                                                              mw_toBeSignedCertificate_ca(
                                                                                          (mw_certificateId_none, mw_certificateId_name),
                                                                                          -,
                                                                                          -,
                                                                                          mw_verificationKeyIndicator_verificationKey(v_public_verification_key),
                                                                                          -, -, -, -,
                                                                                          -//mw_encryptionKey
                                                                                          ),
                                                              v_signature_
                                                              )) == false) {
            log("f_verify_rca_certificate: signature mismatch");
            return false;
          }
          // Verify Signature
          if (ischosen(p_certificate.issuer.self_)) {
            v_publicVerificationKey := p_certificate.toBeSigned.verifyKeyIndicator.verificationKey;
          } else {
            var HashedId8 v_digest;
            var Certificate v_authorized_certificate;
            var charstring v_cert;
            if (ischosen(p_certificate.issuer.sha256AndDigest)) {
              v_digest := p_certificate.issuer.sha256AndDigest;
            } else if (ischosen(p_certificate.issuer.sha384AndDigest)) {
              v_digest := p_certificate.issuer.sha384AndDigest;
            } else {
              log("f_verify_rca_certificate: Invalid certificate issuer ", p_certificate.issuer);
              return false;
            }
            if (f_getCertificateFromDigest(v_digest, v_authorized_certificate, v_cert) == false) {
              log("f_verify_rca_certificate: Fail to load p_authorized_certificate");
              return false;
            }
            v_publicVerificationKey := v_authorized_certificate.toBeSigned.verifyKeyIndicator.verificationKey
          }
          log("f_verify_rca_certificate: v_publicVerificationKey= ", v_publicVerificationKey);
          if (f_verifyCertificateSignatureWithPublicKey(p_certificate, v_publicVerificationKey) == false) {
            log("f_verify_rca_certificate: signature not verified");
            return false;
          }
        }
      } else {
        if (match(p_certificate, mw_etsiTs103097Certificate(
                                                            -,
                                                            mw_toBeSignedCertificate_ca(
                                                                                        (mw_certificateId_none, mw_certificateId_name),
                                                                                        -,
                                                                                        -,
                                                                                        mw_verificationKeyIndicator_reconstructionValue
                                                                                        ),
                                                            v_signature_
                                                            )) == false) {
          log("f_verify_rca_certificate: verificationKey mismatch");
          return false;
        }
        // TODO Verify Signature
      }

      if (p_check_region_restriction == true) {
        var Certificate v_authorized_certificate;
        var template GeographicRegion v_geographic_region := ?;

        if (f_readCertificate(p_authorized_certificate, v_authorized_certificate) == false) {
          log("f_verify_rca_certificate: Fail to load p_authorized_certificate");
          return false;
        }
        log("f_verify_rca_certificate: v_authorized_certificate=", v_authorized_certificate);

        if (PICS_SEC_CIRCULAR_REGION == true) {
          v_geographic_region := mw_geographicRegion_circle;
        } else if (PICS_SEC_RECTANGULAR_REGION == true) {
          v_geographic_region := mw_geographicRegion_rectangular;
        } else if (PICS_SEC_POLYGONAL_REGION == true) {
          v_geographic_region := mw_geographicRegion_polygonal;
        } else if (PICS_SEC_IDENTIFIED_REGION == true) {
        v_geographic_region := mw_geographicRegion_identified(
                                                              {
                                                                (mw_identifiedRegion_country_only, mw_identifiedRegion_country_and_region)
                                                                }
                                                              );
        }
        if (match(p_certificate, mw_etsiTs103097Certificate(
                                                            -,
                                                            mw_toBeSignedCertificate_ca(
                                                                                        -,
                                                                                        -,
                                                                                        -,
                                                                                        -,
                                                                                        -,
                                                                                        -,
                                                                                        v_geographic_region
                                                                                        )
                                                            )) == false) {
          log("f_verify_rca_certificate: Geographical region mismatch");
          return false;
        }
        // Check interception of area
        if (f_checkRegionValidityRestiction(v_authorized_certificate, p_certificate) == false) {
          log("f_verify_rca_certificate: Geographical region intersection mismatch");
          return false;
        }
      }
      // Check appPermissions
      if (p_check_app_permissions == true) {
        var integer v_idx, v_jdx;
        var charstring v_psid := ""; // 'psid' currently processed
        var charstring v_psidsFound := ";"; // Used to build the list of the 'psid' already processed
        var template charstring m_found_pattern; // Used in regex to verify that 'psid' was not found before
        var Certificate v_authorized_certificate;

        if (f_readCertificate(p_authorized_certificate, v_authorized_certificate) == false) {
          log("f_verify_rca_certificate: Fail to load p_authorized_certificate");
          return false;
        }
        log("f_verify_rca_certificate: v_authorized_certificate=", v_authorized_certificate);
        if (match(v_authorized_certificate.toBeSigned.certIssuePermissions, { mw_psidGroupPermissions }) == false) {
          log("f_verify_rca_certificate: eeType mismatch");
          return false;
        }

        for (v_idx := 0; v_idx < lengthof(p_certificate.toBeSigned.appPermissions); v_idx := v_idx + 1) {
          log("f_verify_rca_certificate: Processing ", p_certificate.toBeSigned.appPermissions[v_idx]);
          if (match(p_certificate.toBeSigned.appPermissions[v_idx], mw_appPermissions) == false) {
            log("f_verify_rca_certificate: PsidSsp mismatch");
            return false;
          }
          // Check uniqueness of PSIDs
          v_psid := int2str(p_certificate.toBeSigned.appPermissions[v_idx].psid);
          m_found_pattern := pattern "*({v_psid})*";
          if (regexp(v_psidsFound, m_found_pattern, 0) == v_psid) {
            log("f_verify_rca_certificate: Psid uniqueness is not verified");
            return false; // v_psid exist at least 2 times, uniqueness is not verified
          }
          // v_psid non found, add it into the built list
          v_psidsFound := v_psidsFound & v_psid & ";";
          // Check that 'psid' is in the certIssuePermissions component in the issuing certificate
          if (match(v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions, mw_subjectPermissions_explicit) == false) {
            for (v_jdx := 0; v_jdx < lengthof(v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit); v_jdx := v_jdx + 1) {
              if (int2str(v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit[v_jdx].psid) == v_psid) {
                break;
              }
            } // End of 'for'statement
            if (v_jdx == lengthof(v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit)) {
              log("f_verify_rca_certificate: Psid is not in the list of the issuing certificate");
              return false;
            }
          }
        } // End of 'for'statement
      }

      if (p_check_app_ssps == true) {
        var integer v_idx, v_jdx;
        var Certificate v_authorized_certificate;

        if (f_readCertificate(p_authorized_certificate, v_authorized_certificate) == false) {
          log("f_verify_rca_certificate: Fail to load p_authorized_certificate");
          return false;
        }
        log("f_verify_rca_certificate: v_authorized_certificate=", v_authorized_certificate);
        for (v_idx := 0; v_idx < lengthof(p_certificate.toBeSigned.appPermissions); v_idx := v_idx + 1) {
          log("f_verify_rca_certificate: Processing ", p_certificate.toBeSigned.appPermissions[v_idx]);
          if (match(p_certificate.toBeSigned.appPermissions[v_idx], mw_appPermissions(-, ?)) == false) {
            log("f_verify_rca_certificate: appPermissions mismatch");
            return false;
          }
          // Check that 'ssp' is in the certIssuePermissions component in the issuing certificate
          for (v_jdx := 0; v_jdx < lengthof(v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit); v_jdx := v_jdx + 1) {
            log("f_verify_rca_certificate: compare psid ", v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit[v_jdx].psid, " - ", p_certificate.toBeSigned.appPermissions[v_idx].psid);
            if (v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit[v_jdx].psid == p_certificate.toBeSigned.appPermissions[v_idx].psid) {
              break;
            }
          } // End of 'for'statement
          if (v_jdx == lengthof(v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit)) {
            log("f_verify_rca_certificate: Psid is not in the list of the issuing certificate");
            return false;
          } else {
            var BitmapSsp v_ssp_ca := substr(v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit[v_jdx].sspRange.bitmapSspRange.sspValue, 1, -1 + lengthof(v_authorized_certificate.toBeSigned.certIssuePermissions[0].subjectPermissions.explicit[v_jdx].sspRange.bitmapSspRange.sspValue));
            log("f_verify_rca_certificate: v_ssp_ca= ", v_ssp_ca, " - ssp= ", p_certificate.toBeSigned.appPermissions[v_idx].ssp.bitmapSsp);
            if (v_ssp_ca != p_certificate.toBeSigned.appPermissions[v_idx].ssp.bitmapSsp) {
              log("f_verify_rca_certificate: SSPs mismatch: CA");
              return false;
            }
          }
        } // End of 'for'statement
      }

      if (p_check_app_validity_period == true) {
        var integer v_idx, v_jdx;
        var Certificate v_authorized_certificate;
        var UInt32 v_duration, v_duration_ca;

        if (f_readCertificate(p_authorized_certificate, v_authorized_certificate) == false) {
          log("f_verify_rca_certificate: Fail to load p_authorized_certificate");
          return false;
        }
        log("f_verify_rca_certificate: v_authorized_certificate=", v_authorized_certificate);
        // Check start date (indicating X_START_VALIDITY ( X_START_VALIDITY >= X_START_VALIDITY_CA ))
        if (p_certificate.toBeSigned.validityPeriod.start_ < v_authorized_certificate.toBeSigned.validityPeriod.start_) {
          log("f_verify_rca_certificate: validityPeriod.start_ mismatch");
          return false;
        }
        // Check duration (value <= X_START_VALIDITY_CA + X_DURATION_CA - X_START_VALIDITY)
        v_duration := duration_to_uint32(p_certificate.toBeSigned.validityPeriod.duration);
        v_duration_ca := duration_to_uint32(v_authorized_certificate.toBeSigned.validityPeriod.duration);
        if (v_duration > (v_authorized_certificate.toBeSigned.validityPeriod.start_ + v_duration_ca - p_certificate.toBeSigned.validityPeriod.start_)) {
          log("f_verify_rca_certificate: validityPeriod.duration mismatch");
          return false;
        }
      }
      return true;
    }

    function duration_to_uint32(
                                in Duration p_duration
                                ) return UInt32 {
      if (ischosen(p_duration.microseconds)) {
        return p_duration.microseconds * 1000000;
      }
      else if (ischosen(p_duration.milliseconds)) {
        return p_duration.milliseconds * 1000;
      }
      else if (ischosen(p_duration.seconds)) {
        return p_duration.seconds;
      }
      else if (ischosen(p_duration.minutes)) {
        return p_duration.minutes * 60;
      }
      else if (ischosen(p_duration.hours)) {
        return p_duration.hours * 3600;
      }
      else if (ischosen(p_duration.sixtyHours)) {
        return p_duration.sixtyHours * 60 * 3600;
      }
      else if (ischosen(p_duration.sixtyHours)) {
        return p_duration.sixtyHours * 60 * 3600;
      }
      // No choice!
      return p_duration.years * 31536000; // One calendar common year has 365 days
    }

  } // End of group dc

  group ctl {

    function f_build_ctl(
                         in charstring p_ea_certificate_id,
                         in charstring p_aa_certificate_id,
                         in charstring p_rca_certificate_id,
                         out ToBeSignedRcaCtl p_to_be_signed_rca_ctl
                         ) {
      // Local variables
      var EtsiTs103097Certificate v_ea_certificate;
      var EtsiTs103097Certificate v_aa_certificate;
      var Oct32 v_rca_hash;
      var CtlCommands v_ctl_commands;
      var Time32 v_time;

      log(">>> f_build_ctl");

      // Load certificates
      f_readCertificate(p_ea_certificate_id, v_ea_certificate);
      f_readCertificate(p_aa_certificate_id, v_aa_certificate);
      f_getCertificateHash256(p_rca_certificate_id, v_rca_hash);
      v_ctl_commands := {
        { add := { ea := valueof(m_ea_entry(v_ea_certificate, PICS_EA_ENDPOINT)) } },
        { add := { aa := valueof(m_aa_entry(v_aa_certificate, PICS_AA_ENDPOINT)) } },
        { add := { dc := valueof(m_dc_entry(PICS_DC_ENDPOINT, { f_hashedId8FromSha256(v_rca_hash) })) } }
      };
      log("f_build_ctl: v_ctl_commands= ", v_ctl_commands);
      // Build the main data structure
      v_time := f_getCurrentTime() / 1000;/*in seconds*/
      p_to_be_signed_rca_ctl := valueof(m_to_be_signed_rca_full_ctl(v_time + 30 * 86400/*30 days in seconds*/, PX_CTL_SEQUENCE_NUMBER, v_ctl_commands));

      log("<<< f_build_ctl: p_to_be_signed_rca_ctl= ", p_to_be_signed_rca_ctl);
    } // End of function f_build_ctl

    function f_sign_dc_ctl(
                           in charstring p_signer_certificate_id,
                           in ToBeSignedRcaCtl p_to_be_signed_rca_ctl,
                           out Ieee1609Dot2Data p_ieee_1609Dot2_signed_data
                           ) {
      // Local variables
      var EtsiTs103097Certificate v_certificate;
      var EtsiTs102941Data v_etsi_ts_102941_data;
      var octetstring v_pki_message;
      var ToBeSignedData v_tbs;
      var octetstring v_private_key;
      var octetstring v_issuer;
      var bitstring v_tbs_encoded;
      var octetstring v_sig;
      var Signature v_signature;

      log(">>> f_sign_dc_ctl");

      f_readSigningKey(p_signer_certificate_id, v_private_key);
      f_getCertificateHash(p_signer_certificate_id, v_issuer);
      f_readCertificate(p_signer_certificate_id, v_certificate);

      // Encode the main data structure
      v_etsi_ts_102941_data := valueof(m_etsiTs102941Data_to_be_signed_rca_ctl(p_to_be_signed_rca_ctl));
      v_pki_message := bit2oct(encvalue(v_etsi_ts_102941_data));
      // Signed the encoded PKI message
      v_tbs := valueof(
                       m_toBeSignedData(
                                        m_signedDataPayload(
                                                            m_etsiTs103097Data_unsecured(v_pki_message)
                                                            ),
                                        m_headerInfo_inner_pki_ctl_response(-, (f_getCurrentTime() * 1000)/*us*/)
                                        )
                       );
      v_tbs_encoded := encvalue(v_tbs);
      // Sign the certificate
      v_sig := f_signWithEcdsa(bit2oct(v_tbs_encoded), v_issuer, v_private_key);
      if (PX_VE_ALG == e_nist_p256) {
        v_signature := valueof(
                               m_signature_ecdsaNistP256(
                                                         m_ecdsaP256Signature(
                                                                              m_eccP256CurvePoint_x_only(
                                                                                                         substr(v_sig, 0, 32)
                                                                                                         ),
                                                                              substr(v_sig, 32, 32)
                                                                              )
                                                         ));
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        v_signature := valueof(
                               m_signature_ecdsaBrainpoolP256r1(
                                                                m_ecdsaP256Signature(
                                                                                      m_eccP256CurvePoint_x_only(
                                                                                                                substr(v_sig, 0, 32)
                                                                                                                ),
                                                                                      substr(v_sig, 32, 32)
                                                                ));
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
      } else if (PX_VE_ALG == e_nist_p384) {
        v_signature := valueof(
                               m_signature_ecdsaNistP384(
                                                         m_ecdsaP384Signature(
                                                                              m_eccP384CurvePoint_x_only(
                                                                                                        substr(v_sig, 0, 48)
                                                                                                        ),
                                                                              substr(v_sig, 48, 48)
                                                                              )
                                                         ));
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        v_signature := valueof(
                               m_signature_ecdsaBrainpoolP384r1(
                                                                m_ecdsaP384Signature(
                                                                                     m_eccP384CurvePoint_x_only(
                                                                                                                substr(v_sig, 0, 48)
                                                                                                                ),
                                                                                     substr(v_sig, 48, 48)
                                                                                     )
                                                                ));
      }
      log("f_sign_dc_ctl: v_signature= ", v_signature);
      p_ieee_1609Dot2_signed_data := valueof(
                                              m_etsiTs103097Data_signed(
                                                                        m_signedData(
                                                                                    sha384,
                                                                                    v_tbs,
                                                                                    m_signerIdentifier_certificates({v_certificate}),
                                                                                    v_signature
                                                                                    )
                                                                        )
                                              );
      log("<<< f_sign_dc_ctl: p_ieee_1609Dot2_signed_data= ", p_ieee_1609Dot2_signed_data);
    } // End of function f_sign_dc_ctl

    function f_verify_full_ctl(
                               in ToBeSignedRcaCtl p_to_be_signed_rca_ctl
                               ) return boolean {
      log(">>> f_verify_full_ctl: p_to_be_signed_rca_ctl= ", p_to_be_signed_rca_ctl);

      // 1. Check mandatory fields
      log("f_verify_full_ctl matching= ", match(p_to_be_signed_rca_ctl, mw_to_be_signed_rca_full_ctl));
      if (match(p_to_be_signed_rca_ctl, mw_to_be_signed_rca_full_ctl) == false) {
        return false;
      }

      log("f_verify_full_ctl: ctlCommands length: ", lengthof(p_to_be_signed_rca_ctl.ctlCommands));
      for (var integer v_i := 0;  v_i < lengthof(p_to_be_signed_rca_ctl.ctlCommands); v_i := v_i + 1) {
        var CtlCommand v_ctl_command := p_to_be_signed_rca_ctl.ctlCommands[v_i];

        if (ischosen(v_ctl_command.delete)) {
          log("f_verify_full_ctl: ctlCommands shall not contains 'delete' variant");
          return false;
        } else {
          if (f_verify_ctl_entry(v_ctl_command.add) == false) {
            log("f_verify_full_ctl: ctlCommands contains invalid entries");
            return false;
          }
        }
      } // End of 'for' statements
      return true;
    } // End of function f_verify_full_ctl

    function f_verify_ctl_entry(
                                in CtlEntry p_ctl_entry
                                ) return boolean {
      log(">>> f_verify_ctl_entry: p_ctl_entry=", p_ctl_entry);

      if (ischosen(p_ctl_entry.rca)) {
        if (match(p_ctl_entry.rca, mw_root_ca_entry(mw_etsiTs103097Certificate)) == false) {
          return false;
        } else {
          // TODO Verify RCA certificate & signature
        }
     } else if (ischosen(p_ctl_entry.ea)) {
        if (match(p_ctl_entry.ea, mw_ea_entry(mw_etsiTs103097Certificate)) == false) {
          return false;
        } else {
          // TODO Verify RCA certificate & signature
        }
      } else if (ischosen(p_ctl_entry.aa)) {
        if (match(p_ctl_entry.aa, mw_aa_entry(mw_etsiTs103097Certificate)) == false) {
          return false;
        } else {
          // TODO Verify RCA certificate & signature
        }
      } else if (ischosen(p_ctl_entry.dc)) {
        if (match(p_ctl_entry.dc, mw_dc_entry) == false) {
          return false;
        } else {
          // TODO Verify RCA certificate & signature
        }
      } else {
        return false;
      }

      return true;
    } // End of function f_verify_ctl_entry

  } // End of group ctl

  group crl {

    function f_build_crl(
                         in template (omit) charstring p_ea_certificate_id := omit,
                         in template (omit) charstring p_aa_certificate_id := omit,
                         out ToBeSignedCrl p_to_be_signed_crl
                         ) {
      // Local variables
      var HashedId8 v_hashed_id8;
      var CrlEntries v_crl_entries := {}; // Empty list
      var integer v_counter := 0;
      var Time32 v_time;

      log(">>> f_build_crl");

      if (ispresent(p_ea_certificate_id)) {
        f_getCertificateHash(valueof(p_ea_certificate_id), v_hashed_id8);
        v_crl_entries[v_counter] := v_hashed_id8;
        v_counter := v_counter + 1;
      }
      if (ispresent(p_aa_certificate_id)) {
        f_getCertificateHash(valueof(p_aa_certificate_id), v_hashed_id8);
        v_crl_entries[v_counter] := v_hashed_id8;
        v_counter := v_counter + 1;
      }
      log("f_build_crl: v_crl_entries= ", v_crl_entries);
      // Build the main data structure
      v_time := f_getCurrentTime() / 1000; /*in seconds*/
      p_to_be_signed_crl := valueof(m_to_be_signed_crl(v_time, v_time + 30 * 86400/*30 days in seconds*/, v_crl_entries));

      log("<<< f_build_crl: p_to_be_signed_crl= ", p_to_be_signed_crl);
    } // End of function f_build_crl

    function f_sign_dc_crl(
                           in charstring p_signer_certificate_id,
                           in ToBeSignedCrl p_to_be_signed_crl,
                           out Ieee1609Dot2Data p_ieee_1609Dot2_signed_data
                           ) {
      // Local variables
      var EtsiTs103097Certificate v_certificate;
      var EtsiTs102941Data v_etsi_ts_102941_data;
      var octetstring v_pki_message;
      var ToBeSignedData v_tbs;
      var octetstring v_private_key;
      var octetstring v_issuer;
      var bitstring v_tbs_encoded;
      var octetstring v_sig;
      var Signature v_signature;

      log(">>> f_sign_dc_crl");

      f_readSigningKey(p_signer_certificate_id, v_private_key);
      f_getCertificateHash(p_signer_certificate_id, v_issuer);
      f_readCertificate(p_signer_certificate_id, v_certificate);

      // Encode the main data structure
      v_etsi_ts_102941_data := valueof(m_etsiTs102941Data_to_be_signed_crl(p_to_be_signed_crl));
      v_pki_message := bit2oct(encvalue(v_etsi_ts_102941_data));
      // Signed the encoded PKI message
      v_tbs := valueof(
                       m_toBeSignedData(
                                        m_signedDataPayload(
                                                            m_etsiTs103097Data_unsecured(v_pki_message)
                                                            ),
                                        m_headerInfo_inner_pki_crl_response(-, (f_getCurrentTime() * 1000)/*us*/)
                                        )
                       );
      v_tbs_encoded := encvalue(v_tbs);
      // Sign the certificate
      v_sig := f_signWithEcdsa(bit2oct(v_tbs_encoded), v_issuer, v_private_key);
      if (PX_VE_ALG == e_nist_p256) {
        v_signature := valueof(
                               m_signature_ecdsaNistP256(
                                                         m_ecdsaP256Signature(
                                                                              m_eccP256CurvePoint_x_only(
                                                                                                         substr(v_sig, 0, 32)
                                                                                                         ),
                                                                              substr(v_sig, 32, 32)
                                                                              )
                                                         ));
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
        v_signature := valueof(
                               m_signature_ecdsaBrainpoolP256r1(
                                                                m_ecdsaP256Signature(
                                                                                      m_eccP256CurvePoint_x_only(
                                                                                                                substr(v_sig, 0, 32)
                                                                                                                ),
                                                                                      substr(v_sig, 32, 32)
                                                                ));
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
      } else if (PX_VE_ALG == e_nist_p384) {
        v_signature := valueof(
                               m_signature_ecdsaNistP384(
                                                         m_ecdsaP384Signature(
                                                                              m_eccP384CurvePoint_x_only(
                                                                                                        substr(v_sig, 0, 48)
                                                                                                        ),
                                                                              substr(v_sig, 48, 48)
                                                                              )
                                                        ));
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
        v_signature := valueof(
                               m_signature_ecdsaBrainpoolP384r1(
                                                                m_ecdsaP384Signature(
                                                                                     m_eccP384CurvePoint_x_only(
                                                                                                                substr(v_sig, 0, 48)
                                                                                                                ),
                                                                                     substr(v_sig, 48, 48)
                                                                                     )
                                                                ));
      }
      log("f_sign_dc_crl: v_signature= ", v_signature);
      p_ieee_1609Dot2_signed_data := valueof(
                                              m_etsiTs103097Data_signed(
                                                                        m_signedData(
                                                                                    sha384,
                                                                                    v_tbs,
                                                                                    m_signerIdentifier_certificates({v_certificate}),
                                                                                    v_signature
                                                                                    )
                                                                        )
                                              );
      log("<<< f_sign_dc_crl: p_ieee_1609Dot2_signed_data= ", p_ieee_1609Dot2_signed_data);
    } // End of function f_sign_dc_crl
    function f_verify_full_crl(
                               in ToBeSignedCrl p_to_be_signed_crl
                               ) return boolean {
      log(">>> f_verify_full_crl: p_to_be_signed_crl= ", p_to_be_signed_crl);
      // 1. Check mandatory fields
      log("f_verify_full_crl matching= ", match(p_to_be_signed_crl, mw_to_be_signed_crl));
      if (match(p_to_be_signed_crl, mw_to_be_signed_crl) == false) {
        return false;
      log("f_verify_full_crl: entries length: ", lengthof(p_to_be_signed_crl.entries));
      for (var integer v_i := 0;  v_i < lengthof(p_to_be_signed_crl.entries); v_i := v_i + 1) {
        var CrlEntry v_crl_entry := p_to_be_signed_crl.entries[v_i];
        log("f_verify_full_crl: crlEntry: v_crl_entry");
      } // End of 'for' statements
      return true;
    } // End of function f_verify_full_crl

  } // End of group crl

  group tlm {

    function f_build_tlm(
                         in charstring p_tlm_certificate_id,
                         in charstring p_rca_certificate_id,
                         out ToBeSignedTlmCtl p_to_be_signed_tlm_crl
                         ) {
      // Local variables
      var EtsiTs103097Certificate v_tlm_certificate;
      var EtsiTs103097Certificate v_rca_certificate;
      var CtlCommands v_ctl_commands; // Empty list
      var Oct32 v_rca_hash;
      var Time32 v_time;

      log(">>> f_build_tlm");

      // Load certificates
      f_readCertificate(p_tlm_certificate_id, v_tlm_certificate);
      f_readCertificate(p_rca_certificate_id, v_rca_certificate);
      f_getCertificateHash256(p_rca_certificate_id, v_rca_hash);
      // Create ctlCommnand list
      v_ctl_commands := {
        { add := { tlm := valueof(m_tlm_entry(v_tlm_certificate, PICS_TLM_ENDPOINT)) } },
        { add := { rca := valueof(m_root_ca_entry(v_rca_certificate)) } },
        { add := { dc := valueof(m_dc_entry(PICS_DC_ENDPOINT, { f_hashedId8FromSha256(v_rca_hash) })) } }
      };
      log("f_build_tlm: v_ctl_commands= ", v_ctl_commands);
      // Build the main data structure
      v_time := f_getCurrentTimeUtc() / 1000/*in s*/;
      //log("f_build_ctl: v_time= ", v_time);
      //log("f_build_ctl: v_time + 86400= ", v_time + 86400);
      p_to_be_signed_tlm_crl := valueof(mw_to_be_signed_tlm_full_ctl(v_time + 86400/*1days*/, 7, v_ctl_commands));

      log("<<< f_build_tlm: p_to_be_signed_tlm_crl= ", p_to_be_signed_tlm_crl);
    } // End of function f_buif_build_tlmld_Tlm

    function f_verify_full_ectl(
                               in ToBeSignedRcaCtl p_to_be_signed_tlm_ectl
                               ) return boolean {
      log(">>> f_verify_full_ectl: p_to_be_signed_tlm_ectl= ", p_to_be_signed_tlm_ectl);

      // 1. Check mandatory fields
      log("f_verify_full_ectl matching= ", match(p_to_be_signed_tlm_ectl, mw_to_be_signed_rca_full_ctl));
      if (match(p_to_be_signed_tlm_ectl, mw_to_be_signed_rca_full_ctl) == false) {
        return false;
      }

      log("f_verify_full_ectl: ctlCommands length: ", lengthof(p_to_be_signed_tlm_ectl.ctlCommands));
      for (var integer v_i := 0;  v_i < lengthof(p_to_be_signed_tlm_ectl.ctlCommands); v_i := v_i + 1) {
        var CtlCommand v_ectl_command := p_to_be_signed_tlm_ectl.ctlCommands[v_i];

        if (ischosen(v_ectl_command.delete)) {
          log("f_verify_full_ectl: ctlCommands shall not contains 'delete' variant");
        } else {
          if (f_verify_ectl_entry(v_ectl_command.add) == false) {
            log("f_verify_full_ectl: ctlCommands contains invalid entries");
        }
      } // End of 'for' statements
    function f_verify_ectl_entry(
                                 in CtlEntry p_ctl_entry
                                 ) return boolean {
      log(">>> f_verify_ectl_entry: p_ctl_entry=", p_ctl_entry);

      if (ischosen(p_ctl_entry.tlm)) {
        if (match(p_ctl_entry.tlm, mw_tlm_entry(mw_etsiTs103097Certificate)) == false) {
        } else {
          // TODO Verify RCA certificate & signature
      } else if (ischosen(p_ctl_entry.dc)) {
        if (match(p_ctl_entry.dc, mw_dc_entry) == false) {
        } else {
          // TODO Verify RCA certificate & signature
      } else if (ischosen(p_ctl_entry.rca)) {
        if (match(p_ctl_entry.rca, mw_root_ca_entry(mw_etsiTs103097Certificate)) == false) {
        } else {
          // TODO Verify RCA certificate & signature
      } else {
        return false;
      return true;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_verify_tlm_ectl_response_message(
                                                in EtsiTs103097Data p_etsi_ts_103097_signed_data,
                                                in boolean p_check_security := true,
                                                out ToBeSignedTlmCtl p_to_be_signed_tlm_ectl
                                                ) return boolean {
      var bitstring v_etsi_ts_102941_data_msg;
      var bitstring v_tbs;
      var Certificate v_certificate;
      var boolean v_result;
      var EtsiTs102941Data v_etsi_ts_102941_data;

      log(">>> f_verify_tlm_ectl_response_message: p_etsi_ts_103097_signed_data= ", p_etsi_ts_103097_signed_data);

      // 1. Verify signature
      log("f_verify_tlm_ectl_response_message: p_etsi_ts_103097_signed_data.content.signedData.tbsData= ", p_etsi_ts_103097_signed_data.content.signedData.tbsData);
      v_tbs := encvalue(p_etsi_ts_103097_signed_data.content.signedData.tbsData);
      if (ischosen(p_etsi_ts_103097_signed_data.content.signedData.signer.certificate)) {
          v_certificate := p_etsi_ts_103097_signed_data.content.signedData.signer.certificate[0];
      } else {
          var charstring v_certificate_id;
          if (f_getCertificateFromDigest(p_etsi_ts_103097_signed_data.content.signedData.signer.digest, v_certificate, v_certificate_id) == false) {
            log("f_verify_tlm_ectl_response_message: Failed to retrieve certificate from digest ", p_etsi_ts_103097_signed_data.content.signedData.signer.digest);
            if (p_check_security == true) {
              return false;
            }
          }
      }
      if (ischosen(p_etsi_ts_103097_signed_data.content.signedData.signature_.ecdsaBrainpoolP384r1Signature)) {
        v_result := f_verifyEcdsa(bit2oct(v_tbs), int2oct(0, 48), p_etsi_ts_103097_signed_data.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey);
      } else {
        v_result := f_verifyEcdsa(bit2oct(v_tbs), int2oct(0, 32), p_etsi_ts_103097_signed_data.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey);
      }
      if (v_result == false) {
        log("f_verify_tlm_ectl_response_message: Failed to verify signature");
        if (p_check_security == true) {
          return false;
        }
      }
      v_etsi_ts_102941_data_msg := oct2bit(p_etsi_ts_103097_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_etsi_ts_102941_data_msg, v_etsi_ts_102941_data) != 0) {
        log("f_verify_tlm_ectl_response_message: Failed to decode EtsiTs102941Data");
        return false;
      } else {
        log("f_verify_tlm_ectl_response_message: v_etsi_ts_102941_data= ", v_etsi_ts_102941_data);
        log("f_verify_pki_response_message: TlmCertificateTrustListMessage matching= ", match(v_etsi_ts_102941_data, mw_etsiTs102941Data_to_be_signed_tlm_ctl));
        if (match(v_etsi_ts_102941_data, mw_etsiTs102941Data_to_be_signed_tlm_ctl) == false) {
          log("f_verify_tlm_ectl_response_message: Failed to decode certificateTrustListTlm");
          return false;
        } else {
          var Time32 v_time := (f_getCurrentTime()/* - 1072915200000*/) / 1000;
          p_to_be_signed_tlm_ectl := v_etsi_ts_102941_data.content.certificateTrustListTlm;
          log("f_verify_tlm_ectl_response_message: p_to_be_signed_tlm_ectl= ", p_to_be_signed_tlm_ectl);
          if (p_to_be_signed_tlm_ectl.nextUpdate <= v_time) {
            log("f_verify_tlm_ectl_response_message: Invalid nextUpdate value: compared values=", p_to_be_signed_tlm_ectl.nextUpdate, "/", v_time);
            return false;
          }
          // TODO Verify RCA certificate & signature
        }
      }

      return true;
    }

    function f_verify_broadcasted_delta_ctl(
                                            in GeoNetworkingPdu p_geonetworking_pdu,
                                            in boolean p_check_security := true
                                            ) return boolean {

      var EtsiTs103097Data v_secured_msg;
      var bitstring v_etsi_ts_102941_data_msg;
      var bitstring v_tbs;
      var Certificate v_certificate;
      var boolean v_result;
      var EtsiTs102941Data v_etsi_ts_102941_data;

      log(">>> f_verify_broadcasted_delta_ctl: p_geonetworking_pdu= ", p_geonetworking_pdu);

      if (not(ispresent(p_geonetworking_pdu.gnPacket.securedMsg))) {
        return false;
      }

      v_secured_msg := p_geonetworking_pdu.gnPacket.securedMsg;
      // 1. Verify signature
      log("f_verify_broadcasted_delta_ctl: v_secured_msg= ", v_secured_msg);
      v_tbs := encvalue(v_secured_msg.content.signedData.tbsData);
      if (ischosen(v_secured_msg.content.signedData.signer.certificate)) {
          v_certificate := v_secured_msg.content.signedData.signer.certificate[0];
      } else {
          var charstring v_certificate_id;
          if (f_getCertificateFromDigest(v_secured_msg.content.signedData.signer.digest, v_certificate, v_certificate_id) == false) {
            log("f_verify_broadcasted_delta_ctl: Failed to retrieve certificate from digest ", v_secured_msg.content.signedData.signer.digest);
            if (p_check_security == true) {
              return false;
            }
          }
      }
      if (ischosen(v_secured_msg.content.signedData.signature_.ecdsaBrainpoolP384r1Signature)) {
        v_result := f_verifyEcdsa(bit2oct(v_tbs), int2oct(0, 48), v_secured_msg.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey);
      } else {
        v_result := f_verifyEcdsa(bit2oct(v_tbs), int2oct(0, 32), v_secured_msg.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey);
      }
      if (v_result == false) {
        log("f_verify_broadcasted_delta_ctl: Failed to verify signature");
        if (p_check_security == true) {
          return false;
        }
      }
      v_etsi_ts_102941_data_msg := oct2bit(v_secured_msg.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_etsi_ts_102941_data_msg, v_etsi_ts_102941_data) != 0) {
        log("f_verify_broadcasted_delta_ctl: Failed to decode EtsiTs102941Data");
        return false;
      } else {
        log("f_verify_broadcasted_delta_ctl: v_etsi_ts_102941_data= ", v_etsi_ts_102941_data);
        // TODO
      }
      return true;
    } // End of function f_verify_broadcasted_delta_ctl

    function f_verify_and_extract_payload(
                                            in GeoNetworkingPdu p_geonetworking_pdu,
                                            in boolean p_check_security := true,
                                            out octetstring p_payload
                                            ) return boolean {

      var EtsiTs103097Data v_secured_msg;
      var bitstring v_tbs;
      var Certificate v_certificate;
      var boolean v_result;
      var EtsiTs102941Data v_etsi_ts_102941_data;

      log(">>> f_verify_and_extract_payload: p_geonetworking_pdu= ", p_geonetworking_pdu);

      if (not(ispresent(p_geonetworking_pdu.gnPacket.securedMsg))) {
        return false;
      }

      v_secured_msg := p_geonetworking_pdu.gnPacket.securedMsg;
      // 1. Verify signature
      log("f_verify_and_extract_payload: v_secured_msg= ", v_secured_msg);
      v_tbs := encvalue(v_secured_msg.content.signedData.tbsData);
      if (ischosen(v_secured_msg.content.signedData.signer.certificate)) {
          v_certificate := v_secured_msg.content.signedData.signer.certificate[0];
      } else {
          var charstring v_certificate_id;
          if (f_getCertificateFromDigest(v_secured_msg.content.signedData.signer.digest, v_certificate, v_certificate_id) == false) {
            log("f_verify_and_extract_payload: Failed to retrieve certificate from digest ", v_secured_msg.content.signedData.signer.digest);
            if (p_check_security == true) {
              return false;
            }
          }
      }
      if (ischosen(v_secured_msg.content.signedData.signature_.ecdsaBrainpoolP384r1Signature)) {
        v_result := f_verifyEcdsa(bit2oct(v_tbs), int2oct(0, 48), v_secured_msg.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey);
      } else {
        v_result := f_verifyEcdsa(bit2oct(v_tbs), int2oct(0, 32), v_secured_msg.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey);
      }
      if (v_result == false) {
        log("f_verify_and_extract_payload: Failed to verify signature");
        if (p_check_security == true) {
          return false;
        }
      }
      log("f_verify_and_extract_payload: v_etsi_ts_102941_data= ", v_secured_msg.content.signedData.tbsData.payload.data.content.unsecuredData);
      // TODO 
      return true;
    } // End of function f_verify_and_extract_payload

ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group tlm

  group awaiting_messages {

    function f_await_http_inner_ec_request_response(
                                                    out octetstring p_private_key_ec,
                                                    out octetstring p_compressed_public_key,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                    out integer p_compressed_mode,
                                                    out HashedId8 p_ec_cert_hashed_id8,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                    out InnerEcResponse p_inner_ec_response,
                                                    in boolean p_strict_checks := true,
                                                    in boolean p_store_ec_certificate := false
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                    ) runs on ItsPkiHttp return boolean {
      var Headers v_headers;
      var Oct32 v_request_hash;
      var Oct16 v_encrypted_sym_key;
      var Oct16 v_aes_sym_key;
      var HashedId8 v_aes_sym_key_hashed_id8;
      var Oct16 v_authentication_vector;
      var Oct12 v_nonce;
      var octetstring v_salt;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_and_encrypted_data;
      var EtsiTs102941Data v_etsi_ts_102941_data;
      var HttpMessage v_response;

      log(">>> f_await_http_inner_ec_request_response: p_strict_checks=", p_strict_checks);
      f_http_build_inner_ec_request(p_private_key_ec, p_compressed_public_key, p_compressed_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce, v_salt, v_ieee1609dot2_signed_and_encrypted_data, v_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      v_aes_sym_key_hashed_id8 := f_hashedId8FromSha256(f_hashWithSha256('80'O & v_aes_sym_key)); // Used to macth the response
      f_init_default_headers_list(-, "inner_ec_request", v_headers);
      f_http_send(
                  v_headers, 
                  m_http_request(
                                 m_http_request_post(
                                                     PICS_HTTP_POST_URI_EC,
                                                     v_headers,
                                                     m_http_message_body_binary(
                                                                                m_binary_body_ieee1609dot2_data(
                                                                                                                v_ieee1609dot2_signed_and_encrypted_data
                                                                                                                )))));
      tc_ac.start;
      alt {
        [] a_await_ec_http_request_from_iut(
                                            mw_http_response(
                                                             mw_http_response_ok(
                                                                                 mw_http_message_body_binary(
                                                                                                             mw_binary_body_ieee1609dot2_data(
                                                                                                                                              mw_enrolmentResponseMessage(
                                                                                                                                                                          mw_encryptedData(
                                                                                                                                                                                           { *, mw_recipientInfo_pskRecipInfo(v_aes_sym_key_hashed_id8), * },
                                                                                                                                                                                           mw_symmetricCiphertext_aes128ccm
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                                                                           )))))),
                                            v_response
                                            ) {
          tc_ac.stop;
          if (f_verify_pki_response_message(p_private_key_ec, v_aes_sym_key, v_authentication_vector, vc_eaWholeHash, v_response.response.body.binary_body.ieee1609dot2_data, p_strict_checks, -, v_etsi_ts_102941_data) == false) {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
            log("f_await_http_inner_ec_request_response: Failed to verify PKI message ***");
            if (p_strict_checks) {
              return false;
            }
          }
          log("f_await_http_inner_ec_request_response: Receive ", v_etsi_ts_102941_data, " ***");
          // Verify the received EC certificate
          log("f_await_http_inner_ec_request_response: match ", match(v_etsi_ts_102941_data.content, mw_enrolmentResponse(mw_innerEcResponse_ok(substr(v_request_hash, 0, 16), mw_etsiTs103097Certificate(-, mw_toBeSignedCertificate_ec)))), " ***"); // TODO In TITAN, this is the only way to get the unmatching in log
          if (match(v_etsi_ts_102941_data.content, mw_enrolmentResponse(mw_innerEcResponse_ok(?/*FIXME YANN Blackberry substr(v_request_hash, 0, 16)*/, mw_etsiTs103097Certificate(-, mw_toBeSignedCertificate_ec)))) == false) {
            log("f_await_http_inner_ec_request_response: Unexpected message received ***");
            if (p_strict_checks) {
              return false;
            }
          }
          if (ischosen(v_etsi_ts_102941_data.content.enrolmentResponse) and ispresent(v_etsi_ts_102941_data.content.enrolmentResponse.certificate)) {
            if (f_verify_ec_certificate(v_etsi_ts_102941_data.content.enrolmentResponse.certificate, vc_eaCertificate, vc_eaHashedId8, p_compressed_public_key, p_compressed_mode, p_ec_cert_hashed_id8) == false) {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
              log("f_await_http_inner_ec_request_response: Cannot verify EC certificate signature ***");
              if (p_strict_checks) {
                return false;
              }
            }
            vc_ec_hashed_id8[vc_ec_keys_counter - 1] := p_ec_cert_hashed_id8;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
            p_inner_ec_response := v_etsi_ts_102941_data.content.enrolmentResponse;
            log("f_await_http_inner_ec_request_response: Well-secured EA certificate received ***");
            log("f_await_http_inner_ec_request_response: p_inner_ec_response= ", p_inner_ec_response);

            if (p_store_ec_certificate) {
              f_store_certificate(p_private_key_ec, p_inner_ec_response.certificate, p_ec_cert_hashed_id8);
            //   var integer v_signing_algorithm;
            //   var octetstring v_public_key_x;
            //   var octetstring v_public_key_y;
            //   var octetstring v_public_key_compressed;
            //   var integer v_verify_compressed_mode;
            //   if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256)) {
            //     v_signing_algorithm := 0; // nist_p_256
            //     if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0;
            //       v_verify_compressed_mode := 0;
            //     } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1;
            //       v_verify_compressed_mode := 1;
            //     } else { // TODO
            //     }
            //     v_public_key_x := v_public_key_compressed; // Key X-Coordinate
            //     fx_get_uncompressed_key_nistp256(p_private_key_ec, v_public_key_compressed, v_verify_compressed_mode, v_public_key_y); // Key Y-Coordinate
            //   } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1)) {
            //     v_signing_algorithm := 2; // brainpool_p_256_r1
            //     if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_0;
            //       v_verify_compressed_mode := 0;
            //     } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_1)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1.compressed_y_1;
            //       v_verify_compressed_mode := 1;
            //     } else { // TODO
            //     }
            //     v_public_key_x := v_public_key_compressed; // Key X-Coordinate
            //     fx_get_uncompressed_key_brainpoolp256r1(p_private_key_ec, v_public_key_compressed, v_verify_compressed_mode, v_public_key_y); // Key Y-Coordinate
            //   } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1)) {
            //     v_signing_algorithm := 3; // brainpool_p_384_r1
            //     if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.compressed_y_0)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.compressed_y_0;
            //       v_verify_compressed_mode := 0;
            //     } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.compressed_y_1)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1.compressed_y_1;
            //       v_verify_compressed_mode := 1;
            //     } else { // TODO
            //     }
            //     v_public_key_x := v_public_key_compressed; // Key X-Coordinate
            //     fx_get_uncompressed_key_brainpoolp384r1(p_private_key_ec, v_public_key_compressed, v_verify_compressed_mode, v_public_key_y); // Key Y-Coordinate
            //   } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP384)) {
            //     v_signing_algorithm := 1; // nist_p_384
            //     if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP384.compressed_y_0)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP384.compressed_y_0;
            //       v_verify_compressed_mode := 0;
            //     } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP384.compressed_y_1)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP384.compressed_y_1;
            //       v_verify_compressed_mode := 1;
            //     } else { // TODO
            //     }
            //     v_public_key_x := v_public_key_compressed; // Key X-Coordinate
            //     fx_get_uncompressed_key_brainpoolp384r1(p_private_key_ec, v_public_key_compressed, v_verify_compressed_mode, v_public_key_y); // Key Y-Coordinate
            //   } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecsigSm2)) {
            //     v_signing_algorithm := 4; // sm2_p_256
            //     if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecsigSm2.compressed_y_0)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecsigSm2.compressed_y_0;
            //       v_verify_compressed_mode := 0;
            //     } else if (ischosen(p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecsigSm2.compressed_y_1)) {
            //       v_public_key_compressed := p_inner_ec_response.certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecsigSm2.compressed_y_1;
            //       v_verify_compressed_mode := 1;
            //     } else { // TODO
            //     }
            //     v_public_key_x := v_public_key_compressed; // Key X-Coordinate
            //     fx_get_uncompressed_key_brainpoolp384r1(p_private_key_ec, v_public_key_compressed, v_verify_compressed_mode, v_public_key_y); // Key Y-Coordinate
            //   } else {
            //     log("*** " & testcasename() & ": INCONC: Wrong certificate format, invalid verification key, back to initial");
            //     f_selfOrClientSyncAndVerdictPreamble(c_prDone, e_timeout);
            //     stop; 
            //   }
            //   log("f_await_http_inner_ec_request_response: : v_signing_algorithm     =", v_signing_algorithm);
            //   log("f_await_http_inner_ec_request_response: : v_public_key_x          =", v_public_key_x);
            //   log("f_await_http_inner_ec_request_response: : v_public_key_y          =", v_public_key_y);
            //   log("f_await_http_inner_ec_request_response: : v_public_key_compressed =", v_public_key_compressed);
            //   log("f_await_http_inner_ec_request_response: : v_verify_compressed_mode=", v_verify_compressed_mode);
            //   var octetstring v_encoded_cert := bit2oct(encvalue(p_inner_ec_response.certificate));
            //   var Oct32 v_ec_cert_hash_256 := f_hashWithSha256(v_encoded_cert);
            //   var HashedId8 v_issuer;
            //   if ((v_signing_algorithm == 1) or (v_signing_algorithm == 3)) {
            //     v_issuer := p_inner_ec_response.certificate.issuer.sha384AndDigest;
            //   } else if (v_signing_algorithm == 4) {
            //     v_issuer := p_inner_ec_response.certificate.issuer.sm3AndDigest;
            //   } else {
            //     v_issuer := p_inner_ec_response.certificate.issuer.sha256AndDigest;
            //   }
            //   if (fx_store_certificate(
            //                            v_signing_algorithm, 
            //                            oct2char(unichar2oct(p_inner_ec_response.certificate.toBeSigned.id.name)), 
            //                            v_encoded_cert, 
            //                            p_private_key_ec, 
            //                            v_public_key_x, v_public_key_y, 
            //                            v_public_key_compressed, v_verify_compressed_mode, v_ec_cert_hash_256, p_ec_cert_hashed_id8, p_ec_cert_hashed_id8, v_issuer,
            //                            omit, omit, omit, omit, omit // Ignore encryption keys
            //       ) == false) {
            //     log("f_await_http_inner_ec_request_response: Failed to store certificate: ", p_inner_ec_response.certificate);
            //     return false;
            //   }
            }

ASN.1 Documenter's avatar
ASN.1 Documenter committed
          } else {
            log("f_await_http_inner_ec_request_response: Invalid message received ***");
            return false;
          }
        }
        [] tc_ac.timeout {
          log("f_await_http_inner_ec_request_response: Expected message not received ***");
        }
      } // End of 'alt' statement
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_await_http_inner_ec_request_response
    group PredefinedRequests {

      template (present) HttpMessage mw_http_ec_request_generic := 
          mw_http_request(
                    mw_http_request_post(
                            PICS_HTTP_POST_URI_EC,
                            -,
                            mw_http_message_body_binary(
                                    mw_binary_body_ieee1609dot2_data(
                                            mw_enrolmentRequestMessage(
                                                    mw_encryptedData()
      )))));
    } // End of predefined requests
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_await_ec_request_send_response(
                                              out InnerEcRequest p_inner_ec_request,
                                              out HttpMessage p_request,
                                              in EnrolmentResponseCode p_response_code := ok,
                                              in template (omit) CertificateSubjectAttributes p_attributes := omit
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                              ) runs on ItsPkiHttp return boolean {
      var boolean v_result := false;
      var HttpMessage v_wrong_request;
      var Headers v_headers;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log(">>> f_await_ec_request_send_response");
      f_init_default_headers_list(-, "inner_ec_response", v_headers);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      tc_ac.start;
      alt {
        [] a_await_ec_http_request_from_iut(mw_http_ec_request_generic, p_request) {
          var Ieee1609Dot2Data v_decrypted_message;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
          var EtsiTs102941Data v_etsi_ts_102941_data;
          var template (value) HttpMessage v_response;
          var Oct16 v_request_hash, v_aes_enc_key;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
          tc_ac.stop;
          if(f_read_ec_request_from_iut_itss( p_request.request.body.binary_body.ieee1609dot2_data,
                                              v_request_hash, v_aes_enc_key,
                                              v_decrypted_message,
                                              v_etsi_ts_102941_data,
                                              p_inner_ec_request
          )){
          var EtsiTs103097Certificate v_ec_certificate;
          var HashedId8 v_ec_certificate_hashed_id8;
            var Ieee1609Dot2Data v_response_message;
            log(">>>>>> f_await_ec_request_send_response v_inner_ec_request=", p_inner_ec_request);

            if(ispresent(p_attributes)){
              if(isvalue(p_attributes.id)){
                p_inner_ec_request.requestedSubjectAttributes.id := valueof(p_attributes.id);
              }
              if(isvalue(p_attributes.validityPeriod)){
                p_inner_ec_request.requestedSubjectAttributes.validityPeriod := valueof(p_attributes.validityPeriod);
              }
              if(isvalue(p_attributes.region)){
                p_inner_ec_request.requestedSubjectAttributes.region := valueof(p_attributes.region);
              }
              if(isvalue(p_attributes.assuranceLevel)){
                p_inner_ec_request.requestedSubjectAttributes.assuranceLevel := valueof(p_attributes.assuranceLevel);
              }
              if(isvalue(p_attributes.appPermissions)){
                p_inner_ec_request.requestedSubjectAttributes.appPermissions := valueof(p_attributes.appPermissions);
              }
              if(isvalue(p_attributes.certIssuePermissions)){
                p_inner_ec_request.requestedSubjectAttributes.certIssuePermissions := valueof(p_attributes.certIssuePermissions);
              }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
            }

            f_http_build_inner_ec_response(p_inner_ec_request, p_response_code, v_request_hash, vc_eaPrivateKey, vc_eaWholeHash, v_aes_enc_key,
                                v_ec_certificate, v_ec_certificate_hashed_id8, p_inner_ec_response, v_response_message);

            v_response := m_http_response(
                                  m_http_response_ok(
                                          m_http_message_body_binary(
                                                  m_binary_body_ieee1609dot2_data(v_response_message)
                                          ), v_headers));
          } else {
            v_response := m_http_response(m_http_response_500_internal_error(v_headers));
            }
            f_http_send(v_headers, v_response);
          v_result := true;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
          }
        [] a_await_ec_http_request_from_iut( mw_http_request(), v_wrong_request) {
          log(">>>>>> f_await_ec_request_send_response: Wrong message received ", v_wrong_request);
          log("            ", match(v_wrong_request, mw_http_request()));
          f_http_send(v_headers, m_http_response(m_http_response_500_internal_error(v_headers)));
          repeat;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        }
        [] tc_ac.timeout {
          log("f_await_ec_request_send_response: Expected message not received ***");
        }
      } // End of 'alt' statement
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return v_result;
    } // End of function f_await_ec_request_send_response
    function f_await_ec_request_send_no_response(
                                                 out HttpMessage p_request
                                                 ) runs on ItsPkiHttp {
      log(">>> f_await_ec_request_send_no_response");

      tc_ac.start;
      alt {
        [] a_await_ec_http_request_from_iut(mw_http_ec_request_generic, p_request) {
          tc_ac.stop;
          log("f_await_ec_request_send_no_response: Restart HTT connection ***");
          f_http_restart("inner_ec_request");
        }
        [] tc_ac.timeout {
          log("f_await_ec_request_send_no_response: Expected message not received ***");
        }
      } // End of 'alt' statement

    } // End of function f_await_ec_request_send_no_response

    function f_await_ec_request_send_error_response(
                                                    out HttpMessage p_request
                                                    ) runs on ItsPkiHttp {
      var Ieee1609Dot2Data v_ieee1609dot2_signed_and_encrypted_data;
      var boolean v_result := false;
      log(">>> f_await_ec_request_send_error_response");
      tc_ac.start;
      alt {
        [] a_await_ec_http_request_from_iut(
                                            mw_http_request(
                                                            mw_http_request_post(
                                                                                 PICS_HTTP_POST_URI_EC,
                                                                                 -,
                                                                                 mw_http_message_body_binary(
                                                                                                             mw_binary_body_ieee1609dot2_data(
                                                                                                                                              mw_enrolmentRequestMessage(
                                                                                                                                                                         mw_encryptedData(
                                                                                                                                                                                          -,
                                                                                                                                                                                          mw_symmetricCiphertext_aes128ccm
                                                                                                                                                                                          )))))),
                                            p_request
                                            ) {
          var template (value) HttpMessage v_response;
          var Headers v_headers;
          f_init_default_headers_list(-, "inner_ec_response", v_headers);
          log("f_await_ec_request_send_error_response: Failed to verify PKI message ***");
          // Send error message
          v_response := m_http_response(m_http_response_ko(m_http_message_body_binary(m_binary_body_ieee1609dot2_data(v_ieee1609dot2_signed_and_encrypted_data)), v_headers, 400, "Bad request")); // Initialize v_reponse with an error message
          f_http_send(v_headers, v_response);
        }
        [] tc_ac.timeout {
          log("f_await_ec_request_send_error_response: Expected message not received ***");
        }
      } // End of 'alt' statement

    } // End of function f_await_ec_request_send_error_response
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group awaiting_messages
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  group pki_functions {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc Build a signed and encrypted PKI request message
     * @param p_private_key         Private key for signature
     * @param p_signer_identifier   Signer identifier for signature, could be self or certificate HashedId8
     * @param p_recipientId         Recipient identifier to be inclued in encrypted layer.
     *                              If value is int2oct(0. 8), the recipient id is the HashedId8 of the symmetric key used by the sender to encrypt the message to which the response is built
     * @param p_public_key_compressed The public compressed key (canonical form) for encryption
     * @param p_compressed_mode      The compressed mode of the public compressed key (canonical form) for encryption
     * @param p_pki_message         The PKI message to be secured
     * @param p_ieee1609dot2_signed_and_encrypted_data The secured message
     * @return true on success, false otherwise
     */
    function f_build_pki_secured_request_message_signed_with_pop(
                                                                 in octetstring p_private_key,
                                                                 in SignerIdentifier p_signer_identifier,
                                                                 in HashedId8 p_recipientId,
                                                                 in octetstring p_public_key_compressed,
                                                                 in integer p_compressed_mode,
                                                                 in octetstring p_salt,
                                                                 in octetstring p_pki_message,
                                                                 in SignAlgorithm p_enc_algorithm, // TODO Use RCA to check encryption alg
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                 in boolean p_alter_signature := false,
                                                                 out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                                 out Oct16 p_aes_sym_key,
                                                                 out Oct16 p_encrypted_sym_key,
                                                                 out Oct16 p_authentication_vector,
                                                                 out Oct12 p_nonce,
                                                                 out Oct32 p_request_hash
                                                                 ) return boolean {
      // Local variables
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var template (value) ToBeSignedData v_tbs;
      var octetstring v_tbs_signed;
      var Signature v_signature;
      var template (value) Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var octetstring v_encoded_request;
      var HashedId8 v_recipientId;
      var octetstring v_public_compressed_ephemeral_key;
      var integer v_public_compressed_ephemeral_mode;
      var octetstring v_encrypted_request;
      var EncryptedDataEncryptionKey v_encrypted_data_encryption_key;
      var bitstring v_enc_value;

      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_private_key= ", p_private_key);
      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_signer_identifier= ", p_signer_identifier);
      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_recipientId= ", p_recipientId);
      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_public_key_compressed= ", p_public_key_compressed);
      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_compressed_mode= ", p_compressed_mode);
      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_salt= ", p_salt);
      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_pki_message= ", p_pki_message);
      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_enc_algorithm= ", p_enc_algorithm);
      log(">>> f_build_pki_secured_request_message_signed_with_pop: p_alter_signature= ", p_alter_signature);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Signed the encoded PKI message
      v_tbs := m_toBeSignedData(
                                m_signedDataPayload(
                                                    m_etsiTs103097Data_unsecured(p_pki_message)
                                                   ),
                                m_headerInfo_inner_pki_request(-, (f_getCurrentTime() * 1000)/*us*/)
                               );
      log("f_build_pki_secured_request_message_signed_with_pop: v_tbs: ", v_tbs);
      if (ischosen(p_signer_identifier.self_)) {
        v_tbs_signed := f_signWithEcdsa(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key);
      } else {
        var charstring v_certificate_id;
        var octetstring v_hash;
        fx_readCertificateFromDigest(p_signer_identifier.digest, v_certificate_id); // TODO Add a wrapper function
        f_getCertificateHash(v_certificate_id, v_hash);
        v_tbs_signed := f_signWithEcdsa(bit2oct(encvalue(v_tbs)), v_hash, p_private_key);
      }
      log("f_build_pki_secured_request_message_signed_with_pop: lengthof(v_tbs_signed)= ", lengthof(v_tbs_signed));
      log("f_build_pki_secured_request_message_signed_with_pop: v_tbs_signed= ", v_tbs_signed);
      if (p_alter_signature == true) {
        v_tbs_signed[0] := '0A'O;
        v_tbs_signed[1] := '0A'O;
        log("f_build_pki_secured_request_message_signed_with_pop: Altered signature= ", v_tbs_signed);
      }
      // Add the signature and create EtsiTs103097Data-Signed data structure
      log("f_build_pki_secured_request_message_signed_with_pop: PX_VE_ALG=", PX_VE_ALG);
      if (PX_VE_ALG == e_nist_p256) {
       v_signature := valueof(
                              m_signature_ecdsaNistP256(
                                                        m_ecdsaP256Signature(
                                                                             m_eccP256CurvePoint_x_only(
                                                                                                        substr(v_tbs_signed, 0, 32)
                                                                                                        ),
                                                                             substr(v_tbs_signed, 32, 32)
                                                                             )
                                                        )
                              );
      } else if (PX_VE_ALG == e_brainpool_p256_r1) {
       v_signature := valueof(
                              m_signature_ecdsaBrainpoolP256r1(
                                                               m_ecdsaP256Signature(
                                                                                    m_eccP256CurvePoint_x_only(
                                                                                                               substr(v_tbs_signed, 0, 32)
                                                                                                               ),
                                                                                    substr(v_tbs_signed, 32, 32)
                                                                                    )
                                                               )
                              );
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
      } else if (PX_VE_ALG == e_nist_p384) {
       v_signature := valueof(
                              m_signature_ecdsaNistP384(
                                                        m_ecdsaP384Signature(
                                                                             m_eccP384CurvePoint_x_only(
                                                                                                        substr(v_tbs_signed, 0, 48)
                                                                                                        ),
                                                                             substr(v_tbs_signed, 48, 48)
                                                                             )
                                                        )
                              );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (PX_VE_ALG == e_brainpool_p384_r1) {
       v_signature := valueof(
                              m_signature_ecdsaBrainpoolP384r1(
                                                               m_ecdsaP384Signature(
                                                                                    m_eccP384CurvePoint_x_only(
                                                                                                               substr(v_tbs_signed, 0, 48)
                                                                                                               ),
                                                                                    substr(v_tbs_signed, 48, 48)
                                                                                    )
                                                               )
                              );
      }
      log("f_build_pki_secured_request_message_signed_with_pop: v_signature= ", v_signature);
      v_ieee1609dot2_signed_data := m_etsiTs103097Data_signed(
                                                              m_signedData(
                                                                           sha256,
                                                                           v_tbs,
                                                                           p_signer_identifier,
                                                                           v_signature
                                                                           )
                                                              );
      // Encode EtsiTs103097Data-Signed data structure
      v_encoded_request := bit2oct(encvalue(v_ieee1609dot2_signed_data));
      log("f_build_pki_secured_request_message_signed_with_pop: v_encoded_request= ", v_encoded_request);
      // Encrypt encode EtsiTs103097Data-Signed data structure
      if (p_enc_algorithm == e_nist_p256) {
        v_encrypted_request := f_encryptWithEciesNistp256WithSha256(v_encoded_request, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
      } else if (PX_VE_ALG == e_sm2_p256) {
        v_encrypted_request := f_encryptWithEciesSm2p256WithSha256(v_encoded_request, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (p_enc_algorithm == e_brainpool_p256_r1) {
        v_encrypted_request := f_encryptWithEciesBrainpoolp256r1WithSha256(v_encoded_request, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
      } else {
        log("f_build_pki_secured_request_message_signed_with_pop: Wrong encryption variant");
        return false;
      }
      log("f_build_pki_secured_request_message_signed_with_pop: p_aes_sym_key= ", p_aes_sym_key);
      log("f_build_pki_secured_request_message_signed_with_pop: p_encrypted_sym_key= ", p_encrypted_sym_key);
      log("f_build_pki_secured_request_message_signed_with_pop: p_authentication_vector= ", p_authentication_vector);
      log("f_build_pki_secured_request_message_signed_with_pop: p_nonce= ", p_nonce);
      log("f_build_pki_secured_request_message_signed_with_pop: p_recipientId= ", p_recipientId);
      if (p_recipientId == int2oct(0, 8)) {
        log("f_build_pki_secured_request_message_signed_with_pop: f_hashWithSha256(v_encrypted_sym_key)= ", f_hashWithSha256(p_encrypted_sym_key));
        v_recipientId := f_hashedId8FromSha256(f_hashWithSha256(p_encrypted_sym_key));
      } else {
        v_recipientId := p_recipientId;
      }
      log("f_build_pki_secured_request_message_signed_with_pop: v_recipientId= ", v_recipientId);
      // Fill Certificate template with the public compressed keys (canonical form)
      if (v_public_compressed_ephemeral_mode == 0) {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_compressed_ephemeral_key));
      } else {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
      }
      if (p_enc_algorithm == e_nist_p256) {
        v_encrypted_data_encryption_key := valueof(
                                                   m_encryptedDataEncryptionKey_eciesNistP256(
                                                                                              m_evciesP256EncryptedKey(
                                                                                                                       v_eccP256_curve_point,
                                                                                                                       p_encrypted_sym_key, 
                                                                                                                       p_authentication_vector
                                                                                                                       )));
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (p_enc_algorithm == e_brainpool_p256_r1) {
        v_encrypted_data_encryption_key := valueof(
                                                   m_encryptedDataEncryptionKey_eciesBrainpoolP256r1(
                                                                                                     m_evciesP256EncryptedKey(
                                                                                                                              v_eccP256_curve_point,
                                                                                                                              p_encrypted_sym_key, 
                                                                                                                              p_authentication_vector
                                                                                                                              )));
      } else {
        log("f_build_pki_secured_request_message_signed_with_pop: Wrong encryption variant");
        return false;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      p_ieee1609dot2_signed_and_encrypted_data := valueof(
                                                          m_etsiTs103097Data_encrypted(
                                                                                       m_encryptedData(
                                                                                                       {
                                                                                                         m_recipientInfo_certRecipInfo(
                                                                                                                                       m_pKRecipientInfo(
                                                                                                                                                         v_recipientId,
                                                                                                                                                         v_encrypted_data_encryption_key
                                                                                                                                                         ))
                                                                                                         },
                                                                                                       m_symmetricCiphertext_aes128ccm(
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                       m_aesCcmCiphertext(
                                                                                                                                                          p_nonce,
                                                                                                                                                          v_encrypted_request
                                                                                                                                                          )
                                                                                                                                       )
                                                                                                       )
                                                                                       )
                                                          );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // The 'p_request_hash' shall be the SHA256 digest of the OER representation of the topmost EtsiTs103097Data-Encoded structure
      v_enc_value := encvalue(p_ieee1609dot2_signed_and_encrypted_data);
      p_request_hash := f_hashWithSha256(bit2oct(v_enc_value));
      log("f_build_pki_secured_request_message_signed_with_pop: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_build_pki_secured_request_message_signed_with_pop: ", p_pki_message);
      return true;
    } // End of function f_build_pki_secured_request_message_signed_with_pop
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc Build a signed and encrypted PKI request message without POP with signature
     * @param p_recipientId         Recipient identifier to be inclued in encrypted layer.
     *                              If value is int2oct(0. 8), the recipient id is the HashedId8 of the symmetric key used by the sender to encrypt the message to which the response is built
     * @param p_public_key_compressed The public compressed key (canonical form) for encryption
     * @param p_compressed_mode      The compressed mode of the public compressed key (canonical form) for encryption
     * @param p_pki_message         The PKI message to be secured
     * @param p_ieee1609dot2_signed_and_encrypted_data The secured message
     * @return true on success, false otherwise
     */
    function f_build_pki_secured_request_message(
                                                 in HashedId8 p_recipientId,
                                                 in octetstring p_public_key_compressed,
                                                 in integer p_compressed_mode,
                                                 in octetstring p_salt,
                                                 in octetstring p_pki_message,
                                                 in SignAlgorithm p_enc_algorithm,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                 out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                 out Oct16 p_aes_sym_key,
                                                 out Oct16 p_encrypted_sym_key,
                                                 out Oct16 p_authentication_vector,
                                                 out Oct12 p_nonce,
                                                 out Oct32 p_request_hash
                                                 ) return boolean {
      // Local variables
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var HashedId8 v_recipientId;
      var octetstring v_public_compressed_ephemeral_key;
      var integer v_public_compressed_ephemeral_mode;
      var octetstring v_encrypted_request;
      var EncryptedDataEncryptionKey v_encrypted_data_encryption_key;
      var bitstring v_enc_value;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log(">>> f_build_pki_secured_request_message");
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Encrypt encode EtsiTs103097Data-Signed data structure
      if (p_enc_algorithm == e_nist_p256) {
        v_encrypted_request := f_encryptWithEciesNistp256WithSha256(p_pki_message, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
      } else if (PX_VE_ALG == e_sm2_p256) {
        v_encrypted_request := f_encryptWithEciesSm2p256WithSha256(p_pki_message, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (p_enc_algorithm == e_brainpool_p256_r1) {
        v_encrypted_request := f_encryptWithEciesBrainpoolp256r1WithSha256(p_pki_message, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
      } else {
        log("f_build_pki_secured_request_message: Wrong encryption variant");
        return false;
      }
      log("f_build_pki_secured_request_message: p_aes_sym_key= ", p_aes_sym_key);
      log("f_build_pki_secured_request_message: p_encrypted_sym_key= ", p_encrypted_sym_key);
      log("f_build_pki_secured_request_message: p_authentication_vector= ", p_authentication_vector);
      log("f_build_pki_secured_request_message: p_nonce= ", p_nonce);
      log("f_build_pki_secured_request_message: p_recipientId= ", p_recipientId);
      if (p_recipientId == int2oct(0, 8)) {
        log("f_build_pki_secured_request_message: f_hashWithSha256(v_encrypted_sym_key)= ", f_hashWithSha256(p_encrypted_sym_key));
        v_recipientId := f_hashedId8FromSha256(f_hashWithSha256(p_encrypted_sym_key));
      } else {
        v_recipientId := p_recipientId;
      }
      log("f_build_pki_secured_request_message: v_recipientId= ", v_recipientId);
      // Fill Certificate template with the public compressed keys (canonical form)
      if (v_public_compressed_ephemeral_mode == 0) {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_compressed_ephemeral_key));
      } else {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
      }
      if (p_enc_algorithm == e_nist_p256) {
        v_encrypted_data_encryption_key := valueof(
                                                   m_encryptedDataEncryptionKey_eciesNistP256(
                                                                                              m_evciesP256EncryptedKey(
                                                                                                                       v_eccP256_curve_point,
                                                                                                                       p_encrypted_sym_key, 
                                                                                                                       p_authentication_vector
                                                                                                                       )));
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (p_enc_algorithm == e_brainpool_p256_r1) {
        v_encrypted_data_encryption_key := valueof(
                                                   m_encryptedDataEncryptionKey_eciesBrainpoolP256r1(
                                                                                                     m_evciesP256EncryptedKey(
                                                                                                                              v_eccP256_curve_point,
                                                                                                                              p_encrypted_sym_key, 
                                                                                                                              p_authentication_vector
                                                                                                                              )));
      }
      p_ieee1609dot2_signed_and_encrypted_data := valueof(
                                                          m_etsiTs103097Data_encrypted(
                                                                                       m_encryptedData(
                                                                                                       {
                                                                                                        m_recipientInfo_certRecipInfo(
                                                                                                                                      m_pKRecipientInfo(
                                                                                                                                                        v_recipientId,
                                                                                                                                                        v_encrypted_data_encryption_key
                                                                                                                                                        ))
                                                                                                        },
                                                                                                       m_symmetricCiphertext_aes128ccm(
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                       m_aesCcmCiphertext(
                                                                                                                                                          p_nonce,
                                                                                                                                                          v_encrypted_request
                                                                                                                                                          )
                                                                                                                                       )
                                                                                                      )
                                                                                       )
                                                          );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // The 'p_request_hash' shall be the SHA256 digest of the OER representation of the topmost EtsiTs103097Data-Encoded structure
      v_enc_value := encvalue(p_ieee1609dot2_signed_and_encrypted_data);
      p_request_hash := f_hashWithSha256(bit2oct(v_enc_value));
      log("f_build_pki_secured_request_message: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_build_pki_secured_request_message: ", p_ieee1609dot2_signed_and_encrypted_data);
      return true;
    } // End of function f_build_pki_secured_request_message
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    function f_build_pki_secured_request_message_for_authorization(
                                                                   in HashedId8 p_recipientId,
                                                                   in octetstring p_public_key_compressed,
                                                                   in integer p_compressed_mode,
                                                                   in octetstring p_salt,
                                                                   in octetstring p_pki_message,
                                                                   in SignAlgorithm p_enc_algorithm,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                   out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                                                   out Oct16 p_aes_sym_key,
                                                                   out Oct16 p_encrypted_sym_key,
                                                                   out Oct16 p_authentication_vector,
                                                                   out Oct12 p_nonce,
                                                                   out Oct32 p_request_hash
                                                                   ) return boolean {
      // Local variables
      var Ieee1609Dot2Data v_unsecured_data;
      var octetstring v_pki_message;
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var HashedId8 v_recipientId;
      var octetstring v_public_compressed_ephemeral_key;
      var integer v_public_compressed_ephemeral_mode;
      var octetstring v_encrypted_request;
      var EncryptedDataEncryptionKey v_encrypted_data_encryption_key;
      var bitstring v_enc_value;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log(">>> f_build_pki_secured_request_message_for_authorization");

      // Add Ieee1609Dot2Data layer
      v_unsecured_data := valueof(m_etsiTs103097Data_unsecured(p_pki_message));
      v_pki_message := bit2oct(encvalue(v_unsecured_data));
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Encrypt encode EtsiTs103097Data-Signed data structure
      if (p_enc_algorithm == e_nist_p256) {
        v_encrypted_request := f_encryptWithEciesNistp256WithSha256(v_pki_message, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
      } else if (p_enc_algorithm == e_sm2_p256) {
        v_encrypted_request := f_encryptWithEciesSm2p256WithSha256(v_pki_message, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (p_enc_algorithm == e_brainpool_p256_r1) {
        v_encrypted_request := f_encryptWithEciesBrainpoolp256r1WithSha256(v_pki_message, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce);
      } else {
        log("f_build_pki_secured_request_message_for_authorization: Wrong encryption variant");
        return false;
      }
      log("f_build_pki_secured_request_message_for_authorization: p_aes_sym_key= ", p_aes_sym_key);
      log("f_build_pki_secured_request_message_for_authorization: p_encrypted_sym_key= ", p_encrypted_sym_key);
      log("f_build_pki_secured_request_message_for_authorization: p_authentication_vector= ", p_authentication_vector);
      log("f_build_pki_secured_request_message_for_authorization: p_nonce= ", p_nonce);
      log("f_build_pki_secured_request_message_for_authorization: p_recipientId= ", p_recipientId);
      if (p_recipientId == int2oct(0, 8)) {
        log("f_build_pki_secured_request_message_for_authorization: f_hashWithSha256(v_encrypted_sym_key)= ", f_hashWithSha256(p_encrypted_sym_key));
        v_recipientId := f_hashedId8FromSha256(f_hashWithSha256(p_encrypted_sym_key));
      } else {
        v_recipientId := p_recipientId;
      }
      log("f_build_pki_secured_request_message_for_authorization: v_recipientId= ", v_recipientId);
      // Fill Certificate template with the public compressed keys (canonical form)
      if (v_public_compressed_ephemeral_mode == 0) {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_compressed_ephemeral_key));
      } else {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
      }
      if (p_enc_algorithm == e_nist_p256) {
        v_encrypted_data_encryption_key := valueof(
                                                   m_encryptedDataEncryptionKey_eciesNistP256(
                                                                                              m_evciesP256EncryptedKey(
                                                                                                                       v_eccP256_curve_point,
                                                                                                                       p_encrypted_sym_key, 
                                                                                                                       p_authentication_vector
                                                                                                                       )));
      } else if (PX_VE_ALG == e_sm2_p256) { // FIXME FSCOM
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      } else if (p_enc_algorithm == e_brainpool_p256_r1) {
        v_encrypted_data_encryption_key := valueof(
                                                   m_encryptedDataEncryptionKey_eciesBrainpoolP256r1(
                                                                                                     m_evciesP256EncryptedKey(
                                                                                                                              v_eccP256_curve_point,
                                                                                                                              p_encrypted_sym_key, 
                                                                                                                              p_authentication_vector
                                                                                                                              )));
      }
      p_ieee1609dot2_signed_and_encrypted_data := valueof(
                                                          m_etsiTs103097Data_encrypted(
                                                                                       m_encryptedData(
                                                                                                       {
                                                                                                        m_recipientInfo_certRecipInfo(
                                                                                                                                      m_pKRecipientInfo(
                                                                                                                                                        v_recipientId,
                                                                                                                                                        v_encrypted_data_encryption_key
                                                                                                                                                        ))
                                                                                                        },
                                                                                                       m_symmetricCiphertext_aes128ccm(
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                       m_aesCcmCiphertext(
                                                                                                                                                          p_nonce,
                                                                                                                                                          v_encrypted_request
                                                                                                                                                          )
                                                                                                                                       )
                                                                                                      )
                                                                                       )
                                                          );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // The 'p_request_hash' shall be the SHA256 digest of the OER representation of the topmost EtsiTs103097Data-Encoded structure
      v_enc_value := encvalue(p_ieee1609dot2_signed_and_encrypted_data);
      p_request_hash := f_hashWithSha256(bit2oct(v_enc_value));
      log("f_build_pki_secured_request_message_for_authorization: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_build_pki_secured_request_message_for_authorization: ", p_ieee1609dot2_signed_and_encrypted_data);
      return true;
    } // End of function f_build_pki_secured_request_message_for_authorization
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc Build a signed and encrypted PKI response message
     * @param p_private_key         Private key for signature
     * @param p_signer_identifier   Signer identifier for signature, could be self or certificate HashedId8
     * @param p_recipientId         Recipient identifier to be inclued in encrypted layer.
     *                              If value is int2oct(0. 8), the recipient id is the HashedId8 of the symmetric key used by the sender to encrypt the message to which the response is built
     * @param p_public_key_compressed The public compressed key (canonical form) for encryption
     * @param p_compressed_mode      The compressed mode of the public compressed key (canonical form) for encryption
     * @param p_pki_message         The PKI message to be secured
     * @param p_ieee1609dot2_signed_and_encrypted_data The secured message
     * @return true on success, false otherwise
     */
    function f_build_pki_secured_response_message(
                                                 in octetstring p_private_key,
                                                 in SignerIdentifier p_signer_identifier,
                                                 in octetstring p_pki_message,
                                                 in Oct16 p_aes_sym_key,
                                                 in Oct12 p_nonce,
                                                 out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
                                                 ) return boolean {
      // Local variables
      var template (value) ToBeSignedData v_tbs;
      var octetstring v_tbs_signed;
      var template (value) Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var octetstring v_encoded_inner_ec_response;
      var HashedId8 v_recipientId;
      var octetstring v_encrypted_inner_ec_response;
      var octetstring v_symkeyidentifier;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Signed the encoded PKI message
      v_tbs := m_toBeSignedData(
                                m_signedDataPayload(
                                                    m_etsiTs103097Data_unsecured(p_pki_message)
                                                   ),
                                m_headerInfo_inner_pki_response(-, (f_getCurrentTime() * 1000)/*us*/)
                                );
      if (ischosen(p_signer_identifier.self_)) {
        v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key);
      } else {
        var charstring v_certificate_id;
        var Oct32 v_hash;
        fx_readCertificateFromDigest(p_signer_identifier.digest, v_certificate_id); // TODO Add a wrapper function
        log(">>>>> f_build_pki_secured_response_message: use ", v_certificate_id, " for signing response");
        log(">>>>> f_build_pki_secured_response_message: use ", p_private_key, " as private key");
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        f_getCertificateHash(v_certificate_id, v_hash);
        v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_hash, p_private_key);
      }
      // Add the signature and create EtsiTs103097Data-Signed data structure
      v_ieee1609dot2_signed_data := m_etsiTs103097Data_signed(
                                                              m_signedData(
                                                                           sha256,
                                                                           v_tbs,
                                                                           p_signer_identifier,
                                                                           m_signature_ecdsaNistP256(
                                                                                                     m_ecdsaP256Signature(
                                                                                                                          m_eccP256CurvePoint_x_only(
                                                                                                                                                     substr(v_tbs_signed, 0, 32)
                                                                                                                                                     ),
                                                                                                                          substr(v_tbs_signed, 32, 32)
                                                                                                                          )
                                                                                                     )
                                                                           )
                                                      );
      // Encode EtsiTs103097Data-Signed data structure
      v_encoded_inner_ec_response := bit2oct(encvalue(v_ieee1609dot2_signed_data));
      v_encrypted_inner_ec_response := fx_encrypt_aes_128_ccm_test(p_aes_sym_key, p_nonce, v_encoded_inner_ec_response);
      v_symkeyidentifier := '80'O & p_aes_sym_key;
      log("v_symkeyidentifier= ", v_symkeyidentifier);
      v_recipientId := f_hashedId8FromSha256(f_hashWithSha256(v_symkeyidentifier));
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("v_recipientId= ", v_recipientId);
      // Fill Certificate template with the public compressed keys (canonical form)
      p_ieee1609dot2_signed_and_encrypted_data := valueof(
                                                          m_etsiTs103097Data_encrypted(
                                                                                       m_encryptedData(
                                                                                                       {
                                                                                                        m_recipientInfo_pskRecipInfo(
                                                                                                                                     v_recipientId
                                                                                                                                     )
                                                                                                       },
                                                                                                       m_symmetricCiphertext_aes128ccm(
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                                                                                       m_aesCcmCiphertext(
                                                                                                                                                          p_nonce,
                                                                                                                                                          v_encrypted_inner_ec_response
                                                                                                                                                         )
                                                                                                                                      )
                                                                                                      )
                                                                                       )
                                                         );
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_build_pki_secured_response_message: ", p_ieee1609dot2_signed_and_encrypted_data);
      return true;
    } // End of function f_build_pki_secured_response_message
    function f_read_pki_request_message(
                                  in Ieee1609Dot2Data p_encrypted_message,
                                  in Oct32 p_private_enc_key,
                                  in Oct32 p_salt,
                                  out Oct16 p_request_hash,
                                  out Oct16 p_aes_enc_key,
                                  out Ieee1609Dot2Data p_decrypted_message,
                                  out EtsiTs102941Data p_etsi_ts_102941_data
                                ) return boolean {
      var octetstring v_msg;
      var boolean ret := true;

      // 1. Calculate the request Hash
      v_msg := bit2oct(encvalue(p_encrypted_message));
      log("f_parse_pki_request: Encoded request: ", v_msg);
      p_request_hash := substr(f_hashWithSha256(v_msg), 0, 16);
      log("f_parse_pki_request: p_request_hash= ", p_request_hash);
      log("f_parse_pki_request: p_private_enc_key= ", p_private_enc_key);
      if (false == f_decrypt(p_private_enc_key, p_encrypted_message, p_salt, p_decrypted_message, p_aes_enc_key)) {
        log("f_parse_pki_request: Failed to decrypt message");
      log("f_parse_pki_request: v_ieee1609dot2_signed_data= ", p_decrypted_message);
      log("f_parse_pki_request: p_aes_enc_key= ", p_aes_enc_key);
      select(p_decrypted_message){
        case( mw_etsiTs103097Data_signed(
                    mw_signedData(
                            -,
                            mw_toBeSignedData(
                                    mw_signedDataPayload
                            )
                    )
              )
        ) {
            var bitstring v_msg_bit;
            v_msg_bit := oct2bit(p_decrypted_message.content.signedData.tbsData.payload.data.content.unsecuredData);
            if (decvalue(v_msg_bit, p_etsi_ts_102941_data) != 0) {
              ret := false;
            }
          }
          ret := false;
      }
      return ret;
    } // End of function f_read_pki_request_message

    function f_read_ec_request_from_iut_itss(
                                              in Ieee1609Dot2Data p_encrypted_message,
                                              out Oct16 p_request_hash,
                                              out Oct16 p_aes_enc_key,
                                              out Ieee1609Dot2Data p_decrypted_message,
                                              out EtsiTs102941Data p_etsi_ts_102941_data,
                                              out InnerEcRequest   p_inner_ec_request
                                            ) runs on ItsPkiHttp return boolean {
      // Local variables
      var PublicVerificationKey v_canonical_key;
      var EtsiTs103097Certificate v_ec_certificate;
      var HashedId8 v_ec_certificate_hashed_id8;
      var InnerEcResponse v_inner_ec_response;
/*      
      if(false == f_get_canonical_itss_key(v_canonical_key)){
        log(">>> f_read_ec_request_from_iut_itss: error getting canonical key");
        return false;
      }
*/
      if( f_read_pki_request_message( p_encrypted_message, vc_eaPrivateEncKey, vc_eaWholeHash/*salt*/,
                                          p_request_hash, p_aes_enc_key,
                                          p_decrypted_message,
                                          p_etsi_ts_102941_data
      )) {
        // decode InnerEcRequest 
        var bitstring v_msg_bit := oct2bit(p_etsi_ts_102941_data.content.enrolmentRequest.content.signedData.tbsData.payload.data.content.unsecuredData);
        if (decvalue(v_msg_bit, p_inner_ec_request) != 0) {
          log("f_read_ec_request_from_iut_itss: Failed to decode InnerEcRequest");
        }
        return true;
      }
      return false;
    } // End of function f_read_ec_request_from_iut_itss

ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc Verify the protocol element of the Pki message. 
     *       If p_check_security is set to false, only decryption and decoding of the outer message are verified.
     * @param p_private_enc_key     Private key for decryption
     * @param p_salt
     * @param p_p_ieee1609dot2_encrypted_and_signed_data
     * @param p_check_security      Set to true to verify PKI protocol element such as signatures...
     * @param p_request_hash        The request hash for to be used to build the response
     * @param p_etsi_ts_102941_data The EtsiTs102941Data message
     * @param p_aes_enc_key         The AES 128 encrytion key to be used to encrypt the response
     * @return true on success, false otherwise
     */
    function f_verify_pki_request_message(
                                          in Oct32 p_private_enc_key,
                                          in Oct32 p_salt,
                                          in octetstring p_issuer_hash,
                                          in template (omit) PublicVerificationKey p_verification_key,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                          in Ieee1609Dot2Data p_ieee1609dot2_encrypted_and_signed_data,
                                          in boolean p_check_security := true,
                                          out Oct16 p_request_hash,
                                          out HashedId8 p_bfk_request_hash,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                          out EtsiTs102941Data p_etsi_ts_102941_data,
                                          out Oct16 p_aes_enc_key
                                          ) return boolean {
      // Local variables
      var bitstring v_msg_bit;
      var octetstring v_msg;
      var Oct32 v_hash;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var Certificate v_certificate;
      var charstring v_certificate_id;

      log(">>> f_verify_pki_request_message: p_private_enc_key= ", p_private_enc_key);
      log(">>> f_verify_pki_request_message: p_salt= ", p_salt);
      log(">>> f_verify_pki_request_message: p_issuer_hash= ", p_issuer_hash);
      log(">>> f_verify_pki_request_message: p_verification_key= ", p_verification_key);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log(">>> f_verify_pki_request_message: p_ieee1609dot2_encrypted_and_signed_data= ", p_ieee1609dot2_encrypted_and_signed_data);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // 1. Calculate the request Hash
      v_msg := bit2oct(encvalue(p_ieee1609dot2_encrypted_and_signed_data));
      log("f_verify_pki_request_message: Encoded request: ", v_msg);
      v_hash := f_hashWithSha256(v_msg);
      p_request_hash := substr(v_hash, 0, 16);
      //p_bfk_request_hash := f_hashedId8FromSha256(v_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("f_verify_pki_request_message: p_request_hash= ", p_request_hash);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // 2. Decrypt the InnerEcRequest
      log("f_verify_pki_request_message: p_private_enc_key= ", p_private_enc_key);
      if (f_decrypt(p_private_enc_key, p_ieee1609dot2_encrypted_and_signed_data, p_salt, v_ieee1609dot2_signed_data, p_aes_enc_key) == false) {
        log("f_verify_pki_request_message: Failed to decrypt message");
        return false;
      }
      log("f_verify_pki_request_message: v_ieee1609dot2_signed_data= ", v_ieee1609dot2_signed_data);
      log("f_verify_pki_request_message: p_aes_enc_key= ", p_aes_enc_key);

      // 3. Check basics security
      log(
          match(
                v_ieee1609dot2_signed_data,
                mw_etsiTs103097Data_signed(
                                           mw_signedData(
                                                         -,
                                                         mw_toBeSignedData(
                                                                           mw_signedDataPayload,
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                                                           )
                                                         )
                                )));
      if (match(v_ieee1609dot2_signed_data, mw_etsiTs103097Data_signed(mw_signedData(-, mw_toBeSignedData(mw_signedDataPayload)))) == false) {
        log("f_verify_pki_request_message: Failed to check basic security");
        if (p_check_security == true) {
          return false;
        }
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // 4. Verifiy signature
      log("f_verify_pki_request_message: v_ieee1609dot2_signed_data.content.signedData.tbsData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData);
      v_msg := bit2oct(encvalue(v_ieee1609dot2_signed_data.content.signedData.tbsData));
      if (not ispresent(p_verification_key)){
        var EtsiTs103097Certificate v_cert;
        var charstring v_cert_id;
        if (ischosen(v_ieee1609dot2_signed_data.content.signedData.signer.digest)){
          if (not f_getCertificateFromDigest(v_ieee1609dot2_signed_data.content.signedData.signer.digest, v_cert, v_cert_id)){
            if (p_check_security == true) {
              return false;
            }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
          }
        }
        if (ischosen(v_ieee1609dot2_signed_data.content.signedData.signer.certificate)){
          if(lengthof(v_ieee1609dot2_signed_data.content.signedData.signer.certificate) > 0){
            v_cert := v_ieee1609dot2_signed_data.content.signedData.signer.certificate[0];
ASN.1 Documenter's avatar
ASN.1 Documenter committed
          }
        }
        if (isbound(v_cert)){
          if(ischosen(v_cert.toBeSigned.verifyKeyIndicator.verificationKey)){
            p_verification_key := v_cert.toBeSigned.verifyKeyIndicator.verificationKey;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
          }
        }
      if (ispresent(p_verification_key)){
        log("f_verify_pki_request_message: v_msg= ", v_msg);
        if (false == f_verifyEcdsa(v_msg, int2oct(0, 32), v_ieee1609dot2_signed_data.content.signedData.signature_, valueof(p_verification_key))) {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
          if (p_check_security == true) {
            return false;
          }
        }
      }
      // 5. Return the PKI message
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("f_verify_pki_request_message: v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      v_msg_bit := oct2bit(v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_msg_bit, p_etsi_ts_102941_data) != 0) {
        if (p_check_security == true) {
          return false;
        }
      }
      if (p_etsi_ts_102941_data.version != PkiProtocolVersion) {
        if (p_check_security == true) {
          return false;
        }
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log("<<< f_verify_pki_request_message: true");
      return true;
    } // End of function f_verify_pki_request_message
    /**
     * @desc Verify the protocol element of the Pki message. 
     *       If p_check_security is set to false, only decryption and decoding of the outer message are verified.
     * @param p_private_enc_key     Private key for decryption
     * @param p_salt
     * @param p_p_ieee1609dot2_encrypted_and_signed_data
     * @param p_check_security      Set to true to verify PKI protocol element such as signatures...
     * @param p_request_hash        The request hash for to be used to build the response
     * @param p_etsi_ts_102941_data The EtsiTs102941Data message
     * @param p_aes_enc_key         The AES 128 encrytion key to be used to encrypt the response
     * @return true on success, false otherwise
     */
    function f_verify_pki_request_message_with_certificate(
                                                           in Oct32 p_private_enc_key,
                                                           in Oct32 p_salt,
                                                           in EtsiTs103097Certificate p_signer_certificate,
                                                           in Ieee1609Dot2Data p_ieee1609dot2_encrypted_and_signed_data,
                                                           in boolean p_check_security := true,
                                                           out Oct16 p_request_hash,
                                                           out HashedId8 p_bfk_request_hash,
                                                           out EtsiTs102941Data p_etsi_ts_102941_data,
                                                           out Oct16 p_aes_enc_key
                                                           ) return boolean {
      // Local variables
      var bitstring v_msg_bit;
      var octetstring v_msg;
      var Oct32 v_hash;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;

      log(">>> f_verify_pki_request_message_with_certificate: p_private_enc_key= ", p_private_enc_key);
      log(">>> f_verify_pki_request_message_with_certificate: p_salt= ", p_salt);
      log(">>> f_verify_pki_request_message_with_certificate: p_signer_certificate= ", p_signer_certificate);
      log(">>> f_verify_pki_request_message_with_certificate: p_ieee1609dot2_encrypted_and_signed_data= ", p_ieee1609dot2_encrypted_and_signed_data);

      // 1. Calculate the request Hash
      v_msg := bit2oct(encvalue(p_ieee1609dot2_encrypted_and_signed_data));
      log("f_verify_pki_request_message_with_certificate: Encoded request: ", v_msg);
      v_hash := f_hashWithSha256(v_msg);
      p_request_hash := substr(v_hash, 0, 16);
      //p_bfk_request_hash := f_hashedId8FromSha256(v_hash);
      log("f_verify_pki_request_message_with_certificate: p_request_hash= ", p_request_hash);

      // 2. Decrypt the InnerEcRequest
      log("f_verify_pki_request_message_with_certificate: p_private_enc_key= ", p_private_enc_key);
      if (f_decrypt(p_private_enc_key, p_ieee1609dot2_encrypted_and_signed_data, p_salt, v_ieee1609dot2_signed_data, p_aes_enc_key) == false) {
        log("f_verify_pki_request_message_with_certificate: Failed to decrypt message");
        return false;
      }
      log("f_verify_pki_request_message_with_certificate: v_ieee1609dot2_signed_data= ", v_ieee1609dot2_signed_data);
      log("f_verify_pki_request_message_with_certificate: p_aes_enc_key= ", p_aes_enc_key);

      // 3. Check basics security
      log(
          match(
                v_ieee1609dot2_signed_data,
                mw_etsiTs103097Data_signed(
                                           mw_signedData(
                                                         -,
                                                         mw_toBeSignedData(
                                                                           mw_signedDataPayload,
                                                                           mw_ieee1609Dot2_headerInfo(c_its_aid_SCR)
                                                                           )
                                                         )
                                )));
      if (match(v_ieee1609dot2_signed_data, mw_etsiTs103097Data_signed(mw_signedData(-, mw_toBeSignedData(mw_signedDataPayload)))) == false) {
        log("f_verify_pki_request_message_with_certificate: Failed to check basic security");
        if (p_check_security == true) {
          return false;
        }
      }

      // 4. Verifiy signature
      log("f_verify_pki_request_message_with_certificate: v_ieee1609dot2_signed_data.content.signedData.tbsData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData);
      v_msg := bit2oct(encvalue(v_ieee1609dot2_signed_data.content.signedData.tbsData));
      log("f_verify_pki_request_message_with_certificate: v_msg= ", v_msg);
      
      var octetstring v_enc := bit2oct(encvalue(p_signer_certificate));
      var Oct32 v_issuer := f_hashWithSha256(v_enc);
      log("f_verify_pki_request_message_with_certificate: signing issuer= ", v_issuer);
      if (f_verifyEcdsa(v_msg, v_issuer, v_ieee1609dot2_signed_data.content.signedData.signature_, p_signer_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
        if (p_check_security == true) {
          return false;
        }
      }

      // 4. Return the PKI message
      log("f_verify_pki_request_message_with_certificate: v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      v_msg_bit := oct2bit(v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_msg_bit, p_etsi_ts_102941_data) != 0) {
        if (p_check_security == true) {
          return false;
        }
      }
      if (p_etsi_ts_102941_data.version != PkiProtocolVersion) {
        if (p_check_security == true) {
          return false;
        }
      }

      log("<<< f_verify_pki_request_message_with_certificate: true");
      return true;
    } // End of function f_verify_pki_request_message_with_certificate_with_certificate

ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc Verify the protocol element of the Pki message. 
     *       If p_check_security is set to false, only decryption and decoding of the outer message are verified.
     * @param p_private_key         Private key for decryption
     * @param p_publicEphemeralCompressedKey
     * @param p_publicEphemeralCompressedKeyMode
     * @param p_issuer              Issuer
     * @param p_certificate         Certificate to use for verification key
     * @param p_ieee1609dot2_encrypted_and_signed_data The received encrypted and signed data
     * @param p_check_security      Set to true to verify PKI protocol element such as signatures...
     * @param p_response_type       Response type (0: InnerEcResponse, 1: InnerAtResponse...). Default: 0
     * @param p_etsi_ts_102941_data The EtsiTs102941Data message
     * @return true on success, false otherwise
     */
    function f_verify_pki_response_message(
                                           in octetstring p_private_enc_key,
                                           in Oct16 p_aes_sym_key,
                                           in Oct16 p_authentication_vector, // TODO Tobe removed
                                           in octetstring p_issuer,
                                           in Ieee1609Dot2Data p_ieee1609dot2_encrypted_and_signed_data,
                                           in boolean p_check_security := true,
                                           in integer p_response_type := 0,
                                           out EtsiTs102941Data p_etsi_ts_102941_data
                                           ) return boolean {
      // Local variables
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var octetstring v_plain_message;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var Certificate v_certificate;
      var charstring v_certificate_id;
      var bitstring v_etsi_ts_102941_data_msg;
      var bitstring v_tbs;
      var boolean v_ret;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      log(">>> f_verify_pki_response_message: p_private_enc_key= ", p_private_enc_key);
      log(">>> f_verify_pki_response_message: p_aes_sym_key= ", p_aes_sym_key);
      log(">>> f_verify_pki_response_message: p_authentication_vector= ", p_authentication_vector);
      log(">>> f_verify_pki_response_message: p_issuer= ", p_issuer);
      log(">>> f_verify_pki_response_message: p_check_security= ", p_check_security);
      log(">>> f_verify_pki_response_message: p_response_type= ", p_response_type);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // TODO Check p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.recipients[0].pskRecipInfo. See IEEE Std 1609.2-2017 Clause 6.3.34 PreSharedKeyRecipientInfo
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // 1. Decrypt the data
      v_plain_message := fx_decrypt_aes_128_ccm_test(p_aes_sym_key, p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.ciphertext.aes128ccm.nonce, p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.ciphertext.aes128ccm.ccmCiphertext);
      if (isbound(v_plain_message) == false) {
        return false;
      }
      log("f_verify_pki_response_message: v_plain_message= ", v_plain_message);

      // 2. Decode it
      v_tbs := oct2bit(v_plain_message);
      if (decvalue(v_tbs, v_ieee1609dot2_signed_data) != 0) {
        return false;
      }
      log("f_verify_pki_response_message: v_ieee1609dot2_signed_data= ", v_ieee1609dot2_signed_data);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // 3. Check the signature
      log("f_verify_pki_response_message: v_ieee1609dot2_signed_data.content.signedData.tbsData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData);
      v_tbs := encvalue(v_ieee1609dot2_signed_data.content.signedData.tbsData);
      if (f_getCertificateFromDigest(v_ieee1609dot2_signed_data.content.signedData.signer.digest, v_certificate, v_certificate_id) == false) {
        if (p_check_security == true) {
          return false;
        }
      }
      if (f_verifyEcdsa(bit2oct(v_tbs), p_issuer, v_ieee1609dot2_signed_data.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
        if (p_check_security == true) {
          return false;
        }
      }

      // 4. Verify EtsiTs103097Data-Signed HeaderInfo
      // TODO Parameter p_response_type seems to be useless
      if ((p_response_type == 0) or (p_response_type == 1)) { // InnerEcResponse & InnerAtResponse
        log("f_verify_pki_response_message: headerInfo matching= ", match(v_ieee1609dot2_signed_data.content.signedData.tbsData.headerInfo, mw_headerInfo_inner_pki_response));
        if (match(v_ieee1609dot2_signed_data.content.signedData.tbsData.headerInfo, mw_headerInfo_inner_pki_response) == false) {
          if (p_check_security == true) {
            return false;
          }
        }
      } // else, no check
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // 5. Return the PKI message
      log("f_verify_pki_response_message: v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      v_etsi_ts_102941_data_msg := oct2bit(v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_etsi_ts_102941_data_msg, p_etsi_ts_102941_data) != 0) {
        return false;
      }

      if (p_etsi_ts_102941_data.version != PkiProtocolVersion) {
        return false;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_verify_pki_response_message
    function f_verify_repeated_request(
                                       in HttpMessage p_request_1,
                                       in HttpMessage p_request_2
                                       ) return boolean {

      return false;
    } // End of function f_verify_repeated_request
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc Verify the EC certificate generated by the EA entity
     * @param p_ec_certificate        The new EC certificate
     * @param p_ea_certificate        The certificate issuer
     * @param p_public_key_compressed The public compressed key (canonical form) generated for the InnerEcRequest
     * @param p_compressed_mode       The public compressed key mode
     * @return true on success, false otherwise
     */
    function f_verify_ec_certificate(
                                     in Certificate p_ec_certificate,
                                     in Certificate p_ea_certificate,
                                     in HashedId8 p_ea_hashed_id8,
                                     in octetstring p_public_key_compressed,
                                     in integer p_compressed_mode,
                                     out HashedId8 p_ec_cert_hashed_id8
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                     ) return boolean {
      var bitstring v_encoded_cert;
      var Oct32 v_ec_cert_hash_256;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Calculate the HashedId8 of the whole certificate
      v_encoded_cert := encvalue(p_ec_certificate);
      v_ec_cert_hash_256 := f_hashWithSha256(bit2oct(v_encoded_cert));
      log("f_verify_ec_certificate: ==> EC certificate Hash: ", v_ec_cert_hash_256);
      p_ec_cert_hashed_id8 := f_hashedId8FromSha256(v_ec_cert_hash_256);
      log("f_verify_ec_certificate: ==> EC certificate HashedId8: ", p_ec_cert_hashed_id8);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Check the signer
      log("f_verify_ec_certificate: Check the signer: ", match(p_ec_certificate.issuer, m_issuerIdentifier_sha256AndDigest(p_ea_hashed_id8)));
      log("f_verify_ec_certificate: Check the signer: ", match(p_ec_certificate.issuer, m_issuerIdentifier_sha384AndDigest(p_ea_hashed_id8)));
      if (
          (match(p_ec_certificate.issuer, m_issuerIdentifier_sha256AndDigest(p_ea_hashed_id8)) == false) and
          (match(p_ec_certificate.issuer, m_issuerIdentifier_sha384AndDigest(p_ea_hashed_id8)) == false)
          ) {
        log("f_verify_ec_certificate: Wrong issuer");
        return false;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Check EC certificate signature
      if (f_verifyCertificateSignatureWithPublicKey(p_ec_certificate, p_ea_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
        log("f_verify_ec_certificate: Signature not verified");
        return false;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // TODO Check that requested information are present
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (f_verifySspPermissions(p_ec_certificate.toBeSigned.appPermissions, p_ea_certificate.toBeSigned.appPermissions) == false) {
        log("f_verify_ec_certificate: Ssp permissions not verified");
        return false;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_verify_ec_certificate
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    /**
     * @desc Verify the generated AT certificate 
     * @param p_at_certificate        The new AT certificate
     * @param p_ea_certificate        The certificate issuer
     * @param p_public_key_compressed The public compressed key (canonical form) generated for the InnerAtRequest
     * @param p_compressed_mode       The public compressed key mode
     * @return true on success, false otherwise
     */
    function f_verify_at_certificate(
                                     in Certificate p_at_certificate,
                                     in Certificate p_aa_certificate,
                                     in octetstring p_public_key_compressed,
                                     in integer p_compressed_mode
                                     ) return boolean {
      var bitstring v_encoded_cert;
      var HashedId8 v_at_cert_hashed_id8;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Calculate the HashedId8 of the whole certificate
      v_encoded_cert := encvalue(p_at_certificate);
      v_at_cert_hashed_id8 := f_hashedId8FromSha256(f_hashWithSha256(bit2oct(v_encoded_cert)));
      log("f_verify_at_certificate: EC certificate HashedId8: ", v_at_cert_hashed_id8);
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Check the signer
      log("f_verify_at_certificate: ", match(p_at_certificate.issuer, mw_issuerIdentifier_self()));
      if (match(p_at_certificate.issuer, mw_issuerIdentifier_self)) {
        return false;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // Check EC certificate signature
      if (f_verifyCertificateSignatureWithPublicKey(p_at_certificate, p_aa_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
        log("f_verify_at_certificate: Signature not verified");
        return false;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      // TODO Check that requested information are present
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      if (f_verifySspPermissions(p_aa_certificate.toBeSigned.appPermissions, p_at_certificate.toBeSigned.appPermissions) == false) {
        log("f_verify_at_certificate: Ssp permissions not verified");
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        return false;
      }
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      return true;
    } // End of function f_verify_at_certificate
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group inner_ec_xxx

  group altsteps {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_default_pki_http() runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(
                                                      mw_http_response(
                                                                       mw_http_response_ko
                                                                       )) {
        tc_ac.stop;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
        f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
      }
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(mw_http_request) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Request received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(mw_http_response) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Response received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP message received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] a_shutdown() {
        log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
        stop;
      }
    } // End of altstep a_default_pki_http
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_default_pki_http_ec() runs on ItsPkiHttp {
      [PICS_MULTIPLE_END_POINT] httpEcPort.receive(
                                                   mw_http_response(
                                                                    mw_http_response_ko
                                                                    )) {
        tc_ac.stop;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
        f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpEcPort.receive(mw_http_request) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Request received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpEcPort.receive(mw_http_response) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Response received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpEcPort.receive {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP message received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] a_shutdown() {
        log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
        stop;
      }
    } // End of altstep a_default_pki_http_ec
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_default_pki_http_atv() runs on ItsPkiHttp {
      [PICS_MULTIPLE_END_POINT] httpAtVPort.receive(
                                                   mw_http_response(
                                                                    mw_http_response_ko
                                                                    )) {
        tc_ac.stop;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
        f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpAtVPort.receive(mw_http_request) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Request received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpAtVPort.receive(mw_http_response) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Response received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpAtVPort.receive {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP message received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] a_shutdown() {
        log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
        stop;
      }
    } // End of altstep a_default_pki_http_atv
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_default_pki_http_at() runs on ItsPkiHttp {
      [PICS_MULTIPLE_END_POINT] httpAtPort.receive(
                                                   mw_http_response(
                                                                    mw_http_response_ko
                                                                    )) {
        tc_ac.stop;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
        f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpAtPort.receive(mw_http_request) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Request received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpAtPort.receive(mw_http_response) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Response received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpAtPort.receive {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP message received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] a_shutdown() {
        log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
        stop;
      }
    } // End of altstep a_default_pki_http_at

    altstep a_default_pki_http_ca() runs on ItsPkiHttp {
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive(
                                                   mw_http_response(
                                                                    mw_http_response_ko
                                                                    )) {
        tc_ac.stop;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
        f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive(mw_http_request) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Request received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive(mw_http_response) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Response received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP message received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] a_shutdown() {
        log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
        stop;
      }
    } // End of altstep a_default_pki_http_ca

    altstep a_default_pki_http_tlm() runs on ItsPkiHttp {
      [PICS_MULTIPLE_END_POINT] httpTlmPort.receive(
                                                   mw_http_response(
                                                                    mw_http_response_ko
                                                                    )) {
        tc_ac.stop;
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
        f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpTlmPort.receive(mw_http_request) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Request received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpTlmPort.receive(mw_http_response) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Response received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [PICS_MULTIPLE_END_POINT] httpTlmPort.receive {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP message received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] a_shutdown() {
        log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
        stop;
      }
    } // End of altstep a_default_pki_http_tlm

    altstep a_await_ec_http_request_from_iut(
                                              template HttpMessage p_http_message,
                                              out HttpMessage p_request
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                              ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_request {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("a_await_ec_http_request_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpEcPort.receive(p_http_message) -> value p_request {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("a_await_ec_http_request_from_iut: Received message on httpEcPort");
      }
    } // End of altstep a_await_ec_http_request_from_iut
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_await_ec_http_response_from_iut(
                                              template HttpMessage p_http_message,
                                              out HttpMessage p_response
                                              ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_response {
        log("a_await_ec_http_response_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpEcPort.receive(p_http_message) -> value p_response {
        log("a_await_ec_http_response_from_iut: Received message on httpEcPort");
      }
    } // End of altstep a_await_ec_http_response_from_iut
    altstep a_await_at_http_request_from_iut(
                                             template HttpMessage p_http_message,
                                             out HttpMessage p_request
                                             ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_request {
        log("a_await_at_http_request_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpAtPort.receive(p_http_message) -> value p_request {
        log("a_await_at_http_request_from_iut: Received message on httpAtPort");
      }
    } // End of altstep a_await_at_http_request_from_iut
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_await_at_http_response_from_iut(
                                              template HttpMessage p_http_message,
                                              out HttpMessage p_response
                                              ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_response {
        log("a_await_at_http_response_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpAtPort.receive(p_http_message) -> value p_response {
        log("a_await_at_http_response_from_iut: Received message on httpAtPort");
      }
    } // End of altstep a_await_at_http_response_from_iut
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_await_atv_http_request_from_iut(
                                              template HttpMessage p_http_message,
                                              out HttpMessage p_request
                                              ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_request {
        log("a_await_atv_http_request_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpAtVPort.receive(p_http_message) -> value p_request {
        log("a_await_avt_http_request_from_iut: Received message on httpAtVPort");
      }
    } // End of altstep a_await_atv_http_request_from_iut
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_await_atv_http_response_from_iut(
                                              template HttpMessage p_http_message,
                                              out HttpMessage p_response
                                              ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_response {
        log("a_await_atv_http_response_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpAtVPort.receive(p_http_message) -> value p_response {
        log("a_await_avt_http_response_from_iut: Received message on httpAtVPort");
      }
    } // End of altstep a_await_atv_http_response_from_iut
ASN.1 Documenter's avatar
ASN.1 Documenter committed
    altstep a_await_dc_http_request_from_iut(
                                              template HttpMessage p_http_message,
                                              out HttpMessage p_request
ASN.1 Documenter's avatar
ASN.1 Documenter committed
                                              ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_request {
ASN.1 Documenter's avatar
ASN.1 Documenter committed
        log("a_await_dc_http_request_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive(p_http_message) -> value p_request {
        log("a_await_dc_http_request_from_iut: Received message on httpCaPort");
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      }
    } // End of altstep a_await_dc_http_request_from_iut
    altstep a_await_ctl_http_request_from_iut(
                                              template HttpMessage p_http_message,
                                              out HttpMessage p_request
                                              ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_request {
        log("a_await_ctl_http_request_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive(p_http_message) -> value p_request {
        log("a_await_ctl_http_request_from_iut: Received message on httpCaPort");
      }
    } // End of altstep a_await_ctl_http_request_from_iut
    altstep a_await_crl_http_request_from_iut(
                                              template HttpMessage p_http_message,
                                              out HttpMessage p_request
                                              ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_request {
        log("a_await_crl_http_request_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive(p_http_message) -> value p_request {
        log("a_await_crl_http_request_from_iut: Received message on httpCaPort");
      }
    } // End of altstep a_await_crl_http_request_from_iut
    altstep a_await_cpoc_http_request_from_iut(
                                               template HttpMessage p_http_message,
                                               out HttpMessage p_request
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_request {
        log("a_await_cpoc_http_request_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive(p_http_message) -> value p_request {
        log("a_await_cpoc_http_request_from_iut: Received message on httpCaPort");
      }
    } // End of altstep a_await_cpoc_http_request_from_iut
    altstep a_await_any_http_request_from_iut(
                                               template HttpMessage p_http_message,
                                               out HttpMessage p_request
                                               ) runs on ItsPkiHttp {
      [not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_request {
        log("a_await_any_http_request_from_iut: Received message on httpPort");
      }
      [PICS_MULTIPLE_END_POINT] httpCaPort.receive(p_http_message) -> value p_request {
        log("a_await_any_http_request_from_iut: Received message on httpEcPort");
      }
    } // End of altstep a_await_any_http_request_from_iut
ASN.1 Documenter's avatar
ASN.1 Documenter committed
  } // End of group altsteps
ASN.1 Documenter's avatar
ASN.1 Documenter committed
} // End of module LibItsPki_Functions