LibItsPki_Functions.ttcn 425 KB
Newer Older
ASN.1 Documenter's avatar
ASN.1 Documenter committed
      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
      template (present) HttpMessage mw_http_ec_request_generic (
                                                                  template (present) Ieee1609Dot2Data p_ieee1609dot2_data := mw_enrolmentRequestMessage(mw_encryptedData())
                                                                ) := 
        mw_http_request(
                  mw_http_request_post(
                          PICS_HTTP_POST_URI_EC,
                          -,
                          mw_http_message_body_binary(
                                  mw_binary_body_ieee1609dot2_data( p_ieee1609dot2_data)
                                            
      )));
    } // 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");