LibItsPki_Functions.ttcn 425 KB
Newer Older
                                        in HashedId8 p_requestHash,
                                        out RaEeCertInfo p_ra_ee_cert_info
                                        ) runs on ItsPkiHttp return boolean {
      log(">>> f_generate_ra_ee_cert_info: p_ee_ra_cert_request: ", p_ee_ra_cert_request);

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

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

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

      return true;
    } // End of function f_generate_ra_ee_cert_info

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

      return true
    } // End of function f_generate_ee_ra_download_request

  } // End of group bfk

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

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

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

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

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

      return true;
    }

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

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

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

      return true;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  } // End of group dc

  group ctl {

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

      log(">>> f_build_ctl");

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

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

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

      log(">>> f_sign_dc_ctl");

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

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

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

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

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

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

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

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

      return true;
    } // End of function f_verify_ctl_entry

  } // End of group ctl

  group crl {

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

      log(">>> f_build_crl");

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

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

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

      log(">>> f_sign_dc_crl");

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

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

  } // End of group crl

  group tlm {

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

      log(">>> f_build_tlm");

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

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

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

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

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

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

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

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

      // 1. Verify signature