Newer
Older
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
var charstring v_certificate_id;
var Oct32 v_issuer;
var EtsiTs102941Data v_etsi_ts_102941_data;
log(">>> f_verify_rca_crl_response_message: p_ieee1609dot2_signed_data= ", p_ieee1609dot2_signed_data);
// 1. Verify signature
log("f_verify_rca_crl_response_message: p_ieee1609dot2_signed_data.content.signedData.tbsData= ", p_ieee1609dot2_signed_data.content.signedData.tbsData);
v_tbs := encvalue(p_ieee1609dot2_signed_data.content.signedData.tbsData);
if (f_getCertificateFromDigest(p_ieee1609dot2_signed_data.content.signedData.signer.digest, v_certificate, v_certificate_id) == false) {
if (p_check_security == true) {
return false;
}
}
f_getCertificateHash256(v_certificate_id, v_issuer);
if (f_verifyEcdsa(bit2oct(v_tbs), v_issuer, p_ieee1609dot2_signed_data.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
if (p_check_security == true) {
return false;
}
}
v_etsi_ts_102941_data_msg := oct2bit(p_ieee1609dot2_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() / 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;
}
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
}
}
return true;
}
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 inavlid entries");
return false;
}
}
} // End of 'for' statements
return true;
}
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
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;
}
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
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");
return false;
} else {
if (f_verify_ectl_entry(v_ectl_command.add) == false) {
log("f_verify_full_ectl: ctlCommands contains inavlid entries");
return false;
}
}
} // End of 'for' statements
return true;
}
function f_verify_ctl_entry(
in CtlEntry p_ctl_entry
) return boolean {
if (ischosen(p_ctl_entry.rca)) {
if (match(p_ctl_entry.rca, mw_root_ca_entry(mw_etsiTs103097Certificate)) == false) {
return false;
}
} else if (ischosen(p_ctl_entry.ea)) {
if (match(p_ctl_entry.ea, mw_ea_entry(mw_etsiTs103097Certificate)) == false) {
return false;
}
} else if (ischosen(p_ctl_entry.aa)) {
if (match(p_ctl_entry.aa, mw_aa_entry(mw_etsiTs103097Certificate)) == false) {
return false;
}
} else if (ischosen(p_ctl_entry.dc)) {
if (match(p_ctl_entry.dc, mw_dc_entry) == false) {
return false;
}
} else {
return false;
}
return true;
}
function f_verify_ectl_entry(
in CtlEntry p_ctl_entry
) return boolean {
if (ischosen(p_ctl_entry.tlm)) {
if (match(p_ctl_entry.tlm, mw_tlm_entry(mw_etsiTs103097Certificate)) == false) {
return false;
}
} else {
return false;
}
return true;
}
} // End of group rca
group awaiting_messages {
function f_await_http_inner_ec_request_response(
out Oct32 p_private_key,
out Oct32 p_compressed_public_key,
out integer p_compressed_mode,
out InnerEcResponse p_inner_ec_response,
in boolean p_strict_checks := true
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, 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);
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
)))));
[] 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
)))))),
v_response
) {
if (f_verify_pki_response_message(p_private_key, 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) {
log("f_await_http_inner_ec_request_response: Failed to verify PKI message ***");
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(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;
}
}
Yann Garcia
committed
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, p_compressed_public_key, p_compressed_mode) == false) {
log("f_await_http_inner_ec_request_response: Cannot verify EC certificate signature ***");
if (p_strict_checks) {
return false;
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("p_inner_ec_response= ", p_inner_ec_response);
} 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
} // End of function f_await_http_inner_ec_request_response
function f_await_ec_request_send_response(
out InnerEcResponse p_inner_ec_response
) runs on ItsPkiHttp return boolean {
var HttpMessage v_request;
var boolean v_result := false;
log(">>> f_await_ec_request_send_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
)))))),
v_request
) {
var Ieee1609Dot2Data v_ieee1609dot2_signed_and_encrypted_data;
var EtsiTs102941Data v_etsi_ts_102941_data;
var Oct16 v_request_hash;
var Oct16 v_aes_enc_key;
var InnerEcRequest v_inner_ec_request;
var template (value) HttpMessage v_response;
tc_ac.stop;
f_init_default_headers_list(-, "inner_ec_response", v_headers);
if (f_verify_pki_request_message(vc_eaPrivateEncKey, vc_eaWholeHash/*salt*/, ''O, v_request.request.body.binary_body.ieee1609dot2_data, false, v_request_hash, v_etsi_ts_102941_data, v_aes_enc_key) == false) { // Cannot decrypt the message
log("f_await_ec_request_send_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
} else {
log("f_await_ec_request_send_response: Receive ", v_etsi_ts_102941_data, " ***");
if (f_verify_inner_ec_request_signed_for_pop(v_etsi_ts_102941_data, v_inner_ec_request) == false) {
log("f_await_ec_request_send_response: Failed to verify PKI message ***");
// Send error message
f_http_build_inner_ec_response(v_inner_ec_request/*Not required*/, cantparse, v_request_hash, -, -, v_aes_enc_key, p_inner_ec_response, v_ieee1609dot2_signed_and_encrypted_data);
v_response := m_http_response(m_http_response_ok(m_http_message_body_binary(m_binary_body_ieee1609dot2_data(v_ieee1609dot2_signed_and_encrypted_data)), v_headers));
} else {
f_http_build_inner_ec_response(v_inner_ec_request, ok, v_request_hash, vc_eaPrivateKey, vc_eaWholeHash, v_aes_enc_key, p_inner_ec_response, v_ieee1609dot2_signed_and_encrypted_data);
v_response := m_http_response(m_http_response_ok(m_http_message_body_binary(m_binary_body_ieee1609dot2_data(v_ieee1609dot2_signed_and_encrypted_data)), v_headers));
}
}
[] tc_ac.timeout {
log("f_await_ec_request_send_response: Expected message not received ***");
}
} // End of 'alt' statement
return v_result;
} // End of function f_await_ec_request_send_response
* @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 SecurityAlg p_enc_algorithm, // TODO Use RCA to check encryption alg
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;
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);
// Signed the encoded PKI message
v_tbs := m_toBeSignedData(
m_signedDataPayload(
m_headerInfo_inner_pki_request(-, (f_getCurrentTime() * 1000)/*us*/)
log("f_build_pki_secured_request_message_signed_with_pop: v_tbs: ", v_tbs);
v_tbs_signed := f_signWithEcdsa(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key);
} else {
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);
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
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_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,
// 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
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 (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));
}
v_encrypted_data_encryption_key := valueof(
m_encryptedDataEncryptionKey_eciesNistP256(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
p_encrypted_sym_key,
p_authentication_vector
)));
} 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;
}
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(
m_aesCcmCiphertext(
p_nonce,
v_encrypted_request
)
)
// 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);
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
/**
* @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,
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;
log(">>> f_build_pki_secured_request_message");
// Encrypt encode EtsiTs103097Data-Signed data structure
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 (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));
v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
v_encrypted_data_encryption_key := valueof(
m_encryptedDataEncryptionKey_eciesNistP256(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
p_encrypted_sym_key,
p_authentication_vector
)));
} 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(
m_aesCcmCiphertext(
v_encrypted_request
// 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);
log("<<< f_build_pki_secured_request_message: ", p_ieee1609dot2_signed_and_encrypted_data);
} // End of function f_build_pki_secured_request_message
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,
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;
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));
// Encrypt encode EtsiTs103097Data-Signed data structure
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_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);
log("f_build_pki_secured_request_message_for_authorization: Wrong encryption variant");
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));
}
v_encrypted_data_encryption_key := valueof(
m_encryptedDataEncryptionKey_eciesNistP256(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
p_encrypted_sym_key,
p_authentication_vector
)));
} else if (p_enc_algorithm == e_brainpool_p256_r1) {
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
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(
m_aesCcmCiphertext(
p_nonce,
v_encrypted_request
)
)
)
)
);
// 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);
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
/**
* @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
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
* @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;
// 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;
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
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
v_ieee1609dot2_signed_data := m_etsiTs103097Data_signed(
m_signedData(
sha256,
v_tbs,
p_signer_identifier,
m_signature_ecdsaNistP256(
m_ecdsaP256Signature(
m_eccP256CurvePoint_x_only(
substr(v_tbs_signed, 0, 32)
),
substr(v_tbs_signed, 32, 32)
)
)
)
);
// Encode EtsiTs103097Data-Signed data structure
v_encoded_inner_ec_response := bit2oct(encvalue(v_ieee1609dot2_signed_data));
v_encrypted_inner_ec_response := fx_encrypt_aes_128_ccm_test(p_aes_sym_key, p_nonce, v_encoded_inner_ec_response);
v_recipientId := f_hashedId8FromSha256(f_hashWithSha256(p_aes_sym_key));
log("v_recipientId= ", v_recipientId);
// Fill Certificate template with the public compressed keys (canonical form)
p_ieee1609dot2_signed_and_encrypted_data := valueof(
m_etsiTs103097Data_encrypted(
m_encryptedData(
{
m_recipientInfo_pskRecipInfo(
v_recipientId
)
},
m_SymmetricCiphertext_aes128ccm(
m_aesCcmCiphertext(
p_nonce,
v_encrypted_inner_ec_response
)
)
)
)
);
log("<<< f_build_pki_secured_response_message: ", p_ieee1609dot2_signed_and_encrypted_data);
return true;
} // End of function f_build_pki_secured_response_message
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
/**
* @desc Verify the protocol element of the Pki message.
* If p_check_security is set to false, only decryption and decoding of the outer message are verified.
* @param p_private_enc_key Private key for decryption
* @param p_salt
* @param p_p_ieee1609dot2_encrypted_and_signed_data
* @param p_check_security Set to true to verify PKI protocol element such as signatures...
* @param p_request_hash The request hash for to be used to build the response
* @param p_etsi_ts_102941_data The EtsiTs102941Data message
* @param p_aes_enc_key The AES 128 encrytion key to be used to encrypt the response
* @return true on success, false otherwise
*/
function f_verify_pki_request_message(
in Oct32 p_private_enc_key,
in Oct32 p_salt,
in octetstring p_issuer,
in Ieee1609Dot2Data p_ieee1609dot2_encrypted_and_signed_data,
in boolean p_check_security := true,
out Oct16 p_request_hash,
out EtsiTs102941Data p_etsi_ts_102941_data,
out Oct16 p_aes_enc_key
) return boolean {
// Local variables
var bitstring v_msg_bit;
var octetstring v_msg;
var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
var Certificate v_certificate;
log(">>> f_verify_pki_request_message: p_private_enc_key= ", p_private_enc_key);
log(">>> f_verify_pki_request_message: p_salt= ", p_salt);
log(">>> f_verify_pki_request_message: p_issuer= ", p_issuer);
log(">>> f_verify_pki_request_message: p_ieee1609dot2_encrypted_and_signed_data= ", p_ieee1609dot2_encrypted_and_signed_data);
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
// 1. Calculate the request Hash
v_msg := bit2oct(encvalue(p_ieee1609dot2_encrypted_and_signed_data));
log("f_verify_pki_request_message: Encoded request: ", v_msg);
p_request_hash := substr(f_hashWithSha256(v_msg), 0, 16);
log("f_verify_pki_request_message: v_request_hash= ", p_request_hash);
// 2. Decrypt the InnerEcRequest
log("f_verify_pki_request_message: p_private_enc_key= ", p_private_enc_key);
if (f_decrypt(p_private_enc_key, p_ieee1609dot2_encrypted_and_signed_data, p_salt, v_ieee1609dot2_signed_data, p_aes_enc_key) == false) {
log("f_verify_pki_request_message: Failed to decrypt message");
return false;
}
log("f_verify_pki_request_message: v_ieee1609dot2_signed_data= ", v_ieee1609dot2_signed_data);
log("f_verify_pki_request_message: p_aes_enc_key= ", p_aes_enc_key);
// 3. Check basics security
log(
match(
v_ieee1609dot2_signed_data,
mw_etsiTs103097Data_signed(
mw_signedData(
-,
mw_toBeSignedData(
mw_signedDataPayload,
mw_ieee1609Dot2_headerInfo(c_its_aid_SCR)
)
)
)));
if (match(v_ieee1609dot2_signed_data, mw_etsiTs103097Data_signed(mw_signedData(-, mw_toBeSignedData(mw_signedDataPayload)))) == false) {
log("f_verify_pki_request_message: Failed to check basic security");
if (p_check_security == true) {
return false;
}
}
// 4. Verifiy signature
log("f_verify_pki_request_message: v_ieee1609dot2_signed_data.content.signedData.tbsData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData);
v_msg := bit2oct(encvalue(v_ieee1609dot2_signed_data.content.signedData.tbsData));
log("f_verify_pki_request_message: v_msg= ", v_msg);
if (p_issuer == ''O) { // self
log("f_verify_pki_request_message: Issuer is self, check outer signature using IUT public key (PICS_ITS_S_SIGN_xxx_PUBLIC_KEY)");
var PublicVerificationKey v_verification_key;
log("f_verify_pki_request_message: PX_VE_ALG=", PX_VE_ALG);
if (PX_VE_ALG == e_nist_p256) {
if (PICS_ITS_S_SIGN_NISTP256_PUBLIC_KEY[0] == '02'O) {
v_verification_key.ecdsaNistP256.compressed_y_0 := substr(PICS_ITS_S_SIGN_NISTP256_PUBLIC_KEY, 1, 32);
} else {
v_verification_key.ecdsaNistP256.compressed_y_1 := substr(PICS_ITS_S_SIGN_NISTP256_PUBLIC_KEY, 1, 32);
}
} else if (PX_VE_ALG == e_brainpool_p256_r1) {
Yann Garcia
committed
if (PICS_ITS_S_SIGN_BRAINPOOLP256r1_PUBLIC_KEY[0] == '02'O) {
v_verification_key.ecdsaBrainpoolP256r1.compressed_y_0 := substr(PICS_ITS_S_SIGN_BRAINPOOLP256r1_PUBLIC_KEY, 1, 32);
Yann Garcia
committed
v_verification_key.ecdsaBrainpoolP256r1.compressed_y_1 := substr(PICS_ITS_S_SIGN_BRAINPOOLP256r1_PUBLIC_KEY, 1, 32);
}
} else if (PX_VE_ALG == e_brainpool_p384_r1) {
Yann Garcia
committed
if (PICS_ITS_S_SIGN_BRAINPOOLP384r1_PUBLIC_KEY[0] == '02'O) {
v_verification_key.ecdsaBrainpoolP384r1.compressed_y_0 := substr(PICS_ITS_S_SIGN_BRAINPOOLP384r1_PUBLIC_KEY, 1, 48);
Yann Garcia
committed
v_verification_key.ecdsaBrainpoolP384r1.compressed_y_1 := substr(PICS_ITS_S_SIGN_BRAINPOOLP384r1_PUBLIC_KEY, 1, 48);
}
}
log("f_verify_pki_request_message: v_verification_key=", v_verification_key);
if (f_verifyEcdsa(v_msg, int2oct(0, 32), v_ieee1609dot2_signed_data.content.signedData.signature_, v_verification_key) == false) {
if (p_check_security == true) {
return false;
}
}
//return false;
if (f_getCertificateFromDigest(f_hashedId8FromSha256(p_issuer), v_certificate, v_certificate_id) == false) {
if (p_check_security == true) {
return false;
}
}
log("f_verify_pki_request_message: v_certificate= ", v_certificate);
if (f_verifyEcdsa(v_msg, p_issuer, v_ieee1609dot2_signed_data.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
if (p_check_security == true) {
return false;
}
}
}
// 4. Return the PKI message
log("f_verify_pki_request_message: v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData= ", v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
v_msg_bit := oct2bit(v_ieee1609dot2_signed_data.content.signedData.tbsData.payload.data.content.unsecuredData);
if (decvalue(v_msg_bit, p_etsi_ts_102941_data) != 0) {
if (p_check_security == true) {
return false;
}
}
if (p_etsi_ts_102941_data.version != PkiProtocolVersion) {
if (p_check_security == true) {
return false;
}
}
log("<<< f_verify_pki_request_message: true");
return true;
} // End of function f_verify_pki_request_message
* @desc Verify the protocol element of the Pki message.
* If p_check_security is set to false, only decryption and decoding of the outer message are verified.
* @param p_private_key Private key for decryption
* @param p_publicEphemeralCompressedKey
* @param p_publicEphemeralCompressedKeyMode
* @param p_issuer Issuer
* @param p_certificate Certificate to use for verification key
* @param p_ieee1609dot2_encrypted_and_signed_data The received encrypted and signed data
* @param p_check_security Set to true to verify PKI protocol element such as signatures...
* @param p_response_type Response type (0: InnerEcResponse, 1: InnerAtResponse...). Default: 0
* @param p_etsi_ts_102941_data The EtsiTs102941Data message
* @return true on success, false otherwise
*/
function f_verify_pki_response_message(
in octetstring p_private_enc_key,
in Oct16 p_aes_sym_key,
in Oct16 p_authentication_vector, // TODO Tobe removed
in octetstring p_issuer,
in Ieee1609Dot2Data p_ieee1609dot2_encrypted_and_signed_data,
in boolean p_check_security := true,
in integer p_response_type := 0,
out EtsiTs102941Data p_etsi_ts_102941_data
) return boolean {
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 bitstring v_etsi_ts_102941_data_msg;
var bitstring v_tbs;