Newer
Older
/**
* @author ETSI / STF481
* @version $URL$
* $Id$
* @desc Module containing functions for Security Protocol
*
*/
module LibItsSecurity_Functions {
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;
/**
* @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(in octetstring p_toBeHashedData) 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(in Oct32 p_toBeSignedSecuredMessage) return octetstring {
return fx_signWithEcdsaNistp256WithSha256(
p_toBeSignedSecuredMessage,
PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].signingPrivateKey
} // End of function f_signWithEcdsaNistp256WithSha256
function f_HashedId8FromSha256(in Oct32 p_hash)
return HashedId8 {
return substr(p_hash, 0, 8);
} // End of function f_HashedId8FromSha256
function f_HashedId3FromHashedId8 (in HashedId8 p_hash)
return HashedId3 {
return substr(p_hash, 0, 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
* @return the digest
* @see Draft ETSI TS 103 097 V1.1.6 Clause 4.2.13 HashedId8
function f_calculateDigest(in Certificate p_cert) return HashedId8 {
var octetstring v_toBeHashedData;
var octetstring v_hash;
var integer v_counter;
// Search for digest in the signer_infos field first
for (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_ecdsap256) {
return p_cert.signer_infos[v_counter].signerInfo.digest;
}
} // End of 'for' statement
// digest not found, compute it
v_toBeHashedData := bit2oct(encvalue(p_cert));
v_hash := f_hashWithSha256(v_toBeHashedData);
return substr(v_hash, lengthof(v_hash) - 8, 8);
/**
* @desc Build a template of a secured beacon to be used for the Test Adapter secured beaconing processing
*/
function f_buildSecuredMessagePayloadToBeSigned()
return ToBeSignedSecuredMessage {
var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
c_security_profileOthers,
{ // Field HeaderFields
m_header_field_signer_info(
m_signerInfo_certificate(
PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].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 current time
m_header_field_generation_location(
PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].location
)
}, // End of field HeaderFields
{
m_payload_unsecured(
'AAAAAAAAAA'O // To be replaced by TA with real payload
)
}, // End of field HeaderFields
e_signature
);
/**
* @desc This function build and sign the SecureMessage part covered by the signature process
* @param p_securedMessage The signed SecureMessage part
* @param p_unsecuredPayload The unsigned payload (e.g. a beacon)
* @param p_threeDLocation The ThreeDLocation value
* @param p_headerFields Additional HeaderFields
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_buildGnSecuredCam(
out template (value) SecuredMessage p_securedMessage,
in octetstring p_unsecuredPayload,
in ThreeDLocation p_threeDLocation,
in template (omit) HeaderFields p_headerFields := omit
) return boolean {
// Local variables
var octetstring v_secPayload, v_signature;
var Oct32 v_hash;
var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
// Create SecuredMessage payload to be signed
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
c_security_profileOthers,
{ // Field HeaderFields
m_header_field_signer_info(
m_signerInfo_certificate(
PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate
) // End of template m_signerInfo_certificate
), // End of template m_header_field_signer_info
m_header_field_generation_time(f_getCurrentTime()),
m_header_field_generation_location(
p_threeDLocation
),
m_header_field_message_type(c_messageType_CAM)
}, // End of field HeaderFields
{
m_payload_unsecured(
p_unsecuredPayload
)
}, // End of field HeaderFields
e_signature
);
// Add additional header fields if any
if (ispresent(p_headerFields) == true) {
var integer v_addItemIndex := lengthof(v_toBeSignedSecuredMessage.header_fields);
var integer v_counter;
for (v_counter := 0; v_counter < lengthof(p_headerFields); v_counter := v_counter + 1) {
v_toBeSignedSecuredMessage.header_fields[v_addItemIndex] := p_headerFields[v_counter];
v_addItemIndex := v_addItemIndex + 1;
} // End of 'for' statement
}
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_profileOther( // See Clause 7.3 Generic security profile for other signed messages
v_toBeSignedSecuredMessage.header_fields,
v_toBeSignedSecuredMessage.payload_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)
)
}
); // End of template m_securedMessageBeacon
return true;
}
/**
* @desc This function build and sign the SecureMessage part covered by the signature process
* @param p_securedMessage The signed SecureMessage part
* @param p_unsecuredPayload The unsigned payload (e.g. a beacon)
* @param p_threeDLocation The ThreeDLocation value
* @param p_headerFields Additional HeaderFields
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_buildGnSecuredDenm(
out template (value) SecuredMessage p_securedMessage,
in octetstring p_unsecuredPayload,
in ThreeDLocation p_threeDLocation,
in template (omit) HeaderFields p_headerFields := omit
) return boolean {
// Local variables
var octetstring v_secPayload, v_signature;
var Oct32 v_hash;
var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
// Create SecuredMessage payload to be signed
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
c_security_profileOthers,
{ // Field HeaderFields
m_header_field_signer_info(
m_signerInfo_certificate(
PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate
) // End of template m_signerInfo_certificate
), // End of template m_header_field_signer_info
m_header_field_generation_time(f_getCurrentTime()),
m_header_field_generation_location(
p_threeDLocation
),
m_header_field_message_type(c_messageType_DENM)
}, // End of field HeaderFields
{
m_payload_unsecured(
p_unsecuredPayload
)
}, // End of field HeaderFields
e_signature
);
// Add additional header fields if any
if (ispresent(p_headerFields) == true) {
var integer v_addItemIndex := lengthof(v_toBeSignedSecuredMessage.header_fields);
var integer v_counter;
for (v_counter := 0; v_counter < lengthof(p_headerFields); v_counter := v_counter + 1) {
v_toBeSignedSecuredMessage.header_fields[v_addItemIndex] := p_headerFields[v_counter];
v_addItemIndex := v_addItemIndex + 1;
} // End of 'for' statement
}
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_profileOther( // See Clause 7.3 Generic security profile for other signed messages
v_toBeSignedSecuredMessage.header_fields,
v_toBeSignedSecuredMessage.payload_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)
)
}
); // End of template m_securedMessageBeacon
return true;
} // End of function f_buildGnSecuredDenm
garciay
committed
/**
* @desc This function build and sign the SecureMessage part covered by the signature process
* @param p_securedMessage The signed SecureMessage part
* @param p_unsecuredPayload The unsigned payload (e.g. a beacon)
* @param p_threeDLocation The ThreeDLocation value
* @param p_headerFields Additional HeaderFields
* @return true on success, false otherwise
* @verdict Unchanged
*/
function f_buildGnSecuredOtherMessage(
out template (value) SecuredMessage p_securedMessage,
in octetstring p_unsecuredPayload,
in ThreeDLocation p_threeDLocation,
in template (omit) HeaderFields p_headerFields := omit
) return boolean {
// Local variables
var octetstring v_secPayload, v_signature;
var Oct32 v_hash;
var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage;
// Create SecuredMessage payload to be signed
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
c_security_profileOthers,
{ // Field HeaderFields
m_header_field_signer_info(
m_signerInfo_certificate(
PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate
) // End of template m_signerInfo_certificate
), // End of template m_header_field_signer_info
m_header_field_generation_time(f_getCurrentTime()),
m_header_field_generation_location(
p_threeDLocation
)
}, // End of field HeaderFields
{
m_payload_unsecured(
p_unsecuredPayload
)
}, // End of field HeaderFields
e_signature
);
// Add additional header fields if any
if (ispresent(p_headerFields) == true) {
var integer v_addItemIndex := lengthof(v_toBeSignedSecuredMessage.header_fields);
var integer v_counter;
for (v_counter := 0; v_counter < lengthof(p_headerFields); v_counter := v_counter + 1) {
v_toBeSignedSecuredMessage.header_fields[v_addItemIndex] := p_headerFields[v_counter];
v_addItemIndex := v_addItemIndex + 1;
} // End of 'for' statement
}
log("v_toBeSignedSecuredMessage= ", v_toBeSignedSecuredMessage);
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_profileOther( // See Clause 7.3 Generic security profile for other signed messages
v_toBeSignedSecuredMessage.header_fields,
v_toBeSignedSecuredMessage.payload_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)
)
garciay
committed
)
)
}
); // End of template m_securedMessageBeacon
return true;
} // End of function f_buildGnSecuredOtherMessage
} // End of group hostSignatureHelpers
group deviceSignatureHelpers {
/**
* @desc Verify the signature of the provided certificate
* @param p_cert Certificate to be verified
* @param p_publicKey Public key to verify the certificate signature
*/
function f_verifyCertificateSignatureWithPublicKey(
in template (value) Certificate p_cert,
in template (value) PublicKey p_publicKey
// Local variables
var octetstring v_secPayload;
var octetstring v_signedData;
var Oct32 v_hash;
var boolean v_result := false;
var template (value) ToBeSignedCertificate v_toBeSignedCertificate;
// Create Certificate payload to be signed
v_toBeSignedCertificate := m_toBeSignedCertificate(p_cert);
v_secPayload := bit2oct(encvalue(v_toBeSignedCertificate));
// // Calculate the hash of the SecuredMessage payload to be signed
// v_hash := fx_hashWithSha256(v_secPayload);
//
p_cert.signature_.signature_.ecdsa_signature.r.x &
p_cert.signature_.signature_.ecdsa_signature.s;
v_result := f_verifyWithEcdsaNistp256WithSha256(
v_hash,
v_signedData,
p_publicKey.public_key.eccPoint.x,
p_publicKey.public_key.eccPoint.y.y
} // End of finction f_verifyCertificateSignatureWithPublicKey
/**
* @desc Verify the signature of the provided secured message
* @param p_cert Certificate to be verified
* @param p_verify Issuing certificate
* @return true on success, false otherwise
* @verdict
*/
function f_verifyCertificateSignatureWithIssuingCertificate(
in template (value) Certificate p_cert,
in template (value) Certificate p_verify
) return boolean {
return f_verifyCertificateSignatureWithPublicKey(p_cert, p_verify.subject_attributes[0].attribute.key);
} // End of function f_verifyCertificateSignatureWithIssuingCertificate
} // End of group hostSignatureHelpers
group deviceSignatureHelpers {
/**
* @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
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;
// Create SecuredMessage payload to be signed
v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage(
p_securedMessage.security_profile,
p_securedMessage.header_fields,
p_securedMessage.payload_fields,
e_signature
);
v_secPayload := bit2oct(encvalue(v_toBeSignedSecuredMessage));
// Calculate the hash of the SecuredMessage payload to be signed
v_hash := fx_hashWithSha256(v_secPayload);
// Verify payload
for (v_counter := 0; v_counter < lengthof(p_securedMessage.trailer_fields); v_counter := v_counter + 1) {
if (
(p_securedMessage.trailer_fields[v_counter].type_ == e_signature) and
(p_securedMessage.trailer_fields[v_counter].trailerField.signature_.algorithm == e_ecdsa_nistp256_with_sha256)
) {
v_signedData :=
'0000'O &
p_securedMessage.trailer_fields[v_counter].trailerField.signature_.signature_.ecdsa_signature.r.x &
p_securedMessage.trailer_fields[v_counter].trailerField.signature_.signature_.ecdsa_signature.s;
v_result := f_verifyWithEcdsaNistp256WithSha256(
v_hash,
v_signedData,
p_publicKey.public_key.eccPoint.x,
p_publicKey.public_key.eccPoint.y.y
);
}
} // End of 'for' statement
return 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
) return boolean {
return f_verifyGnSecuredMessageSignatureWithPublicKey(p_securedMessage,
p_certificate.subject_attributes[0].attribute.key);
} // 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 template (value) SecuredMessage p_securedMessage,
in HeaderFieldType p_headerFieldType
) return HeaderField {
var HeaderField v_return;
var integer v_length := lengthof(p_securedMessage.header_fields);
var integer v_index;
for (v_index := 0; v_index < v_length; v_index := v_index + 1) {
if (p_securedMessage.header_fields[v_index].type_ == p_headerFieldType) {
v_return := p_securedMessage.header_fields[v_index];
break;
}
}
return v_return;
}
/**
* @desc return SignerInfo SecuredMessage field
*/
function f_getMsgSignerInfo (
in template (value) SecuredMessage p_securedMessage
) return SignerInfo {
var HeaderField v_hf := f_getMsgHeaderField(p_securedMessage, e_signer_info);
return v_hf.headerField.signer;
}
return null;
}
}// End of group messageGetters
group certificateGetters {
function f_getCertificateValidityRestriction(
in template (value) Certificate p_cert,
in ValidityRestrictionType p_type
) return ValidityRestriction {
var ValidityRestriction v_return;
var integer v_length := lengthof(p_cert.validity_restrictions);
for (v_index := 0; v_index < v_length; v_index := v_index + 1) {
if( p_cert.validity_restrictions[v_index].type_ == p_type ) {
v_return := p_cert.validity_restrictions[v_index];
break;
}
}
return v_return;
}
function f_getCertificateSignerInfo (
in template (value) Certificate p_cert
) return SignerInfo {
var SignerInfo ret;
if (lengthof(p_cert.signer_infos) > 0) {
ret := p_cert.signer_infos[0];
}
return ret;
}
function f_askForCertificate (in template (value) HashedId8 p_digest) {
// Send CAM message with insert the request_unrecognized_certificate
// header containing specified digest
/* TODO: Waiting Alex to understand how to send message
var SecuredMessage v_msg;
if ( f_buildGnSecuredCam (v_msg,
in octetstring p_unsecuredPayload,
in ThreeDLocation p_threeDLocation,
in template (omit) HeaderFields p_headerFileds := omit
)) {
}
*/
} // End of group helpersFunctions
group externalFunctions {
/**
* @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 externalFunctions