Newer
Older
/**
* @author ETSI / STF544
* @version $URL$
* $Id$
* @desc Module containing functions for ITS PKI ATS
* @copyright ETSI Copyright Notification
* No part may be reproduced except as authorized by written permission.
* The copyright and the foregoing restriction extend to reproduction in all media.
* All rights reserved.
*
*/
module LibItsPki_Functions {
// LibCommon
import from LibCommon_Time all;
import from LibCommon_VerdictControl all;
import from LibCommon_Sync all;
import from LibCommon_BasicTypesAndValues all;
import from LibCommon_DataStrings all;
// LibIts
import from IEEE1609dot2BaseTypes language "ASN.1:1997" all;
import from IEEE1609dot2 language "ASN.1:1997" all;
import from EtsiTs102941BaseTypes language "ASN.1:1997" all;
import from EtsiTs102941TypesEnrolment language "ASN.1:1997" all;
import from EtsiTs102941TypesAuthorization language "ASN.1:1997" all;
import from EtsiTs102941TypesAuthorizationValidation language "ASN.1:1997" all;
import from EtsiTs102941MessagesCa language "ASN.1:1997" all;
import from EtsiTs103097Module language "ASN.1:1997" all;
import from ITS_Container language "ASN.1:1997" all;
import from CAM_PDU_Descriptions language "ASN.1:1997" all;
// LibItsCommon
import from LibItsCommon_Functions all;
import from LibItsCommon_ASN1_NamedNumbers all;
import from LibItsCommon_Pixits all;
// LibItsGeoNetworking
import from LibItsGeoNetworking_TypesAndValues all;
import from LibItsGeoNetworking_TestSystem all;
import from LibItsGeoNetworking_Pixits all;
// LibItsSecurity
import from LibItsSecurity_TypesAndValues all;
import from LibItsSecurity_Templates all;
import from LibItsSecurity_Functions all;
import from LibItsSecurity_TestSystem all;
// LibItsHttp
import from LibItsHttp_TypesAndValues all;
import from LibItsHttp_Templates all;
import from LibItsHttp_BinaryTemplates all;
import from LibItsHttp_Functions all;
function f_cfMtcUp(
out ItsPkiItss p_itss,
out ItsPkiHttp p_pki
) runs on ItsMtc {
p_itss := ItsPkiItss.create("IUT") alive;
p_pki := ItsPkiHttp.create("TS") alive;
connect(self:syncPort, mtc:syncPort);
connect(p_itss:syncPort, self:syncPort);
connect(p_pki:syncPort, self:syncPort);
}
/**
* @desc Setups default configuration
* @param p_certificate_id The certificate identifier the TA shall use in case of secured IUT
in charstring p_ea_certificate_id := "CERT_TS_A_EA", // TODO Use a constant
in charstring p_aa_certificate_id := "CERT_TS_A_AA"
) runs on ItsPkiHttp /* TITAN TODO: system ItsPkiHttpSystem */ {
map(self:httpPort, system:httpPort);
} else {
map(self:httpEcPort, system:httpEcPort);
map(self:httpAtVPort, system:httpAtVPort);
map(self:httpAtPort, system:httpAtPort);
}
f_initialiseSecuredMode(p_ea_certificate_id, p_aa_certificate_id); // TODO To be removed???
// Setup EA certificate shared with PKI EA entity
f_readCertificate(p_ea_certificate_id, vc_eaCertificate);
f_readSigningKey(p_ea_certificate_id, vc_eaPrivateKey); // TODO To be removed
f_readEncryptingKey(p_ea_certificate_id, vc_eaPrivateEncKey);
f_getCertificateDigest(p_ea_certificate_id, vc_eaHashedId8);
f_getCertificateHash(p_ea_certificate_id, vc_eaWholeHash);
log("f_cfHttpUp: vc_eaPrivateKey= ", vc_eaPrivateKey);
log("f_cfHttpUp: vc_eaPrivateEncKey= ", vc_eaPrivateEncKey);
log("f_cfHttpUp: vc_eaHashedId8= ", vc_eaHashedId8);
log("f_cfHttpUp: vc_eaWholeHash= ", vc_eaWholeHash);
// Setup AA certificate shared with PKI AA entity
f_readCertificate(p_aa_certificate_id, vc_aaCertificate);
f_getCertificateDigest(p_aa_certificate_id, vc_aaHashedId8);
f_getCertificateHash(p_aa_certificate_id, vc_aaWholeHash);
log("f_cfHttpUp: vc_aaHashedId8= ", vc_aaHashedId8);
log("f_cfHttpUp: vc_aaWholeHash= ", vc_aaWholeHash);
if (PICS_MULTIPLE_END_POINT == false) {
activate(a_default_pki_http());
} else {
activate(a_default_pki_http_ec());
activate(a_default_pki_http_atv());
activate(a_default_pki_http_at());
}
in charstring p_certificate_id := "CERT_TS_A_EA" // TODO Use a constant
) runs on ItsPkiItss /* TITAN TODO: system ItsPkiItssSystem */ {
map(self:geoNetworkingPort, system:geoNetworkingPort);
map(self:utPort, system:utPort);
f_initializeState();
// activate(a_default_pki()); TOTO Defualt from geoNet
/**
* @desc Deletes default configuration
*/
function f_cfMtcDown(
inout ItsPkiItss p_itss,
inout ItsPkiHttp p_pki
) runs on ItsMtc {
disconnect(self:syncPort, mtc:syncPort);
disconnect(p_itss:syncPort, self:syncPort);
disconnect(p_pki:syncPort, self:syncPort);
p_itss.done;
p_pki.done;
}
/**
* @desc Deletes default configuration
*/
function f_cfHttpDown() runs on ItsPkiHttp /* TITAN TODO: system ItsPkiHttpSystem */ {
if (PICS_MULTIPLE_END_POINT == false) {
unmap(self:httpPort, system:httpPort);
} else {
unmap(self:httpEcPort, system:httpEcPort);
unmap(self:httpAtVPort, system:httpAtVPort);
unmap(self:httpAtPort, system:httpAtPort);
}
f_uninitialiseSecuredMode();
/**
* @desc Deletes default configuration
*/
function f_cfDown_itss() runs on ItsPkiItss /* TITAN TODO: system ItsPkiItssSystem */ {
unmap(self:geoNetworkingPort, system:geoNetworkingPort);
unmap(self:utPort, system:utPort);
} // End of function f_cfDown
/**
* @desc Initialise secure mode if required
*/
function f_initialiseSecuredMode(
in charstring p_certificate_id := "CERT_TS_A_EA", // TODO Use a constant
in charstring p_peerCertificateId := "CERT_IUT_A_EA"
) runs on ItsSecurityBaseComponent {
if(not(f_loadCertificates(PX_IUT_SEC_CONFIG_NAME))) {
log("*** INFO: TEST CASE NOW STOPPING ITSELF! ***");
setverdict(inconc);
// f_prepareCertificates(p_certificate_id, vc_aaCertificate, vc_atCertificate);
function f_uninitialiseSecuredMode() runs on ItsSecurityBaseComponent {
f_unloadCertificates();
} // End of function f_uninitialiseSecuredMode()
function f_initializeState() runs on ItsPkiItss {
var Oct8 v_hashedId8ToBeUsed;
log(">>> f_initializeState: vc_hashedId8ToBeUsed= ", vc_hashedId8ToBeUsed);
v_hashedId8ToBeUsed := f_setupIutCertificate(vc_hashedId8ToBeUsed);
log("f_initializeState: v_hashedId8ToBeUsed= ", v_hashedId8ToBeUsed);
f_utInitializeIut(UtPkiInitialize: { v_hashedId8ToBeUsed } );
f_sleep(PX_NEIGHBOUR_DISCOVERY_DELAY);
// f_acLoadScenario(p_scenario);
// f_acStartScenario();
}
group ut_port {
function f_utInitializeIut(template (value) UtPkiInitialize p_init) runs on ItsPkiItss {
utPort.send(p_init);
tc_wait.start;
alt {
[] utPort.receive(UtPkiResults: { utPkiInitializeResult := true }) {
tc_wait.stop;
log("*** f_utInitializeIut: INFO: IUT initialized ***");
}
[] utPort.receive {
tc_wait.stop;
log("*** f_utInitializeIut: INFO: IUT could not be initialized ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[] tc_wait.timeout {
log("*** f_utInitializeIut: INFO: IUT could not be initialized in time ***");
f_selfOrClientSyncAndVerdict("error", e_timeout);
}
}
} // End of function f_utInitializeIut
function f_sendUtTriggerEnrolmentRequestPrimitive(
in octetstring p_canonical_id := ''O,
in Oct1 p_enc_algorithm := '00'O,
in octetstring p_private_key := ''O,
in octetstring p_public_key_compressed := ''O,
in integer p_compressed_mode := 0
) runs on ItsPkiItss {
var TriggerEnrolmentRequest v_ut_trigger_enrolment_request;
var octetstring v_compressed_public_key;
if (p_compressed_mode == 2) { // TODO v_compressed_public_key := int2oct(p_compressed_mode, 1) & p_public_key_compressed?
v_compressed_public_key := '02'O & p_public_key_compressed;
} else {
v_compressed_public_key := '03'O & p_public_key_compressed;
v_ut_trigger_enrolment_request := { p_canonical_id, p_enc_algorithm, p_private_key, v_compressed_public_key };
utPort.send(UtPkiTrigger: { triggerEnrolmentRequest := v_ut_trigger_enrolment_request });
tc_ac.start;
alt {
[] utPort.receive(UtPkiResults: { utPkiTriggerResult := true }) {
tc_ac.stop;
}
[] utPort.receive(UtPkiResults: { utPkiTriggerResult := false }) {
tc_ac.stop;
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
log("*** f_sendUtTriggerEnrolmentRequestPrimitive: ERROR: Received unexpected message ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[] tc_ac.timeout {
log("*** f_sendAcPkiPrimitive: ERROR: Timeout while waiting for adapter control event result ***");
f_selfOrClientSyncAndVerdict("error", e_timeout);
}
} // End of 'alt' statement
} // End of function f_sendUtTriggerEnrolmentRequestPrimitive
function f_sendUtTriggerAuthorizationRequestPrimitive(
in octetstring p_canonical_id := ''O,
in Oct1 p_enc_algorithm := '00'O,
in octetstring p_private_key := ''O,
in octetstring p_public_key_compressed := ''O,
in integer p_compressed_mode := 0
) runs on ItsPkiItss {
var TriggerAuthorizationRequest v_ut_trigger_enrolment_request;
var octetstring v_compressed_public_key;
if (p_compressed_mode == 2) { // TODO v_compressed_public_key := int2oct(p_compressed_mode, 1) & p_public_key_compressed?
v_compressed_public_key := '02'O & p_public_key_compressed;
} else {
v_compressed_public_key := '03'O & p_public_key_compressed;
}
v_ut_trigger_enrolment_request := { p_canonical_id, p_enc_algorithm, p_private_key, v_compressed_public_key };
utPort.send(UtPkiTrigger: { triggerAuthorizationRequest := v_ut_trigger_enrolment_request });
tc_ac.start;
alt {
[] utPort.receive(UtPkiResults: { utPkiTriggerResult := true }) {
tc_ac.stop;
}
[] utPort.receive(UtPkiResults: { utPkiTriggerResult := false }) {
tc_ac.stop;
log("*** f_sendUtTriggerAuthorizationRequestPrimitive: ERROR: Received unexpected message ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[] tc_ac.timeout {
log("*** f_sendAcPkiPrimitive: ERROR: Timeout while waiting for adapter control event result ***");
f_selfOrClientSyncAndVerdict("error", e_timeout);
}
} // End of 'alt' statement
} // End of function f_sendUtTriggerAuthorizationRequestPrimitive
} // End of group ut_port
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
group helpers {
function f_generate_key_pair(
out octetstring p_private_key,
out octetstring p_public_key_x,
out octetstring p_public_key_y,
out octetstring p_public_key_compressed,
out integer p_compressed_mode
) return boolean {
if (PX_EC_ALG == e_nist_p256) {
f_generate_key_pair_nistp256(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
f_generate_key_pair_brainpoolp256(p_private_key, p_public_key_x, p_public_key_y, p_public_key_compressed, p_compressed_mode);
} else {
// error
return false;
}
return true;
}
function f_signWithEcdsa(
in octetstring p_toBeSignedSecuredMessage,
in octetstring p_certificateIssuer,
in octetstring p_privateKey
) return octetstring {
if (PX_VE_ALG == e_nist_p256) {
return f_signWithEcdsaNistp256WithSha256(p_toBeSignedSecuredMessage, p_certificateIssuer, p_privateKey);
} else if (PX_VE_ALG == e_brainpool_p256_r1) {
return f_signWithEcdsaBrainpoolp256WithSha256(p_toBeSignedSecuredMessage, p_certificateIssuer, p_privateKey);
} else if (PX_VE_ALG == e_brainpool_p384_r1) {
return f_signWithEcdsaBrainpoolp384WithSha384(p_toBeSignedSecuredMessage, p_certificateIssuer, p_privateKey);
}
return ''O;
} // End of function f_signWithEcdsa
function f_verifyEcdsa(
in octetstring p_tbs,
in octetstring p_issuer,
in Signature p_signature_,
in PublicVerificationKey p_verification_key
) return boolean {
var boolean v_ret := false;
log(" >>> f_verifyEcdsa: p_tbs", p_tbs);
log(" >>> f_verifyEcdsa: p_issuer", p_issuer);
log(" >>> f_verifyEcdsa: p_signature_", p_signature_);
log(" >>> f_verifyEcdsa: p_verification_key", p_verification_key);
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
if (ischosen(p_verification_key.ecdsaNistP256)) {
if (ischosen(p_verification_key.ecdsaNistP256.compressed_y_0)) {
v_ret := f_verifyWithEcdsaNistp256WithSha256(
p_tbs,
p_issuer,
p_signature_.ecdsaNistP256Signature.rSig.x_only & p_signature_.ecdsaNistP256Signature.sSig,
p_verification_key.ecdsaNistP256.compressed_y_0,
0);
} else {
v_ret := f_verifyWithEcdsaNistp256WithSha256(
p_tbs,
p_issuer,
p_signature_.ecdsaNistP256Signature.rSig.x_only & p_signature_.ecdsaNistP256Signature.sSig,
p_verification_key.ecdsaNistP256.compressed_y_1,
1);
}
} else if (ischosen(p_verification_key.ecdsaBrainpoolP256r1)) {
if (ischosen(p_verification_key.ecdsaBrainpoolP256r1.compressed_y_0)) {
v_ret := f_verifyWithEcdsaBrainpoolp256WithSha256(
p_tbs,
p_issuer,
p_signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only & p_signature_.ecdsaBrainpoolP256r1Signature.sSig,
p_verification_key.ecdsaBrainpoolP256r1.compressed_y_0,
0);
} else {
v_ret := f_verifyWithEcdsaBrainpoolp256WithSha256(
p_tbs,
p_issuer,
p_signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only & p_signature_.ecdsaBrainpoolP256r1Signature.sSig,
p_verification_key.ecdsaBrainpoolP256r1.compressed_y_1,
1);
}
} else if (ischosen(p_verification_key.ecdsaBrainpoolP384r1)) {
if (ischosen(p_verification_key.ecdsaBrainpoolP384r1.compressed_y_0)) {
v_ret := f_verifyWithEcdsaBrainpoolp384WithSha384(
p_tbs,
p_issuer,
p_signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only & p_signature_.ecdsaBrainpoolP384r1Signature.sSig,
p_verification_key.ecdsaBrainpoolP384r1.compressed_y_0,
0);
} else {
v_ret := f_verifyWithEcdsaBrainpoolp384WithSha384(
p_tbs,
p_issuer,
p_signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only & p_signature_.ecdsaBrainpoolP384r1Signature.sSig,
p_verification_key.ecdsaBrainpoolP384r1.compressed_y_1,
1);
}
}
return v_ret;
} // End of function f_verifyEcdsa
} // End of group helpers
group http { // TODO Split into EnnerEc, Authorization & AuthorizationValidation
function f_http_build_inner_ec_request( // TODO Cleanup parameters
out octetstring p_public_key_compressed,
out integer p_compressed_mode,
out Oct16 p_aes_sym_key,
out Oct16 p_encrypted_sym_key,
out Oct16 p_authentication_vector,
out Oct12 p_nonce,
out octetstring p_salt,
out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
var InnerEcRequest v_inner_ec_request;
var Ieee1609Dot2Data v_inner_ec_request_signed_for_pop;
var octetstring v_public_enc_key;
var integer v_compressed_enc_key_mode;
if (f_generate_inner_ec_request(p_private_key, p_public_key_compressed, p_compressed_mode, v_inner_ec_request) == false) {
log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequest ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
log ("f_http_build_enrolment_request: ==> EC verification private key: ", p_private_key);
log ("f_http_build_enrolment_request: ==> EC verification public compressed key: ", p_public_key_compressed);
log ("f_http_build_enrolment_request: ==> EC verification public compressed mode: ", p_compressed_mode);
// Generate InnerEcRequestSignedForPoP
if (f_generate_inner_ec_request_signed_for_pop(p_private_key, v_inner_ec_request, v_inner_ec_request_signed_for_pop) == false) {
log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
log("f_http_build_enrolment_request: v_inner_ec_request_signed_for_pop= ", v_inner_ec_request_signed_for_pop);
// Secure InnerEcRequestSignedForPoP message
if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
log("*** f_http_build_inner_ec_request: ERROR: Non canonical EA certificate ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
if (PICS_SEC_FIXED_KEYS) { // Debug mode: Use fixed values
v_public_enc_key := 'DD4F6B0DF57C6E3BD0E32B565CACA1D858CEB08A5C2BBAB2C23E203C6DE697FF'O;
v_compressed_enc_key_mode := 0;
}
log("f_http_build_inner_ec_request: Public encryption key: ", v_public_enc_key);
log("f_http_build_inner_ec_request: Public encryption key comp: ", v_compressed_enc_key_mode);
if (PICS_SECPKI_REENROLMENT == false) { // This is the first enrolment, we used Factory keys
v_result := f_build_pki_secured_request_message_signed_with_pop(PICS_ITS_S_SIGN_NITSP256_PRIVATE_KEY, valueof(m_signerIdentifier_self), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
// TODO Retrieve EC certificate from the first enrolment instead of PX
log("f_http_build_inner_ec_request: v_ec_private_key: ", PX_EC_PRIVATE_KEY);
log("f_http_build_inner_ec_request: v_ec_hashed_id8: ", PX_EC_HASHED_ID8);
v_result := f_build_pki_secured_request_message_signed_with_pop(PX_EC_PRIVATE_KEY, valueof(m_signerIdentifier_digest(PX_EC_HASHED_ID8)), PX_EC_HASHED_ID8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
log("*** f_http_build_inner_ec_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
f_selfOrClientSyncAndVerdict("error", e_error);
} else {
log("f_http_build_inner_ec_request: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
log("f_http_build_inner_ec_request: p_request_hash= ", p_request_hash);
function f_http_build_invalid_enrolment_request(
out octetstring p_private_key,
out octetstring p_public_key_compressed,
out integer p_compressed_mode,
out Oct16 p_aes_sym_key,
out Oct16 p_encrypted_sym_key,
out Oct16 p_authentication_vector,
out Oct12 p_nonce,
out octetstring p_salt,
out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
) runs on ItsPkiHttp {
var InnerEcRequest v_inner_ec_request;
var Ieee1609Dot2Data v_inner_ec_request_signed_for_pop;
var octetstring v_public_enc_key;
var integer v_compressed_enc_key_mode;
var boolean v_ret_code;
if (f_generate_inner_ec_request(p_private_key, p_public_key_compressed, p_compressed_mode, v_inner_ec_request) == false) {
log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequest ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
log ("f_http_build_invalid_enrolment_request: EC verification private key: ", p_private_key);
log ("f_http_build_invalid_enrolment_request: EC verification public compressed key: ", p_public_key_compressed);
log ("f_http_build_invalid_enrolment_request: EC verification public compressed mode: ", p_compressed_mode);
// Generate InnerEcRequestSignedForPoP
if (f_generate_inner_ec_request_signed_for_pop(p_private_key, v_inner_ec_request, v_inner_ec_request_signed_for_pop) == false) {
log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
log("f_http_build_invalid_enrolment_request: v_inner_ec_request_signed_for_pop= ", v_inner_ec_request_signed_for_pop);
// Modify signature to get an error
if (ischosen(v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaNistP256Signature)) {
v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaNistP256Signature.sSig[1] := bit2oct('10101010'B xor4b oct2bit(v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaNistP256Signature.sSig[1]));
} else {
v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig[1] := bit2oct('10101010'B xor4b oct2bit(v_inner_ec_request_signed_for_pop.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig[1]));
}
// Secure InnerEcRequestSignedForPoP message
if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
log("*** f_http_build_invalid_enrolment_request: ERROR: Non canonical EA certificate ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
log("*** f_http_build_invalid_enrolment_request: Public encryption key: ", v_public_enc_key);
log("*** f_http_build_invalid_enrolment_request: Public encryption key comp: ", v_compressed_enc_key_mode);
if (PICS_SECPKI_REENROLMENT == false) { // This is the first enrolment, we used Factory keys
v_ret_code := f_build_pki_secured_request_message_signed_with_pop(PICS_ITS_S_SIGN_NITSP256_PRIVATE_KEY, valueof(m_signerIdentifier_self), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
// TODO Retrieve EC certificate from the first enrolment instead of PX
log("f_http_build_inner_ec_request: v_ec_private_key: ", PX_EC_PRIVATE_KEY);
log("f_http_build_inner_ec_request: v_ec_hashed_id8: ", PX_EC_HASHED_ID8);
v_ret_code := f_build_pki_secured_request_message_signed_with_pop(PX_EC_PRIVATE_KEY, valueof(m_signerIdentifier_digest(PX_EC_HASHED_ID8)), PX_EC_HASHED_ID8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_inner_ec_request_signed_for_pop(v_inner_ec_request_signed_for_pop))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash);
log("*** f_http_build_invalid_enrolment_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
log("*** f_http_build_invalid_enrolment_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data = ", p_ieee1609dot2_signed_and_encrypted_data);
} // End of function f_http_build_invalid_enrolment_request
function f_http_build_inner_ec_response(
in InnerEcRequest p_inner_ec_request,
in EnrolmentResponseCode p_responseCode := ok,
in Oct16 p_request_hash,
in octetstring p_private_key := ''O,
in octetstring p_digest := ''O,
in Oct16 p_aes_sym_key,
out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
) return boolean {
// Local variables
var bitstring v_msg_bit;
var octetstring v_msg;
var Oct12 v_nonce;
var Ieee1609Dot2Data v_ieee1609dot2_signed_data;
var InnerEcResponse v_inner_ec_response;
var EtsiTs103097Certificate v_ec_certificate;
var boolean p_result := false;
log(">>> f_http_build_inner_ec_response: p_inner_ec_request= ", p_inner_ec_request);
log(">>> f_http_build_inner_ec_response: p_responseCode= ", p_responseCode);
log(">>> f_http_build_inner_ec_response: p_request_hash= ", p_request_hash);
log(">>> f_http_build_inner_ec_response: p_private_key= ", p_private_key);
log(">>> f_http_build_inner_ec_response: p_digest= ", p_digest);
log(">>> f_http_build_inner_ec_response: p_aes_sym_key= ", p_aes_sym_key);
// Check expectred response
if (p_responseCode != ok) {
v_inner_ec_response := valueof(
m_innerEcResponse_ko(
p_request_hash,
p_responseCode
)
);
p_result := true;
} else {
// Generate the certificate
if (f_generate_ec_certificate_for_inner_ec_response(p_inner_ec_request, p_private_key, p_digest, v_ec_certificate) == false) {
log("f_http_build_inner_ec_response: Failed to generate the certificate");
v_inner_ec_response := valueof(
m_innerEcResponse_ko(
p_request_hash,
incompleterequest
)
);
} else {
v_inner_ec_response := valueof(
m_innerEcResponse_ok(
p_request_hash,
v_ec_certificate
)
);
}
}
// Secure the response
log("f_http_build_inner_ec_response: v_inner_ec_response= ", v_inner_ec_response);
v_msg := bit2oct(encvalue(v_inner_ec_response));
v_nonce := int2oct(f_getCurrentTime(), 32); // Random value
// TODO Consider Sha384: m_signerIdentifier_digest(f_HashedId8FromSha384(p_digest))
if (f_build_pki_secured_response_message(p_private_key,
valueof(m_signerIdentifier_digest(f_HashedId8FromSha256(p_digest))),// in SignerIdentifier p_signer_identifier,
v_msg,
p_aes_sym_key,
v_nonce,
p_ieee1609dot2_signed_and_encrypted_data
) == false) {
log("f_http_build_inner_ec_response: Failed to generate the certificate");
v_inner_ec_response := valueof(
m_innerEcResponse_ko(
p_request_hash,
deniedrequest
)
);
} else {
p_result := true;
}
return p_result;
} // End of function f_http_build_inner_ec_response
function f_http_build_authorization_request(
in Certificate p_ec_certificate, // Enrolment credentials certificate
in octetstring p_ec_private_key,
out octetstring p_private_key,
out octetstring p_private_enc_key,
out octetstring p_public_compressed_enc_key,
out Oct16 p_aes_sym_key,
out Oct16 p_encrypted_sym_key,
out Oct16 p_authentication_vector,
out Oct12 p_nonce,
out octetstring p_salt,
out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
out Oct32 p_request_hash
) runs on ItsPkiHttp {
var octetstring v_public_key_x;
var octetstring v_public_key_y;
var octetstring v_public_enc_key_x;
var octetstring v_public_enc_key_y;
var octetstring v_public_enc_key;
var integer v_compressed_enc_key_mode;
var InnerAtRequest v_inner_at_request;
var Ieee1609Dot2Data v_inner_at_request_data;
var InnerAtRequest v_authorization_request;
var bitstring v_authorization_request_msg;
// Generate the InnerAtRequest
if (f_generate_inner_at_request(vc_eaCertificate, vc_eaHashedId8, p_ec_certificate, p_ec_private_key, p_private_key, p_public_key_compressed, p_compressed_key_mode, p_private_enc_key, p_public_compressed_enc_key, p_compressed_enc_key_mode, v_inner_at_request) == false) {
log("*** f_http_build_authorization_request: ERROR: Failed to generate AuthorizationValidationRequest ***");
f_selfOrClientSyncAndVerdict("error", e_error);
log("f_http_build_authorization_request: v_inner_at_request= ", v_inner_at_request);
// Secure InnerAtRequest message
if (f_extract_enc_key(vc_aaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
log("*** f_http_build_authorization_request: ERROR: Non canonical AA certificate ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
if (PICS_SEC_FIXED_KEYS) { // Debug mode: Use fixed values
v_public_enc_key := 'DD4F6B0DF57C6E3BD0E32B565CACA1D858CEB08A5C2BBAB2C23E203C6DE697FF'O;
v_compressed_enc_key_mode := 0;
}
log("*** f_http_build_authorization_request: Public encryption key: ", v_public_enc_key);
log("*** f_http_build_authorization_request: Public encryption key comp: ", v_compressed_enc_key_mode);
p_salt := vc_aaWholeHash;
log("*** f_http_build_authorization_request: p_salt: ", p_salt);
if (PX_AUTHORIZATION_REQUEST_WITH_POP) {
if(f_build_pki_secured_request_message_signed_with_pop(PICS_ITS_S_SIGN_NITSP256_PRIVATE_KEY, valueof(m_signerIdentifier_self), vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_inner_at_request))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
log("*** f_http_build_authorization_request: ERROR: Failed to generate Authorization Request ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
} else { // Only encryption of EtsiTs102941Data/InnerAtRequest
log("*** f_http_build_authorization_request: POP signature not applied");
if(f_build_pki_secured_request_message_for_authorization(vc_aaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_request(v_inner_at_request))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
log("*** f_http_build_authorization_request: ERROR: Failed to generate Authorization Request ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
}
log("*** f_http_build_authorization_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
log("*** f_http_build_authorization_request: DEBUG: p_request_hash= ", p_request_hash);
} // End of function f_http_build_authorization_request
out integer p_compressed_key_mode,
out octetstring p_private_enc_key,
out octetstring p_public_compressed_enc_key,
out integer p_compressed_enc_key_mode,
out Oct16 p_aes_sym_key,
out Oct16 p_encrypted_sym_key,
out Oct16 p_authentication_vector,
out Oct12 p_nonce,
out octetstring p_salt,
out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data,
out Oct32 p_request_hash
) runs on ItsPkiHttp {
// Local variables
var AuthorizationValidationRequest v_authorization_validation_request;
var bitstring v_authorization_validation_request_msg;
var octetstring v_public_enc_key;
var integer v_compressed_enc_key_mode;
// Copy the sharedAtRequest component from the InnerAtRequest received in the AuthorizationRequestMessage
v_authorization_validation_request.sharedAtRequest := p_inner_at_request.sharedAtRequest;
// Copy the ecSignature component from the InnerAtRequest received in the AuthorizationRequestMessage or AuthorizationRequestMessageWithPop
v_authorization_validation_request.ecSignature := p_inner_at_request.ecSignature;
// Secure the Pki message
if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
log("*** f_http_build_authorization_validation_request: ERROR: Non canonical EA certificate ***");
log("*** f_http_build_authorization_validation_request: Public encryption key: ", v_public_enc_key);
log("*** f_http_build_authorization_validation_request: Public encryption key comp: ", v_compressed_enc_key_mode);
// Secure InnerAtRequest message
if (f_extract_enc_key(vc_eaCertificate, v_public_enc_key, v_compressed_enc_key_mode) == false) {
log("*** f_http_build_authorization_validation_request: ERROR: Non canonical EA certificate ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
if (PICS_SEC_FIXED_KEYS) { // Debug mode: Use fixed values
v_public_enc_key := 'DD4F6B0DF57C6E3BD0E32B565CACA1D858CEB08A5C2BBAB2C23E203C6DE697FF'O;
v_compressed_enc_key_mode := 0;
}
log("*** f_http_build_authorization_validation_request: Public encryption key: ", v_public_enc_key);
log("*** f_http_build_authorization_validation_request: Public encryption key comp: ", v_compressed_enc_key_mode);
p_salt := vc_eaWholeHash;
log("*** f_http_build_authorization_validation_request: p_salt: ", p_salt);
if(f_build_pki_secured_request_message_signed_with_pop(PICS_ITS_S_SIGN_NITSP256_PRIVATE_KEY, valueof(m_signerIdentifier_self), vc_eaHashedId8/*recipientId*/, v_public_enc_key, v_compressed_enc_key_mode, p_salt, bit2oct(encvalue(m_etsiTs102941Data_authorization_validation_request(v_authorization_validation_request))), p_ieee1609dot2_signed_and_encrypted_data, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_request_hash) == false) {
log("*** f_http_build_authorization_validation_request: ERROR: Failed to generate Authorization Request ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
log("*** f_http_build_authorization_validation_request: DEBUG: p_ieee1609dot2_signed_and_encrypted_data= ", p_ieee1609dot2_signed_and_encrypted_data);
log("*** f_http_build_authorization_validation_request: DEBUG: p_request_hash= ", p_request_hash);
} // End of function f_http_build_authorization_validation_request
} // End of group http
group generate_certificates {
function f_generate_ec_certificate(
out Certificate p_ec_certificate
) return boolean {
var octetstring v_public_key_x;
var octetstring v_public_key_y;
var octetstring p_public_key_compressed;
var integer p_compressed_mode;
var EccP256CurvePoint v_ecc_p256_curve_point;
var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
valueof(m_appPermissions(36, { bitmapSsp := '830001'O })),
valueof(m_appPermissions(37, { bitmapSsp := '830001'O }))
};
var template (value) EtsiTs103097Certificate v_cert;
var bitstring v_tbs;
var Oct32 v_sig;
var bitstring v_enc_msg;
var PublicVerificationKey v_public_verification_key;
log(">>> f_generate_ec_certificate");
// Generate verification keys for the certificate
if (f_generate_key_pair(p_private_key, v_public_key_x, v_public_key_y, p_public_key_compressed, p_compressed_mode) == false) {
log("f_generate_ec_certificate: Failed to generate verification key");
return false;
}
if (p_compressed_mode == 0) {
v_ecc_p256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_public_key_compressed));
} else {
v_ecc_p256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_public_key_compressed));
}
if (PX_EC_ALG == e_nist_p256) {
v_public_verification_key := valueof(
m_publicVerificationKey_ecdsaNistP256(
v_ecc_p256_curve_point
));
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
v_public_verification_key := valueof(
m_publicVerificationKey_ecdsaBrainpoolP256r1(
v_ecc_p256_curve_point
));
} else {
log("f_generate_ec_certificate: Wrong encryption algorithm, check PX_EC_ALG");
return false;
}
v_cert := m_etsiTs103097Certificate(
m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(f_hashWithSha256('616263'O))),
m_toBeSignedCertificate_at(
v_appPermissions,
m_verificationKeyIndicator_verificationKey(
v_public_verification_key
),
),
m_geographicRegion_identifiedRegion(
{
m_identifiedRegion_country_only(12),
m_identifiedRegion_country_only(34)
}
)
)
);
// Encode it ==> Get octetstring
v_tbs := encvalue(v_cert.toBeSigned);
// Sign the certificate
v_sig := f_signWithEcdsa(bit2oct(v_tbs), int2oct(11, 32), p_private_key);
if ((PX_VE_ALG == e_nist_p256) or (PX_VE_ALG == e_brainpool_p256_r1)) {
v_cert.signature_ := 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_p384_r1) {
v_cert.signature_ := m_signature_ecdsaBrainpoolP384r1(
m_ecdsaP384Signature(
m_eccP384CurvePoint_x_only(
substr(v_sig, 0, 48)
),
substr(v_sig, 48, 48)
)
);
}
log("f_generate_ec_certificate: v_cert= ", v_cert);
p_ec_certificate := valueof(v_cert);
return true;
} // End of function f_generate_ec_certificate
function f_generate_ec_certificate_for_inner_ec_response(
in InnerEcRequest p_inner_ec_request,
in octetstring p_private_key,
in octetstring p_digest,
out EtsiTs103097Certificate p_ec_certificate
) return boolean {
var EtsiTs103097Certificate v_cert;
var IssuerIdentifier v_issuer;
var bitstring v_tbs;
var octetstring v_sig;
log(">>> f_generate_ec_certificate_for_inner_ec_response");
v_issuer := valueof(m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(p_digest))); // TODO Check sha256/384 f_HashedId8FromSha384
v_cert := valueof(
m_etsiTs103097Certificate(
v_issuer,
m_toBeSignedCertificate_ec(
p_inner_ec_request.requestedSubjectAttributes.id,
p_inner_ec_request.requestedSubjectAttributes.appPermissions,
m_verificationKeyIndicator_verificationKey(
p_inner_ec_request.publicKeys.verificationKey
),
p_inner_ec_request.requestedSubjectAttributes.validityPeriod,
p_inner_ec_request.requestedSubjectAttributes.region,
p_inner_ec_request.requestedSubjectAttributes.assuranceLevel,
p_inner_ec_request.publicKeys.encryptionKey
)
)
);
// Encode it ==> Get octetstring
v_tbs := encvalue(v_cert.toBeSigned);
// Sign the certificate
v_sig := f_signWithEcdsa(bit2oct(v_tbs), p_digest, p_private_key);
if (PX_VE_ALG == e_nist_p256) {
v_cert.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_cert.signature_ := valueof(
m_signature_ecdsaBrainpoolP256r1(
m_ecdsaP256Signature(
m_eccP256CurvePoint_x_only(
substr(v_sig, 0, 32)
),
substr(v_sig, 32, 32)
)
)
);
v_cert.signature_ := valueof(
m_signature_ecdsaBrainpoolP384r1(
m_ecdsaP384Signature(
m_eccP384CurvePoint_x_only(
substr(v_sig, 0, 48)
),
substr(v_sig, 48, 48)
)
)
);
p_ec_certificate := valueof(v_cert);
log("f_generate_ec_certificate_for_inner_ec_response: p_ec_certificate= ", p_ec_certificate);
return true;
} // End of function f_generate_ec_certificate_for_inner_ec_response
function f_generate_at_certificate(
in octetstring p_private_key,
in InnerEcRequest p_inner_ec_request,
out Certificate p_at_certificate
) return boolean {
var SequenceOfPsidSsp v_appPermissions := { // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
valueof(m_appPermissions(36, { bitmapSsp := '830001'O })),
valueof(m_appPermissions(37, { bitmapSsp := '830001'O }))
};
var template (value) EtsiTs103097Certificate v_cert;
var bitstring v_tbs;
var Oct32 v_sig;
var bitstring v_enc_msg;
var PublicVerificationKey v_public_verification_key;
if (PX_EC_ALG == e_nist_p256) {
v_public_verification_key := valueof(
m_publicVerificationKey_ecdsaNistP256(
p_inner_ec_request.publicKeys.verificationKey.ecdsaNistP256
));
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
v_public_verification_key := valueof(
m_publicVerificationKey_ecdsaBrainpoolP256r1(
p_inner_ec_request.publicKeys.verificationKey.ecdsaBrainpoolP256r1
));
} else {
// Error
log("f_generate_ec_certificate: Wrong encryption algorithm, check PX_EC_ALG");
return false;
}
v_cert := m_etsiTs103097Certificate(
m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(f_hashWithSha256('616263'O))),
m_toBeSignedCertificate_at(
v_appPermissions,
m_verificationKeyIndicator_verificationKey(
v_public_verification_key
),
),
m_geographicRegion_identifiedRegion(
{
m_identifiedRegion_country_only(12),
m_identifiedRegion_country_only(34)
}
)
)
);
// Encode it ==> Get octetstring
v_tbs := encvalue(v_cert.toBeSigned);
// Sign the certificate
v_sig := f_signWithEcdsa(bit2oct(v_tbs), int2oct(11, 32), p_private_key);
if ((PX_VE_ALG == e_nist_p256) or (PX_VE_ALG == e_brainpool_p256_r1)) {
v_cert.signature_ := 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_p384_r1) {
v_cert.signature_ := m_signature_ecdsaBrainpoolP384r1(
m_ecdsaP384Signature(
m_eccP384CurvePoint_x_only(
substr(v_sig, 0, 48)
),
substr(v_sig, 48, 48)
)
);
}
log("v_cert= ", v_cert);
p_at_certificate := valueof(v_cert);
return true;
} // End of function f_generate_at_certificate
} // End of group generate_certificates
out octetstring p_private_key,
out octetstring p_public_key_compressed,
out integer p_compressed_mode,
out InnerEcRequest p_inner_ec_request
) return boolean {
var EccP256CurvePoint v_eccP256_curve_point;
log (">>> f_generate_inner_ec_request");
// Generate keys for the certificate to be requested
if (f_generate_key_pair(p_private_key, v_publicKeyX, v_publicKeyY, p_public_key_compressed, p_compressed_mode) == false) {
log ("f_generate_inner_ec_request: failed to generate keys");
if (p_compressed_mode == 0) {
v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(p_public_key_compressed));
v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(p_public_key_compressed));
// Build the Proof of Possession InnerEcRequest
p_inner_ec_request := valueof(
m_innerEcRequest(
m_publicVerificationKey_ecdsaNistP256(v_eccP256_curve_point)
),
m_certificateSubjectAttributes(
{ // ETSI TS 102 965 Table A.1: ETSI ITS standardized ITS-AIDs
valueof(m_appPermissions(c_its_aid_SCR, { bitmapSsp := '00C0'O }))
m_duration_years(1) // TODO Use PIXIT
{
m_identifiedRegion_country_only(12), // TODO Use PIXIT
m_identifiedRegion_country_only(34) // TODO Use PIXIT
}
),
if (PICS_SECPKI_REENROLMENT) { // This is a re-enrolment, the identifier of its current valid Enrolment Credential
log("f_generate_inner_ec_request: This is a re-enrolment");
p_inner_ec_request.itsId := PX_EC_HASHED_ID8;
}
log("f_generate_inner_ec_request: ", p_inner_ec_request);
} // End of function f_generate_inner_ec_request
function f_generate_inner_ec_request_signed_for_pop(
in octetstring p_private_key,
in InnerEcRequest p_inner_ec_request,
out Ieee1609Dot2Data p_inner_ec_request_signed_for_pop
) return boolean {
// Local variables
var template (value) EccP256CurvePoint v_eccP256_curve_point;
var octetstring v_encoded_inner_ec_request;
var template (value) ToBeSignedData v_tbs;
var octetstring v_tbs_signed;
var Signature v_signature;
// Encode it
v_encoded_inner_ec_request := bit2oct(encvalue(p_inner_ec_request));
// Signed the encoded InnerEcRequestSignedForPop
v_tbs := m_toBeSignedData(
m_signedDataPayload(
m_etsiTs103097Data_unsecured(
v_encoded_inner_ec_request
)
),
m_headerInfo_inner_pki_request(
-,
f_getCurrentTimeUtc()
)
);
// Signed the encoded InnerEcRequestSignedForPop
v_tbs_signed := f_signWithEcdsa(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key);
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
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_generate_inner_ec_request_signed_for_pop: v_signature= ", v_signature);
p_inner_ec_request_signed_for_pop := valueof(
m_etsiTs103097Data_signed(
m_signedData(
sha256,
v_tbs,
m_signerIdentifier_self,
log("<<< f_generate_inner_ec_request_signed_for_pop: p_inner_ec_request_signed_for_pop= ", p_inner_ec_request_signed_for_pop);
return true;
} // End of function f_generate_inner_ec_request_signed_for_pop
function f_verify_inner_ec_request_signed_for_pop(
in EtsiTs102941Data p_etsi_ts_102941_data,
out InnerEcRequest p_inner_ec_request
) return boolean {
var bitstring v_msg_bit;
log(">>> f_verify_inner_ec_request_signed_for_pop: ", p_etsi_ts_102941_data);
// 1. Decode content
v_msg_bit := oct2bit(p_etsi_ts_102941_data.content.enrolmentRequest.content.signedData.tbsData.payload.data.content.unsecuredData);
if (decvalue(v_msg_bit, p_inner_ec_request) != 0) {
log("f_verify_inner_ec_request_signed_for_pop: Failed to decode InnerEcRequest");
return false;
} else {
log("f_verify_inner_ec_request_signed_for_pop: v_inner_ec_request= ", p_inner_ec_request);
// 2. Verify the InnerEcRequestSignedForPop signature
}
return true;
} // End of function f_verify_inner_ec_request_signed_for_pop
function f_generate_inner_ec_response(
in octetstring p_inner_ec_request_hash,
in EtsiTs103097Certificate p_certificate,
out InnerEcResponse p_inner_ec_response
) return boolean {
// Local variables
// Build the Proof of Possession InnerEcResponse
p_inner_ec_response := valueof(
m_innerEcResponse_ok(
substr(p_inner_ec_request_hash, 0, 16),
p_certificate
)
);
return true;
} // End of function f_generate_inner_ec_response
group inner_at_xxx {
function f_generate_inner_at_request(
in Certificate p_ea_certificate,
in Oct8 p_ea_hashed_id8,
in Certificate p_ec_certificate,
in octetstring p_ec_private_key,
out octetstring p_private_key,
out octetstring p_public_key_compressed,
out integer p_compressed_key_mode,
out octetstring p_private_enc_key,
out octetstring p_public_compressed_enc_key,
out integer p_compressed_enc_key_mode,
out InnerAtRequest p_inner_at_request
) return boolean {
// Local variables
var octetstring v_public_key_x;
var octetstring v_public_key_y;
var octetstring v_public_enc_key_x;
var octetstring v_public_enc_key_y;
var bitstring v_enc_value;
var octetstring v_ec_hash;
var Oct8 v_ec_hashed_id8;
var octetstring public_enc_key_x;
var octetstring public_enc_key_y;
var Oct32 v_hmac_key;
var octetstring v_message_to_tag;
var Oct16 v_key_tag;
var octetstring v_hash_shared_at_request;
var template (value) ToBeSignedData v_tbs;
var octetstring v_tbs_signed;
var Ieee1609Dot2Data v_signed_at_signature;
var template (value) EccP256CurvePoint v_eccP256_curve_point;
var template (value) EccP256CurvePoint v_enc_eccP256_curve_point;
var HashAlgorithm v_hashId;
var Signature v_signature;
// Generate verification keys for the certificate to be requested
if (f_generate_key_pair(p_private_key, v_public_key_x, v_public_key_y, p_public_key_compressed, p_compressed_key_mode) == false) {
log("f_generate_inner_at_request: Failed to generate verification key");
return false;
}
log ("f_generate_inner_at_request: AT verification private key: ", p_private_key);
log ("f_generate_inner_at_request: AT verification public compressed key: ", p_public_key_compressed);
log ("f_generate_inner_at_request: AT verification public compressed mode: ", p_compressed_key_mode);
// Generate encryption keys for the certificate to be requested
if (PX_INCLUDE_ENCRYPTION_KEYS) {
if (f_generate_key_pair(p_private_enc_key, v_public_enc_key_x, v_public_enc_key_y, p_public_compressed_enc_key, p_compressed_enc_key_mode) == false) {
log("f_generate_inner_at_request: Failed to generate encryption key");
return false;
}
} else {
p_private_enc_key := ''O;
p_public_compressed_enc_key := ''O;
p_compressed_enc_key_mode := -1;
}
// Calculate the whole certificate SHA
v_enc_value := encvalue(p_ec_certificate);
if (ischosen(p_ec_certificate.issuer.sha256AndDigest)) {
v_ec_hash := f_hashWithSha256(bit2oct(v_enc_value));
v_ec_hashed_id8 := f_HashedId8FromSha256(v_ec_hash);
v_ec_hash := f_hashWithSha384(bit2oct(v_enc_value));
v_ec_hashed_id8 := f_HashedId8FromSha384(v_ec_hash);
log("f_generate_inner_at_request: v_ec_hash= ", v_ec_hash);
// Generate 32 octets length secret key
v_hmac_key := f_hashWithSha256(int2oct(f_getCurrentTime(), 12));
log("f_generate_inner_at_request: v_hmac_key= ", v_hmac_key);
// Generate tag based on the concatenation of verification keys & encryption keys
v_message_to_tag := v_public_key_x & v_public_key_y & v_public_enc_key_x & v_public_enc_key_y;
log("f_generate_inner_at_request: v_message_to_tag= ", v_message_to_tag); // FIXME encryption keys could be optional
v_key_tag := fx_hmac_sha256(v_hmac_key, v_message_to_tag); // TODO Rename and use a wrapper function
log("f_generate_inner_at_request: v_key_tag= ", v_key_tag);
// Build the SharedAtRequest
p_inner_at_request.sharedAtRequest := valueof(
m_shared_at_request(
p_ea_hashed_id8, // eaId identifies the EA certificate shared with EA entity
substr(v_key_tag, 0, 16), // Calculated keyTag
valueof(
m_certificate_subject_attributes( // FIXME Review subjectPermissions
p_ec_certificate.toBeSigned.appPermissions,
p_ec_certificate.toBeSigned.certRequestPermissions,
p_ec_certificate.toBeSigned.id,
p_ec_certificate.toBeSigned.validityPeriod,
p_ec_certificate.toBeSigned.region,
p_ec_certificate.toBeSigned.assuranceLevel
))) // Desired attributes
);
// Calculate the hash of the SharedAtRequest
v_hash_shared_at_request := f_hashWithSha256(bit2oct(encvalue(p_inner_at_request.sharedAtRequest)));
log("f_generate_inner_at_request: v_hash_shared_at_request= ", v_hash_shared_at_request);
// Build the ETsiTs103097Data-SignedExternalPayload
m_signedDataPayload_ext(v_hash_shared_at_request), // Payload containing extDataHash
m_headerInfo_inner_pki_request( // HeaderInfo
-,
f_getCurrentTimeUtc())
log("f_generate_inner_at_request: v_tbs= ", v_tbs);
// Signed ToBeSigned payload using the private key of EC certificate obtained from Enrolment request
// In case of ITS-S privacy, v_signed_at_signature contained the data to be encrypted
if (ischosen(p_ec_certificate.signature_.ecdsaBrainpoolP384r1Signature)) {
v_hashId := sha384;
v_tbs_signed := f_signWithEcdsaBrainpoolp384WithSha384(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
v_signature := valueof(
m_signature_ecdsaBrainpoolP384r1(
m_ecdsaP384Signature(
m_eccP384CurvePoint_x_only(
substr(v_tbs_signed, 0, 48)
),
substr(v_tbs_signed, 48, 48)
)
)
);
} else {
v_hashId := sha256;
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
if (ischosen(p_ec_certificate.signature_.ecdsaBrainpoolP256r1Signature)) {
v_tbs_signed := f_signWithEcdsaBrainpoolp256WithSha256(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
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 (ischosen(p_ec_certificate.signature_.ecdsaNistP256Signature)) {
v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
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 {
// Error
log("f_generate_inner_at_request: Failed to process signature");
return false;
}
v_signed_at_signature := valueof(
m_etsiTs103097Data_signed(
m_signedData(
m_signerIdentifier_digest(v_ec_hashed_id8), // Signer is thehasheId8 of the EC certificate obtained from Enrolment request
log("f_generate_inner_at_request: v_signed_at_signature= ", v_signed_at_signature);
if (PICS_ITS_S_WITH_PRIVACY) { // Build EtsiTs102097Data-Encrypted structure
var octetstring v_public_enc_key;
var integer v_compressed_mode;
var Oct12 v_nonce;
var Oct16 v_authentication_vector;
var Oct16 v_encrypted_sym_key;
var HashedId8 v_recipientId;
var octetstring v_public_compressed_ephemeral_key;
var integer v_public_compressed_ephemeral_mode;
var octetstring v_enc_signed_ec_signature;
var EncryptedDataEncryptionKey v_encrypted_data_encryption_key;
// Use EA certificate for the encryption
if (PX_EC_ALG == e_nist_p256) {
if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0)) {
v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_0;
v_compressed_mode := 0;
} else if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1)) {
v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesNistP256.compressed_y_1;
v_compressed_mode := 1;
} else {
log("f_generate_inner_at_request: Wrong NistP256 encryption variant");
return false;
}
v_enc_signed_ec_signature := f_encryptWithEciesNistp256WithSha256(bit2oct(encvalue(v_signed_at_signature)), v_public_enc_key, v_compressed_mode, ''O, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce, PICS_SEC_FIXED_KEYS);
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
v_enc_signed_ec_signature := f_encryptWithEciesBrainpoolp256WithSha256(bit2oct(encvalue(v_signed_at_signature)), v_public_enc_key, v_compressed_mode, ''O, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce, PICS_SEC_FIXED_KEYS);
} else {
log("f_generate_inner_at_request: Wrong encryption variant");
return false;
}
if (v_compressed_mode == 0) {
v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_enc_key));
} else {
v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_enc_key));
}
log("f_generate_inner_at_request: v_eccP256_curve_point= ", v_eccP256_curve_point);
log("f_generate_inner_at_request: v_encrypted_sym_key= ", v_encrypted_sym_key);
log("f_generate_inner_at_request: v_authentication_vector= ", v_authentication_vector);
v_encrypted_data_encryption_key := valueof(
m_encryptedDataEncryptionKey_eciesNistP256(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
v_encrypted_sym_key,
v_authentication_vector
)));
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0)) {
v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_0;
v_compressed_mode := 0;
} else if (ischosen(p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1)) {
v_public_enc_key := p_ea_certificate.toBeSigned.encryptionKey.publicKey.eciesBrainpoolP256r1.compressed_y_1;
v_compressed_mode := 1;
} else {
log("f_generate_inner_at_request: Wrong BrainpoolP256r1 encryption variant");
return false;
}
v_enc_signed_ec_signature := f_encryptWithEciesNistp256WithSha256(bit2oct(encvalue(v_signed_at_signature)), v_public_enc_key, v_compressed_mode, ''O, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce, PICS_SEC_FIXED_KEYS);
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
v_enc_signed_ec_signature := f_encryptWithEciesBrainpoolp256WithSha256(bit2oct(encvalue(v_signed_at_signature)), v_public_enc_key, v_compressed_mode, ''O, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, v_aes_sym_key, v_encrypted_sym_key, v_authentication_vector, v_nonce, PICS_SEC_FIXED_KEYS);
} else {
log("f_generate_inner_at_request: Wrong encryption variant");
return false;
}
v_encrypted_data_encryption_key := valueof(
m_encryptedDataEncryptionKey_eciesBrainpoolP256r1(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
v_encrypted_sym_key,
v_authentication_vector
)));
log("f_generate_inner_at_request: Wrong encryption variant");
v_recipientId := p_ea_hashed_id8; // RecipientId is the HashedId8 of the EA certificate
log("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));
}
p_inner_at_request.ecSignature := valueof(
m_ec_signature(
m_etsiTs103097Data_encrypted(
m_encryptedData(
{
m_recipientInfo_signedDataRecipInfo(
m_pKRecipientInfo(
v_recipientId,
v_encrypted_data_encryption_key ))
},
m_SymmetricCiphertext_aes128ccm(
m_aesCcmCiphertext(
v_enc_signed_ec_signature
)
)
)
} else { // Skip the encryption, alowed to be re-identified by the AA
p_inner_at_request.ecSignature := valueof(m_ec_signature_ext_payload(v_signed_at_signature));
// Build the InnerAtRequest, EcSignature field is already set
if (p_compressed_key_mode == 0) {
v_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_0(v_public_key_x);
v_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_1(v_public_key_x);
}
if (p_compressed_enc_key_mode == 0) {
v_enc_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_0(v_public_enc_key_x);
v_enc_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_1(v_public_enc_key_x);
}
p_inner_at_request.publicKeys := valueof( // The freshly generated public keys to be used for the requested AT certificate
m_publicKeys(
m_publicVerificationKey_ecdsaNistP256(
v_eccP256_curve_point
),
m_encryptionKey( // FIXME Encryption keys could be optional
-,
m_publicEncryptionKey_ecdsaNistP256(v_enc_eccP256_curve_point)
)
)
);
p_inner_at_request.hmacKey := v_hmac_key;
log("p_inner_at_request= ", p_inner_at_request);
return true;
} // End of function f_generate_inner_at_request
function f_generate_inner_at_response(
in octetstring p_authorization_request_hash,
in EtsiTs103097Certificate p_certificate,
out InnerAtResponse p_authorization_response
) return boolean {
// Local variables
// Build the Proof of Possession InnerEcResponse
p_authorization_response := valueof(
substr(p_authorization_request_hash, 0, 16),
p_certificate
} // End of function f_generate_inner_at_response
} // End of group inner_at_xxx
group authorization_validation_xxx {
} // End of group authorization_validation_xxx
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
function f_http_send(
in HeaderLines p_headers,
in template (value) HttpMessage p_http_message
) runs on ItsPkiHttp {
if (not(PICS_MULTIPLE_END_POINT)) {
httpPort.send(p_http_message);
} else {
var charstring_list v_content_text;
f_get_header(p_headers, c_header_content_text, v_content_text);
if (not(isvalue(v_content_text))) {
log("f_http_send: Failed to send message: header not found: ", c_header_content_text);
return;
}
if (v_content_text == { "inner_ec_request" }) {
log("f_http_send: Send on EC end point");
f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_EC }, p_headers);
if (ischosen(p_http_message.request)) {
p_http_message.request.header := p_headers;
} else {
p_http_message.response.header := p_headers;
}
httpEcPort.send(p_http_message);
} else if (v_content_text == { "inner_atv_request" }) {
log("f_http_send: Send on ATV end point");
f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_ATV }, p_headers);
if (ischosen(p_http_message.request)) {
p_http_message.request.header := p_headers;
} else {
p_http_message.response.header := p_headers;
}
httpAtVPort.send(p_http_message);
} else if (v_content_text == { "inner_at_request" }) {
log("f_http_send: Send on AT end point");
f_set_headers_list({ c_header_host }, { PICS_HEADER_HOST_AT }, p_headers);
if (ischosen(p_http_message.request)) {
p_http_message.request.header := p_headers;
} else {
p_http_message.response.header := p_headers;
}
httpAtPort.send(p_http_message);
} else {
log("f_http_send: Invalid header value: ", v_content_text);
}
}
} // End of function f_http_send
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
) runs on ItsPkiHttp return boolean {
var HeaderLines v_headers;
var Oct32 v_request_hash;
var Oct16 v_encrypted_sym_key;
var Oct16 v_aes_sym_key;
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");
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);
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
)))));
[not(PICS_MULTIPLE_END_POINT)] httpPort.receive(
mw_http_response(
mw_http_response_ok(
mw_http_message_body_binary(
mw_binary_body_ieee1609dot2_data(
mw_enrolmentResponseMessage(
mw_encryptedData(
-,
mw_SymmetricCiphertext_aes128ccm
))))))) -> value 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, false, v_etsi_ts_102941_data) == false) {
log("f_await_http_inner_ec_request_response: Failed to verify PKI message ***");
} else {
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, -))))) {
p_inner_ec_response := v_etsi_ts_102941_data.content.enrolmentResponse;
if (f_verify_ec_certificate(v_etsi_ts_102941_data.content.enrolmentResponse.certificate, vc_eaCertificate, p_compressed_public_key, p_compressed_mode)) {
log("f_await_http_inner_ec_request_response: Well-secured EA certificate received ***");
log("p_inner_ec_response= ", p_inner_ec_response);
return true;
} else {
log("f_await_http_inner_ec_request_response: Cannot verify EC certificate signature ***");
} else {
log("f_await_http_inner_ec_request_response: Unexpected message received ***");
}
}
}
[PICS_MULTIPLE_END_POINT] httpEcPort.receive(
mw_http_response(
mw_http_response_ok(
mw_http_message_body_binary(
mw_binary_body_ieee1609dot2_data(
mw_enrolmentResponseMessage(
mw_encryptedData(
-,
mw_SymmetricCiphertext_aes128ccm
))))))) -> value 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, false, v_etsi_ts_102941_data) == false) {
log("f_await_http_inner_ec_request_response: Failed to verify PKI message ***");
} else {
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, -))))) {
p_inner_ec_response := v_etsi_ts_102941_data.content.enrolmentResponse;
if (f_verify_ec_certificate(v_etsi_ts_102941_data.content.enrolmentResponse.certificate, vc_eaCertificate, p_compressed_public_key, p_compressed_mode)) {
log("f_await_http_inner_ec_request_response: Well-secured EA certificate received ***");
log("p_inner_ec_response= ", p_inner_ec_response);
return true;
} else {
log("f_await_http_inner_ec_request_response: Cannot verify EC certificate signature ***");
return true; // For debug mode only
}
} else {
log("f_await_http_inner_ec_request_response: Unexpected message received ***");
}
}
}
[] tc_ac.timeout {
log("f_await_http_inner_ec_request_response: Expected message not received ***");
}
} // End of 'alt' statement
return false;
} // End of function f_await_http_inner_ec_request_response
} // End of group awaiting_messages
* @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,
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");
// Signed the encoded PKI message
v_tbs := m_toBeSignedData(
m_signedDataPayload(
m_headerInfo_inner_pki_request(-, f_getCurrentTimeUtc())
log("f_build_pki_secured_request_message_signed_with_pop: signer: ", p_signer_identifier);
if (PICS_SECPKI_REENROLMENT == false) { // This is the first enrolment, we used Factory keys
//if (ischosen(p_signer_identifier.self_)) {
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)), PX_EC_HASH, p_private_key);
}
// Add the signature and create EtsiTs103097Data-Signed data structure
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
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));
// Encrypt encode EtsiTs103097Data-Signed data structure
if (PICS_SEC_FIXED_KEYS) {
p_salt := '77C0637C3558B3238FDE1EEC376DA080BE4076FB8491CA0F8C19FD34DF298CEB'O;
}
if (PX_EC_ALG == e_nist_p256) {
v_encrypted_request := f_encryptWithEciesNistp256WithSha256(v_encoded_request, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, PICS_SEC_FIXED_KEYS);
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
v_encrypted_request := f_encryptWithEciesBrainpoolp256WithSha256(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, PICS_SEC_FIXED_KEYS);
} 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));
}
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
if (PX_EC_ALG == e_nist_p256) {
v_encrypted_data_encryption_key := valueof(
m_encryptedDataEncryptionKey_eciesNistP256(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
p_encrypted_sym_key,
p_authentication_vector
)));
} else if (PX_EC_ALG == 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);
if (PICS_SEC_FIXED_KEYS) {
p_request_hash := '10ED97A2F2933DD3AC55F47022D125E18F5E1AA024613E616A75BA4979EFE318'O;
} else {
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);
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
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
p_salt := '77C0637C3558B3238FDE1EEC376DA080BE4076FB8491CA0F8C19FD34DF298CEB'O;
if (PX_EC_ALG == e_nist_p256) {
v_encrypted_request := f_encryptWithEciesNistp256WithSha256(p_pki_message, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, PICS_SEC_FIXED_KEYS);
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
v_encrypted_request := f_encryptWithEciesBrainpoolp256WithSha256(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, PICS_SEC_FIXED_KEYS);
} 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));
if (PX_EC_ALG == e_nist_p256) {
v_encrypted_data_encryption_key := valueof(
m_encryptedDataEncryptionKey_eciesNistP256(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
p_encrypted_sym_key,
p_authentication_vector
)));
} else if (PX_EC_ALG == 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);
if (PICS_SEC_FIXED_KEYS) {
p_request_hash := '10ED97A2F2933DD3AC55F47022D125E18F5E1AA024613E616A75BA4979EFE318'O;
} else {
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
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
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");
// 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
if (PICS_SEC_FIXED_KEYS) {
p_salt := '77C0637C3558B3238FDE1EEC376DA080BE4076FB8491CA0F8C19FD34DF298CEB'O;
}
if (PX_EC_ALG == e_nist_p256) {
v_encrypted_request := f_encryptWithEciesNistp256WithSha256(v_pki_message, p_public_key_compressed, p_compressed_mode, p_salt, v_public_compressed_ephemeral_key, v_public_compressed_ephemeral_mode, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, PICS_SEC_FIXED_KEYS);
} else if (PX_EC_ALG == e_brainpool_p256_r1) {
v_encrypted_request := f_encryptWithEciesBrainpoolp256WithSha256(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, PICS_SEC_FIXED_KEYS);
} else {
log("f_build_pki_secured_request_message: Wrong encryption variant");
return false;
}
log("f_build_pki_secured_request_message: p_aes_sym_key= ", p_aes_sym_key);
log("f_build_pki_secured_request_message: p_encrypted_sym_key= ", p_encrypted_sym_key);
log("f_build_pki_secured_request_message: p_authentication_vector= ", p_authentication_vector);
log("f_build_pki_secured_request_message: p_nonce= ", p_nonce);
log("f_build_pki_secured_request_message: p_recipientId= ", p_recipientId);
if (p_recipientId == int2oct(0, 8)) {
log("f_build_pki_secured_request_message: f_hashWithSha256(v_encrypted_sym_key)= ", f_hashWithSha256(p_encrypted_sym_key));
v_recipientId := f_HashedId8FromSha256(f_hashWithSha256(p_encrypted_sym_key));
} else {
v_recipientId := p_recipientId;
}
log("f_build_pki_secured_request_message: v_recipientId= ", v_recipientId);
// Fill Certificate template with the public compressed keys (canonical form)
if (v_public_compressed_ephemeral_mode == 0) {
v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_0(v_public_compressed_ephemeral_key));
} else {
v_eccP256_curve_point := valueof(m_eccP256CurvePoint_compressed_y_1(v_public_compressed_ephemeral_key));
}
if (PX_EC_ALG == e_nist_p256) {
v_encrypted_data_encryption_key := valueof(
m_encryptedDataEncryptionKey_eciesNistP256(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
p_encrypted_sym_key,
p_authentication_vector
)));
} else if (PX_EC_ALG == 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(
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);
if (PICS_SEC_FIXED_KEYS) {
p_request_hash := '10ED97A2F2933DD3AC55F47022D125E18F5E1AA024613E616A75BA4979EFE318'O;
} else {
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);
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
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
* @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_getCurrentTimeUtc())
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
);
if (ischosen(p_signer_identifier.self_)) {
v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key);
} else {
var charstring v_certificate_id;
var octetstring v_hash;
fx_readCertificateFromDigest(p_signer_identifier.digest, v_certificate_id); // TODO Add a wrapper function
f_getCertificateHash(v_certificate_id, v_hash);
v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_hash, p_private_key);
}
// Add the signature and create EtsiTs103097Data-Signed data structure
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
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
/**
* @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);
// 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));
if (f_getCertificateFromDigest(f_HashedId8FromSha256(p_issuer), v_certificate) == 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_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,
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;
var boolean v_ret;
log(">>> f_verify_pki_response_message: p_private_enc_key= ", p_private_enc_key);
log(">>> f_verify_pki_response_message: p_aes_sym_key= ", p_aes_sym_key);
log(">>> f_verify_pki_response_message: p_authentication_vector= ", p_authentication_vector);
log(">>> f_verify_pki_response_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
// 1. Decrypt the data
v_plain_message := fx_decrypt_aes_128_ccm_test(p_aes_sym_key, p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.ciphertext.aes128ccm.nonce, p_ieee1609dot2_encrypted_and_signed_data.content.encryptedData.ciphertext.aes128ccm.ccmCiphertext);
if (isbound(v_plain_message) == false) {
return false;
}
log("f_verify_pki_response_message: v_plain_message= ", v_plain_message);
// 2. Decode it
v_tbs := oct2bit(v_plain_message);
if (decvalue(v_tbs, v_ieee1609dot2_signed_data) != 0) {
log("f_verify_pki_response_message: v_ieee1609dot2_signed_data= ", v_ieee1609dot2_signed_data);
log("f_verify_pki_response_message: 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;
}
}
if (f_verifyEcdsa(bit2oct(v_tbs), p_issuer, v_ieee1609dot2_signed_data.content.signedData.signature_, v_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
if (p_check_security == true) {
return false;
}
log("f_verify_pki_response_message: 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;
}
if (p_etsi_ts_102941_data.version != PkiProtocolVersion) {
} // End of function f_verify_pki_response_message
* @desc Verify the EC certificate generated by the EA entity
* @param p_ec_certificate The new EC certificate
* @param p_ea_certificate The certificate issuer
* @param p_public_key_compressed The public compressed key (canonical form) generated for the InnerEcRequest
* @param p_compressed_mode The public compressed key mode
* @return true on success, false otherwise
*/
function f_verify_ec_certificate(
in Certificate p_ec_certificate,
in octetstring p_public_key_compressed,
in integer p_compressed_mode
) return boolean {
var HashedId8 v_ec_cert_hashed_id8;
// Calculate the HashedId8 of the whole certificate
v_encoded_cert := encvalue(p_ec_certificate);
v_ec_cert_hash := f_hashWithSha256(bit2oct(v_encoded_cert));
log("f_verify_ec_certificate: ==> EC certificate Hash: ", v_ec_cert_hash);
v_ec_cert_hashed_id8 := f_HashedId8FromSha256(v_ec_cert_hash);
log("f_verify_ec_certificate: ==> EC certificate HashedId8: ", v_ec_cert_hashed_id8);
// Check the signer
log("f_verify_ec_certificate: ", match(p_ec_certificate.issuer, mw_issuerIdentifier_sha256AndDigest));
if (match(p_ec_certificate.issuer, mw_issuerIdentifier_sha256AndDigest)) {
// Check EC certificate signature
// TODO Who sign the EC certificate?
if (f_verifyCertificateSignatureWithPublicKey(p_ec_certificate, p_ea_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
log("f_verify_ec_certificate: Signature not verified");
return false;
// TODO Check that requested information are present
return true;
} // End of function f_verify_ec_certificate
* @desc Verify the generated AT certificate
* @param p_at_certificate The new AT certificate
* @param p_ea_certificate The certificate issuer
* @param p_public_key_compressed The public compressed key (canonical form) generated for the InnerAtRequest
* @param p_compressed_mode The public compressed key mode
* @return true on success, false otherwise
*/
function f_verify_at_certificate(
in Certificate p_at_certificate,
in Certificate p_aa_certificate,
in octetstring p_public_key_compressed,
in integer p_compressed_mode
) return boolean {
var bitstring v_encoded_cert;
var HashedId8 v_at_cert_hashed_id8;
// Calculate the HashedId8 of the whole certificate
v_encoded_cert := encvalue(p_at_certificate);
v_at_cert_hashed_id8 := f_HashedId8FromSha256(f_hashWithSha256(bit2oct(v_encoded_cert)));
log("f_verify_at_certificate: EC certificate HashedId8: ", v_at_cert_hashed_id8);
// Check the signer
log("f_verify_at_certificate: ", match(p_at_certificate.issuer, mw_issuerIdentifier_self()));
if (match(p_at_certificate.issuer, mw_issuerIdentifier_self)) {
return false;
}
// Check EC certificate signature
// TODO Who sign the EC certificate?
if (f_verifyCertificateSignatureWithPublicKey(p_at_certificate, p_aa_certificate.toBeSigned.verifyKeyIndicator.verificationKey) == false) {
log("f_verify_at_certificate: Signature not verified");
return false;
}
return true;
} // End of function f_verify_at_certificate
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 {
log(">>> f_extract_enc_key: ", p_certificate);
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;
log("f_extract_enc_key: Non canonical certificate: ", p_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 certificate: ", p_certificate);
log("f_extract_enc_key: Invalid certificate: ", p_certificate);
return false;
}
return true;
} // End of function f_extract_enc_key
} // End of group security_function
altstep a_default_pki_http() runs on ItsPkiHttp {
[not(PICS_MULTIPLE_END_POINT)] httpPort.receive(
mw_http_response(
mw_http_response_ko
)) {
tc_ac.stop;
log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
}
[not(PICS_MULTIPLE_END_POINT)] httpPort.receive(mw_http_request) {
log("*** a_default: ERROR: Unexpected HTTP Request received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[not(PICS_MULTIPLE_END_POINT)] httpPort.receive(mw_http_response) {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP Response received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[not(PICS_MULTIPLE_END_POINT)] httpPort.receive {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP message received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[] a_shutdown() {
log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
stop;
}
} // End of altstep a_default_pki_http
altstep a_default_pki_http_ec() runs on ItsPkiHttp {
[PICS_MULTIPLE_END_POINT] httpEcPort.receive(
mw_http_response(
mw_http_response_ko
)) {
tc_ac.stop;
log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
}
[PICS_MULTIPLE_END_POINT] httpEcPort.receive(mw_http_request) {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP Request received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[PICS_MULTIPLE_END_POINT] httpEcPort.receive(mw_http_response) {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP Response received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP message received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[] a_shutdown() {
log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
stop;
}
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
} // End of altstep a_default_pki_http_ec
altstep a_default_pki_http_atv() runs on ItsPkiHttp {
[PICS_MULTIPLE_END_POINT] httpAtVPort.receive(
mw_http_response(
mw_http_response_ko
)) {
tc_ac.stop;
log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
}
[PICS_MULTIPLE_END_POINT] httpAtVPort.receive(mw_http_request) {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP Request received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[PICS_MULTIPLE_END_POINT] httpAtVPort.receive(mw_http_response) {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP Response received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[PICS_MULTIPLE_END_POINT] httpAtVPort.receive {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP message received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[] a_shutdown() {
log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
stop;
}
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
} // End of altstep a_default_pki_http_atv
altstep a_default_pki_http_at() runs on ItsPkiHttp {
[PICS_MULTIPLE_END_POINT] httpAtPort.receive(
mw_http_response(
mw_http_response_ko
)) {
tc_ac.stop;
log("*** " & testcasename() & ": FAIL: Unexpected message received ***");
f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error);
}
[PICS_MULTIPLE_END_POINT] httpAtPort.receive(mw_http_request) {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP Request received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[PICS_MULTIPLE_END_POINT] httpAtPort.receive(mw_http_response) {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP Response received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[PICS_MULTIPLE_END_POINT] httpAtPort.receive {
tc_ac.stop;
log("*** a_default: ERROR: Unexpected HTTP message received ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
[] a_shutdown() {
log("*** a_default: INFO: TEST COMPONENT NOW STOPPING ITSELF! ***");
stop;
}
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
altstep a_await_ec_http_response_from_iut(
template HttpMessage p_http_message,
out HttpMessage p_response
) runs on ItsPkiHttp {
[not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_response {
log("a_await_ec_http_response_from_iut: Received message on httpPort");
}
[PICS_MULTIPLE_END_POINT] httpEcPort.receive(p_http_message) -> value p_response {
log("a_await_ec_http_response_from_iut: Received message on httpEcPort");
}
} // End of altstep a_await_ec_http_response_from_iut
altstep a_await_at_http_response_from_iut(
template HttpMessage p_http_message,
out HttpMessage p_response
) runs on ItsPkiHttp {
[not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_response {
log("a_await_at_http_response_from_iut: Received message on httpPort");
}
[PICS_MULTIPLE_END_POINT] httpAtPort.receive(p_http_message) -> value p_response {
log("a_await_at_http_response_from_iut: Received message on httpAtPort");
}
} // End of altstep a_await_at_http_response_from_iut
altstep a_await_avt_http_response_from_iut(
template HttpMessage p_http_message,
out HttpMessage p_response
) runs on ItsPkiHttp {
[not(PICS_MULTIPLE_END_POINT)] httpPort.receive(p_http_message) -> value p_response {
log("a_await_avt_http_response_from_iut: Received message on httpPort");
}
[PICS_MULTIPLE_END_POINT] httpAtVPort.receive(p_http_message) -> value p_response {
log("a_await_avt_http_response_from_iut: Received message on httpAtVPort");
}
} // End of altstep a_await_avt_http_response_from_iut