LibItsPki_Functions.ttcn 81.2 KB
Newer Older
        var charstring v_certificate_id;
        var octetstring v_hash;
        fx_readCertificateFromDigest(p_signer_identifier.digest, v_certificate_id); // TODO Add a wrapper function
        f_getCertificateHash(v_certificate_id, v_hash);
        v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_hash, p_private_key);
      }
      // Add the signature and create EtsiTs103097Data-Signed data structure
Yann Garcia's avatar
Yann Garcia committed
      v_ieee1609dot2_signed_data := m_etsiTs103097Data_signed(
                                                              m_signedData(
                                                                           sha256,
                                                                           v_tbs,
Yann Garcia's avatar
Yann Garcia committed
                                                                           m_signature_ecdsaNistP256(
                                                                                                     m_ecdsaP256Signature(
                                                                                                                          m_eccP256CurvePoint_x_only(
                                                                                                                                                     substr(v_tbs_signed, 0, 32)
                                                                                                                                                     ),
                                                                                                                          substr(v_tbs_signed, 32, 32)
                                                                                                                          )
                                                                                                     )
                                                                           )
                                                      );
      // Encode EtsiTs103097Data-Signed data structure
Yann Garcia's avatar
Yann Garcia committed
      v_encoded_inner_ec_request := bit2oct(encvalue(v_ieee1609dot2_signed_data));
      // Encrypt encode EtsiTs103097Data-Signed data structure
      if (PICS_SEC_FIXED_KEYS) {
        p_publicKeyCompressed := '8C5E20FE31935F6FA682A1F6D46E4468534FFEA1A698B14B0B12513EED8DEB11'O;
        p_compressedMode := 0;
        p_salt := '9169155B08B07674CBADF75FB46A7B0D'O;
      }
      v_encrypted_inner_ec_request := f_encryptWithEciesNistp256WithSha256(v_encoded_inner_ec_request, p_publicKeyCompressed, p_compressedMode, p_salt, v_publicEphemeralKeyCompressed, v_ephemeralKeyModeCompressed, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, PICS_SEC_FIXED_KEYS);
      log("p_aes_sym_key=", p_aes_sym_key);
      log("p_encrypted_sym_key=", p_encrypted_sym_key);
      log("p_authentication_vector=", p_authentication_vector);
      log("p_nonce=", p_nonce);
      log("p_recipientId=", p_recipientId);
      if (p_recipientId == int2oct(0, 8)) {
        log("f_hashWithSha256(v_encrypted_sym_key)=", f_hashWithSha256(p_encrypted_sym_key));
        v_recipientId := f_HashedId8FromSha256(f_hashWithSha256(p_encrypted_sym_key));
      } else {
        v_recipientId := p_recipientId;
      }
      log("v_recipientId=", v_recipientId);
Yann Garcia's avatar
Yann Garcia committed
      // Fill Certificate template with the public compressed keys (canonical form)
      if (v_ephemeralKeyModeCompressed == 0) {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_publicEphemeralKeyCompressed));
      } else {
        v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_publicEphemeralKeyCompressed));
      }
      p_ieee1609dot2_signed_and_encrypted_data := valueof(
                                                          m_etsiTs103097Data_encrypted(
                                                                                       m_encryptedData(
                                                                                                       {
                                                                                                        m_recipientInfo_signedDataRecipInfo(
                                                                                                                                            m_pKRecipientInfo(
                                                                                                                                                              v_recipientId,
                                                                                                                                                              m_encryptedDataEncryptionKey_eciesNistP256(
                                                                                                                                                                                                      m_evciesP256EncryptedKey(
                                                                                                                                                                                                                               v_eccP256_curve_point,
                                                                                                                                                                                                                               p_encrypted_sym_key, 
                                                                                                                                                                                                                               p_authentication_vector
Yann Garcia's avatar
Yann Garcia committed
                                                                                                        ))))
                                                                                                       },
                                                                                                       m_SymmetricCiphertext_aes128ccm(
                                                                                                                                       m_aesCcmCiphertext(
Yann Garcia's avatar
Yann Garcia committed
                                                                                                                                                          v_encrypted_inner_ec_request
                                                                                                                                                         )
                                                                                                                                      )
                                                                                                      )
                                                                                       )
                                                         );
      
      return true;
garciay's avatar
garciay committed
    } // End of function f_build_pki_secured_message
    
    /**
     * @desc Verify the protocol element of the Pki message 
     * @param p_private_key         Private key for decryption
     * @param p_publicEphemeralCompressedKey
     * @param p_publicEphemeralCompressedKeyMode
     * @param p_issuer              Issuer
     * @param p_certificate         Certificate to use for verification key
     * @param p_ieee1609dot2_encrypted_and_signed_data The received encrypted and signed data
     * @param p_check_security      Set to true to check signatures
     * @param p_etsi_ts_102941_data The EtsiTs102941Data message
     * @return true on success, false otherwise
     */
                                  in octetstring p_private_enc_key,
                                  //                                  in octetstring p_publicEphemeralCompressedKey, // TODO Useless, to be removed
                                  //                                  in integer p_publicEphemeralCompressedKeyMode, // TODO Useless, to be removed
                                  in Oct16 p_aes_sym_key,
                                  in Oct16 p_authentication_vector, // TODO Tobe removed
                                  //                                  in Oct12 p_nonce,                 // TODO Tobe removed
                                  //                                  in octetstring p_salt,
                                  in Certificate p_certificate, // TODO Tobe removed
                                  in Ieee1609Dot2Data p_ieee1609dot2_encrypted_and_signed_data,
                                  in boolean p_check_security := true,
                                  out EtsiTs102941Data p_etsi_ts_102941_data
                                  ) return boolean {
garciay's avatar
garciay committed
      // Local variables
      var octetstring v_public_enc_key;
      var integer v_compressed_enc_key_mode;
      var octetstring v_plain_message;
      var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
      var Certificate v_certificate;
      var bitstring v_etsi_ts_102941_data_msg;
      var bitstring v_tbs;
      var boolean v_ret;
      
      log(">>> f_verify_pki_message: p_private_enc_key= ", p_private_enc_key);
      log(">>> f_verify_pki_message: p_aes_sym_key=", p_aes_sym_key);
      log(">>> f_verify_pki_message: p_authentication_vector=", p_authentication_vector);
      log(">>> f_verify_pki_message: p_issuer=", p_issuer);
      
      // TODO Check p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.recipients[0].pskRecipInfo. See IEEE Std 1609.2-2017 Clause 6.3.34 PreSharedKeyRecipientInfo
      
      v_plain_message := fx_test_decrypt_aes_128_ccm_test(p_aes_sym_key, p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.ciphertext.aes128ccm.nonce, p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.ciphertext.aes128ccm.ccmCiphertext);
      if (isbound(v_plain_message) == false) {
        return false;
      }
      log("v_plain_message= ", v_plain_message);

      // 2. Decode it
      v_tbs := oct2bit(v_plain_message);
      if (decvalue(v_tbs, v_ieee1609dot2_signed_data) != 0) {
garciay's avatar
garciay committed
        if (p_check_security == true) {
          return false;
        }
      }
      log("v_ieee1609dot2_signed_data= ", v_ieee1609dot2_signed_data);
      
      // 3. Check the signature
      log("v_ieee1609dot2_signed_data.content.signedData.tbsData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData);
      v_tbs := encvalue(v_ieee1609dot2_signed_data.content.signedData.tbsData);
      if (f_getCertificateFromDigest(v_ieee1609dot2_signed_data.content.signedData.signer.digest, v_certificate) == false) {
        if (p_check_security == true) {
          return false;
        }
      }
      log("v_certificate= ", v_certificate);
      if (ischosen(v_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0)) {
        v_ret := f_verifyWithEcdsaNistp256WithSha256(
                                                     bit2oct(v_tbs),
                                                     p_issuer,
                                                     v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only & v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.sSig,
                                                     v_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_0,
                                                     0);
      } else {
        v_ret := f_verifyWithEcdsaNistp256WithSha256(
                                                     bit2oct(v_tbs),
                                                     p_issuer,
                                                     v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only & v_ieee1609dot2_signed_data.content.signedData.signature_.ecdsaNistP256Signature.sSig,
                                                     v_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256.compressed_y_1,
garciay's avatar
garciay committed
      if (v_ret == false) {
        if (p_check_security == true) {
          return false;
        }
      // 4. Return the PKI message
      log("v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      v_etsi_ts_102941_data_msg := oct2bit(v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
      if (decvalue(v_etsi_ts_102941_data_msg, p_etsi_ts_102941_data) != 0) {
        return false;
      }

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

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

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

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