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
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
group geometryFunctions {
/**
* @desc Check that given location is valid
* @param p_location location to be checked
* @return true on success, false otherwise
*/
function f_isValidTwoDLocation(in template (value) TwoDLocation p_location
) return boolean {
return not ( p_location.longitude > c_maxLongitude
or p_location.longitude < c_minLongitude
or p_location.latitude < c_minLatitude
or p_location.latitude > c_maxLatitude );
}
/**
* @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 boolean {
return not ( p_r2.northwest.longitude > p_r1.southeast.longitude
or p_r2.southeast.longitude < p_r1.northwest.longitude
or p_r2.southeast.latitude > p_r1.northwest.latitude
or p_r2.northwest.latitude < p_r1.southeast.latitude );
}
function f_isContinuousRectangularRegions(in template (value) RectangularRegions regions
) return boolean {
// TODO: implement it
return true;
}
}