/** * @author ETSI / STF481 * @version $URL$ * $Id$ * @desc Module containing functions for Security Protocol * */ module LibItsSecurity_Functions { // Libcommon import from LibCommon_BasicTypesAndValues all; import from LibCommon_DataStrings all; // LibItsCommon import from LibItsCommon_Functions all; // LibItsSecurity import from LibItsSecurity_TypesAndValues all; import from LibItsSecurity_Templates all; import from LibItsSecurity_Pixits all; 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 */ 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 /** * @desc Compute the HashedId8 value from the hash value * @param p_hash The hash value * @return The HashedId8 value * @verdict */ function f_HashedId8FromSha256( in Oct32 p_hash ) return HashedId8 { return substr(p_hash, lengthof(p_hash) - 8, 8); } // End of function f_HashedId8FromSha256 /** * @desc Compute the HashedId3 value from the HashedId8 value * @param p_hashp_hashedId8 The HashedId8 value * @return The HashedId3 value * @verdict */ 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 */ 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.6 Clause 4.2.13 HashedId8 */ function f_calculateDigestFromCertificate( 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); } group hostSignatureHelpers { /** * @desc Build a template of a secured beacon to be used for the Test Adapter secured beaconing processing */ function f_buildSecuredMessagePayloadToBeSigned() return ToBeSignedSecuredMessage { // Local variables var template (value) ToBeSignedSecuredMessage v_toBeSignedSecuredMessage; // Build the beacon template 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 ); return valueof(v_toBeSignedSecuredMessage); } /** * @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_addCertificate Set to true to add the AT certificate in header fields. Otherwise, only the AA certificate digest will be added * @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 template (omit) boolean p_addCertificate := false, 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 if (valueof(p_addCertificate) == true) { // Add the AT certificate v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileCAMs, { // 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_message_type(c_messageType_CAM) }, // End of field HeaderFields { m_payload_unsecured( p_unsecuredPayload ) }, // End of field HeaderFields e_signature ); } else { // Add the AT certificate digest v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileCAMs, { // Field HeaderFields m_header_field_signer_info( m_signerInfo_digest( PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate.signer_infos[0].signerInfo.digest ) // End of template m_signerInfo_digest ), // End of template m_header_field_digest m_header_field_generation_time(f_getCurrentTime()), m_header_field_message_type(c_messageType_CAM) }, // End of field HeaderFields { m_payload_unsecured( p_unsecuredPayload ) }, // End of field HeaderFields e_signature ); } log("v_toBeSignedSecuredMessage=", v_toBeSignedSecuredMessage); // 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)); log("v_secPayload= ", v_secPayload); // Calculate the hash of the SecuredMessage payload to be signed v_hash := f_hashWithSha256(v_secPayload); log("v_hash= ", v_hash); // Signed payload v_signature := f_signWithEcdsaNistp256WithSha256( v_hash ); log("v_signature= ", v_signature); p_securedMessage := md_secureMessage_profileCam( // See Clause 7.1 Security profile for CAMs 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_securedMessage_profileCam 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_addCertificate Set to true to add the AT certificate in header fields. Otherwise, only the AA certificate digest will be added * @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) boolean p_addCertificate := false, 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 if (valueof(p_addCertificate) == true) { // Add the AA certificate v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileDENMs, { // 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 ); } else { // Add the AA certificate digest v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileDENMs, { // Field HeaderFields m_header_field_signer_info( m_signerInfo_digest( PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate.signer_infos[0].signerInfo.digest ) // End of template m_signerInfo_digest ), // End of template m_header_field_digest 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 } 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 := md_secureMessage_profileDenm( // See Clause 7.2 Security profile for DENMs 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_securedMessage_profileDenm return true; } // End of function f_buildGnSecuredDenm /** * @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_addCertificate Set to true to add the AT certificate in header fields. Otherwise, only the AA certificate digest will be added * @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) boolean p_addCertificate := false, 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 if (valueof(p_addCertificate) == true) { // Add the AA certificate 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 ); } else { // Add the AA certificate digest v_toBeSignedSecuredMessage := m_toBeSignedSecuredMessage( c_security_profileOthers, { // Field HeaderFields m_header_field_signer_info( m_signerInfo_digest( PX_TA_CONFIGS[PX_CERTIFICATE_CONFIG_IDX].atCertificate.signer_infos[0].signerInfo.digest ) // End of template m_signerInfo_digest ), // End of template m_header_field_digest 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 := md_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 md_securedMessage_profileOther return true; } // 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 */ function f_verifyCertificateSignatureWithPublicKey( in template (value) Certificate p_certificateToBeVerified, in template (value) PublicKey p_publicKey ) return boolean { // Local variables var octetstring toBeVerifiedData; var octetstring v_signature; var boolean v_result := false; 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 v_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) ); return v_result; } // 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 ) return boolean { 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( valueof(p_securedMessage.security_profile), p_securedMessage.header_fields, p_securedMessage.payload_fields, e_signature ); 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); if ( (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) ); break; } } // End of 'for' statement // log("f_verifyGnSecuredMessageSignatureWithPublicKey: v_result=", v_result); 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 { var integer v_counter; for (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 group messageGetters { /** * @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 */ function f_getMsgHeaderField( in template (value) 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 (valueof(p_securedMessage).header_fields[i].type_ == p_headerFieldType) { p_return := valueof(p_securedMessage).header_fields[i]; return true; } } return false; } /** * @desc return SignerInfo SecuredMessage field */ function f_getMsgSignerInfo ( in template (value) SecuredMessage p_securedMessage, out SignerInfo p_signerInfo ) return boolean { var HeaderField v_hf; if(f_getMsgHeaderField(p_securedMessage, e_signer_info, v_hf)){ if(isbound(v_hf.headerField.signer)){ p_signerInfo := v_hf.headerField.signer; return true; } } return false; } }// End of group messageGetters group certificateGetters { 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; } } return false; } 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; } } return false; } }// End of group certificateGetters } // End of group helpersFunctions group externalFunctions { group signing { /** * @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 geodesic { /** * @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; } // End of group geodesic } // End of group externalFunctions 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 (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 boolean { 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 ) return boolean { // TODO: call external function return true; } // 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 ) return boolean { // TODO: convert rectangular regions to polygons and check polygons return true; } // 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 */ function f_isValidPolygonalRegion( in template (value) PolygonalRegion p_region ) return boolean { // 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 ) return boolean { // TODO: call external function return true; } // End of function f_isPolygonalRegionInside /** * @desc */ function f_isIdentifiedRegionInside(in template (value) UInt16 p_parent, in template (value) UInt16 p_region ) return boolean { // TODO: call external function return valueof(p_parent) == valueof(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); } } return v_ret; } // 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 ) return boolean { // 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 ) return boolean { // Sanity check if (not isbound(p_region) or not isbound(p_location) or (lengthof(p_region) == 0)) { return false; } 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 ) return boolean { // Sanity check if (not isbound(p_region) or not isbound(p_location) or (lengthof(p_region) == 0)) { return false; } 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 ) return boolean { // 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 ) return boolean { // FIXME To be removed return false; } // End of function f_isLocationInsideOtherRegion } // End of group geometryFunctions } // End of module LibItsSecurity_Functions