Skip to content
LibItsPki_Functions.ttcn 82.3 KiB
Newer Older
Yann Garcia's avatar
Yann Garcia 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 {
    
  // 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;
  
  // 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;
Yann Garcia's avatar
Yann Garcia committed
  import from EtsiTs103097Module language "ASN.1:1997" all;
  import from ITS_Container language "ASN.1:1997" all;
  import from CAM_PDU_Descriptions language "ASN.1:1997" all;
  
  // LibItsCommon
garciay's avatar
garciay committed
  import from LibItsCommon_TypesAndValues all;
Yann Garcia's avatar
Yann Garcia committed
  import from LibItsCommon_Functions all;
  import from LibItsCommon_ASN1_NamedNumbers all;
  import from LibItsCommon_Pixits all;
  // LibItsGeoNetworking
  import from LibItsGeoNetworking_Pixits all;
  
Yann Garcia's avatar
Yann Garcia committed
  // LibItsSecurity
  import from LibItsSecurity_TypesAndValues all;
  import from LibItsSecurity_Templates all;
  import from LibItsSecurity_Functions all;
  import from LibItsSecurity_Pics all;
Yann Garcia's avatar
Yann Garcia committed
  import from LibItsSecurity_Pixits all;
  import from LibItsSecurity_TestSystem all;
Yann Garcia's avatar
Yann Garcia committed
  // LibItsHttp
  import from LibItsHttp_TypesAndValues all;
  import from LibItsHttp_Templates all;
Yann Garcia's avatar
Yann Garcia committed
  import from LibItsHttp_TestSystem all;
Yann Garcia's avatar
Yann Garcia committed
  // LibItsPki
  import from LibItsPki_TypesAndValues all;
Yann Garcia's avatar
Yann Garcia committed
  import from LibItsPki_Templates all;
  import from LibItsPki_Pics all;
garciay's avatar
garciay committed
  import from LibItsPki_Pixits all;
Yann Garcia's avatar
Yann Garcia committed
  import from LibItsPki_TestSystem all;
  
  group pkiConfigurationFunctions {
Yann Garcia's avatar
Yann Garcia committed
     
Yann Garcia's avatar
Yann Garcia committed
     /**
Yann Garcia's avatar
Yann Garcia committed
     * @desc    Setups default configuration   
     * @param   p_certificateId The certificate identifier the TA shall use in case of secured IUT
     */
    function f_cfHttpUp(
garciay's avatar
garciay committed
                        in charstring p_ea_certificate_id := "CERT_TS_A_EA", // TODO Use a constant
                        in charstring p_ec_certificate_id := "CERT_TS_A_EC",
                        in charstring p_peerCertificateId := "CERT_IUT_A_EA"
garciay's avatar
garciay committed
                        ) runs on ItsPkiHttp /* TITAN TODO: system ItsPkiHttpSystem */ {
Yann Garcia's avatar
Yann Garcia committed
      
      map(self:httpPort, system:httpPort);
      f_connect4SelfOrClientSync();
garciay's avatar
garciay committed
      f_initialiseSecuredMode(p_ea_certificate_id, p_peerCertificateId);
Yann Garcia's avatar
Yann Garcia committed
      
garciay's avatar
garciay committed
      f_readCertificate(p_ea_certificate_id, vc_eaCertificate);
      f_readSigningKey(p_ea_certificate_id, vc_eaPrivateKey);
      f_readCertificate(p_ec_certificate_id, vc_ecCertificate);
      f_readSigningKey(p_ec_certificate_id, vc_ecPrivateKey);
      f_readEncryptingKey(p_ea_certificate_id, vc_eaPrivateEncKey);
      f_getCertificateDigest(p_ea_certificate_id, vc_eaHashedId8);
      f_getCertificateHash(p_ea_certificate_id, vc_eaWholeHash);
garciay's avatar
garciay committed
      f_getCertificateDigest(p_ec_certificate_id, vc_ecHashedId8);
      f_readCertificate(p_peerCertificateId, vc_peerEaCertificate);
      f_getCertificateHash(p_peerCertificateId, vc_eaPeerWholeHash);
      
      activate(a_default_pki_http());
Yann Garcia's avatar
Yann Garcia committed
    } // End of function f_cfHttpUp
    function f_cfUp_itss(
                         in charstring p_certificateId := "CERT_TS_A_EA" // TODO Use a constant
                         ) runs on ItsPkiItss /* TITAN TODO: system ItsPkiItssSystem */ {
      
      map(self:geoNetworkingPort, system:geoNetworkingPort);
      map(self:utPort, system:utPort);
Yann Garcia's avatar
Yann Garcia committed
      //map(self:acPort, system:acPort);
Yann Garcia's avatar
Yann Garcia committed
      // activate(a_default_pki()); TOTO Defualt from geoNet
    } // End of function f_cfUp_itss
Yann Garcia's avatar
Yann Garcia committed
    /**
     * @desc    Deletes default configuration 
     */
    function f_cfHttpDown() runs on ItsPkiHttp /* TITAN TODO: system ItsPkiHttpSystem */ {
      unmap(self:httpPort, system:httpPort);
      f_disconnect4SelfOrClientSync();
Yann Garcia's avatar
Yann Garcia committed
    } // End of function f_cfHttpDown
    
    /**
     * @desc    Deletes default configuration 
     */
    function f_cfDown_itss() runs on ItsPkiItss /* TITAN TODO: system ItsPkiItssSystem */ {
      unmap(self:geoNetworkingPort, system:geoNetworkingPort);
      unmap(self:utPort, system:utPort);
Yann Garcia's avatar
Yann Garcia committed
      //unmap(self:acPort, system:acPort);
      
    } // End of function f_cfDown
    
Yann Garcia's avatar
Yann Garcia committed
    /**
     * @desc Initialise secure mode if required
     */
    function f_initialiseSecuredMode(
                                     in charstring p_certificateId  := "CERT_TS_A_EA", // TODO Use a constant
                                     in charstring p_peerCertificateId := "CERT_IUT_A_EA"
                                     ) runs on ItsSecurityBaseComponent {
Yann Garcia's avatar
Yann Garcia committed
      // Local variables
      
      // Load certificates
      if( not f_loadCertificates(PX_IUT_SEC_CONFIG_NAME) ) {
        log("*** INFO: TEST CASE NOW STOPPING ITSELF! ***");
      f_prepareCertificates(p_certificateId, vc_aaCertificate, vc_atCertificate);
Yann Garcia's avatar
Yann Garcia committed
    } // End of function f_initialiseSecuredMode()
    
    function f_uninitialiseSecuredMode() runs on ItsSecurityBaseComponent {
Yann Garcia's avatar
Yann Garcia committed
      f_unloadCertificates();
    } // End of function f_uninitialiseSecuredMode()
    
    function f_initializeState() runs on ItsPkiItss {
      var Oct8 v_hashedId8ToBeUsed := f_setupIutCertificate(vc_hashedId8ToBeUsed);

      f_utInitializeIut(UtPkiInitialize: { v_hashedId8ToBeUsed } );

      f_sleep(PX_NEIGHBOUR_DISCOVERY_DELAY);
      
      //      f_acLoadScenario(p_scenario);
      //      f_acStartScenario();
    }
    
Yann Garcia's avatar
Yann Garcia committed
  } // End of pkiConfigurationFunctions
  group ut_port {

    function f_utInitializeIut(template (value) UtPkiInitialize p_init) runs on ItsPkiItss {
Yann Garcia's avatar
Yann Garcia committed
      timer tc_wait := PX_TAC;
      
      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);
        }
      }
      
    } // End of function f_utInitializeIut
    
    function f_sendUtTriggerPrimitive(
                                      in charstring p_cannonicalId,
                                      in Oct1 p_encAlgorithm,
                                      in octetstring p_private_key,
                                      in octetstring p_publicKeyCompressed,
                                      in integer p_compressedMode
                                      ) runs on ItsPkiItss {
      var TriggerEnrolmentRequest v_ut_trigger_enrolment_request;
      var octetstring v_compressed_public_key;

      if (p_compressedMode == 2) { // TODO v_compressed_public_key := int2oct(p_compressedMode, 1) & p_publicKeyCompressed?
        v_compressed_public_key := '02'O & p_publicKeyCompressed;
      } else {
        v_compressed_public_key := '03'O & p_publicKeyCompressed;
      }
      
      v_ut_trigger_enrolment_request := { p_cannonicalId, p_encAlgorithm, 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_sendUtTriggerPrimitive: ERROR: Received unexpected message ***");
          f_selfOrClientSyncAndVerdict("error", e_error);
        }
        [] 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_sendUtTriggerPrimitive
    
  } // End of group ut_port

    function f_http_build_inner_ec_request( // TODO Cleanup parameters
garciay's avatar
garciay committed
                                           out octetstring p_private_key,
                                           out octetstring p_publicKeyCompressed,
                                           out integer p_compressedMode,
                                           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,
garciay's avatar
garciay committed
                                           out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                           out Oct32 p_request_hash
garciay's avatar
garciay committed
                                           ) runs on ItsPkiHttp {
      var InnerEcRequest v_inner_ec_request;
      var Ieee1609Dot2Data v_inner_ec_request_signed_for_pop;
garciay's avatar
garciay committed
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var boolean v_ret_code;
Yann Garcia's avatar
Yann Garcia committed
      if (f_generate_inner_ec_request(p_private_key, p_publicKeyCompressed, p_compressedMode, v_inner_ec_request) == false) {
        log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequest ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      // 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) {
Yann Garcia's avatar
Yann Garcia committed
        log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      log("v_inner_ec_request_signed_for_pop= ", v_inner_ec_request_signed_for_pop);
      
      // Secure InnerEcRequestSignedForPoP message
garciay's avatar
garciay committed
      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);
      log("*** f_http_build_inner_ec_request: First enrolment: ", PX_FIRST_ENROLMENT);
      p_salt := vc_eaWholeHash;
garciay's avatar
garciay committed
      if (PX_FIRST_ENROLMENT == true) { // This is the first enrolment, we used Factory keys
        v_ret_code := f_build_pki_secured_message(PICS_ITS_S_SIGN_NITSP256_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))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
garciay's avatar
garciay committed
      } else { // We use last valid EC certificate
      v_ret_code := f_build_pki_secured_message(vc_ecPrivateKey, valueof(m_signerIdentifier_digest(vc_ecHashedId8)), 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))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
garciay's avatar
garciay committed
      }
      if (v_ret_code == false) {
Yann Garcia's avatar
Yann Garcia committed
        log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
Yann Garcia's avatar
Yann Garcia committed
      log("*** f_http_build_inner_ec_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
      log("*** f_http_build_inner_ec_request: DEBUG: p_request_hash= ", p_request_hash);
Yann Garcia's avatar
Yann Garcia committed
    } // End of function f_http_build_inner_ec_request
    function f_http_build_invalid_enrolment_request(
                                                    out octetstring p_private_key,
                                                    out octetstring p_publicKeyCompressed,
                                                    out integer p_compressedMode,
                                                    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;
garciay's avatar
garciay committed
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var boolean v_ret_code;
Yann Garcia's avatar
Yann Garcia committed
      if (f_generate_inner_ec_request(p_private_key, p_publicKeyCompressed, p_compressedMode, v_inner_ec_request) == false) {
        log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequest ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      // 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("v_inner_ec_request_signed_for_pop= ", v_inner_ec_request_signed_for_pop);
      
      // Secure InnerEcRequestSignedForPoP message
garciay's avatar
garciay committed
      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_eaWholeHash;
garciay's avatar
garciay committed
      if (PX_FIRST_ENROLMENT == true) { // This is the first enrolment, we used Factory keys
        v_ret_code := f_build_pki_secured_message(PICS_ITS_S_SIGN_NITSP256_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))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
garciay's avatar
garciay committed
      } else { // We use last valid EC certificate
        v_ret_code := f_build_pki_secured_message(vc_ecPrivateKey, valueof(m_signerIdentifier_digest(vc_ecHashedId8)), 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))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
garciay's avatar
garciay 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
garciay's avatar
garciay committed

    function f_http_build_inner_at_request(
                                           out octetstring p_private_key,
                                           out octetstring p_publicKeyCompressed,
                                           out integer p_compressedMode,
                                           out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
                                           out Oct32 p_request_hash
garciay's avatar
garciay committed
                                           ) runs on ItsPkiHttp {
      // Local variables
      // Local variables
      var InnerAtRequest v_authorization_request;
      var bitstring v_authorization_request_msg;
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      
      if (f_generate_authorization_request(vc_eaCertificate, vc_eaHashedId8, p_private_key, p_publicKeyCompressed, p_compressedMode, v_authorization_request) == false) {
        log("*** f_http_build_authorization_request: ERROR: Failed to generate AuthorizationValidationRequest ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      // Secure the Pki 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_authorization_request: Public encryption key: ", v_public_enc_key);
      log("*** f_http_build_authorization_request: Public encryption key comp: ", v_compressed_enc_key_mode);


      /**
         TODO: Load certificate according to the IUT role
         ==> a complete fucntion which set up the TestSustem certificate,keyy... according to the IUT role
       **/
      log("*** f_http_build_inner_ec_request: ERROR: Need to add TestSystem variable vc_aa ***");
      f_selfOrClientSyncAndVerdict("error", e_error);
      /* if (f_build_pki_secured_message(vc_aaPrivateKey, valueof(m_signerIdentifier_digest(vc_aaHashedId8)), vc_eaHashedId8/\*recipientId*\/, v_public_enc_key, v_compressed_enc_key_mode, vc_eaWholeHash, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_authorization_request))), p_ieee1609dot2_signed_and_encrypted_data, p_request_hash) == false) { */
      /*   log("*** f_http_build_authorization_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***"); */
      /*   f_selfOrClientSyncAndVerdict("error", e_error); */
      /* } */
garciay's avatar
garciay committed
      
      log("*** f_http_build_authorization_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data = ", p_ieee1609dot2_signed_and_encrypted_data);
garciay's avatar
garciay committed
    } // End of function f_http_build_inner_at_request
Yann Garcia's avatar
Yann Garcia committed
    function f_http_build_authorization_validation_request(
garciay's avatar
garciay committed
                                                           out octetstring p_private_key,
                                                           out octetstring p_publicKeyCompressed,
                                                           out integer p_compressedMode,
                                                           out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
                                                           ) runs on ItsPkiHttp {
      // Local variables
      var AuthorizationValidationRequest v_authorization_validation_request;
      var bitstring v_authorization_validation_request_msg;
garciay's avatar
garciay committed
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
garciay's avatar
garciay committed
      
      if (f_generate_authorization_validation_request(vc_eaCertificate, vc_eaHashedId8, p_private_key, p_publicKeyCompressed, p_compressedMode, v_authorization_validation_request) == false) {
        log("*** f_http_build_authorization_validation_request: ERROR: Failed to generate AuthorizationValidationRequest ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
garciay's avatar
garciay committed
      // Secure the Pki 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 ***");
garciay's avatar
garciay committed
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
garciay's avatar
garciay 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);


      /**
         TODO: Load certificate according to the IUT role
         ==> a complete fucntion which set up the TestSustem certificate,keyy... according to the IUT role
       **/
      log("*** f_http_build_inner_ec_request: ERROR: Need to add TestSystem variable vc_aa ***");
      f_selfOrClientSyncAndVerdict("error", e_error);
      /* if (f_build_pki_secured_message(vc_aaPrivateKey, valueof(m_signerIdentifier_digest(vc_aaHashedId8)), vc_eaHashedId8/\*recipientId*\/, v_public_enc_key, v_compressed_enc_key_mode, vc_eaWholeHash, bit2oct(encvalue(m_etsiTs102941Data_authorization_validation_request(v_authorization_validation_request))), p_ieee1609dot2_signed_and_encrypted_data, p_request_hash) == false) { */
garciay's avatar
garciay committed
      /*   log("*** f_http_build_authorization_validation_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***"); */
      /*   f_selfOrClientSyncAndVerdict("error", e_error); */
      /* } */
garciay's avatar
garciay committed
      
      log("*** f_http_build_authorization_validation_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data = ", p_ieee1609dot2_signed_and_encrypted_data);
    } // End of function f_http_build_authorization_validation_request
Yann Garcia's avatar
Yann Garcia committed
    

  group generate_certificates {

    function f_generate_ec_certificate(
                                       in octetstring p_private_key,
                                       in InnerEcRequest p_inner_ec_request,
                                       out Certificate p_ec_certificate
                                       ) return boolean {
      var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
        valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), 
        valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) 
      };
      var template (value) EtsiTs103097Certificate v_cert;
      var bitstring v_tbs;
      var Oct32 v_sig;
      var bitstring v_enc_msg;
      
      v_cert := m_etsiTs103097Certificate(
                                          m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(f_hashWithSha256('616263'O))),
                                          m_toBeSignedCertificate_at(
                                                                     v_appPermissions,
                                                                     m_verificationKeyIndicator_verificationKey(
                                                                                                                m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                                      p_inner_ec_request.publicKeys.verificationKey.ecdsaNistP256
                                                                                                                                                      )),
                                                                     m_validityPeriod(
                                                                                      17469212,
                                                                                      m_duration_years(10)
                                                                                      ),
                                                                     m_geographicRegion_identifiedRegion(
                                                                                                         {
                                                                                                           m_identifiedRegion_country_only(12), 
                                                                                                           m_identifiedRegion_country_only(34)
                                                                                                           }
                                                                                                         )
                                                                     )
                                          );
      // Encode it ==> Get octetstring
      v_tbs := encvalue(v_cert.toBeSigned);
      // Sign the certificate using ECDSA/SHA-256 (NIST p-256)
      v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_tbs), int2oct(11, 32), p_private_key);
      v_cert.signature_ := m_signature_ecdsaNistP256(
                                                     m_ecdsaP256Signature(
                                                                          m_eccP256CurvePoint_x_only(
                                                                                                     substr(v_sig, 0, 32)
                                                                                                     ),
                                                                          substr(v_sig, 32, 32)
                                                                          )
                                                     );
      log("v_cert= ", v_cert);
      
      p_ec_certificate := valueof(v_cert);
      return true;
    } // End of function f_generate_ec_certificate
    
    function f_generate_at_certificate(
                                       in octetstring p_private_key,
                                       in InnerEcRequest p_inner_ec_request,
                                       out Certificate p_at_certificate
                                       ) return boolean {
      var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
        valueof(m_appPermissions(36, { bitmapSsp := '830001'O })), 
        valueof(m_appPermissions(37, { bitmapSsp := '830001'O })) 
      };
      var template (value) EtsiTs103097Certificate v_cert;
      var bitstring v_tbs;
      var Oct32 v_sig;
      var bitstring v_enc_msg;
      
      v_cert := m_etsiTs103097Certificate(
                                          m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(f_hashWithSha256('616263'O))),
                                          m_toBeSignedCertificate_at(
                                                                     v_appPermissions,
                                                                     m_verificationKeyIndicator_verificationKey(
                                                                                                                m_publicVerificationKey_ecdsaNistP256(
                                                                                                                                                      p_inner_ec_request.publicKeys.verificationKey.ecdsaNistP256
                                                                                                                                                      )),
                                                                     m_validityPeriod(
                                                                                      17469212,
                                                                                      m_duration_years(10)
                                                                                      ),
                                                                     m_geographicRegion_identifiedRegion(
                                                                                                         {
                                                                                                           m_identifiedRegion_country_only(12), 
                                                                                                           m_identifiedRegion_country_only(34)
                                                                                                           }
                                                                                                         )
                                                                     )
                                          );
      // Encode it ==> Get octetstring
      v_tbs := encvalue(v_cert.toBeSigned);
      // Sign the certificate using ECDSA/SHA-256 (NIST p-256)
      v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_tbs), int2oct(11, 32), p_private_key);
      v_cert.signature_ := m_signature_ecdsaNistP256(
                                                     m_ecdsaP256Signature(
                                                                          m_eccP256CurvePoint_x_only(
                                                                                                     substr(v_sig, 0, 32)
                                                                                                     ),
                                                                          substr(v_sig, 32, 32)
                                                                          )
                                                     );
      log("v_cert= ", v_cert);
      
      p_at_certificate := valueof(v_cert);
      return true;
    } // End of function f_generate_at_certificate
    
  } // End of group generate_certificates 
Yann Garcia's avatar
Yann Garcia committed
  
  group inner_ec_xxx {
    
garciay's avatar
garciay committed
    function f_generate_inner_ec_request(
                                         out octetstring p_private_key,
                                         out octetstring p_publicKeyCompressed,
garciay's avatar
garciay committed
                                         out integer p_compressedMode,
                                         out InnerEcRequest p_inner_ec_request
                                         ) return boolean {
Yann Garcia's avatar
Yann Garcia committed
      // Local variables
Yann Garcia's avatar
Yann Garcia committed
      var Oct32 v_publicKeyX;
      var Oct32 v_publicKeyY;
      var EccP256CurvePoint v_eccP256_curve_point;

      log (">>> f_generate_inner_ec_request");
Yann Garcia's avatar
Yann Garcia committed
      // Generate keys for the certificate to be requested
Yann Garcia's avatar
Yann Garcia committed
      if (f_generate_key_pair_nistp256(p_private_key, v_publicKeyX, v_publicKeyY, p_publicKeyCompressed, p_compressedMode) == false) {
        log ("f_generate_inner_ec_request: failed to generate keys");
Yann Garcia's avatar
Yann Garcia committed
        return false;
      }
      if (p_compressedMode == 0) {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_publicKeyCompressed));
Yann Garcia's avatar
Yann Garcia committed
      } else {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_publicKeyCompressed));
Yann Garcia's avatar
Yann Garcia committed
      }
      log ("f_generate_inner_ec_request: ", v_eccP256_curve_point);
garciay's avatar
garciay committed
      // Build the Proof of Possession InnerEcRequest
Yann Garcia's avatar
Yann Garcia committed
      p_inner_ec_request := valueof(
                                    m_innerEcRequest(
                                                     PICS_ITS_S_CANONICAL_ID,
Yann Garcia's avatar
Yann Garcia committed
                                                     m_publicKeys(
                                                                  m_publicVerificationKey_ecdsaNistP256(v_eccP256_curve_point)
Yann Garcia's avatar
Yann Garcia committed
                                                                  ),
                                                     m_certificateSubjectAttributes(
                                                                                    { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
                                                                                      valueof(m_appPermissions(623, { bitmapSsp := '00C0'O }))
Yann Garcia's avatar
Yann Garcia committed
                                                                                    },
                                                                                    m_validityPeriod(
                                                                                                     f_getCurrentTime() / 1000,
                                                                                                     m_duration_years(1) // TODO Use PIXIT
Yann Garcia's avatar
Yann Garcia committed
                                                                                    m_geographicRegion_identifiedRegion(
                                                                                                                        {
                                                                                                                          m_identifiedRegion_country_only(12), // TODO Use PIXIT
                                                                                                                          m_identifiedRegion_country_only(34) // TODO Use PIXIT
                                                                                                                          }
                                                                                                                        ),
garciay's avatar
garciay committed
                                                                                    'C0'O // TODO Use PIXIT
      log ("f_generate_inner_ec_request: ", p_inner_ec_request);
Yann Garcia's avatar
Yann Garcia committed
      
      return true;
garciay's avatar
garciay committed
    } // End of function f_generate_inner_ec_request
garciay's avatar
garciay committed
    function f_generate_inner_ec_request_signed_for_pop(
garciay's avatar
garciay committed
                                                        in InnerEcRequest p_inner_ec_request,
                                                        out Ieee1609Dot2Data p_inner_ec_request_signed_for_pop
Yann Garcia's avatar
Yann Garcia committed
    ) return boolean {
      // Local variables
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var octetstring v_encoded_inner_ec_request;
      var template (value) ToBeSignedData v_tbs;
garciay's avatar
garciay committed
      
      // Encode it
      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_ec_request(
                                                              c_its_aid_SCR,
garciay's avatar
garciay committed
                               );
      // Signed the encoded InnerEcRequestSignedForPop
      v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key);
      // Finalyse signed InnerEcRequestSignedForPop
      p_inner_ec_request_signed_for_pop := valueof(
                                                   m_etsiTs103097Data_signed(
                                                                             m_signedData(
                                                                                          sha256,
                                                                                          v_tbs,
                                                                                          m_signerIdentifier_self,
                                                                                          m_signature_ecdsaNistP256(
                                                                                                                    m_ecdsaP256Signature(
                                                                                                                                         m_eccP256CurvePoint_x_only(
                                                                                                                                                                    substr(v_tbs_signed, 0, 32)
                                                                                                                                                                    ),
                                                                                                                                         substr(v_tbs_signed, 32, 32)
                                                                                                                                         )
                                                                                                                    )
                                                                                          )
                                                                             )
                                                   );
      return true;
    } // End of function f_generate_inner_ec_request_signed_for_pop
    
    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
      
      // Build the Proof of Possession InnerEcResponse
      p_inner_ec_response := valueof(
                                     m_innerEcResponse_ok(
                                                          substr(p_inner_ec_request_hash, 0, 16),
                                                          p_certificate
                                                          )
                                     );
      
      return true;
    } // End of function f_generate_inner_ec_response
    
garciay's avatar
garciay committed
  } // End of group inner_ec_xxx

  group inner_at_xxx {

    function f_generate_inner_at_request(
                                         in Certificate p_ec_certificate,
                                         in octetstring p_private_key,
                                         in Certificate p_ea_certificate,
                                         in HashedId8 p_eaHashedId8,
                                         in boolean p_itss_privacy,
                                         out octetstring p_private_enc_key,
                                         out octetstring p_publicEncKeyCompressed,
                                         out integer p_compressedMode,
                                         out InnerAtRequest p_inner_at_request,
                                         out Ieee1609Dot2Data p_inner_at_request_data
                                         ) return boolean {
      // Local variables
Yann Garcia's avatar
Yann Garcia committed
      var octetstring public_enc_key_x;
      var octetstring public_enc_key_y;
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var Oct32 v_hmac_key;
      var octetstring v_message_to_tag;
      var Oct16 v_key_tag;
      var octetstring v_whole_certificate_hash;
      var octetstring v_hash_shared_at_request;
      var template (value) ToBeSignedData v_tbs;
      var octetstring v_tbs_signed;
      var Ieee1609Dot2Data v_signed_ec_signature;
      
      // Generate encryption keys for the certificate to be requested
Yann Garcia's avatar
Yann Garcia committed
      if (f_generate_key_pair_nistp256(p_private_enc_key, public_enc_key_x, public_enc_key_y, p_publicEncKeyCompressed, p_compressedMode) == false) {
        return false;
      }
      if (p_compressedMode == 0) {
        v_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_0(p_publicEncKeyCompressed);
      } else {
        v_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_1(p_publicEncKeyCompressed);
      }
      
      // Generate 32 octets length secret key
garciay's avatar
garciay committed
      v_hmac_key := f_hashWithSha256(int2oct(f_getCurrentTime(), 12));
      log("v_hmac_key=", v_hmac_key);

      // Generate tag based on the concatenation of ???
      if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey)) {
        if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256)) {
          if (ischosen(p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
          v_message_to_tag := '02'O & p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0;
          } else {
          v_message_to_tag := '03'O & p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1;
          }
        } else {
          // TODO
          /* if (ischosen(p_ec_certificate.verifyKeyIndicator.ecdsaBrainpoolP256.compressed_y_0)) { */
          /*   v_message_to_tag := '02'O & p_ec_certificate.verifyKeyIndicator.ecdsaBrainpoolP256.compressed_y_0; */
          /* } else { */
          /*   v_message_to_tag := '03'O & p_ec_certificate.verifyKeyIndicator.ecdsaBrainpoolP256.compressed_y_1; */
          /* } */
        }
      } else {
        return false;
      }
      if (p_compressedMode == 0) {
        v_message_to_tag := v_message_to_tag & '02'O & p_publicEncKeyCompressed;
      } else {
        v_message_to_tag := v_message_to_tag & '03'O & p_publicEncKeyCompressed;
      }
      log("v_message_to_tag=", v_message_to_tag);
Yann Garcia's avatar
Yann Garcia committed
      v_key_tag := fx_hmac_sha256(v_hmac_key, v_message_to_tag); // TODO Rename and use a wrapper function
      log("v_key_tag=", v_key_tag);

      // Build the SharedAtRequest
      p_inner_at_request.publicKeys := valueof(
                                               m_publicKeys(
                                                            m_publicVerificationKey_ecdsaNistP256(
                                                                                                  p_ec_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256
                                                                                                  ),
                                                            m_encryptionKey(
                                                                            -,
                                                                            m_publicEncryptionKey_ecdsaNistP256(v_eccP256_curve_point)
                                                                            )
                                                            )
                                               );
      p_inner_at_request.hmacKey := v_hmac_key;
      p_inner_at_request.sharedAtRequest  := valueof(
                                                     m_shared_at_request(
                                                                         p_eaHashedId8,
                                                                         v_key_tag,
                                                                         valueof(
                                                                                 m_certificate_subject_attributes( // FIXME Review subjectPermissions
                                                                                                                  p_ec_certificate.toBeSigned.appPermissions,
                                                                                                                  { { subjectPermissions := { all_ := NULL }, minChainLength := 1, chainLengthRange   := 0, eeType := '00000000'B } },
                                                                                                                  p_ec_certificate.toBeSigned.id,
                                                                                                                  p_ec_certificate.toBeSigned.validityPeriod,
                                                                                                                  p_ec_certificate.toBeSigned.region,
                                                                                                                  p_ec_certificate.toBeSigned.assuranceLevel
                                                                                                                  ))));
      v_hash_shared_at_request := f_hashWithSha256(bit2oct(encvalue(p_inner_at_request.sharedAtRequest)));
      log("v_hash_shared_at_request=", v_hash_shared_at_request);
      // Build the ToBeSigned payload
      v_tbs := m_toBeSignedData(
                                m_signedDataPayload_ext(v_hash_shared_at_request),
                                m_headerInfo_inner_ec_request(
                                                              c_its_aid_SCR,
                                                              f_getCurrentTimeUtc())
                               );
garciay's avatar
garciay committed
      log("v_tbs=", v_tbs);
      // Signed ToBeSigned payload
      v_whole_certificate_hash := f_hashWithSha256(bit2oct(encvalue(p_ec_certificate)));
garciay's avatar
garciay committed
      log("v_whole_certificate_hash=", v_whole_certificate_hash);
      v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_whole_certificate_hash, p_private_key);
      v_signed_ec_signature := valueof(
                                       m_etsiTs103097Data_signed(
                                                                 m_signedData(
                                                                              sha256,
                                                                              v_tbs,
                                                                              m_signerIdentifier_digest(
                                                                                                        f_HashedId8FromSha256(
                                                                                                                              v_whole_certificate_hash
                                                                                                                              )
                                                                                                        ),
                                                                              m_signature_ecdsaNistP256(
                                                                                                        m_ecdsaP256Signature(
                                                                                                                             m_eccP256CurvePoint_x_only(
                                                                                                                                                        substr(v_tbs_signed, 0, 32)
                                                                                                                                                        ),
                                                                                                                             substr(v_tbs_signed, 32, 32)
                                                                                                                             )
                                                                                                        )
                                                                              )
                                                                 )
                                       );
      // Encrypt EcSignature with EA certificate
      if (p_itss_privacy) {
        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_publicEphemeralKeyCompressed;
        var integer v_ephemeralKeyModeCompressed;
        var octetstring v_enc_signed_ec_signature;
        
garciay's avatar
garciay committed
        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 {
          return false;
        }
        v_enc_signed_ec_signature := f_encryptWithEciesNistp256WithSha256(bit2oct(encvalue(v_signed_ec_signature)), v_public_enc_key, v_compressed_mode, ''O, v_publicEphemeralKeyCompressed, v_ephemeralKeyModeCompressed, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce);
        v_recipientId := p_eaHashedId8;
        log("v_recipientId=", v_recipientId);
        // Fill Certificate template with the public compressed keys (canonical form)
        if (v_ephemeralKeyModeCompressed == 0) {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_publicEphemeralKeyCompressed));
        } else {
          v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_publicEphemeralKeyCompressed));
        }
        p_inner_at_request.ecSignature := valueof(
                                                  m_ec_signature(
                                                                 m_etsiTs103097Data_encrypted(
                                                                                              m_encryptedData(
                                                                                                              {
                                                                                                                m_recipientInfo_signedDataRecipInfo(
                                                                                                                                                    m_pKRecipientInfo(
                                                                                                                                                                      v_recipientId,
                                                                                                                                                                      m_encryptedDataEncryptionKey_eciesNistP256(
                                                                                                                                                                                                                 m_evciesP256EncryptedKey(
                                                                                                                                                                                                                                          v_eccP256_curve_point,
                                                                                                                                                                                                                                          v_encrypted_sym_key, 
                                                                                                                                                                                                                                          v_authentication_vector
                                                                                                                                                                                                                                          ))))
                                                                                                                },
                                                                                                              m_SymmetricCiphertext_aes128ccm(
                                                                                                                                              m_aesCcmCiphertext(
                                                                                                                                                                 v_nonce, 
                                                                                                                                                                 v_enc_signed_ec_signature
                                                                                                                                                                 )
                                                                                                                                              )
                                                                                                              )
                                                                               )
                                                                 )
                                                  );
      } else {
        p_inner_at_request.ecSignature := valueof(m_ec_signature_ext_payload(v_signed_ec_signature));
      }
      log("p_inner_at_request=", p_inner_at_request);
      
      return true;
    } // End of function f_generate_inner_at_request
    
    function f_generate_inner_at_response(
                                          in Certificate p_ec_certificate,
                                          in octetstring p_private_key,
                                          in HashedId8 p_eaHashedId8,
                                          out octetstring p_private_enc_key,
                                          out octetstring p_publicEncKeyX,
                                          out octetstring p_publicEncKeyY,
                                          out octetstring p_publicEncKeyCompressed,
                                          out integer p_compressedMode,
                                          out InnerAtRequest p_inner_at_request,
                                          out Ieee1609Dot2Data p_inner_at_request_data
                                          ) return boolean {
      // Local variables
      return false;
    } // End of function f_generate_inner_at_response
    
  } // End of group inner_at_xxx
  
  group authorization_xxx {
    
    function f_generate_authorization_request(
                                              in Certificate p_ea_certificate,
                                              in HashedId8 p_ea_certificate_hashed_id8,
                                              out octetstring p_private_key,
                                              out octetstring p_publicKeyCompressed,
                                              out integer p_compressedMode,
                                              out InnerAtRequest p_authorization_request
                                              ) return boolean {
      // Local variables
      var octetstring v_private_enc_key;
      var Oct32 v_publicEncKeyCompressed;
      var integer v_compressedMode;
      var InnerEcRequest v_inner_ec_request;
      var Certificate v_ec_certificate;
      var InnerAtRequest v_inner_at_request;
      var Ieee1609Dot2Data v_inner_at_request_data;
      
      if (f_generate_inner_ec_request(p_private_key, p_publicKeyCompressed, p_compressedMode, v_inner_ec_request) == false) {
        return false;
      }
      if (f_generate_ec_certificate(p_private_key, v_inner_ec_request, v_ec_certificate) == false) {
        return false;
      }
      if (f_generate_inner_at_request(v_ec_certificate, p_private_key, p_ea_certificate, p_ea_certificate_hashed_id8, true, v_private_enc_key, v_publicEncKeyCompressed, v_compressedMode, v_inner_at_request, v_inner_at_request_data) == false) {
        return false;
      }
      
      p_authorization_request.sharedAtRequest := v_inner_at_request.sharedAtRequest;
      p_authorization_request.ecSignature := v_inner_at_request.ecSignature;
      
      log("f_generate_authorization_request: ", p_authorization_request);
      
      return true;
    } // End of function f_generate_authorization_request
    
    function f_generate_authorization_response(
                                               in octetstring p_authorization_request_hash,
                                               in CertificateSubjectAttributes p_Certificate_subject_attributes,
                                               out InnerAtResponse p_authorization_response
                                               ) return boolean {
      // Local variables
      
      // Build the Proof of Possession InnerAtResponse
      /*p_authorization_response := valueof(
                                          m_innerAtResponse_ok(
                                                               p_authorization_request_hash,
                                                               p_Certificate_subject_attributes
                                                               )
                                                               );*/
      
      return true;
    } // End of function f_generate_authorization_response
    
  } // End of group authorization_xxx
  
  group authorization_validation_xxx {
    
    function f_generate_authorization_validation_request(
garciay's avatar
garciay committed
                                                         in Certificate p_ea_certificate,
                                                         in HashedId8 p_ea_certificate_hashed_id8,
                                                         out octetstring p_private_key,
                                                         out octetstring p_publicKeyCompressed,
                                                         out integer p_compressedMode,
                                                         out AuthorizationValidationRequest p_authorization_validation_request
                                                         ) return boolean {
garciay's avatar
garciay committed
      // Local variables
      var octetstring v_private_enc_key;
      var Oct32 v_publicEncKeyCompressed;
      var integer v_compressedMode;
      var InnerEcRequest v_inner_ec_request;
      var Certificate v_ec_certificate;
      var InnerAtRequest v_inner_at_request;
      var Ieee1609Dot2Data v_inner_at_request_data;
      
      if (f_generate_inner_ec_request(p_private_key, p_publicKeyCompressed, p_compressedMode, v_inner_ec_request) == false) {
        return false;
      }
      if (f_generate_ec_certificate(p_private_key, v_inner_ec_request, v_ec_certificate) == false) {
        return false;
      }
      if (f_generate_inner_at_request(v_ec_certificate, p_private_key, p_ea_certificate, p_ea_certificate_hashed_id8, true, v_private_enc_key, v_publicEncKeyCompressed, v_compressedMode, v_inner_at_request, v_inner_at_request_data) == false) {
        return false;
      }
      
      p_authorization_validation_request.sharedAtRequest := v_inner_at_request.sharedAtRequest;
      p_authorization_validation_request.ecSignature := v_inner_at_request.ecSignature;
      
      log("f_generate_authorization_validation_request: ", p_authorization_validation_request);
Yann Garcia's avatar
Yann Garcia committed
      
      return true;
    } // End of function f_generate_authorization_validation_request
    
    function f_generate_authorization_validation_response(
                                                          in octetstring p_authorization_validation_request_hash,
                                                          in CertificateSubjectAttributes p_Certificate_subject_attributes,
Yann Garcia's avatar
Yann Garcia committed
                                                          out AuthorizationValidationResponse p_authorization_validation_response
                                                          ) return boolean {
      // Local variables
      
      // Build the Proof of Possession InnerEcResponse
      p_authorization_validation_response := valueof(
                                                     m_authorizationValidationResponse_ok(
                                                                                          substr(p_authorization_validation_request_hash, 0, 16),
                                                                                          p_Certificate_subject_attributes
                                                                                          )
                                                     );
      
      return true;
    } // End of function f_generate_authorization_validation_response
    
  } // End of group authorization_validation_xxx
  
garciay's avatar
garciay committed
  group pki_functions {
    /**
     * @desc Build a signed and encrypted PKI 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_publicKeyCompressed The public compressed key (canonical form) for encryption
     * @param p_compressedMode      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
     */
garciay's avatar
garciay committed
    function f_build_pki_secured_message(
                                         in octetstring p_private_key,
                                         in SignerIdentifier p_signer_identifier,
                                         in HashedId8 p_recipientId,
                                         in octetstring p_publicKeyCompressed,
garciay's avatar
garciay committed
                                         in integer p_compressedMode,
                                         in octetstring p_pki_message,
                                         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
garciay's avatar
garciay committed
                                         ) return boolean {
      // Local variables
      var template (value) EccP256CurvePoint v_eccP256_curve_point;
      var template (value) ToBeSignedData v_tbs;
Yann Garcia's avatar
Yann Garcia committed
      var template (value) Ieee1609Dot2Data v_ieee1609dot2_signed_data;
garciay's avatar
garciay committed
      var octetstring v_encoded_inner_ec_request;
      var octetstring v_publicEphemeralKeyCompressed;
Yann Garcia's avatar
Yann Garcia committed
      var integer v_ephemeralKeyModeCompressed;
      var octetstring v_encrypted_inner_ec_request;
      // Signed the encoded PKI message
Yann Garcia's avatar
Yann Garcia committed
      v_tbs := m_toBeSignedData(
                                m_signedDataPayload(
garciay's avatar
garciay committed
                                                    m_etsiTs103097Data_unsecured(p_pki_message)
Yann Garcia's avatar
Yann Garcia committed
                                                   ),
                                m_headerInfo_inner_ec_request(c_its_aid_SCR, f_getCurrentTimeUtc())
Yann Garcia's avatar
Yann Garcia committed
                               );
      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 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_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_hash, p_private_key);
      }
      // Add the signature and create EtsiTs103097Data-Signed data structure
Yann Garcia's avatar
Yann Garcia committed
      v_ieee1609dot2_signed_data := m_etsiTs103097Data_signed(
                                                              m_signedData(
                                                                           sha256,
                                                                           v_tbs,
Yann Garcia's avatar
Yann Garcia committed
                                                                           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
Yann Garcia's avatar
Yann Garcia committed
      v_encoded_inner_ec_request := bit2oct(encvalue(v_ieee1609dot2_signed_data));
      // Calculate the SHA256 of v_encoded_inner_ec_request
      p_request_hash := f_hashWithSha256(v_encoded_inner_ec_request);
      log("p_request_hash= ", p_request_hash);
      // Encrypt encode EtsiTs103097Data-Signed data structure
      if (PICS_SEC_FIXED_KEYS) {
        p_publicKeyCompressed := '8C5E20FE31935F6FA682A1F6D46E4468534FFEA1A698B14B0B12513EED8DEB11'O;
        p_compressedMode := 0;
        p_salt := '9169155B08B07674CBADF75FB46A7B0D'O;
      }
      v_encrypted_inner_ec_request := f_encryptWithEciesNistp256WithSha256(v_encoded_inner_ec_request, p_publicKeyCompressed, p_compressedMode, p_salt, v_publicEphemeralKeyCompressed, v_ephemeralKeyModeCompressed, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, PICS_SEC_FIXED_KEYS);
      log("p_aes_sym_key=", p_aes_sym_key);
      log("p_encrypted_sym_key=", p_encrypted_sym_key);
      log("p_authentication_vector=", p_authentication_vector);
      log("p_nonce=", p_nonce);
      log("p_recipientId=", p_recipientId);
      if (p_recipientId == int2oct(0, 8)) {
        log("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("v_recipientId=", v_recipientId);
Yann Garcia's avatar
Yann Garcia committed
      // Fill Certificate template with the public compressed keys (canonical form)
      if (v_ephemeralKeyModeCompressed == 0) {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_publicEphemeralKeyCompressed));
      } else {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_publicEphemeralKeyCompressed));
      }
      p_ieee1609dot2_signed_and_encrypted_data := valueof(
                                                          m_etsiTs103097Data_encrypted(
                                                                                       m_encryptedData(
                                                                                                       {
                                                                                                        m_recipientInfo_signedDataRecipInfo(
                                                                                                                                            m_pKRecipientInfo(
                                                                                                                                                              v_recipientId,
                                                                                                                                                              m_encryptedDataEncryptionKey_eciesNistP256(
                                                                                                                                                                                                      m_evciesP256EncryptedKey(
                                                                                                                                                                                                                               v_eccP256_curve_point,
                                                                                                                                                                                                                               p_encrypted_sym_key, 
                                                                                                                                                                                                                               p_authentication_vector
Yann Garcia's avatar
Yann Garcia committed
                                                                                                        ))))
                                                                                                       },
                                                                                                       m_SymmetricCiphertext_aes128ccm(
                                                                                                                                       m_aesCcmCiphertext(
Yann Garcia's avatar
Yann Garcia committed
                                                                                                                                                          v_encrypted_inner_ec_request
                                                                                                                                                         )
                                                                                                                                      )
                                                                                                      )
                                                                                       )
                                                         );
      
      return true;
garciay's avatar
garciay committed
    } // End of function f_build_pki_secured_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_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_etsi_ts_102941_data The EtsiTs102941Data message
     * @return true on success, false otherwise
     */
                                  in octetstring p_private_enc_key,
                                  in Oct16 p_aes_sym_key,
                                  in Oct16 p_authentication_vector, // TODO Tobe removed
                                  in Certificate p_certificate, // TODO Tobe removed
                                  in Ieee1609Dot2Data p_ieee1609dot2_encrypted_and_signed_data,
                                  in boolean p_check_security := true,
                                  out EtsiTs102941Data p_etsi_ts_102941_data
                                  ) return boolean {
garciay's avatar
garciay committed
      // 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 bitstring v_etsi_ts_102941_data_msg;
      var bitstring v_tbs;
      var boolean v_ret;
      
      log(">>> f_verify_pki_message: p_private_enc_key= ", p_private_enc_key);
      log(">>> f_verify_pki_message: p_aes_sym_key=", p_aes_sym_key);
      log(">>> f_verify_pki_message: p_authentication_vector=", p_authentication_vector);
      log(">>> f_verify_pki_message: p_issuer=", p_issuer);
      
      // TODO Check p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.recipients[0].pskRecipInfo. See IEEE Std 1609.2-2017 Clause 6.3.34 PreSharedKeyRecipientInfo
      
Yann Garcia's avatar
Yann Garcia committed
      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("v_plain_message= ", v_plain_message);

      // 2. Decode it
      v_tbs := oct2bit(v_plain_message);
      if (decvalue(v_tbs, v_ieee1609dot2_signed_data) != 0) {
      }
      log("v_ieee1609dot2_signed_data= ", v_ieee1609dot2_signed_data);
      
      // 3. Check the signature
      log("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) == false) {
        if (p_check_security == true) {
          return false;
        }
      }
      //log("v_certificate= ", v_certificate);
      if (ischosen(v_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
        v_ret := f_verifyWithEcdsaNistp256WithSha256(
                                                     bit2oct(v_tbs),
                                                     p_issuer,
                                                     v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only & v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.sSig,
                                                     v_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0,
                                                     0);
      } else {
        v_ret := f_verifyWithEcdsaNistp256WithSha256(
                                                     bit2oct(v_tbs),
                                                     p_issuer,
                                                     v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only & v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.sSig,
                                                     v_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1,
garciay's avatar
garciay committed
      if (v_ret == false) {
        if (p_check_security == true) {
          return false;
        }
      // 4. Return the PKI message
      log("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;
      }

garciay's avatar
garciay committed
      if (p_etsi_ts_102941_data.version != PkiProtocolVersion) {
        if (p_check_security == true) {
          return false;
        }
garciay's avatar
garciay committed
      
      return true;
    } // End of function f_verify_pki_message
    
    /**
     * @desc Verify the generated EA certificate 
     * @param p_ea_certificate      The new EA certificate
     * @param p_publicKeyCompressed The public compressed key (canonical form) for signature check
     * @param p_compressedMode      The public compressed key mode
     * @return true on success, false otherwise
     */
    function f_verify_ea_certificate(
                                     in Certificate p_ea_certificate,
                                     in octetstring p_publicKeyCompressed,
                                     in integer p_compressedMode
                                     ) return boolean {
      var bitstring v_encoded_tbs;
      var boolean v_result;
      
      // Check certificate format
      v_result := match(p_ea_certificate, mw_etsiTs103097Certificate(mw_issuerIdentifier_self, mw_toBeSignedCertificate_ea, -));
      // Check the signer
      
      // Check EA certificate signature
      v_encoded_tbs := encvalue(p_ea_certificate.toBeSigned);
      v_result := v_result and f_verifyWithEcdsaNistp256WithSha256(
                                                                   bit2oct(v_encoded_tbs),
                                                                   int2oct(0, 32), // self
                                                                   p_ea_certificate.signature_.ecdsaNistP256Signature.rSig.x_only & p_ea_certificate.signature_.ecdsaNistP256Signature.sSig,
                                                                   p_publicKeyCompressed, 
                                                                   p_compressedMode);
      
      return v_result;
    } // End of function f_verify_ea_certificate
    
    /**
     * @desc Verify the generated AA certificate 
     * @param p_aa_certificate      The new EA certificate
     * @param p_publicKeyCompressed The public compressed key (canonical form) for signature check
     * @param p_compressedMode      The public compressed key mode
     * @return true on success, false otherwise
     */
    function f_verify_aa_certificate(
                                     in Certificate p_aa_certificate,
                                     in octetstring p_publicKeyCompressed,
                                     in integer p_compressedMode
                                     ) return boolean {
      var bitstring v_encoded_tbs;
      var boolean v_result;
      
      // Check certificate format
      v_result := match(p_aa_certificate, mw_etsiTs103097Certificate(mw_issuerIdentifier_self, mw_toBeSignedCertificate_aa, -));
      // Check the signer
      
      // Check EA certificate signature
      v_encoded_tbs := encvalue(p_aa_certificate.toBeSigned);
      v_result := v_result and f_verifyWithEcdsaNistp256WithSha256(
                                                                   bit2oct(v_encoded_tbs),
                                                                   int2oct(0, 32), // self
                                                                   p_aa_certificate.signature_.ecdsaNistP256Signature.rSig.x_only & p_aa_certificate.signature_.ecdsaNistP256Signature.sSig,
                                                                   p_publicKeyCompressed, 
                                                                   p_compressedMode);
      
      return v_result;
    } // End of function f_verify_aa_certificate
    
Yann Garcia's avatar
Yann Garcia committed
  } // End of group inner_ec_xxx
garciay's avatar
garciay committed

  group security_function { // TODO To be moved in LibItsSecurity_Function module

    function f_extract_enc_key(
                               in Certificate p_certificate,
                               out octetstring p_public_enc_key,
                               out integer p_compressed_enc_key_mode
                               ) return boolean {
      if (ischosen(p_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256)) {
        if (ischosen(p_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0)) {
        p_public_enc_key := p_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0;
        p_compressed_enc_key_mode := 0;
        } else if (ischosen(p_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1)) {
        p_public_enc_key := p_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1;
        p_compressed_enc_key_mode := 1;
        } else {
          log("f_extract_enc_key: Non canonical EA certificate");
          return false;
        }
      } else if (ischosen(p_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1)) {
        if (ischosen(p_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0)) {
        p_public_enc_key := p_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0;
        p_compressed_enc_key_mode := 0;
        } else if (ischosen(p_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1)) {
          p_public_enc_key := p_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1;
          p_compressed_enc_key_mode := 0;
        } else {
          log("f_extract_enc_key: Non canonical EA certificate");
          return false;
        }
      } else {
        log("f_extract_enc_key: Invalid EA certificate");
        return false;
      }

      return true;
    } // End of function f_extract_enc_key
    
  } // End of group security_function
  group altstes {
    
    altstep a_default_pki_http() runs on ItsPkiHttp {
      [] httpPort.receive( 
                          mw_http_response(
                                           mw_http_response_ko
                                           )) {
        tc_ac.stop;
        log("*** a_default: ERROR: HTTP Server error ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] httpPort.receive(mw_http_request) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Request received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] httpPort.receive(mw_http_response) {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP Response received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
      [] httpPort.receive {
        tc_ac.stop;
        log("*** a_default: ERROR: Unexpected HTTP message received ***");
        f_selfOrClientSyncAndVerdict("error", e_error);
      }
    }
  }
  
Yann Garcia's avatar
Yann Garcia committed
} // End of module LibItsPki_Functions