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_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;
* @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);
f_connect4SelfOrClientSync();
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_readCertificate(p_aa_certificate_id, vc_ecCertificate); // TODO To be removed
// f_readSigningKey(p_aa_certificate_id, vc_ecPrivateKey); // TODO To be removed
// f_readEncryptingKey(p_ea_certificate_id, vc_eaPrivateEncKey); // TODO To be removed
f_getCertificateDigest(p_ea_certificate_id, vc_eaHashedId8);
f_getCertificateHash(p_ea_certificate_id, 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("vc_aaHashedId8= ", vc_aaHashedId8);
log("vc_aaWholeHash= ", vc_aaWholeHash);
// f_readCertificate(p_peerCertificateId, vc_peerEaCertificate); // TODO To be removed
// f_getCertificateHash(p_peerCertificateId, vc_eaPeerWholeHash); // TODO To be removed
activate(a_default_pki_http());
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_cfHttpDown() runs on ItsPkiHttp /* TITAN TODO: system ItsPkiHttpSystem */ {
unmap(self:httpPort, system:httpPort);
f_disconnect4SelfOrClientSync();
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 := f_setupIutCertificate(vc_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_sendUtTriggerPrimitive(
in octetstring p_private_key,
in octetstring p_public_key_compressed,
in integer p_compressed_mode
) 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;
log("*** f_sendUtTriggerPrimitive: 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_sendUtTriggerPrimitive
} // End of group ut_port
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;
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_inner_ec_request: ERROR: Failed to generate InnerEcRequest ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
// 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("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);
log("*** f_http_build_inner_ec_request: First enrolment: ", PX_FIRST_ENROLMENT);
if (PX_FIRST_ENROLMENT == true) { // 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);
var Oct32 v_ec_private_key;
var HashedId8 v_ec_hashed_id8;
// Retrieve EC certificate from the first enrolment
// TODO Set v_ec_private_key & v_ec_hashed_id8
v_ret_code := f_build_pki_secured_request_message_signed_with_pop(v_ec_private_key, valueof(m_signerIdentifier_digest(v_ec_hashed_id8)), v_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);
}
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);
}
// 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("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_inner_ec_request: ERROR: Non canonical EA certificate ***");
f_selfOrClientSyncAndVerdict("error", e_error);
}
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 (PX_FIRST_ENROLMENT == true) { // 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);
var Oct32 v_ec_private_key;
var HashedId8 v_ec_hashed_id8;
// Retrieve EC certificate from the first enrolment
// TODO Set v_ec_private_key & v_ec_hashed_id8
v_ret_code := f_build_pki_secured_request_message_signed_with_pop(v_ec_private_key, valueof(m_signerIdentifier_digest(v_ec_hashed_id8)), v_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_authorization_request(
in Certificate p_ec_certificate, // Enrolment credentials certificate
in octetstring p_ec_private_key,
out octetstring p_private_key,
out octetstring p_public_key_compressed,
out integer p_compressed_mode,
out octetstring p_private_enc_key,
out octetstring p_public_compressed_enc_key,
out integer p_compressedEncMode,
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 verification keys for the certificate to be requested
if (f_generate_key_pair_nistp256(p_private_key, v_public_key_x, v_public_key_y, p_public_key_compressed, p_compressed_mode) == false) {
log("*** f_http_build_authorization_request: ERROR: Failed to generate verification key ***");
f_selfOrClientSyncAndVerdict("error", e_error);
return;
}
// Generate encryption keys for the certificate to be requested
if (PX_INCLUDE_ENCRYPTION_KEYS) {
if (f_generate_key_pair_nistp256(p_private_enc_key, v_public_enc_key_x, v_public_enc_key_y, p_public_compressed_enc_key, p_compressedEncMode) == false) {
log("*** f_http_build_authorization_request: ERROR: Failed to generate encryption key ***");
f_selfOrClientSyncAndVerdict("error", e_error);
return;
}
}
if (f_generate_inner_at_request(vc_eaCertificate, vc_eaHashedId8, p_ec_certificate, p_ec_private_key, p_private_key, v_public_key_x, v_public_key_y, p_compressed_mode, p_private_enc_key, v_public_enc_key_x, v_public_enc_key_y, p_compressedEncMode, v_inner_at_request) == false) {
log("*** f_http_build_authorization_request: ERROR: Failed to generate AuthorizationValidationRequest ***");
f_selfOrClientSyncAndVerdict("error", e_error);
log("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_inner_ec_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);
log("*** f_http_build_authorization_request: First enrolment: ", PX_FIRST_ENROLMENT);
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(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 octetstring p_public_key_compressed,
out integer p_compressed_mode,
out Ieee1609Dot2Data p_ieee1609dot2_signed_and_encrypted_data
) 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;
/* TODO if (f_generate_authorization_validation_request(vc_eaCertificate, vc_eaHashedId8, p_private_key, p_public_key_compressed, p_compressed_mode, v_authorization_validation_request) == false) {
log("*** f_http_build_authorization_validation_request: ERROR: Failed to generate AuthorizationValidationRequest ***");
f_selfOrClientSyncAndVerdict("error", e_error);
// 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_inner_ec_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);
/**
TODO: Load certificate according to the IUT role
==> a complete fucntion which set up the TestSustem certificate,keyy... according to the IUT role
**/
log("*** f_http_build_inner_ec_request: ERROR: Need to add TestSystem variable vc_aa ***");
f_selfOrClientSyncAndVerdict("error", e_error);
/* if (f_build_pki_secured_request_message_signed_with_pop(vc_aaPrivateKey, valueof(m_signerIdentifier_digest(vc_aaHashedId8)), vc_eaHashedId8/\*recipientId*\/, v_public_enc_key, v_compressed_enc_key_mode, vc_eaWholeHash, bit2oct(encvalue(m_etsiTs102941Data_authorization_validation_request(v_authorization_validation_request))), p_ieee1609dot2_signed_and_encrypted_data, p_request_hash) == false) { */
/* log("*** f_http_build_authorization_validation_request: ERROR: Failed to generate InnerEcRequestSignedForPop ***"); */
/* 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);
} // 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;
log(">>> f_generate_ec_certificate");
// Generate verification keys for the certificate
if (f_generate_key_pair_nistp256(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));
}
v_cert := m_etsiTs103097Certificate(
m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(f_hashWithSha256('616263'O))),
m_toBeSignedCertificate_at(
v_appPermissions,
m_verificationKeyIndicator_verificationKey(
m_publicVerificationKey_ecdsaNistP256(
)),
m_validityPeriod(
17469212,
m_duration_years(10)
),
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 using ECDSA/SHA-256 (NIST p-256)
v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_tbs), int2oct(11, 32), p_private_key);
v_cert.signature_ := m_signature_ecdsaNistP256(
m_ecdsaP256Signature(
m_eccP256CurvePoint_x_only(
substr(v_sig, 0, 32)
),
substr(v_sig, 32, 32)
)
);
log("f_generate_ec_certificate: v_cert= ", v_cert);
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
p_ec_certificate := valueof(v_cert);
return true;
} // End of function f_generate_ec_certificate
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;
v_cert := m_etsiTs103097Certificate(
m_issuerIdentifier_sha256AndDigest(f_HashedId8FromSha256(f_hashWithSha256('616263'O))),
m_toBeSignedCertificate_at(
v_appPermissions,
m_verificationKeyIndicator_verificationKey(
m_publicVerificationKey_ecdsaNistP256(
p_inner_ec_request.publicKeys.verificationKey.ecdsaNistP256
)),
m_validityPeriod(
17469212,
m_duration_years(10)
),
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 using ECDSA/SHA-256 (NIST p-256)
v_sig := f_signWithEcdsaNistp256WithSha256(bit2oct(v_tbs), int2oct(11, 32), p_private_key);
v_cert.signature_ := m_signature_ecdsaNistP256(
m_ecdsaP256Signature(
m_eccP256CurvePoint_x_only(
substr(v_sig, 0, 32)
),
substr(v_sig, 32, 32)
)
);
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_nistp256(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));
log ("f_generate_inner_ec_request: ", v_eccP256_curve_point);
// 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(623, { bitmapSsp := '00C0'O }))
f_getCurrentTime() / 1000,
m_duration_years(1) // TODO Use PIXIT
{
m_identifiedRegion_country_only(12), // TODO Use PIXIT
m_identifiedRegion_country_only(34) // TODO Use PIXIT
}
),
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;
// 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_ec_request(
c_its_aid_SCR,
f_getCurrentTimeUtc()
)
);
// Signed the encoded InnerEcRequestSignedForPop
v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), int2oct(0, 32), p_private_key);
// Finalyse signed InnerEcRequestSignedForPop
p_inner_ec_request_signed_for_pop := valueof(
m_etsiTs103097Data_signed(
m_signedData(
sha256,
v_tbs,
m_signerIdentifier_self,
m_signature_ecdsaNistP256(
m_ecdsaP256Signature(
m_eccP256CurvePoint_x_only(
substr(v_tbs_signed, 0, 32)
),
substr(v_tbs_signed, 32, 32)
)
)
)
)
);
return true;
} // End of function f_generate_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 octetstring p_ec_private_key,
in octetstring p_public_key_x,
in octetstring p_public_key_y,
in integer p_compressed_key_mode,
in octetstring p_private_enc_key,
in octetstring p_public_enc_key_x,
in octetstring p_public_enc_key_y,
in integer p_compressed_enc_key_mode,
out InnerAtRequest p_inner_at_request
) return boolean {
// Local variables
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_ec_signature;
var template (value) EccP256CurvePoint v_eccP256_curve_point;
var template (value) EccP256CurvePoint v_enc_eccP256_curve_point;
var HashAlgorithm v_hashId;
// 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("v_ec_hash= ", v_ec_hash);
// Generate 32 octets length secret key
v_hmac_key := f_hashWithSha256(int2oct(f_getCurrentTime(), 12));
log("v_hmac_key= ", v_hmac_key);
// Generate tag based on the concatenation of verification keys & encryption keys
v_message_to_tag := p_public_key_x & p_public_key_y & p_public_enc_key_x & p_public_enc_key_y;
log("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("v_key_tag= ", v_key_tag);
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,
{ { subjectPermissions := { all_ := NULL }, minChainLength := 1, chainLengthRange := 0, eeType := '00000000'B } },
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("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_ec_request( // HeaderInfo
c_its_aid_SCR,
f_getCurrentTimeUtc())
);
log("v_tbs= ", v_tbs);
// Signed ToBeSigned payload using the private key of EC certificate obtained from Enrolment request
v_tbs_signed := f_signWithEcdsaNistp256WithSha256(bit2oct(encvalue(v_tbs)), v_ec_hash, p_ec_private_key);
// In case of ITS-S privacy, v_signed_ec_signature contained the data to be encrypted
if (ischosen(p_ec_certificate.signature_.ecdsaBrainpoolP384r1Signature)) {
v_hashId := sha384;
} else {
v_hashId := sha256;
}
v_signed_ec_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
m_signature_ecdsaNistP256(
m_ecdsaP256Signature(
m_eccP256CurvePoint_x_only(
substr(v_tbs_signed, 0, 32)
),
substr(v_tbs_signed, 32, 32)
)
)
)
)
);
log("v_signed_ec_signature= ", v_signed_ec_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;
// Use EA certificate for the encryption
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 {
return false;
}
v_enc_signed_ec_signature := f_encryptWithEciesNistp256WithSha256(bit2oct(encvalue(v_signed_ec_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);
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,
m_encryptedDataEncryptionKey_eciesNistP256(
m_evciesP256EncryptedKey(
v_eccP256_curve_point,
v_authentication_vector
))))
},
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_ec_signature));
}
// Build the InnerAtRequest, EcSignature field is already set
if (p_compressed_key_mode == 0) {
v_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_0(p_public_key_x);
} else {
v_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_1(p_public_key_x);
}
if (p_compressed_enc_key_mode == 0) {
v_enc_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_0(p_public_enc_key_x);
} else {
v_enc_eccP256_curve_point := m_eccP256CurvePoint_compressed_y_1(p_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
group awaiting_messages {
function f_await_http_inner_ec_request_response(
out Oct32 p_private_key,
out Oct32 p_compressed_public_key,
out integer p_compressed_mode,
out InnerEcResponse p_inner_ec_response
) 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");
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
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);
httpPort.send(
m_http_request(
m_http_request_post(
PICS_HTTP_POST_URI,
v_headers,
m_http_message_body_binary(
m_binary_body_ieee1609dot2_data(
v_ieee1609dot2_signed_and_encrypted_data
)))));
tc_ac.start;
alt {
[] 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 {
tc_ac.stop;
if (f_verify_pki_message(p_private_key, v_aes_sym_key, v_authentication_vector, vc_eaWholeHash, vc_eaCertificate, 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, -))))) {
if (f_verify_ec_certificate(v_etsi_ts_102941_data.content.enrolmentResponse.certificate, p_compressed_public_key, p_compressed_mode)) {
p_inner_ec_response := v_etsi_ts_102941_data.content.enrolmentResponse;
log("f_await_http_inner_ec_request_response: Well-secured EA certificate received ***");
log("p_inner_ec_response= ", p_inner_ec_response);
return true;
} else {
log("f_await_http_inner_ec_request_response: Cannot verify EC certificate signature ***");