Newer
Older
/**
* @author ETSI / STF481
* @version $URL$
* $Id$
* @desc Module containing functions for Security Protocol
*
*/
module LibItsSecurity_Functions {
import from LibCommon_BasicTypesAndValues all;
garciay
committed
import from LibCommon_DataStrings all;
garciay
committed
// LibItsCommon
import from LibItsCommon_Functions all;
import from LibItsSecurity_TypesAndValues all;
garciay
committed
import from LibItsSecurity_Templates all;
import from LibItsSecurity_Pixits all;
import from LibItsSecurity_TestSystem all;
* @desc Produces a 256-bit (32-byte) hash value
* @param p_toBeHashedData Data to be used to calculate the hash value
* @return The hash value
*/
function f_hashWithSha256(
) return Oct32 {
return fx_hashWithSha256(p_toBeHashedData);
} // End of function f_hashWithSha256
* @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signaturee
* @param p_toBeSignedSecuredMessage The data to be signed
* @return The signature value
*/
function f_signWithEcdsaNistp256WithSha256(
) runs on ItsSecurityBaseComponent return octetstring {
return fx_signWithEcdsaNistp256WithSha256(
vc_signingPrivateKey
} // End of function f_signWithEcdsaNistp256WithSha256
* @desc Compute the HashedId8 value from the hash value
* @param p_hash The hash value
* @return The HashedId8 value
* @verdict
*/
function f_HashedId8FromSha256(
) return HashedId8 {
return substr(p_hash, lengthof(p_hash) - 8, 8);
* @desc Compute the HashedId3 value from the HashedId8 value
* @param p_hashp_hashedId8 The HashedId8 value
* @return The HashedId3 value
* @verdict Unchanged
*/
function f_HashedId3FromHashedId8(
in HashedId8 p_hashedId8
) return HashedId3 {
return substr(p_hashedId8, lengthof(p_hashedId8) - 3, 3);
} // End of function f_HashedId3FromHashedId8
* @desc Verify the signature of the specified data
* @param p_toBeVerifiedData The data to be verified
* @param p_signature The signature
* @param p_ecdsaNistp256PublicKeyX The public key (x coordinate)
* @param p_ecdsaNistp256PublicKeyY The public key (y coordinate)
* @return true on success, false otherwise
*/
garciay
committed
function f_verifyWithEcdsaNistp256WithSha256(
in octetstring p_toBeVerifiedData,
in octetstring p_signature,
in octetstring p_ecdsaNistp256PublicKeyX,
in octetstring p_ecdsaNistp256PublicKeyY
) return boolean {
return fx_verifyWithEcdsaNistp256WithSha256(
p_toBeVerifiedData,
p_signature,
p_ecdsaNistp256PublicKeyX,
p_ecdsaNistp256PublicKeyY);
} // End of function f_verifyWithEcdsaNistp256WithSha256
* @desc Calculate digest over the certificate
* @param p_cert The certificate
* @return the digest
* @see Draft ETSI TS 103 097 V1.1.9 Clause 4.2.13 HashedId8
function f_calculateDigestFromCertificate(
) return HashedId8 {
var octetstring v_toBeHashedData;
var octetstring v_hash;
// Search for digest in the signer_infos field first
for (var integer v_counter := 0; v_counter < lengthof(p_cert.signer_infos); v_counter := v_counter + 1) {
if (p_cert.signer_infos[v_counter].type_ == e_certificate_digest_with_sha256) {
return p_cert.signer_infos[v_counter].signerInfo.digest;
}
} // End of 'for' statement
log ("f_calculateDigestFromCertificate: Not found in certificate, compute it");
v_toBeHashedData := bit2oct(encvalue(p_cert));
v_hash := f_hashWithSha256(v_toBeHashedData);
return substr(v_hash, lengthof(v_hash) - 8, 8);
/**
* @desc 2004/01/01 00:00:00 epoch in milliseconds
*/
const Time64 c_offsetGnTime := 1072915200;
* @desc Build a template of a secured beacon to be used for the Test Adapter secured beaconing processing
*/
function f_buildSecuredMessagePayloadToBeSigned(
) runs on ItsSecurityBaseComponent return ToBeSignedSecuredMessage {
var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
if (p_includeCertificate == true) {
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
{ // Field HeaderFields
m_header_field_signer_info(
m_signerInfo_certificate(
vc_atCertificate
) // End of template m_signerInfo_certificate
), // End of template m_header_field_signer_info
m_header_field_generation_time(oct2int('BBBBBBBB'O)), // To be replaced by TA with generation time
m_header_field_generation_location(
),
m_header_field_verification_advice_recommended
}, // End of field HeaderFields
m_payload_signed(
'AAAAAAAAAA'O // To be replaced by TA with real payload
),
e_signature
);
} else {
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
{ // Field HeaderFields
m_header_field_signer_info(
m_signerInfo_digest(
vc_atCertificate.signer_infos[0].signerInfo.digest
) // End of template m_signerInfo_certificate
), // End of template m_header_field_signer_info
m_header_field_generation_time(oct2int('BBBBBBBB'O)), // To be replaced by TA with generation time
m_header_field_generation_location(
),
m_header_field_verification_advice_recommended
}, // End of field HeaderFields
m_payload_signed(
'AAAAAAAAAA'O // To be replaced by TA with real payload
),
* @desc This function build and sign the SecureMessage part covered by the signature process
* @param p_securedMessage The signed SecureMessage part
* @param p_payloadField Payloads to be included in the message
* @param p_mandatoryHeaders Mandatory headers for the selected profile
* @param p_headerFields HeaderFields to be inserted in the message
* @param p_securityProfile Selected security profile
* @return true on success, false otherwise
*/
function f_buildGnSecuredMessage(
out template (value) SecuredMessage p_securedMessage,
in template (value) SecPayload p_payloadField,
in template (value) HeaderFields p_mandatoryHeaders,
in template (omit) HeaderFields p_headerFields := omit
) runs on ItsSecurityBaseComponent return boolean {
var octetstring v_secPayload, v_signature;
var Oct32 v_hash;
var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
var SecPayload v_toBeSignedPayload;
v_headerFields := valueof(p_mandatoryHeaders);
// Merge p_headerFields and v_mandatoryHeaders into v_headerFields
i := 0; // index for p_headerFields
j := 0; // index for v_mandatoryHeaders
k := 0; // index for v_headerFields
if (lengthof(valueof(p_headerFields)) > 0 and valueof(p_headerFields[i]).type_ == e_signer_info) {
v_headerFields[k] := valueof(p_headerFields[i]);
k := k + 1;
i := i + 1;
}
for ( j := j; j < lengthof(p_mandatoryHeaders); j := j + 1) {
// Search for mandatory header in p_HeaderFields
for(n:=0; n < lengthof(p_headerFields); n:=n+1) {
if (valueof(p_headerFields[n]).type_ == valueof(p_mandatoryHeaders[j]).type_) {
// mandatory header already in p_HeaderFields
break;
} // End of 'for' statement
if (n >= lengthof(p_headerFields)) {
if (valueof(p_mandatoryHeaders[j]).type_ != e_signer_info) {
// Add headers from p_headerFields having lower number than mandatory header
for (n := i; n < lengthof(p_headerFields) and valueof(p_headerFields[n]).type_ < valueof(p_mandatoryHeaders[j]).type_; n:=n+1) {
v_headerFields[k] := valueof(p_headerFields[n]);
k := k + 1;
i := i + 1;
v_headerFields[k] := valueof(p_mandatoryHeaders[j]);
for ( i := i; i < lengthof(p_headerFields); i := i + 1) {
// Add headers from p_headerFields having lower number than mandatory header
v_headerFields[k] := valueof(p_headerFields[i]);
k := k + 1;
// Prepare payload to be signed
if (
(valueof(p_payloadField).type_ == e_signed) or
(valueof(p_payloadField).type_ == e_signed_and_encrypted
)) {
v_toBeSignedPayload := valueof(p_payloadField);
} // TODO else, check draft
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
v_headerFields,
v_toBeSignedPayload,
v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage));
// Calculate the hash of the SecuredMessage payload to be signed
v_hash := f_hashWithSha256(v_secPayload);
// Signed payload
v_signature := f_signWithEcdsaNistp256WithSha256(
v_hash
);
p_securedMessage := m_securedMessage(
v_toBeSignedSecuredMessage.header_fields,
{
m_trailer_field_signature(
m_signature(
m_ecdsaSignature(
m_eccPointecdsa_nistp256_with_sha256_y_coordinate_only(
substr(v_signature, 2, 32)
),
substr(v_signature, 34, 32)
)
* @desc This function build and sign the SecureMessage part covered by the signature process
* @param p_securedMessage The signed SecureMessage part
* @param p_payloadField Payloads to be included in the message
* @param p_signerInfoType Add digest or AT certificate or certificate chain
* @param p_threeDLocation The 3D location
* @param p_headerFields HeaderFields to be inserted in the message
* @param p_certificateName The certificate identifier to be used. Default: TA_CERT_A
* @param p_addMissingHeaders Whether to add mandatory headers not present in p_headerFields
*
* @see Draft ETSI TS 103 097 V1.1.9 Clause 7.1 Security profile for CAMs
out template (value) SecuredMessage p_securedMessage,
in template (value) SecPayload p_payloadField,
in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
in template (omit) HeaderFields p_headerFields := omit,
in template (omit) charstring p_certificateName := omit,
in boolean p_addMissingHeaders := true
) runs on ItsSecurityBaseComponent return boolean {
var Certificate v_aaCertificate, v_atCertificate;
var HeaderFields v_mandatoryHeaders := {};
var HeaderField v_signerInfo;
if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCertA)) {
if (f_readCertificate(valueof(p_certificateName) & ".AA_CERT", v_aaCertificate) == false) {
return false;
}
if (f_readCertificate(valueof(p_certificateName) & ".AT_CERT", v_atCertificate) == false) {
return false;
}
} else {
v_aaCertificate := vc_aaCertificate;
v_atCertificate := vc_atCertificate;
// Prepare mandatory headers
if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_certificate(
v_atCertificate
)));
}
if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_certificates(
{
v_aaCertificate,
v_atCertificate
}
)
if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_digest(
v_atCertificate.signer_infos[0].signerInfo.digest
valueof(m_header_field_generation_time(1000 * (f_getCurrentTime() - c_offsetGnTime))), // In us
valueof(m_header_field_its_aid(c_its_aid_CAM))
return f_buildGnSecuredMessage(p_securedMessage, p_payloadField, v_mandatoryHeaders, p_headerFields);
/**
* @desc This function build and sign the SecureMessage part covered by the signature process
* @param p_securedMessage The signed SecureMessage part
* @param p_payloadField Payloads to be included in the message
* @param p_signerInfoType Add digest or AT certificate or certificate chain
* @param p_threeDLocation The 3D location
* @param p_headerFields HeaderFields to be inserted in the message
* @param p_certificateName The certificate identifier to be used. Default: TA_CERT_A
* @param p_addMissingHeaders Whether to add mandatory headers not present in p_headerFields
* @return true on success, false otherwise
*/
function f_buildGnSecuredDenm(
out template (value) SecuredMessage p_securedMessage,
in template (value) SecPayload p_payloadField,
in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
in ThreeDLocation p_threeDLocation,
in template (omit) HeaderFields p_headerFields := omit,
in template (omit) charstring p_certificateName := omit,
in boolean p_addMissingHeaders := true
) runs on ItsSecurityBaseComponent return boolean {
// Local variables
var Certificate v_aaCertificate, v_atCertificate;
var HeaderFields v_mandatoryHeaders := {};
var HeaderField v_signerInfo;
if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCertA)) {
if (f_readCertificate(valueof(p_certificateName) & ".AA_CERT", v_aaCertificate) == false) {
return false;
}
if (f_readCertificate(valueof(p_certificateName) & ".AT_CERT", v_atCertificate) == false) {
return false;
}
} else {
v_aaCertificate := vc_aaCertificate;
v_atCertificate := vc_atCertificate;
}
// Prepare mandatory headers
if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_certificate(
v_atCertificate
)));
}
if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_certificates(
{
v_aaCertificate,
v_atCertificate
}
)
if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_digest(
v_atCertificate.signer_infos[0].signerInfo.digest
valueof(m_header_field_generation_time(1000 * (f_getCurrentTime() - c_offsetGnTime))), // In us
valueof(m_header_field_generation_location(p_threeDLocation)),
valueof(m_header_field_its_aid(c_its_aid_DENM))
// Build the secured message and return it
return f_buildGnSecuredMessage(p_securedMessage, p_payloadField, v_mandatoryHeaders, p_headerFields);
* @desc This function build and sign the SecureMessage part covered by the signature process
* @param p_securedMessage The signed SecureMessage part
* @param p_payloadField Payloads to be included in the message
* @param p_signerInfoType Add digest or AT certificate or certificate chain
* @param p_threeDLocation The 3D location
* @param p_headerFields HeaderFields to be inserted in the message
* @param p_certificateName The certificate identifier to be used. Default: TA_CERT_A
* @param p_addMissingHeaders Whether to add mandatory headers not present in p_headerFields
* @return true on success, false otherwise
*/
function f_buildGnSecuredOtherMessage(
out template (value) SecuredMessage p_securedMessage,
in template (value) SecPayload p_payloadField,
in template (omit) SignerInfoType p_signerInfoType := e_certificate_digest_with_sha256,
in ThreeDLocation p_threeDLocation,
in template (omit) HeaderFields p_headerFields := omit,
in template (omit) charstring p_certificateName := omit,
in boolean p_addMissingHeaders := true
) runs on ItsSecurityBaseComponent return boolean {
var Certificate v_aaCertificate, v_atCertificate;
var HeaderFields v_mandatoryHeaders := {};
var HeaderField v_signerInfo;
if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCertA)) {
if (f_readCertificate(valueof(p_certificateName) & ".AA_CERT", v_aaCertificate) == false) {
return false;
}
if (f_readCertificate(valueof(p_certificateName) & ".AT_CERT", v_atCertificate) == false) {
return false;
}
} else {
v_aaCertificate := vc_aaCertificate;
v_atCertificate := vc_atCertificate;
// Prepare mandatory headers
if (valueof(p_signerInfoType) == e_certificate) { // Add the AT certificate
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_certificate(
v_atCertificate
)));
}
if (valueof(p_signerInfoType) == e_certificate_chain) { // Add the AT certificate + AA Certificate
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_certificates(
{
v_aaCertificate,
v_atCertificate
}
)
if (valueof(p_signerInfoType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest
v_signerInfo := valueof(
m_header_field_signer_info(
m_signerInfo_digest(
v_atCertificate.signer_infos[0].signerInfo.digest
valueof(m_header_field_generation_time(1000 * (f_getCurrentTime() - c_offsetGnTime))), // In us
valueof(m_header_field_generation_location(p_threeDLocation))
// Build the secured message and return it
return f_buildGnSecuredMessage(p_securedMessage, p_payloadField, v_mandatoryHeaders, p_headerFields);
} // End of function f_buildGnSecuredOtherMessage
} // End of group hostSignatureHelpers
group deviceSignatureHelpers {
* @desc Verify the signature of the provided certificate
* @param p_certificateToBeVerified Certificate to be verified
* @param p_publicKey Public key to verify the certificate signature
* @return true on success, false otherwise
* @verdict
*/
in template (value) Certificate p_certificateToBeVerified,
in template (value) PublicKey p_publicKey
) return boolean {
// Local variables
var octetstring toBeVerifiedData;
var octetstring v_signature;
var template (value) ToBeSignedCertificate v_toBeSignedCertificate;
// Create Certificate payload to be verified
v_toBeSignedCertificate := m_toBeSignedCertificate(p_certificateToBeVerified);
toBeVerifiedData := bit2oct(encvalue(v_toBeSignedCertificate));
// Build the signature
'0000'O &
valueof(p_certificateToBeVerified.signature_.signature_.ecdsa_signature.r.x) &
valueof(p_certificateToBeVerified.signature_.signature_.ecdsa_signature.s);
// Verify the certificate
v_result := f_verifyWithEcdsaNistp256WithSha256(
toBeVerifiedData,
v_signature,
valueof(p_publicKey.public_key.eccPoint.x),
valueof(p_publicKey.public_key.eccPoint.y.y)
} // End of finction f_verifyCertificateSignatureWithPublicKey
* @desc Verify the signature of the provided secured message
* @param p_certificateToBeVerified Certificate to be verified
* @param p_issuingCertificate Issuing certificate
* @return true on success, false otherwise
* @verdict
*/
function f_verifyCertificateSignatureWithIssuingCertificate(
in template (value) Certificate p_certificateToBeVerified,
in template (value) Certificate p_issuingCertificate
var integer v_counter;
for (v_counter := 0; v_counter < lengthof(p_issuingCertificate.subject_attributes); v_counter := v_counter + 1) {
if (valueof(p_issuingCertificate.subject_attributes[v_counter].type_) == e_verification_key) {
return f_verifyCertificateSignatureWithPublicKey(
p_certificateToBeVerified,
p_issuingCertificate.subject_attributes[v_counter].attribute.key);
}
} // End of 'for' statement
return false;
} // End of function f_verifyCertificateSignatureWithIssuingCertificate
* @desc Verify the signature of the provided secured message
* @param p_securedMessage The message to be verified
* @param p_publicKey The ECDSA public key to verify a signature
* @param p_certificate Certificate to be used to verify the message
* @return true on success, false otherwise
* @verdict
*/
function f_verifyGnSecuredMessageSignatureWithPublicKey(
in template (value) SecuredMessage p_securedMessage,
in template (value) PublicKey p_publicKey
) return boolean {
// Local variables
var octetstring v_secPayload;
var octetstring v_signedData;
var Oct32 v_hash;
var integer v_counter;
var boolean v_result := false;
var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
// log(">>> f_verifyGnSecuredMessageSignatureWithPublicKey: ", p_securedMessage);
// Create SecuredMessage payload to be signed
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
p_securedMessage.payload_field,
v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage));
// log("f_verifyGnSecuredMessageSignatureWithPublicKey: v_secPayload=", v_secPayload);
// Calculate the hash of the SecuredMessage payload to be signed
v_hash := fx_hashWithSha256(v_secPayload);
// log("f_verifyGnSecuredMessageSignatureWithPublicKey: v_hash=", v_hash);
// Verify payload
for (v_counter := 0; v_counter < lengthof(p_securedMessage.trailer_fields); v_counter := v_counter + 1) {
var SecuredMessage v_securedMessage := valueof(p_securedMessage);
(v_securedMessage.trailer_fields[v_counter].type_ == e_signature) and
(v_securedMessage.trailer_fields[v_counter].trailerField.signature_.algorithm == e_ecdsa_nistp256_with_sha256)
v_signedData :=
'0000'O &
v_securedMessage.trailer_fields[v_counter].trailerField.signature_.signature_.ecdsa_signature.r.x &
v_securedMessage.trailer_fields[v_counter].trailerField.signature_.signature_.ecdsa_signature.s;
// log("f_verifyGnSecuredMessageSignatureWithPublicKey: v_signedData=", v_signedData);
v_result := f_verifyWithEcdsaNistp256WithSha256(
v_hash,
v_signedData,
valueof(p_publicKey.public_key.eccPoint.x),
valueof(p_publicKey.public_key.eccPoint.y.y)
}
} // End of 'for' statement
// log("f_verifyGnSecuredMessageSignatureWithPublicKey: v_result=", v_result);
} // End of function f_verifyCertificateSignatureWithPublicKey
/**
* @desc Verify the signature of the provided secured message
* @param p_securedMessage
* @param p_certificate Certificate to be used to verify the message
* @return true on success, false otherwise
* @verdict
*/
function f_verifyGnSecuredMessageSignatureWithCertificate(
in template (value) SecuredMessage p_securedMessage,
in template (value) Certificate p_certificate
for (var integer v_counter := 0; v_counter < lengthof(p_certificate.subject_attributes); v_counter := v_counter + 1) {
var SubjectAttribute v_subjectAttribute := valueof(p_certificate.subject_attributes[v_counter]);
// log("f_verifyGnSecuredMessageSignatureWithCertificate: processing ", v_subjectAttribute);
if (v_subjectAttribute.type_ == e_verification_key) {
// if (valueof(p_certificate.subject_attributes[v_counter].type_) == e_verification_key) {
return f_verifyGnSecuredMessageSignatureWithPublicKey(
p_securedMessage,
p_certificate.subject_attributes[v_counter].attribute.key);
}
} // End of 'for' statement
return false;
} // End of function f_verifyGnSecuredOtherMessageWithDeviceCertificate
} // End of group deviceSignatureHelpers
garciay
committed
* @desc return SecuredMessage header field of given type or null if none
* @param p_msg the SecuredMessage
* @param p_type header field type
* @return HeaderField of given type if any or null
*/
in SecuredMessage p_securedMessage,
in HeaderFieldType p_headerFieldType,
out HeaderField p_return
) return boolean {
var integer v_length := lengthof(p_securedMessage.header_fields);
for (var integer i := 0; i < v_length; i := i + 1) {
if (p_securedMessage.header_fields[i].type_ == p_headerFieldType) {
p_return := p_securedMessage.header_fields[i];
log("f_getMsgHeaderField: return false");
* @desc return SignerInfo SecuredMessage field
*/
function f_getMsgSignerInfo (
in SecuredMessage p_securedMessage,
out SignerInfo p_signerInfo
) return boolean {
var HeaderField v_hf;
if (f_getMsgHeaderField(p_securedMessage, e_signer_info, v_hf) == true) {
if (isbound(v_hf.headerField.signer)) {
p_signerInfo := v_hf.headerField.signer;
return true;
}
log("f_getMsgSignerInfo: return false");
}// End of group messageGetters
group certificateGetters {
* @desc Set the generation location as defined in Draft ETSI TS 103 097 V1.1.9 Clause 7.2 Security profile for DENMs
* @param p_latitude The latitude value of the ITS-S position
* @param p_longitude The longitude value of the ITS-S position
* @param p_elevation The elevation value of the ITS-S position
function f_setGenerationLocation(
in WGSLatitude p_latitude,
in WGSLongitude p_longitude,
in Oct2 p_elevation := '0000'O
) runs on ItsSecurityBaseComponent {
vc_location := {
p_elevation
}
} // End of function f_setGenerationLocation
* @desc Load in memory cache the certificates available
* @param p_configId A configuration identifier
* @remark This method SHALL be call before any usage of certificates
* @return true on success, false otherwise
*/
) runs on ItsSecurityBaseComponent return boolean {
var boolean v_result;
// Setup certificates memory cache
if (fx_loadCertificates(PX_ROOT_PATH_FOR_SECURITY, p_configId) == true) {
// Setup security component variables
f_readCertificate(cc_taCertA & ".AA_CERT", vc_aaCertificate);
f_readCertificate(cc_taCertA & ".AT_CERT", vc_atCertificate);
f_readPrivateKeys(cc_taCertA & ".PRIVATE_KEYS", vc_signingPrivateKey, vc_encryptPrivateKey);
return true;
}
log("f_loadCertificates: Failed to access ", p_configId);
return false;
} // End of function f_loadCertificates
/**
* @desc Unload from memory cache the certificates available
* @return true on success, false otherwise
*/
function f_unloadCertificates() runs on ItsSecurityBaseComponent return boolean {
// Reset security component variables
vc_signingPrivateKey := '0000000000000000000000000000000000000000000000000000000000000000'O;
vc_encryptPrivateKey := '0000000000000000000000000000000000000000000000000000000000000000'O;
// Clear certificates memory cache
return fx_unloadCertificates();
} // End of function f_unloadCertificates
* @desc Read the specified certificate
* @param p_certificateId the certificate identifier
* @param p_certificate the expected certificate
* @return true on success, false otherwise
*/
in charstring p_certificateId,
out Certificate p_certificate
) runs on ItsSecurityBaseComponent return boolean {
var octetstring v_certificate;
if (fx_readCertificate(p_certificateId, v_certificate) == true) {
var bitstring v_oct2bit;
var integer v_result;
v_oct2bit := oct2bit(v_certificate);
v_result := decvalue(v_oct2bit, p_certificate);
if (v_result == 0) {
return true;
}
}
log("f_readCertificate: Failed to retrieve ", p_certificateId);
} // End of function f_readCertificate
/**
* @desc Read the private keys for the specified certificate
* @param p_keysId the keys identifier
* @param p_signingPrivateKey the signing private key
* @param p_encryptPrivateKey the encrypt private key
* @return true on success, false otherwise
*/
function f_readPrivateKeys(
in charstring p_keysId,
out Oct32 p_signingPrivateKey,
out Oct32 p_encryptPrivateKey
) runs on ItsSecurityBaseComponent return boolean {
return fx_readPrivateKeys(p_keysId, p_signingPrivateKey, p_encryptPrivateKey);
} // End of function f_readPrivateKeys
function f_getCertificateValidityRestriction(
in template (value) Certificate p_cert,
in ValidityRestrictionType p_type,
out ValidityRestriction p_return
) return boolean {
for (var integer i := 0; i < lengthof(p_cert.validity_restrictions); i := i + 1) {
if (valueof(p_cert).validity_restrictions[i].type_ == p_type) {
p_return := valueof(p_cert).validity_restrictions[i];
return true;
log("f_getCertificateValidityRestriction: Failed to retrieve ", p_type);
} // End of function f_getCertificateValidityRestriction
function f_getCertificateSignerInfo(
in template (value) Certificate p_cert,
out SignerInfo p_si
) return boolean {
if (isbound(valueof(p_cert).signer_infos)
and lengthof(p_cert.signer_infos) > 0) {
p_si := valueof(p_cert).signer_infos[0];
return true;
}
return false;
function f_getCertificateSubjectAttribute(
in template (value) Certificate p_cert,
in SubjectAttributeType p_type,
out SubjectAttribute p_return
) return boolean {
for (var integer i := 0; i < lengthof(p_cert.subject_attributes); i := i + 1) {
if (valueof(p_cert).subject_attributes[i].type_ == p_type) {
p_return := valueof(p_cert).subject_attributes[i];
return true;
}
}
log("f_getCertificateSubjectAttribute: Failed to retrieve ", p_type);
} // End of group helpersFunctions
* @desc Produces a 256-bit (32-byte) hash value
* @param p_toBeHashedData Data to be used to calculate the hash value
* @return The hash value
*/
external function fx_hashWithSha256(in octetstring p_toBeHashedData) return Oct32;
/**
* @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signaturee
* @param p_toBeSignedSecuredMessage The data to be signed
* @param p_privateKey The private key
* @return The signature value
*/
external function fx_signWithEcdsaNistp256WithSha256(in octetstring p_toBeSignedSecuredMessage, in octetstring/*UInt64*/ p_privateKey) return octetstring;
/**
* @desc Verify the signature of the specified data
* @param p_toBeVerifiedData The data to be verified
* @param p_signature The signature
* @param p_ecdsaNistp256PublicKeyX The public key (x coordinate)
* @param p_ecdsaNistp256PublicKeyY The public key (y coordinate)
* @return true on success, false otherwise
*/
external function fx_verifyWithEcdsaNistp256WithSha256(in octetstring p_toBeVerifiedData, in octetstring p_signature, in octetstring p_ecdsaNistp256PublicKeyX, in octetstring p_ecdsaNistp256PublicKeyY) return boolean;
/**
* @desc Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
* This function should not be used by the ATS
* @param p_privateKey The new private key value
* @param p_publicKeyX The new public key value (x coordinate)
* @param p_publicKeyX The new public key value (y coordinate)
* @return true on success, false otherwise
*/
external function fx_generateKeyPair(out octetstring/*UInt64*/ p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean;
} // End of group signing
group encryption {
} // End of group encryption
group certificatesLoader {
/**
* @desc Load in memory cache the certificates available in the specified directory
* @param p_rootDirectory Root directory to access to the certificates identified by the certificate ID
* @param p_configId A configuration identifier
* @remark This method SHALL be call before any usage of certificates
* @return true on success, false otherwise
*/
external function fx_loadCertificates(in charstring p_rootDirectory, in charstring p_configId) return boolean;
/**
* @desc Unload from memory cache the certificates
* @return true on success, false otherwise
*/
external function fx_unloadCertificates() return boolean;
* @desc Read the specified certificate
* @param p_certificateId the certificate identifier
* @param p_certificate the expected certificate
* @return true on success, false otherwise
*/
external function fx_readCertificate(in charstring p_certificateId, out octetstring p_certificate) return boolean;
/**
* @desc Read the private keys for the specified certificate
* @param p_keysId the keys identifier
* @param p_signingPrivateKey the signing private key
* @param p_encryptPrivateKey the encrypt private key
* @return true on success, false otherwise
*/
external function fx_readPrivateKeys(in charstring p_keysId, out Oct32 p_signingPrivateKey, out Oct32 p_encryptPrivateKey) return boolean;
} // End of group certificatesLoader
* @desc Check that given polygon doesn't have neither self-intersections nor holes.
* @param p_region Polygonal Region
* @return true on success, false otherwise
* @verdict Unchanged
*/
external function fx_isValidPolygonalRegion(in PolygonalRegion p_region) return boolean;
* @desc Check if a polygonal regin is inside another one
* @param p_parent The main polygonal region
* @param p_region The polygonal region to be included
* @return true on success, false otherwise
* @verdict Unchanged
*/
external function fx_isPolygonalRegionInside(in PolygonalRegion p_parent, in PolygonalRegion p_region) return boolean;
* @desc Check that the location is inside a circular region
* @param p_region The circular region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
external function fx_isLocationInsideCircularRegion(in CircularRegion p_region, in ThreeDLocation p_location) return boolean;
* @desc Check that the location is inside a rectangular region
* @param p_region The rectangular region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
external function fx_isLocationInsideRectangularRegion(in RectangularRegions p_region, in ThreeDLocation p_location) return boolean;
* @desc Check that the location is inside a polygonal region
* @param p_region The polygonal region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
external function fx_isLocationInsidePolygonalRegion(in PolygonalRegion p_region, in ThreeDLocation p_location) return boolean;
* @desc Check if the location is inside an identified region
* @param p_region The identified region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
external function fx_isLocationInsideIdentifiedRegion(in IdentifiedRegion p_region, in ThreeDLocation p_location) return boolean;
* @desc Convert a spacial coordinate from DMS to Dms
* @param p_degrees The degrees (D)
* @param p_minutes The minutes (M)
* @param p_seconds The seconds (S)
* @param p_latlon The latitude/longitude: (N|S|E|W)
* @return The decimal coordinate on success, 0.0, otherwise
* @verdict Unchanged
*/
external function fx_dms2dd(in Int p_degrees, in Int p_minutes, in float p_seconds, in Oct1 p_latlon) return float;
} // End of group externalFunctions
* @desc Check that given location is valid
* @param p_location location to be checked
* @return true on success, false otherwise
*/
(valueof(p_location).longitude != c_maxLongitude + 1) and
(valueof(p_location).latitude != c_maxLatitude + 1);
} // End of function f_isValidTwoDLocation
* @desc Check that two given rectanlular regions are intersected
* Note: Regions must be normalized(northwest.latitude >= southeast.latitude)
* TODO: Add case when
* @param p_r1 Region 1
* @param p_r2 Region 2
*
* @return true on success, false otherwise
*/
function f_isRectangularRegionsIntersected(
in template (value) RectangularRegion p_r1,
in template (value) RectangularRegion p_r2
return not (
valueof(p_r2).northwest.longitude > valueof(p_r1).southeast.longitude or
valueof(p_r2).southeast.longitude < valueof(p_r1).northwest.longitude or
valueof(p_r2).southeast.latitude > valueof(p_r1).northwest.latitude or
valueof(p_r2).northwest.latitude < valueof(p_r1).southeast.latitude
);
} // End of function f_isRectangularRegionsIntersected
function f_isContinuousRectangularRegions(
in template (value) RectangularRegions regions
} // End of function f_isRectangularRegionsIntersected
/**
* @desc Check if a polygonal regin is inside another one
* @param p_parent The main polygonal region
* @param p_region The polygonal region to be included
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_isRectangularRegionsInside(
in template (value) RectangularRegions p_parent,
in template (value) RectangularRegions p_region
// TODO: convert rectangular regions to polygons and check polygons
} // End of function f_isRectangularRegionsInside
* @desc Check that given polygon doesn't have neither self-intersections nor holes.
* @param p_region Polygonal Region
* @return true on success, false otherwise
* @verdict Unchanged
*/
in template (value) PolygonalRegion p_region
// Sanity check
if (not isbound(p_region) or (lengthof(p_region) == 0)) {
return false;
}
return fx_isValidPolygonalRegion(valueof(p_region));
} // End of function f_isValidPolygonalRegion
* @desc Check if a polygonal regin is inside another one
* @param p_parent The main polygonal region
* @param p_region The polygonal region to be included
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_isPolygonalRegionInside(
in template (value) PolygonalRegion p_parent,
in template (value) PolygonalRegion p_region
// Sanity check
if (not isbound(p_parent) or not isbound(p_region) or (lengthof(p_parent) == 0) or (lengthof(p_region) == 0)) {
return false;
}
return fx_isPolygonalRegionInside(valueof(p_parent), valueof(p_region));
} // End of function f_isPolygonalRegionInside
function f_isIdentifiedRegionInside(
in template (value) UInt16 p_parent,
in template (value) UInt16 p_region
} // End of function f_isIdentifiedRegionInside
* @desc Check that the location is inside a region
* @param p_region The region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_isLocationInsideRegion(
in template (value) GeographicRegion p_region,
in template (value) ThreeDLocation p_location
) return boolean {
var boolean v_ret := false;
select (p_region.region_type) {
case (e_none) {
v_ret := true;
}
case (e_circle) {
v_ret := f_isLocationInsideCircularRegion(p_region.region.circular_region, p_location);
case (e_rectangle) {
v_ret := f_isLocationInsideRectangularRegion(p_region.region.rectangular_region, p_location);
case (e_polygon) {
v_ret := f_isLocationInsidePolygonalRegion(p_region.region.polygonal_region, p_location);
case (e_id) {
v_ret := f_isLocationInsideIdentifiedRegion(p_region.region.id_region, p_location);
case else {
v_ret := f_isLocationInsideOtherRegion(p_region.region.other_region, p_location);
} // End of function f_isLocationInsideRegion
/**
* @desc Check that the location is inside a circular region
* @param p_region The circular region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_isLocationInsideCircularRegion(
in template (value) CircularRegion p_region,
in template (value) ThreeDLocation p_location
// Sanity check
if (not isbound(p_region) or not isbound(p_location)) {
return false;
}
return fx_isLocationInsideCircularRegion(valueof(p_region), valueof(p_location));
} // End of function f_isLocationInsideCircularRegion
/**
* @desc Check that the location is inside a rectangular region
* @param p_region The rectangular region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_isLocationInsideRectangularRegion(
in template (value) RectangularRegions p_region,
in template (value) ThreeDLocation p_location
// Sanity check
if (not isbound(p_region) or not isbound(p_location) or (lengthof(p_region) == 0)) {
return false;
}
// log("f_isLocationInsideRectangularRegion: p_polygonalArea: ", p_region);
// log("f_isLocationInsideRectangularRegion: p_location: ", p_location);
return fx_isLocationInsideRectangularRegion(valueof(p_region), valueof(p_location));
} // End of function f_isLocationInsideRectangularRegion
/**
* @desc Check that the location is inside a polygonal region
* @param p_region The polygonal region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_isLocationInsidePolygonalRegion(
in template (value) PolygonalRegion p_region,
in template (value) ThreeDLocation p_location
// Sanity check
if (not isbound(p_region) or not isbound(p_location) or (lengthof(p_region) == 0)) {
return false;
}
// log("f_isLocationInsidePolygonalRegion: p_polygonalArea: ", p_region, " - ", valueof(p_region));
// log("f_isLocationInsidePolygonalRegion: p_location: ", p_location, " - ", valueof(p_location));
return fx_isLocationInsidePolygonalRegion(valueof(p_region), valueof(p_location));
} // End of function f_isLocationInsidePolygonalRegion
/**
* @desc Check if the location is inside an identified region
* @param p_region The identified region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_isLocationInsideIdentifiedRegion(
in template (value) IdentifiedRegion p_region,
in template (value) ThreeDLocation p_location
// Sanity check
if (not isbound(p_region) or not isbound(p_location)) {
return false;
}
return fx_isLocationInsideIdentifiedRegion(valueof(p_region), valueof(p_location));
} // End of function f_isLocationInsideIdentifiedRegion
/**
* @desc Check if the location is inside an undefined region
* @param p_region The identified region to consider
* @param p_location The device location
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_isLocationInsideOtherRegion(
in template (value) octetstring p_region,
in template (value) ThreeDLocation p_location
} // End of function f_isLocationInsideOtherRegion
* @desc Convert a spacial coordinate from DMS to Dms
* @param p_degrees The degrees (D)
* @param p_minutes The minutes (M)
* @param p_seconds The seconds (S)
* @param p_latlon The latitude/longitude: (N|S|E|W)
* @return The decimal coordinate on success, 0.0, otherwise
* @verdict Unchanged
*/
in integer p_degrees,
in integer p_minutes,
in float p_seconds,
in charstring p_latlon
// Sanity checks
if (lengthof(p_latlon) != 1) {
return 0.0;
} else if ((p_latlon != "N") and (p_latlon != "S") and (p_latlon != "E") and (p_latlon != "W")) {
return 0.0;
}
return fx_dms2dd(p_degrees, p_minutes, p_seconds, v_latlon);
} // End of function f_dms2dd
/**
* @desc Convert the latitude from float to int
* @param p_latitude The latitude to be converted. Significand length shall be 7 digits length
* @return The converted latitude
* @verdict Unchanged
*/
function f_ddlat2int(
in float p_latitude
) return WGSLatitude {
return float2int(p_latitude * 10000000.0); // Significand length shall be 7 digits length
}
/**
* @desc Convert the longitude from float to int
* @param p_longitude The longitude to be converted. Significand length shall be 6 digits length
* @return The converted longitude
* @verdict Unchanged
*/
function f_ddlon2int(
in float p_longitude
) return WGSLongitude {
return float2int(p_longitude * 1000000.0); // Significand length shall be 6 digits length
}
} // End of module LibItsSecurity_Functions