/** * @author ETSI / STF481 / STF507 / STF517 / STF538 / STF545 * @version $URL$ * $Id$ * @desc Module containing functions for Security Protocol * @copyright ETSI Copyright Notification * No part may be reproduced except as authorized by written permission. * The copyright and the foregoing restriction extend to reproduction in all media. * All rights reserved. * */ module LibItsSecurity_Functions { // Libcommon import from LibCommon_BasicTypesAndValues all; import from LibCommon_DataStrings all; // LibIts import from IEEE1609dot2BaseTypes language "ASN.1:1997" all; import from IEEE1609dot2 language "ASN.1:1997" all; import from EtsiTs103097Module language "ASN.1:1997" all; // LibItsCommon //import from LibItsCommon_Functions all; //import from LibItsCommon_TypesAndValues all; import from LibItsCommon_Pixits all; // LibItsSecurity import from LibItsSecurity_TypesAndValues all; import from LibItsSecurity_Templates all; import from LibItsSecurity_Pixits all; import from LibItsSecurity_Pics all; import from LibItsSecurity_TestSystem 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 384-bit (48-byte) hash value * @param p_toBeHashedData Data to be used to calculate the hash value * @return The hash value */ function f_hashWithSha384( in octetstring p_toBeHashedData ) return Oct48 { return fx_hashWithSha384(p_toBeHashedData); } // End of function f_hashWithSha256 /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 * @param p_toBeSignedSecuredMessage The data to be signed * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_privateKey The private key for signature * @return The signature value */ function f_signWithEcdsaNistp256WithSha256( in octetstring p_toBeSignedSecuredMessage, in Oct32 p_certificateIssuer, in Oct32 p_privateKey ) return octetstring { return fx_signWithEcdsaNistp256WithSha256( p_toBeSignedSecuredMessage, p_certificateIssuer, p_privateKey ); } // End of function f_signWithEcdsaNistp256WithSha256 /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 * @param p_toBeSignedSecuredMessage The data to be signed * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_privateKey The private key for signature * @return The signature value */ function f_signWithEcdsaBrainpoolp256WithSha256( in octetstring p_toBeSignedSecuredMessage, in Oct32 p_certificateIssuer, in Oct32 p_privateKey ) return octetstring { return fx_signWithEcdsaBrainpoolp256WithSha256( p_toBeSignedSecuredMessage, p_certificateIssuer, p_privateKey ); } // End of function f_signWithEcdsaBrainpoolp256WithSha256 /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 * @param p_toBeSignedSecuredMessage The data to be signed * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_privateKey The private key for signature * @return The signature value */ function f_signWithEcdsaBrainpoolp384WithSha384( in octetstring p_toBeSignedSecuredMessage, in Oct48 p_certificateIssuer, in Oct48 p_privateKey ) return octetstring { log(">>> f_signWithEcdsaBrainpoolp384WithSha384: ", p_toBeSignedSecuredMessage); log(">>> f_signWithEcdsaBrainpoolp384WithSha384: ", p_certificateIssuer); log(">>> f_signWithEcdsaBrainpoolp384WithSha384: ", p_privateKey); return fx_signWithEcdsaBrainpoolp384WithSha384( p_toBeSignedSecuredMessage, p_certificateIssuer, p_privateKey ); } // End of function f_signWithEcdsaBrainpoolp384WithSha384 function f_decrypt( in octetstring p_encryptPrivateKey, in EtsiTs103097Data p_encrypedSecuredMessage, in octetstring p_salt, out EtsiTs103097Data p_decrypedSecuredMessage, out octetstring p_aes_sym_enc_key ) return boolean { if (ischosen(p_encrypedSecuredMessage.content.encryptedData)) { var PKRecipientInfo v_pKRecipientInfo; var RecipientInfo v_recipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0]; var octetstring v_decryptedSecuredMessage; // Check the private encryption key if (not(isbound(p_encryptPrivateKey))) { log("*** " & testcasename() & ":ERROR: Failed to load encryption private key ***"); return false; } if (ischosen(v_recipientInfo.certRecipInfo)) { v_pKRecipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0].certRecipInfo; // Read the certificate based on the recipientId } else if (ischosen(v_recipientInfo.signedDataRecipInfo)) { v_pKRecipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0].signedDataRecipInfo; // Read the certificate based on the recipientId } else { log("*** " & testcasename() & ":ERROR: Unsupported RecipientInfo variant ***"); return false; } if (isbound(v_pKRecipientInfo)) { if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256)) { var SymmetricCiphertext v_ciphertext := p_encrypedSecuredMessage.content.encryptedData.ciphertext; if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_0)) { v_decryptedSecuredMessage := f_decryptWithEciesNistp256WithSha256( v_ciphertext.aes128ccm.ccmCiphertext, p_encryptPrivateKey, v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_0, 0, v_pKRecipientInfo.encKey.eciesNistP256.c, v_pKRecipientInfo.encKey.eciesNistP256.t, v_ciphertext.aes128ccm.nonce, p_salt, p_aes_sym_enc_key ); } else if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_1)) { v_decryptedSecuredMessage := f_decryptWithEciesNistp256WithSha256( v_ciphertext.aes128ccm.ccmCiphertext, p_encryptPrivateKey, v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_1, 1, v_pKRecipientInfo.encKey.eciesNistP256.c, v_pKRecipientInfo.encKey.eciesNistP256.t, v_ciphertext.aes128ccm.nonce, p_salt, p_aes_sym_enc_key ); } else { log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***"); return false; } if (isbound(v_decryptedSecuredMessage)) { var bitstring v_decode := oct2bit(v_decryptedSecuredMessage); if (decvalue(v_decode, p_decrypedSecuredMessage) == 0) { return true; } else { log("*** " & testcasename() & ":ERROR: Faild to decode secured message ***"); } } } else if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1)) { var SymmetricCiphertext v_ciphertext := p_encrypedSecuredMessage.content.encryptedData.ciphertext; if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_0)) { v_decryptedSecuredMessage := f_decryptWithEciesBrainpoolp256WithSha256( v_ciphertext.aes128ccm.ccmCiphertext, p_encryptPrivateKey, v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_0, 0, v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.c, v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.t, v_ciphertext.aes128ccm.nonce, p_salt, p_aes_sym_enc_key ); } else if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_1)) { v_decryptedSecuredMessage := f_decryptWithEciesBrainpoolp256WithSha256( v_ciphertext.aes128ccm.ccmCiphertext, p_encryptPrivateKey, v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_1, 1, v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.c, v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.t, v_ciphertext.aes128ccm.nonce, p_salt, p_aes_sym_enc_key ); } else { log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***"); return false; } } else { log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***"); return false; } // TODO else, other variants shall be processed here if } else { log("*** " & testcasename() & ":ERROR: Invalid recipient info ***"); return false; } if (isbound(v_decryptedSecuredMessage)) { var bitstring v_decode := oct2bit(v_decryptedSecuredMessage); if (decvalue(v_decode, p_decrypedSecuredMessage) == 0) { return true; } else { log("*** " & testcasename() & ":ERROR: Faild to decode secured message ***"); } } } else { log("*** " & testcasename() & ":ERROR: Message not encrypted ***"); } return false; } // End of function f_decrypt /** * @desc Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Nist-P256 algorithm * @param p_toBeEncryptedSecuredMessage The data to be encrypted * @param p_recipientsPublicKeyCompressed The Recipient's compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_publicEphemeralKeyCompressed The generated ephemeral compressed key * @param p_ephemeralKeyModeCompressed The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_encrypted_sym_key The encrypted AES 128 CCM symmetric key * @param p_authentication_vector The tag of the AES 128 CCM symmetric key encryption * @param p_nonce The nonce vector of the AES 128 CCM symmetric key encryption * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf * @return The encrypted message */ function f_encryptWithEciesNistp256WithSha256( in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_recipientsPublicKeyCompressed, in integer p_compressed_mode, in octetstring p_salt, out Oct32 p_publicEphemeralKeyCompressed, out integer p_ephemeralKeyModeCompressed, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce, in boolean p_use_hardcoded_values := false ) return octetstring { return fx_encryptWithEciesNistp256WithSha256( p_toBeEncryptedSecuredMessage, p_recipientsPublicKeyCompressed, p_compressed_mode, p_salt, p_publicEphemeralKeyCompressed, p_ephemeralKeyModeCompressed, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_use_hardcoded_values ); } // End of function f_encryptWithEciesNistp256WithSha256 /** * @desc Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Nist-P256 algorithm * @param p_encryptedSecuredMessage The data to be decrypted * @param p_publicEphemeralKeyCompressed The generated ephemeral compressed key * @param p_ephemeralKeyModeCompressed The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_encrypted_sym_key The encrypted AES 128 CCM symmetric key * @param p_authentication_vector The tag of the AES 128 CCM symmetric key encryption * @param p_nonce The nonce vector of the AES 128 CCM symmetric key encryption * @return The decrypted message * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf */ function f_decryptWithEciesNistp256WithSha256( in octetstring p_encryptedSecuredMessage, in Oct32 p_privateEncKey, in Oct32 p_publicEphemeralKeyCompressed, in integer p_ephemeralKeyModeCompressed, in Oct16 p_encrypted_sym_key, in Oct16 p_authentication_vector, in Oct12 p_nonce, in Oct32 p_salt, out Oct16 p_aes_sym_enc_key ) return octetstring { return fx_decryptWithEciesNistp256WithSha256( p_encryptedSecuredMessage, p_privateEncKey, p_publicEphemeralKeyCompressed, p_ephemeralKeyModeCompressed, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_salt, p_aes_sym_enc_key ); } // End of function f_decryptWithEcdsaNistp256WithSha256 /** * @desc Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Brainpool-P256 algorithm * @param p_toBeEncryptedSecuredMessage The data to be encrypted * @param p_recipientsPublicKeyCompressed The Recipient's compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_publicEphemeralKeyCompressed The generated ephemeral compressed key * @param p_ephemeralKeyModeCompressed The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_encrypted_sym_key The encrypted AES 128 CCM symmetric key * @param p_authentication_vector The tag of the AES 128 CCM symmetric key encryption * @param p_nonce The nonce vector of the AES 128 CCM symmetric key encryption * @return The encrypted message * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf */ function f_encryptWithEciesBrainpoolp256WithSha256( in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_recipientsPublicKeyCompressed, in integer p_compressed_mode, in octetstring p_salt, out Oct32 p_publicEphemeralKeyCompressed, out integer p_ephemeralKeyModeCompressed, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce, in boolean p_use_hardcoded_values := false ) return octetstring { return fx_encryptWithEciesBrainpoolp256WithSha256( p_toBeEncryptedSecuredMessage, p_recipientsPublicKeyCompressed, p_compressed_mode, p_salt, p_publicEphemeralKeyCompressed, p_ephemeralKeyModeCompressed, p_aes_sym_key, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_use_hardcoded_values ); } // End of function f_encryptWithEciesBrainpoolp256WithSha256 /** * @desc Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Brainpool-P256 algorithm * @param p_encryptedSecuredMessage The data to be decrypted * @param p_publicEphemeralKeyCompressed The generated ephemeral compressed key * @param p_ephemeralKeyModeCompressed The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_encrypted_sym_key The encrypted AES 128 CCM symmetric key * @param p_authentication_vector The tag of the AES 128 CCM symmetric key encryption * @param p_nonce The nonce vector of the AES 128 CCM symmetric key encryption * @return The decrypted message * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf */ function f_decryptWithEciesBrainpoolp256WithSha256( in octetstring p_encryptedSecuredMessage, in Oct32 p_privateEncKey, in Oct32 p_publicEphemeralKeyCompressed, in integer p_ephemeralKeyModeCompressed, in Oct16 p_encrypted_sym_key, in Oct16 p_authentication_vector, in Oct12 p_nonce, in Oct32 p_salt, out Oct16 p_aes_sym_enc_key ) return octetstring { return fx_decryptWithEciesBrainpoolp256WithSha256( p_encryptedSecuredMessage, p_privateEncKey, p_publicEphemeralKeyCompressed, p_ephemeralKeyModeCompressed, p_encrypted_sym_key, p_authentication_vector, p_nonce, p_salt, p_aes_sym_enc_key ); } // End of function f_decryptWithEcdsaBrainpoolp256WithSha256 /** * @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 HashedId8 value from the hash value * @param p_hash The hash value * @return The HashedId8 value * @verdict */ function f_HashedId8FromSha384( in Oct48 p_hash ) return HashedId8 { return substr(p_hash, lengthof(p_hash) - 8, 8); } // End of function f_HashedId8FromSha384 /** * @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_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_signature The signature * @param p_ecdsaNistp256PublicKeyCompressed The compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ function f_verifyWithEcdsaNistp256WithSha256( in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaNistp256PublicKeyCompressed, in integer p_compressed_mode ) return boolean { // log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData", p_toBeVerifiedData); // log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData)); // log("f_verifyWithEcdsaNistp256WithSha256: signature", p_signature); // log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyCompressed", p_ecdsaNistp256PublicKeyCompressed); return fx_verifyWithEcdsaNistp256WithSha256( p_toBeVerifiedData, p_certificateIssuer, p_signature, p_ecdsaNistp256PublicKeyCompressed, p_compressed_mode ); } // End of function f_verifyWithEcdsaNistp256WithSha256 /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @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_1( // TODO To be removed in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaNistp256PublicKeyX, in Oct32 p_ecdsaNistp256PublicKeyY ) return boolean { // log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData", p_toBeVerifiedData); // log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData)); // log("f_verifyWithEcdsaNistp256WithSha256: signature", p_signature); // log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyX", p_ecdsaNistp256PublicKeyX); // log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyY", p_ecdsaNistp256PublicKeyY); return fx_verifyWithEcdsaNistp256WithSha256_1( p_toBeVerifiedData, p_certificateIssuer, p_signature, p_ecdsaNistp256PublicKeyX, p_ecdsaNistp256PublicKeyY); } // End of function f_verifyWithEcdsaNistp256WithSha256_1 /** * @Desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_signature The signature * @param p_ecdsaBrainpoolp256PublicKeyCompressed The compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ function f_verifyWithEcdsaBrainpoolp256WithSha256( in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaBrainpoolp256PublicKeyCompressed, in integer p_compressed_mode ) return boolean { // log("f_verifyWithEcdsaBrainpoolp256WithSha256: toBeVerifiedData", p_toBeVerifiedData); // log("f_verifyWithEcdsaBrainpoolp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData)); // log("f_verifyWithEcdsaBrainpoolp256WithSha256: signature", p_signature); // log("f_verifyWithEcdsaBrainpoolp256WithSha256: ecdsaBrainpoolp256PublicKeyCompressed", p_ecdsaBrainpoolp256PublicKeyCompressed); return fx_verifyWithEcdsaBrainpoolp256WithSha256( p_toBeVerifiedData, p_certificateIssuer, p_signature, p_ecdsaBrainpoolp256PublicKeyCompressed, p_compressed_mode ); } // End of function f_verifyWithEcdsaBrainpoolp256WithSha256 /** * @Desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_signature The signature * @param p_ecdsaBrainpoolp256PublicKeyX The public key (x coordinate) * @param p_ecdsaBrainpoolp256PublicKeyY The public key (y coordinate) * @return true on success, false otherwise */ function f_verifyWithEcdsaBrainpoolp256WithSha256_1( // TODO To be removed in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaBrainpoolp256PublicKeyX, in Oct32 p_ecdsaBrainpoolp256PublicKeyY ) return boolean { // log("f_verifyWithEcdsaBrainpoolp256WithSha256: toBeVerifiedData", p_toBeVerifiedData); // log("f_verifyWithEcdsaBrainpoolp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData)); // log("f_verifyWithEcdsaBrainpoolp256WithSha256: signature", p_signature); // log("f_verifyWithEcdsaBrainpoolp256WithSha256: ecdsaBrainpoolp256PublicKeyX", p_ecdsaBrainpoolp256PublicKeyX); // log("f_verifyWithEcdsaBrainpoolp256WithSha256: ecdsaBrainpoolp256PublicKeyY", p_ecdsaBrainpoolp256PublicKeyY); return fx_verifyWithEcdsaBrainpoolp256WithSha256_1( p_toBeVerifiedData, p_certificateIssuer, p_signature, p_ecdsaBrainpoolp256PublicKeyX, p_ecdsaBrainpoolp256PublicKeyY); } // End of function f_verifyWithEcdsaBrainpoolp256WithSha256_1 /** * @Desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_signature The signature * @param p_ecdsaBrainpoolp384PublicKeyX The public key (x coordinate) * @param p_ecdsaBrainpoolp384PublicKeyY The public key (y coordinate) * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ function f_verifyWithEcdsaBrainpoolp384WithSha384( in octetstring p_toBeVerifiedData, in Oct48 p_certificateIssuer, in Oct96 p_signature, in Oct48 p_ecdsaBrainpoolp384PublicKeyCompressed, in integer p_compressed_mode ) return boolean { // log("f_verifyWithEcdsaBrainpoolp384WithSha384: toBeVerifiedData", p_toBeVerifiedData); // log("f_verifyWithEcdsaBrainpoolp384WithSha384: toBeVerifiedData length", lengthof(p_toBeVerifiedData)); // log("f_verifyWithEcdsaBrainpoolp384WithSha384: signature", p_signature); // log("f_verifyWithEcdsaBrainpoolp384WithSha384: ecdsaBrainpoolp384PublicKeyCompressed", p_ecdsaBrainpoolp384PublicKeyCompressed); return fx_verifyWithEcdsaBrainpoolp384WithSha384( p_toBeVerifiedData, p_certificateIssuer, p_signature, p_ecdsaBrainpoolp384PublicKeyCompressed, p_compressed_mode ); } // End of function f_verifyWithEcdsaBrainpoolp384WithSha384 /** * @Desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_signature The signature * @param p_ecdsaBrainpoolp384PublicKeyX The public key (x coordinate) * @param p_ecdsaBrainpoolp384PublicKeyY The public key (y coordinate) * @return true on success, false otherwise */ function f_verifyWithEcdsaBrainpoolp384WithSha384_1( // TODO To be removed in octetstring p_toBeVerifiedData, in Oct48 p_certificateIssuer, in Oct96 p_signature, in Oct48 p_ecdsaBrainpoolp384PublicKeyX, in Oct48 p_ecdsaBrainpoolp384PublicKeyY ) return boolean { // log("f_verifyWithEcdsaBrainpoolp384WithSha384: toBeVerifiedData", p_toBeVerifiedData); // log("f_verifyWithEcdsaBrainpoolp384WithSha384: toBeVerifiedData length", lengthof(p_toBeVerifiedData)); // log("f_verifyWithEcdsaBrainpoolp384WithSha384: signature", p_signature); // log("f_verifyWithEcdsaBrainpoolp384WithSha384: ecdsaBrainpoolp384PublicKeyX", p_ecdsaBrainpoolp384PublicKeyX); // log("f_verifyWithEcdsaBrainpoolp384WithSha384: ecdsaBrainpoolp384PublicKeyY", p_ecdsaBrainpoolp384PublicKeyY); return fx_verifyWithEcdsaBrainpoolp384WithSha384_1( p_toBeVerifiedData, p_certificateIssuer, p_signature, p_ecdsaBrainpoolp384PublicKeyX, p_ecdsaBrainpoolp384PublicKeyY); } // End of function f_verifyWithEcdsaBrainpoolp384WithSha384_1 /** * @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) * @param p_publicKeyCompressed The compressed public keys * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ function f_generate_key_pair_nistp256( out Oct32 p_privateKey, out Oct32 p_publicKeyX, out Oct32 p_publicKeyY, out Oct32 p_publicKeyCompressed, out integer p_compressed_mode ) return boolean { log(">>> f_generate_key_pair_nistp256"); if (PICS_SEC_FIXED_KEYS) { // Debug mode: Use fixed values p_privateKey := '43481BC44C073C1432DB6EC4F0EF57062BEA08E4C19F811567325AD1FD1C6577'O; p_publicKeyX := '0B5D74B033531C51D17B4F218DD4E39289AE4BF2EE3D7BAB7C07DAF0C14F0317'O; p_publicKeyY := '5D49B139A9237832FDE24D77555878CE65D6C2284A1BDA4CE08ABDD4071E0255'O; p_publicKeyCompressed := '0B5D74B033531C51D17B4F218DD4E39289AE4BF2EE3D7BAB7C07DAF0C14F0317'O; p_compressed_mode := 1; return true; } return fx_generateKeyPair_nistp256(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode); } /** * @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) * @param p_publicKeyCompressed The compressed public keys * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ function f_generate_key_pair_brainpoolp256( out Oct32 p_privateKey, out Oct32 p_publicKeyX, out Oct32 p_publicKeyY, out Oct32 p_publicKeyCompressed, out integer p_compressed_mode ) return boolean { log(">>> f_generate_key_pair_brainpoolp256"); return fx_generateKeyPair_brainpoolp256(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode); } /** * @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) * @param p_publicKeyCompressed The compressed public keys * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ function f_generate_key_pair_brainpoolp384( out Oct48 p_privateKey, out Oct48 p_publicKeyX, out Oct48 p_publicKeyY, out Oct48 p_publicKeyCompressed, out integer p_compressed_mode ) return boolean { return fx_generateKeyPair_brainpoolp384(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode); } /** * @desc Calculate digest over the certificate * @param p_cert The certificate * @return the HashedId8 value * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.13 HashedId8 */ function f_calculateDigestFromCertificate( in Certificate p_cert ) return HashedId8 { var octetstring v_hash; if (PICS_SEC_SHA256) { v_hash := f_calculateDigestSha256FromCertificate(p_cert); } if (PICS_SEC_SHA384) { v_hash := f_calculateDigestSha384FromCertificate(p_cert); } return substr(v_hash, lengthof(v_hash) - 8, 8); } // End of function f_calculateDigestFromCertificate /** * @desc Calculate digest over the certificate * @param p_cert The certificate * @return the HashedId8 value * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.13 HashedId8 */ function f_calculateDigestSha256FromCertificate( in EtsiTs103097Certificate p_cert ) return HashedId8 { var octetstring v_toBeHashedData; var octetstring v_hash; v_toBeHashedData := bit2oct(encvalue(p_cert)); v_hash := f_hashWithSha256(v_toBeHashedData); return substr(v_hash, lengthof(v_hash) - 8, 8); } // End of function f_calculateDigestSha256FromCertificate function f_calculateDigestSha384FromCertificate( in EtsiTs103097Certificate p_cert ) return HashedId8 { var octetstring v_toBeHashedData; var octetstring v_hash; v_toBeHashedData := bit2oct(encvalue(p_cert)); v_hash := f_hashWithSha384(v_toBeHashedData); return substr(v_hash, lengthof(v_hash) - 8, 8); } // End of function f_calculateDigestSha384FromCertificate function f_duration2time( in Duration p_duration ) return UInt16 { if (ischosen(p_duration.seconds)) { return p_duration.seconds; } else if (ischosen(p_duration.minutes)) { return p_duration.minutes; } else if (ischosen(p_duration.hours)) { return p_duration.hours; } else if (ischosen(p_duration.sixtyHours)) { return p_duration.sixtyHours; } else if (ischosen(p_duration.years)) { return p_duration.years; } return 0; // Unrechable code } // End of function f_duration2time group hostSignatureHelpers { /** * @desc Initialize [out] certificates according to the specified certificate name * @param p_certificateName The certificate name to be used * @param p_aaCertificate The AA certificate [out] * @param p_atCertificate The AT certificate [out] * @return true on succes, false otherwise * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.13 HashedId8 */ function f_prepareCertificates( in template (omit) charstring p_certificateName, out EtsiTs103097Certificate p_aaCertificate, out EtsiTs103097Certificate p_atCertificate ) runs on ItsSecurityBaseComponent return boolean { var charstring v_certificate_id; //log(">>> f_prepareCertificates: ", p_certificateName); // Load certificates if required if ((lengthof(p_certificateName) > 0) and (valueof(p_certificateName) != cc_taCert_A)) { var HashedId8 v_digest; if (f_readCertificate(valueof(p_certificateName), p_atCertificate) == false){ log("f_prepareCertificates: Failed to read certificate ", p_certificateName); return false; } if (ischosen(p_atCertificate.issuer.sha256AndDigest)) { v_digest := p_atCertificate.issuer.sha256AndDigest; } else if (ischosen(p_atCertificate.issuer.sha384AndDigest)) { v_digest := p_atCertificate.issuer.sha384AndDigest; } else { log("f_prepareCertificates: Invalid certificate issuer ", p_atCertificate.issuer); return false; } if (f_getCertificateFromDigest(v_digest, p_aaCertificate, v_certificate_id) == false) { log("f_prepareCertificates: Failed to read certificate issuer ", v_digest); return false; } } else { p_atCertificate := vc_atCertificate; p_aaCertificate := vc_aaCertificate; } // Store the certificate to build this message vc_lastAtCertificateUsed := p_atCertificate; return true; } // End of function f_prepareCertificates /** * @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_headerInfo HeaderInfo to be inserted in the message * @param p_securityProfile Selected security profile * @return true on success, false otherwise */ function f_buildGnSecuredMessage( inout EtsiTs103097Data p_securedMessage, in charstring p_certificateName, in ToBeSignedData p_payloadField ) runs on ItsSecurityBaseComponent return boolean { // Local variables var octetstring v_secPayload, v_signature; var ToBeSignedData v_toBeSignedData; var octetstring v_certificateIssuer; var octetstring v_privateKey; log(">>> f_buildGnSecuredMessage: p_securedMessage=", p_securedMessage); log(">>> f_buildGnSecuredMessage: p_payloadField=", p_payloadField); // Prepare payload to be signed v_toBeSignedData := valueof(p_payloadField); v_secPayload := bit2oct(encvalue(v_toBeSignedData)); // Signed payload if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCert_A)) { if(not f_readSigningKey(valueof(p_certificateName), v_privateKey)){ return false; } } else { if(not f_readSigningKey(cc_taCert_A, v_privateKey)){ return false; } } f_getCertificateHash(p_certificateName, v_certificateIssuer); if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature)) { v_signature := f_signWithEcdsaNistp256WithSha256( v_secPayload, v_certificateIssuer, v_privateKey ); p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaNistP256( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only(substr(v_signature, 0, 32)), substr(v_signature, 32, 32) ) )); } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) { v_signature := f_signWithEcdsaBrainpoolp256WithSha256( v_secPayload, v_certificateIssuer, v_privateKey ); p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only(substr(v_signature, 0, 32)), substr(v_signature, 32, 32) ) )); } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature)) { v_signature := f_signWithEcdsaBrainpoolp384WithSha384( v_secPayload, v_certificateIssuer, v_privateKey ); p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1( m_ecdsaP384Signature( m_eccP384CurvePoint_x_only(substr(v_signature, 0, 48)), substr(v_signature, 48, 48) ) )); } // TODO To be continued log("<<< f_buildGnSecuredMessage: p_securedMessage=", p_securedMessage); return true; } // End of function f_buildGnSecuredMessage /** * @desc This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases * @param p_securedMessage The signed SecureMessage part * @param p_certificateName The certificate name * @param p_protocolVersion The protocol version to be set. Default: 2 * @param p_trailerStatus The Traile behaviour: *
  • 0 for no trailer
  • *
  • 1 for invalid trailer
  • *
  • 2 for duplicated trailer
  • * @param p_payloadField Payloads to be included in the message * @param p_mandatoryHeaders Mandatory headers for the selected profile * @param p_headerInfo HeaderInfo to be inserted in the message * @param p_securityProfile Selected security profile * @return true on success, false otherwise */ function f_buildGnSecuredMessage_Bo( inout EtsiTs103097Data p_securedMessage, in template (value) charstring p_certificateName, in UInt8 p_protocolVersion := c_protocol_version, in integer p_trailerStatus := 0, in template (value) ToBeSignedData p_payloadField, in template (value) HeaderInfo p_mandatoryHeaders, in template (omit) HeaderInfo p_headerInfo := omit ) return boolean { // Local variables var octetstring v_secPayload, v_signature; var template (value) ToBeSignedData v_toBeSignedData; var integer i, j, k, n; var HeaderInfo v_headerFields; var Ieee1609Dot2Content v_toBeSignedPayload; var Oct32 v_privateKey; var UInt8 v_trailerSize; // Prepare headers if (not(ispresent(p_headerInfo))) { v_headerFields := valueof(p_mandatoryHeaders); } else {/* FIXME To be reviewed // Merge p_headerInfo and v_mandatoryHeaders into v_headerFields i := 0; // index for p_headerInfo j := 0; // index for v_mandatoryHeaders k := 0; // index for v_headerFields // Special processing for signer_info if (lengthof(valueof(p_headerInfo)) > 0 and valueof(p_headerInfo[i].type_) == e_signer_info) { v_headerFields[k] := valueof(p_headerInfo[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_headerInfo); n := n + 1) { if (valueof(p_headerInfo[n].type_) == valueof(p_mandatoryHeaders[j].type_)) { // mandatory header already in p_HeaderFields break; } } // End of 'for' statement if (n >= lengthof(p_headerInfo)) { if (valueof(p_mandatoryHeaders[j].type_) != e_signer_info) { // Add headers from p_headerInfo having lower number than mandatory header for (n := i; n < lengthof(p_headerInfo) and valueof(p_headerInfo[n].type_) < valueof(p_mandatoryHeaders[j].type_); n := n + 1) { v_headerFields[k] := valueof(p_headerInfo[n]); k := k + 1; i := i + 1; } } // Add mandatory header v_headerFields[k] := valueof(p_mandatoryHeaders[j]); k := k + 1; } } // End of 'for' statement // Add remaining headers from p_HeaderFields for ( i := i; i < lengthof(p_headerInfo); i := i + 1) { // Add headers from p_headerInfo having lower number than mandatory header v_headerFields[k] := valueof(p_headerInfo[i]); k := k + 1; } // End of 'for' statement */} // Prepare payload to be signed /* FIXME To be reviewed v_toBeSignedPayload := valueof(p_payloadField); // log("p_trailerStatus=", p_trailerStatus); if (p_trailerStatus == 0) { v_trailerSize := 0; } else if (p_trailerStatus == 1) { v_trailerSize := 67; } else if (p_trailerStatus == 2) { v_trailerSize := 2 * 67; } else { v_trailerSize := 67; } v_toBeSignedData := m_toBeSignedSecuredMessage_wrong_protocol( v_headerFields, v_toBeSignedPayload, e_signature, p_protocolVersion, v_trailerSize );*/ // log("m_toBeSignedSecuredMessage_wrong_protocol=", v_toBeSignedData); /* FIXME To be reviewedv_secPayload := bit2oct(encvalue(v_toBeSignedData)); // log("v_secPayload=", v_secPayload); // Signed payload if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCert_A)) { if(not f_readSigningKey(valueof(p_certificateName), v_privateKey)){ return false; } } else { if(not f_readSigningKey(cc_taCert_A, v_privateKey)){ return false; } } v_signature := f_signWithEcdsaNistp256WithSha256( v_secPayload, v_privateKey );*/ // log("v_signature=", v_signature); // log("p_trailerStatus=", p_trailerStatus); /* FIXME To be reviewed if (p_trailerStatus == 0) { // No signature p_securedMessage := m_securedMessage( valueof(v_toBeSignedData.header_fields), p_payloadField, { } ); v_trailerSize := 0; } else if (p_trailerStatus == 2) { // Duplicate signature p_securedMessage := m_securedMessage( valueof(v_toBeSignedData.header_fields), p_payloadField, { 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) ) ) ), 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) ) ) ) } ); } else if (p_trailerStatus == 3) { // Signature with reserved algorthm p_securedMessage := m_ieee1609Dot2Data_wrong_protocol( p_protocolVersion, valueof(v_toBeSignedData.header_fields), p_payloadField, { m_trailer_field_signature( m_unknownSignature( v_signature ) ) } ); } else { // Invalid signature p_securedMessage := m_securedMessage( valueof(v_toBeSignedData.header_fields), p_payloadField, { 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) ) ) ) } ); p_securedMessage.trailer_fields[0].trailerField.signature_.ecdsaNistP256Signature.sSig := not4b(valueof(p_securedMessage.trailer_fields[0].trailerField.signature_.ecdsaNistP256Signature.sSig)); }*/ return false;/* FIXME To be reviewed true;*/ } // End of function f_buildGnSecuredMessage_Bo /** * @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_signerIdentifierType Add digest or AT certificate or certificate chain * @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_headerInfo * @return true on success, false otherwise * * @see Draft ETSI TS 103 097 V1.1.14 Clause 7.1 Security profile for CAMs */ function f_buildGnSecuredCam( inout EtsiTs103097Data p_securedMessage, in ToBeSignedData p_payloadField, in SignerIdentifier p_signerIdentifierType, in charstring p_certificateName := ""/*, in boolean p_addMissingHeaders := true*/ ) runs on ItsSecurityBaseComponent return boolean { // Local variables var EtsiTs103097Certificate v_aaCertificate, v_atCertificate; log(">>> f_buildGnSecuredCam: p_securedMessage= ", p_securedMessage); log(">>> f_buildGnSecuredCam: p_payloadField= ", p_payloadField); // Load certificates if required if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) { return false; } //log("f_buildGnSecuredCam: v_atCertificate = ", v_atCertificate); // Fill the structure with default values, these values will be updated later p_securedMessage := valueof(m_etsiTs103097Data_signed( m_signedData( sha256, p_payloadField, m_signerIdentifier_self, m_signature_ecdsaNistP256( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only(int2oct(0, 32)), int2oct(0, 32) ) ) ) )); // Prepare mandatory headers //log("f_buildGnSecuredCam: p_signerIdentifierType=", p_signerIdentifierType); if (ischosen(p_signerIdentifierType.certificate)) { // Add the AT certificate log("*** " & testcasename() & "f_buildGnSecuredCam: TODO ***"); stop; /* TODO * v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificate( v_atCertificate ))); } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificates( { v_aaCertificate, v_atCertificate } ) ));*/ } else if (ischosen(p_signerIdentifierType.digest)) { // Add the AT certificate digest if (ischosen(v_atCertificate.issuer.sha256AndDigest)) { p_securedMessage.content.signedData.hashId := sha256; p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest( f_calculateDigestSha256FromCertificate(v_atCertificate) )); } else if (ischosen(v_atCertificate.issuer.sha384AndDigest)) { p_securedMessage.content.signedData.hashId := sha384; p_securedMessage.content.signedData.signer := valueof(m_signerIdentifier_digest( f_calculateDigestSha384FromCertificate(v_atCertificate) )); } } else { log("*** " & testcasename() & "f_buildGnSecuredCam: TODO ***"); stop; } if (ispresent(v_atCertificate.signature_)) { if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP256r1Signature)) { p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1( m_ecdsaP256Signature( m_eccP256CurvePoint_x_only(int2oct(0, 32)), int2oct(0, 32) ) )); } else if (ischosen(v_atCertificate.signature_.ecdsaBrainpoolP384r1Signature)) { p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1( m_ecdsaP384Signature( m_eccP384CurvePoint_x_only(int2oct(0, 48)), int2oct(0, 48) ) )); } // else, m_signature_ecdsaNistP256 already chosen by default } //log("f_buildGnSecuredCam: p_securedMessage = ", p_securedMessage); return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/); } // End of function f_buildGnSecuredCam /** * @desc This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases * @param p_securedMessage The signed SecureMessage part * @param p_protocolVersion The protocol version to be set. Default: 2 * @param p_trailerStatus The Traile behaviour: *
  • 0 for no trailer
  • *
  • 1 for invalid trailer
  • *
  • 2 for duplicated trailer
  • * @param p_payloadField Payloads to be included in the message * @param p_signerIdentifierType Add digest or AT certificate or certificate chain * @param p_threeDLocation The 3D location * @param p_headerInfo HeaderInfo 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_headerInfo * @param p_alterATCertificateSignature Set to true to alter the AT certificate signature * @param p_alterAACertificateSignature Set to true to alter the AA certificate signature * @return true on success, false otherwise * * @see Draft ETSI TS 103 097 V1.1.14 Clause 7.1 Security profile for CAMs */ function f_buildGnSecuredCam_Bo( inout EtsiTs103097Data p_securedMessage, in UInt8 p_protocolVersion := c_protocol_version, in integer p_trailerStatus := 0, in ToBeSignedData p_payloadField, in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed in template (omit) HeaderInfo p_headerInfo := omit, in charstring p_certificateName := "", in boolean p_addMissingHeaders := true, in boolean p_alterATCertificateSignature := false, in boolean p_alterAACertificateSignature := false ) runs on ItsSecurityBaseComponent return boolean { // Local variables var EtsiTs103097Certificate v_aaCertificate, v_atCertificate; var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0)); var HeaderInfo v_signerInfo; // Load certificates if required if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) { return false; } if (p_alterATCertificateSignature == true) { v_atCertificate.signature_.ecdsaNistP256Signature.sSig := not4b(v_atCertificate.signature_.ecdsaNistP256Signature.sSig); } if (p_alterAACertificateSignature == true) { v_aaCertificate.signature_.ecdsaNistP256Signature.sSig := not4b(v_aaCertificate.signature_.ecdsaNistP256Signature.sSig); } /* FIXME To be reviewed if (p_addMissingHeaders == true) { // Prepare mandatory headers if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificate( v_atCertificate ))); } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificates( { v_aaCertificate, v_atCertificate } ) )); } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest v_signerInfo := valueof( m_header_info_signer_info( m_issuerIdentifier_sha256AndDigest( f_calculateDigestFromCertificate(v_atCertificate) ))); } v_mandatoryHeaders := { v_signerInfo, valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us valueof(m_header_info_its_aid(c_its_aid_CAM)) } }*/ return f_buildGnSecuredMessage_Bo(p_securedMessage, p_certificateName, p_protocolVersion, p_trailerStatus, p_payloadField, v_mandatoryHeaders, p_headerInfo); } // End of function f_buildGnSecuredCam_Bo /** * @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_signerIdentifierType Add digest or AT certificate or certificate chain * @param p_threeDLocation The 3D location * @param p_headerInfo HeaderInfo 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_headerInfo * @return true on success, false otherwise */ function f_buildGnSecuredDenm( inout EtsiTs103097Data p_securedMessage, in ToBeSignedData p_payloadField, in SignerIdentifier p_signerIdentifierType, in ThreeDLocation p_threeDLocation, in template (omit) HeaderInfo p_headerInfo := omit, in charstring p_certificateName := "", in boolean p_addMissingHeaders := true ) runs on ItsSecurityBaseComponent return boolean { // Local variables var EtsiTs103097Certificate v_aaCertificate, v_atCertificate; var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0)); var HeaderInfo v_signerInfo; // Load certificates if required if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) { return false; } // Add additional headers if required /* FIXME To be reviewed if (p_addMissingHeaders == true) { // Prepare mandatory headers if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificate( v_atCertificate ))); } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificates( { v_aaCertificate, v_atCertificate } ) )); } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest v_signerInfo := valueof( m_header_info_signer_info( m_issuerIdentifier_sha256AndDigest( v_atCertificate.cracaId ))); } v_mandatoryHeaders := { v_signerInfo, valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us valueof(m_header_info_generation_location(p_threeDLocation)), valueof(m_header_info_its_aid(c_its_aid_DENM)) } }*/ // Build the secured message and return it return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/); } // End of function f_buildGnSecuredDenm /** * @desc This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases * @param p_securedMessage The signed SecureMessage part * @param p_protocolVersion The protocol version to be set. Default: 2 * @param p_trailerStatus The Traile behaviour: *
  • 0 for no trailer
  • *
  • 1 for invalid trailer
  • *
  • 2 for duplicated trailer
  • * @param p_payloadField Payloads to be included in the message * @param p_signerIdentifierType Add digest or AT certificate or certificate chain * @param p_threeDLocation The 3D location * @param p_headerInfo HeaderInfo 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_headerInfo * @return true on success, false otherwise */ function f_buildGnSecuredDenm_Bo( inout EtsiTs103097Data p_securedMessage, in UInt8 p_protocolVersion := c_protocol_version, in integer p_trailerStatus := 0, in ToBeSignedData p_payloadField, in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed in ThreeDLocation p_threeDLocation, in template (omit) HeaderInfo p_headerInfo := omit, in charstring p_certificateName := "", in boolean p_addMissingHeaders := true ) runs on ItsSecurityBaseComponent return boolean { // Local variables var EtsiTs103097Certificate v_aaCertificate, v_atCertificate; var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0)); var HeaderInfo v_signerInfo; // Load certificates if required if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) { return false; } // Add additional headers if required /* FIXME To be reviewed if (p_addMissingHeaders == true) { // Prepare mandatory headers if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificate( v_atCertificate ))); } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificates( { v_aaCertificate, v_atCertificate } ) )); } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest v_signerInfo := valueof( m_header_info_signer_info( m_issuerIdentifier_sha256AndDigest( v_atCertificate.cracaId ))); } v_mandatoryHeaders := { v_signerInfo, valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us valueof(m_header_info_generation_location(p_threeDLocation)), valueof(m_header_info_its_aid(c_its_aid_DENM)) } }*/ // Build the secured message and return it return f_buildGnSecuredMessage_Bo(p_securedMessage, p_certificateName, p_protocolVersion, p_trailerStatus, p_payloadField, v_mandatoryHeaders, p_headerInfo); } // End of function f_buildGnSecuredDenm_Bo /** * @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_signerIdentifierType Add digest or AT certificate or certificate chain * @param p_threeDLocation The 3D location * @param p_headerInfo HeaderInfo 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_headerInfo * @return true on success, false otherwise */ function f_buildGnSecuredOtherMessage( inout EtsiTs103097Data p_securedMessage, in ToBeSignedData p_payloadField, in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed in ThreeDLocation p_threeDLocation, in template (omit) HeaderInfo p_headerInfo := omit, in charstring p_certificateName := "", in boolean p_addMissingHeaders := true ) runs on ItsSecurityBaseComponent return boolean { // Local variables var EtsiTs103097Certificate v_aaCertificate, v_atCertificate; var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0)); var HeaderInfo v_signerInfo; // Load certificates if required if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) { return false; } // Add additional headers if required /* FIXME To be reviewed if (p_addMissingHeaders == true) { // Prepare mandatory headers if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificate( v_atCertificate ))); } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificates( { v_aaCertificate, v_atCertificate } ) )); } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest v_signerInfo := valueof( m_header_info_signer_info( m_issuerIdentifier_sha256AndDigest( v_atCertificate.cracaId ))); } v_mandatoryHeaders := { v_signerInfo, valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us valueof(m_header_info_generation_location(p_threeDLocation)) } }*/ // Build the secured message and return it return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/); } // End of function f_buildGnSecuredOtherMessage /** * @desc This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases * @param p_securedMessage The signed SecureMessage part * @param p_protocolVersion The protocol version to be set. Default: 2 * @param p_trailerStatus The Traile behaviour: *
  • 0 for no trailer
  • *
  • 1 for invalid trailer
  • *
  • 2 for duplicated trailer
  • * @param p_payloadField Payloads to be included in the message * @param p_signerIdentifierType Add digest or AT certificate or certificate chain * @param p_threeDLocation The 3D location * @param p_headerInfo HeaderInfo 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_headerInfo * @return true on success, false otherwise */ function f_buildGnSecuredOtherMessage_Bo( inout EtsiTs103097Data p_securedMessage, in UInt8 p_protocolVersion := c_protocol_version, in integer p_trailerStatus := 0, in ToBeSignedData p_payloadField, in SignerIdentifier p_signerIdentifierType, // FIXME To be reviewed in ThreeDLocation p_threeDLocation, in template (omit) HeaderInfo p_headerInfo := omit, in charstring p_certificateName := "", in boolean p_addMissingHeaders := true ) runs on ItsSecurityBaseComponent return boolean { // Local variables var EtsiTs103097Certificate v_aaCertificate, v_atCertificate; var HeaderInfo v_mandatoryHeaders := valueof(m_ieee1609Dot2_headerInfo(0)); var HeaderInfo v_signerInfo; // Load certificates if required if (f_prepareCertificates(p_certificateName, v_aaCertificate, v_atCertificate) == false) { return false; } // Add additional headers if required /* FIXME To be reviewed if (p_addMissingHeaders == true) { // Prepare mandatory headers if (valueof(p_signerIdentifierType) == e_certificate) { // Add the AT certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificate( v_atCertificate ))); } else if (valueof(p_signerIdentifierType) == e_certificate_chain) { // Add the AT certificate + AA EtsiTs103097Certificate v_signerInfo := valueof( m_header_info_signer_info( m_signerIdentifier_certificates( { v_aaCertificate, v_atCertificate } ) )); } else if (valueof(p_signerIdentifierType) == e_certificate_digest_with_sha256) { // Add the AT certificate digest v_signerInfo := valueof( m_header_info_signer_info( m_issuerIdentifier_sha256AndDigest( v_atCertificate.cracaId ))); } v_mandatoryHeaders := { v_signerInfo, valueof(m_header_info_generation_time(1000 * f_getCurrentTime())), // In us valueof(m_header_info_generation_location(p_threeDLocation)) } }*/ // FIXME To be done // Build the secured message and return it return f_buildGnSecuredMessage(p_securedMessage, p_certificateName, p_payloadField/*, v_mandatoryHeaders*/); } // End of function f_buildGnSecuredOtherMessage_Bo } // End of group hostSignatureHelpers group deviceSignatureHelpers { /** * @desc Retrieve the HashedId8 to be sent to the IUT, based on the provided certificate identifier * @param p_certificateName The certificate the IUT shall use * @return The HashedId8 to be sent to the IUT in the UtInitialize command * @verdict Unchanged * @remark Component variable vc_hashedId8ToBeUsed shall be set with the IUT certificate to be used */ function f_setupIutCertificate( in charstring p_certificateName ) runs on ItsSecurityBaseComponent return HashedId8 { // Local variables var HashedId8 v_hashedId8 := '0000000000000000'O; // Sanity check if (lengthof(p_certificateName) == 0) { return v_hashedId8; } // Load certificates if(f_getCertificateDigest(p_certificateName, v_hashedId8) == false) { v_hashedId8 := '0000000000000000'O; } return v_hashedId8; } // End of function f_setupIutCertificate /** * @desc Verify the signature of the provided certificate * @param p_certificateToBeVerified EtsiTs103097Certificate 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) EtsiTs103097Certificate p_certificateToBeVerified, in template (value) PublicVerificationKey p_publicVerificationKey ) return boolean { var ToBeSignedCertificate v_toBeSignedCertificate; var octetstring v_enc_msg; var octetstring v_signature; var octetstring v_issuer; log(">>> f_verifyCertificateSignatureWithPublicKey: p_certificateToBeVerified=", p_certificateToBeVerified); log(">>> f_verifyCertificateSignatureWithPublicKey: p_publicVerificationKey=", p_publicVerificationKey); // Create ToBeSignedCertificate payload to be signed v_toBeSignedCertificate := valueof(p_certificateToBeVerified.toBeSigned); log("f_verifyCertificateSignatureWithPublicKey: v_toBeSignedCertificate=", v_toBeSignedCertificate); v_enc_msg := bit2oct(encvalue(v_toBeSignedCertificate)); log("f_verifyCertificateSignatureWithPublicKey: v_enc_msg=", v_enc_msg); // Verify payload if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP256r1)) { if (ischosen(p_certificateToBeVerified.issuer.self_)) { v_issuer := int2oct(0, 32); } else { var charstring v_certificate; if (fx_readCertificateFromDigest(valueof(p_certificateToBeVerified.issuer.sha256AndDigest), v_certificate) == false) { log("f_verifyCertificateSignatureWithPublicKey: Invalid issuer: ", p_certificateToBeVerified.issuer.sha256AndDigest); return false; } if (f_getCertificateHash(v_certificate, v_issuer) == false) { log("f_verifyCertificateSignatureWithPublicKey: Invalid certificate: " & v_certificate); return false; } } v_signature := valueof(p_certificateToBeVerified.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only) & valueof(p_certificateToBeVerified.signature_.ecdsaBrainpoolP256r1Signature.sSig); log("f_verifyCertificateSignatureWithPublicKey: v_signedData=", v_signature); if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP256r1.uncompressedP256)) { return f_verifyWithEcdsaBrainpoolp256WithSha256_1( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaBrainpoolP256r1.uncompressedP256.x), valueof(p_publicVerificationKey.ecdsaBrainpoolP256r1.uncompressedP256.y) ); } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP256r1.compressed_y_0)) { return f_verifyWithEcdsaBrainpoolp256WithSha256( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaBrainpoolP256r1.compressed_y_0), 0 // Latest bit of the Y-coordinate is 0 ); } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP256r1.compressed_y_1)) { return f_verifyWithEcdsaBrainpoolp256WithSha256( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaBrainpoolP256r1.compressed_y_1), 1 // Latest bit of the Y-coordinate is 1 ); } else { log("f_verifyCertificateSignatureWithPublicKey: Unknown PublicVerificationKey value"); return false; } } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP384r1)) { if (ischosen(p_certificateToBeVerified.issuer.self_)) { v_issuer := int2oct(0, 48); } else { var charstring v_certificate; if (fx_readCertificateFromDigest(valueof(p_certificateToBeVerified.issuer.sha384AndDigest), v_certificate) == false) { log("f_verifyCertificateSignatureWithPublicKey: Invalid issuer: ", p_certificateToBeVerified.issuer.sha384AndDigest); return false; } if (f_getCertificateHash(v_certificate, v_issuer) == false) { log("f_verifyCertificateSignatureWithPublicKey: Invalid certificate: " & v_certificate); return false; } } v_signature := valueof(p_certificateToBeVerified.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only) & valueof(p_certificateToBeVerified.signature_.ecdsaBrainpoolP384r1Signature.sSig); log("f_verifyCertificateSignatureWithPublicKey: v_signedData=", v_signature); if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP384r1.uncompressedP384)) { return f_verifyWithEcdsaBrainpoolp384WithSha384_1( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaBrainpoolP384r1.uncompressedP384.x), valueof(p_publicVerificationKey.ecdsaBrainpoolP384r1.uncompressedP384.y) ); } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP384r1.compressed_y_0)) { return f_verifyWithEcdsaBrainpoolp384WithSha384( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaBrainpoolP384r1.compressed_y_0), 0 // Latest bit of the Y-coordinate is 0 ); } else if (ischosen(p_publicVerificationKey.ecdsaBrainpoolP384r1.compressed_y_1)) { return f_verifyWithEcdsaBrainpoolp384WithSha384( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaBrainpoolP384r1.compressed_y_1), 1 // Latest bit of the Y-coordinate is 1 ); } else { log("f_verifyCertificateSignatureWithPublicKey: Unknown PublicVerificationKey value"); return false; } } else if (ischosen(p_publicVerificationKey.ecdsaNistP256)) { if (ischosen(p_certificateToBeVerified.issuer.self_)) { v_issuer := int2oct(0, 32); } else { var charstring v_certificate; if (fx_readCertificateFromDigest(valueof(p_certificateToBeVerified.issuer.sha256AndDigest), v_certificate) == false) { log("f_verifyCertificateSignatureWithPublicKey: Invalid issuer: ", p_certificateToBeVerified.issuer.sha256AndDigest); return false; } if (f_getCertificateHash(v_certificate, v_issuer) == false) { log("f_verifyCertificateSignatureWithPublicKey: Invalid certificate: " & v_certificate); return false; } } v_signature := valueof(p_certificateToBeVerified.signature_.ecdsaNistP256Signature.rSig.x_only) & valueof(p_certificateToBeVerified.signature_.ecdsaNistP256Signature.sSig); log("f_verifyCertificateSignatureWithPublicKey: v_signedData=", v_signature); if (ischosen(p_publicVerificationKey.ecdsaNistP256.uncompressedP256)) { return f_verifyWithEcdsaNistp256WithSha256_1( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaNistP256.uncompressedP256.x), valueof(p_publicVerificationKey.ecdsaNistP256.uncompressedP256.y) ); } else if (ischosen(p_publicVerificationKey.ecdsaNistP256.compressed_y_0)) { return f_verifyWithEcdsaNistp256WithSha256( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaNistP256.compressed_y_0), 0 // Latest bit of the Y-coordinate is 0 ); } else if (ischosen(p_publicVerificationKey.ecdsaNistP256.compressed_y_1)) { return f_verifyWithEcdsaNistp256WithSha256( v_enc_msg, v_issuer, v_signature, valueof(p_publicVerificationKey.ecdsaNistP256.compressed_y_1), 1 // Latest bit of the Y-coordinate is 1 ); } else { log("f_verifyCertificateSignatureWithPublicKey: Unknown PublicVerificationKey value"); return false; } } return false; } // End of finction f_verifyCertificateSignatureWithPublicKey /** * @desc Verify the signature of the provided secured message * @param p_certificateToBeVerified EtsiTs103097Certificate to be verified * @param p_issuingCertificate Issuing certificate * @return true on success, false otherwise * @verdict */ function f_verifyCertificateSignatureWithIssuingCertificate( in template (value) EtsiTs103097Certificate p_certificateToBeVerified, in template (value) EtsiTs103097Certificate p_issuingCertificate ) return boolean { // Sanity checks if (not(ischosen(p_issuingCertificate.toBeSigned.verifyKeyIndicator.verificationKey))) { return false; } return f_verifyCertificateSignatureWithPublicKey( p_certificateToBeVerified, p_issuingCertificate.toBeSigned.verifyKeyIndicator.verificationKey ); } // End of function f_verifyCertificateSignatureWithIssuingCertificate /** * @desc Verify the signature of the provided secured message for ECDSA Nist-P256 algorithm * @param p_securedMessage The message to be verified * @param p_publicKey The ECDSA public key to verify a signature * @param p_certificate EtsiTs103097Certificate to be used to verify the message * @return true on success, false otherwise * @verdict Unchanged */ function f_verifyGnSecuredMessageSignature_ecdsaNistP256( in template (value) Ieee1609Dot2Data p_securedMessage, in template (value) Oct32 p_certificateIssuer, in template (value) EccP256CurvePoint p_publicKey ) return boolean { // Local variables var octetstring v_secPayload; var octetstring v_signedData; var boolean v_result := false; var template (value) ToBeSignedData v_toBeSignedData; log(">>> f_verifyGnSecuredMessageSignature_ecdsaNistP256: p_securedMessage= ", p_securedMessage); log(">>> f_verifyGnSecuredMessageSignature_ecdsaNistP256: p_certificateIssuer= ", p_certificateIssuer); log(">>> f_verifyGnSecuredMessageSignature_ecdsaNistP256: p_publicKey= ", p_publicKey); // Create Ieee1609Dot2Data payload to be signed v_toBeSignedData := valueof(p_securedMessage.content.signedData.tbsData); log("f_verifyGnSecuredMessageSignature_ecdsaNistP256: v_toBeSignedData=", p_securedMessage.content.signedData.tbsData); v_secPayload := bit2oct(encvalue(v_toBeSignedData)); log("f_verifyGnSecuredMessageSignature_ecdsaNistP256: v_secPayload=", v_secPayload); // Verify payload // TODO Check in standard if x-only only if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only)) { v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.x_only) & valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig); } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.compressed_y_0)) { v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.compressed_y_0) & valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig); } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.compressed_y_1)) { v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.rSig.compressed_y_1) & valueof(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature.sSig); } log("f_verifyGnSecuredMessageSignature_ecdsaNistP256: v_signedData=", v_signedData); if (ischosen(p_publicKey.uncompressedP256)) { v_result := f_verifyWithEcdsaNistp256WithSha256_1( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.uncompressedP256.x), valueof(p_publicKey.uncompressedP256.y) ); } else if (ischosen(p_publicKey.compressed_y_0)) { v_result := f_verifyWithEcdsaNistp256WithSha256( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.compressed_y_0), 0 ); } else if (ischosen(p_publicKey.compressed_y_1)) { v_result := f_verifyWithEcdsaNistp256WithSha256( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.compressed_y_1), 1 ); } log("f_verifyGnSecuredMessageSignature_ecdsaNistP256: v_result=", v_result); return v_result; } // End of function f_verifyGnSecuredMessageSignature_ecdsaNistP256 /** * @desc Verify the signature of the provided secured message for ECDSA Brainpool-P256 algorithm * @param p_securedMessage The message to be verified * @param p_publicKey The ECDSA public key to verify a signature * @param p_certificate EtsiTs103097Certificate to be used to verify the message * @return true on success, false otherwise * @verdict Unchanged */ function f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1( in template (value) Ieee1609Dot2Data p_securedMessage, in template (value) Oct32 p_certificateIssuer, in template (value) EccP256CurvePoint p_publicKey ) return boolean { // Local variables var octetstring v_secPayload; var octetstring v_signedData; var boolean v_result := false; var template (value) ToBeSignedData v_toBeSignedData; log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: p_securedMessage= ", p_securedMessage); log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: p_certificateIssuer= ", p_certificateIssuer); log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: p_publicKey= ", p_publicKey); // Create Ieee1609Dot2Data payload to be signed v_toBeSignedData := valueof(p_securedMessage.content.signedData.tbsData); log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: v_toBeSignedData=", p_securedMessage.content.signedData.tbsData); v_secPayload := bit2oct(encvalue(v_toBeSignedData)); log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: v_secPayload=", v_secPayload); // Verify payload v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.rSig.x_only) & valueof(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature.sSig); log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: v_signedData=", v_signedData); if (ischosen(p_publicKey.uncompressedP256)) { v_result := f_verifyWithEcdsaBrainpoolp256WithSha256_1( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.uncompressedP256.x), valueof(p_publicKey.uncompressedP256.y) ); } else if (ischosen(p_publicKey.compressed_y_0)) { v_result := f_verifyWithEcdsaBrainpoolp256WithSha256( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.compressed_y_0), 0 ); } else if (ischosen(p_publicKey.compressed_y_1)) { v_result := f_verifyWithEcdsaBrainpoolp256WithSha256( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.compressed_y_1), 1 ); } log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1: v_result=", v_result); return v_result; } // End of function f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1 /** * @desc Verify the signature of the provided secured message for ECDSA Brainpool-P384 algorithm * @param p_securedMessage The message to be verified * @param p_publicKey The ECDSA public key to verify a signature * @param p_certificate EtsiTs103097Certificate to be used to verify the message * @return true on success, false otherwise * @verdict Unchanged */ function f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1( in template (value) Ieee1609Dot2Data p_securedMessage, in template (value) Oct48 p_certificateIssuer, in template (value) EccP384CurvePoint p_publicKey ) return boolean { // Local variables var octetstring v_secPayload; var octetstring v_signedData; var boolean v_result := false; var template (value) ToBeSignedData v_toBeSignedData; log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: p_securedMessage= ", p_securedMessage); log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: p_certificateIssuer= ", p_certificateIssuer); log(">>> f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: p_publicKey= ", p_publicKey); // Create Ieee1609Dot2Data payload to be signed v_toBeSignedData := valueof(p_securedMessage.content.signedData.tbsData); log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: v_toBeSignedData=", p_securedMessage.content.signedData.tbsData); v_secPayload := bit2oct(encvalue(v_toBeSignedData)); log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: v_secPayload=", v_secPayload); // Verify payload v_signedData := valueof(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.rSig.x_only) & valueof(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature.sSig); log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: v_signedData=", v_signedData); if (ischosen(p_publicKey.uncompressedP384)) { v_result := f_verifyWithEcdsaBrainpoolp384WithSha384_1( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.uncompressedP384.x), valueof(p_publicKey.uncompressedP384.y) ); } else if (ischosen(p_publicKey.compressed_y_0)) { v_result := f_verifyWithEcdsaBrainpoolp384WithSha384( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.compressed_y_0), 0 ); } else if (ischosen(p_publicKey.compressed_y_1)) { v_result := f_verifyWithEcdsaBrainpoolp384WithSha384( v_secPayload, valueof(p_certificateIssuer), v_signedData, valueof(p_publicKey.compressed_y_1), 1 ); } log("f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1: v_result=", v_result); return v_result; } // End of function f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1 /** * @desc Verify the signature of the provided secured message * @param p_securedMessage * @param p_certificate EtsiTs103097Certificate to be used to verify the message * @return true on success, false otherwise * @verdict */ function f_verifyGnSecuredMessageSignatureWithCertificate( in template (value) Ieee1609Dot2Data p_securedMessage, in template (value) charstring p_certificate_id, in template (value) EtsiTs103097Certificate p_certificate ) return boolean { var octetstring v_issuer; var EtsiTs103097Certificate v_certificate; log(">>> f_verifyGnSecuredMessageSignatureWithCertificate: p_securedMessage=", p_securedMessage); log(">>> f_verifyGnSecuredMessageSignatureWithCertificate: p_certificate_id=", p_certificate_id); log(">>> f_verifyGnSecuredMessageSignatureWithCertificate: p_certificate=", p_certificate); if (f_getCertificateHash(valueof(p_certificate_id), v_issuer) == false) { log("f_verifyCertificateSignatureWithPublicKey: Invalid certificate id: " & valueof(p_certificate_id)); return false; } if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) { return f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP256r1(p_securedMessage, v_issuer, p_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP256r1); } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature)) { return f_verifyGnSecuredMessageSignature_ecdsaBrainpoolP384r1(p_securedMessage, v_issuer, p_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaBrainpoolP384r1); } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature)) { return f_verifyGnSecuredMessageSignature_ecdsaNistP256(p_securedMessage, v_issuer, p_certificate.toBeSigned.verifyKeyIndicator.verificationKey.ecdsaNistP256); } return false; } // End of function f_verifyGnSecuredOtherMessageWithDeviceCertificate } // End of group deviceSignatureHelpers group sspPermissions { function f_verifySspPermissions( in SequenceOfPsidSsp p_issuer_ssp_permissions, in SequenceOfPsidSsp p_subordinate_ssp_permissions, in boolean p_strict_checks := false ) return boolean { // Local variables var integer v_idx := 0; log(">>> f_verifySspPermissions: p_issuer_ssp_permissions:", p_issuer_ssp_permissions); log(">>> f_verifySspPermissions: p_subordinate_ssp_permissions: ", p_subordinate_ssp_permissions); for (v_idx := 0; v_idx < lengthof(p_issuer_ssp_permissions); v_idx := v_idx + 1) { var PsidSsp v_issuerPsidSsp := p_issuer_ssp_permissions[v_idx]; var PsidSsp v_subordinatePsidSsp; var boolean v_found := false; var integer v_jdx := 0; log("f_verifySspPermissions: v_issuerPsidSsp: ", v_issuerPsidSsp); // 1. Check permission from issuer is present for (v_jdx := 0; v_jdx < lengthof(p_subordinate_ssp_permissions); v_jdx := v_jdx + 1) { log("f_verifySspPermissions: match=", match(v_issuerPsidSsp, m_appPermissions(p_subordinate_ssp_permissions[v_jdx].psid, p_subordinate_ssp_permissions[v_jdx].ssp))); // 1. Check the version if (p_subordinate_ssp_permissions[v_jdx].ssp.bitmapSsp[0] != '01'O) { log("f_verifySspPermissions: Wrong SSP version control (1 is expected): ", p_subordinate_ssp_permissions[v_jdx].ssp.bitmapSsp[0]); return false; } // 2. Check the version if (match(v_issuerPsidSsp, m_appPermissions(p_subordinate_ssp_permissions[v_jdx].psid, p_subordinate_ssp_permissions[v_jdx].ssp)) == true) { v_subordinatePsidSsp := p_subordinate_ssp_permissions[v_jdx]; v_found := true; break; } } // End of 'for' statement if (v_found == false) { log("f_verifySspPermissions: Permission set not found: ", v_issuerPsidSsp); if (p_strict_checks == true) { return false; } else { return true; } } // 2. Validate bits mask if (ispresent(v_issuerPsidSsp.ssp)) { if (ispresent(v_subordinatePsidSsp.ssp) == false) { log("f_verifySspPermissions: Ssp shall not be omitted: ", v_issuerPsidSsp); if (p_strict_checks == true) { return false; } } if ((ischosen(v_issuerPsidSsp.ssp.bitmapSsp) == false) or (ischosen(v_subordinatePsidSsp.ssp.bitmapSsp) == false)) { log("f_verifySspPermissions: Wrong variant : ", v_issuerPsidSsp, " / ", v_subordinatePsidSsp); if (p_strict_checks == true) { return false; } } if (lengthof(v_issuerPsidSsp.ssp.bitmapSsp) < lengthof(v_subordinatePsidSsp.ssp.bitmapSsp)) { log("f_verifySspPermissions: Ssp not be compliant: ", v_issuerPsidSsp.ssp, " / ", v_subordinatePsidSsp.ssp); if (p_strict_checks == true) { return false; } } else { var charstring v_issuerSsp := bit2str(oct2bit(v_issuerPsidSsp.ssp.bitmapSsp)); var charstring v_subordinateSsp := bit2str(oct2bit(v_subordinatePsidSsp.ssp.bitmapSsp)); for (var integer i := 0; i < lengthof(v_issuerSsp); i := i + 1) { if (v_issuerSsp[i] == "1") { // TODO How to check Permission using SspBitmask/SspValue if (v_subordinateSsp[i] != "1") { log("f_verifySspPermissions: Ssp bitmask mismatch at index: ", i); return false; } } // else, no restriction, subordinate certificate can have any value. } // End of 'for' statement } } } // End of 'for' statement return true; } // End of function f_verifySspPermissions } // End of group sspPermissions group messageGetters { /** * @desc return Ieee1609Dot2Data header field of given type or null if none * @param p_msg the Ieee1609Dot2Data * @param p_type header field type * @return HeaderInfo of given type if any or null */ function f_getMsgHeaderInfo( in template(omit) Ieee1609Dot2Data p_securedMessage, out HeaderInfo p_return ) return boolean { var integer v_length; var Ieee1609Dot2Data v_securedMessage; if (not isvalue(p_securedMessage)) { testcase.stop(__SCOPE__ & " can not handle omitted secured message values"); } v_securedMessage := valueof(p_securedMessage); if (ischosen(v_securedMessage.content.signedData)) { p_return := v_securedMessage.content.signedData.tbsData.headerInfo; return true; } log("f_getMsgHeaderField: return false"); return false; } /** * @desc return SignerIdentifier Ieee1609Dot2Data field */ function f_getMsgSignerIdentifier ( in template(omit) Ieee1609Dot2Data p_securedMessage, out SignerIdentifier p_signerIdentifier ) return boolean { if (not isvalue(p_securedMessage)) { testcase.stop(__SCOPE__ & " can not handle omitted secured message values"); } if (ischosen(p_securedMessage.content.signedData)) { p_signerIdentifier := valueof(p_securedMessage.content.signedData.signer); return true; } log("f_getMsgSignerIdentifier: return false"); return false; } } // End of group messageGetters group certificateGetters { /** * @desc Set the generation location as defined in Draft ETSI TS 103 097 V1.1.14 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 * @verdict Unchanged */ function f_setGenerationLocation( in SecLatitude p_latitude, in SecLongitude p_longitude, in SecElevation p_elevation := 0 ) runs on ItsSecurityBaseComponent { vc_location := { p_latitude, p_longitude, 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 */ function f_loadCertificates( in charstring p_configId ) runs on ItsSecurityBaseComponent return boolean { var charstring v_certificate_id; // Setup certificates memory cache if (fx_loadCertificates(PX_CERTIFICATE_POOL_PATH, p_configId) == true) { // Setup security component variables if (f_readCertificate(PX_CERT_FOR_TS, vc_atCertificate) == true) { var HashedId8 v_issuer; log("Issuer: ", vc_atCertificate.issuer); if (ischosen(vc_atCertificate.issuer.sha256AndDigest)) { v_issuer := vc_atCertificate.issuer.sha256AndDigest; } else if (ischosen(vc_atCertificate.issuer.sha384AndDigest)) { v_issuer := vc_atCertificate.issuer.sha384AndDigest; } else { log("AT certificate cannot be issued by CA"); return false; } log("Selected issuer: ", v_issuer); if (f_getCertificateFromDigest(v_issuer, vc_aaCertificate, v_certificate_id)) { if (f_readSigningKey(cc_taCert_A, vc_signingPrivateKey) == true) { f_readEncryptingKey(cc_taCert_A, vc_encryptPrivateKey); return true; } log("f_loadCertificates: Failed to load signing key for ", cc_taCert_A); } else { log("f_loadCertificates: Failed to load AA certificate for ", cc_taCert_A); } } else { log("f_loadCertificates: Failed to load AT certificate for ", cc_taCert_A); } } else { log("f_loadCertificates: Failed to load certificates from ", PX_CERTIFICATE_POOL_PATH); } 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 := ''O; vc_encryptPrivateKey := ''O; // Clear certificates memory cache return fx_unloadCertificates(); } // End of function f_unloadCertificates /** * @desc Read the specified certificate * @param p_certificate_id the certificate identifier * @param p_certificate the expected certificate * @return true on success, false otherwise */ function f_readCertificate( in charstring p_certificate_id, out EtsiTs103097Certificate p_certificate ) return boolean { var octetstring v_certificate; if (fx_readCertificate(p_certificate_id, 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_certificate_id); return false; } // End of function f_readCertificate /** * @desc Read the specified certificate * @param p_certificate_id the certificate identifier * @param p_digest the digest of the certificate * @return true on success, false otherwise */ function f_getCertificateDigest( in charstring p_certificate_id, out HashedId8 p_digest ) return boolean { if (not fx_readCertificateDigest(p_certificate_id, p_digest)){ log("f_getCertificateDigest: Failed to retrieve digest for ", p_certificate_id); return false; } return true; } // End of function f_getCertificateDigest /** * @desc Read the whole-hash of the certificate * @param p_certificate_id the certificate identifier * @param p_hash the whole-hash of the certificate * @return true on success, false otherwise */ function f_getCertificateHash( in charstring p_certificate_id, out octetstring p_hash ) return boolean { if (not fx_readCertificateHash(p_certificate_id, p_hash)){ log("f_getCertificateHash: Failed to retrieve digest for ", p_certificate_id); return false; } return true; } // End of function f_getCertificateHash /** * @desc Read the whole-hash of the certificate SHA 256 * @param p_certificate_id the certificate identifier * @param p_hash the whole-hash of the certificate using SHA 256 * @return true on success, false otherwise */ function f_getCertificateHash256( in charstring p_certificate_id, out Oct32 p_hash ) return boolean { if (not fx_readCertificateHash256(p_certificate_id, p_hash)){ log("f_getCertificateHash256: Failed to retrieve digest for ", p_certificate_id); return false; } return true; } // End of function f_getCertificateHash function f_getCertificateFromDigest( in HashedId8 p_digest, out EtsiTs103097Certificate p_certificate, out charstring p_certificate_id ) return boolean { if (not(fx_readCertificateFromDigest(p_digest, p_certificate_id))) { log("f_getCertificateFromDigest: Failed to retrieve digest for ", p_digest); return false; } if (not(f_readCertificate(p_certificate_id, p_certificate))) { log("f_getCertificateFromDigest: Failed to retrieve digest for ", p_certificate_id); return false; } return true; } // End of function f_getCertificateFromDigest function f_getCertificateFromHashedId3( in HashedId3 p_digest, out EtsiTs103097Certificate p_certificate ) return boolean { var charstring v_certificate_id; if (not(fx_readCertificateFromHashedId3(p_digest, v_certificate_id))) { log("f_getCertificateFromHashedId3: Failed to retrieve digest for ", p_digest); return false; } if (not(f_readCertificate(v_certificate_id, p_certificate))) { log("f_getCertificateFromHashedId3: Failed to retrieve digest for ", v_certificate_id); return false; } return true; } // End of function f_getCertificateFromHashedId3 /** * @desc Read the signing private key for the specified certificate * @param p_keysId the keys identifier * @param p_signingPrivateKey the signing private key * @return true on success, false otherwise */ function f_readSigningKey( in charstring p_keysId, out Oct32 p_signingPrivateKey ) return boolean { return fx_readSigningKey(p_keysId, p_signingPrivateKey); } // End of function f_readSigningKey /** * @desc Read the encrypting private keys for the specified certificate * @param p_keysId the keys identifier * @param p_encryptPrivateKey the encrypt private key * @return true on success, false otherwise */ function f_readEncryptingKey( in charstring p_keysId, out Oct32 p_encryptPrivateKey ) return boolean { return fx_readEncryptingKey(p_keysId, p_encryptPrivateKey); } // End of function f_readEncryptingKey function f_getCertificateValidityRestriction( in template (value) EtsiTs103097Certificate p_cert, out template (value) ValidityPeriod p_validityPeriod, out template (omit) GeographicRegion p_geographicRegion ) return boolean { p_validityPeriod := valueof(p_cert.toBeSigned.validityPeriod); if (ispresent(p_cert.toBeSigned.region)) { p_geographicRegion := valueof(p_cert.toBeSigned.region); } else { p_geographicRegion := omit; } return true; } // End of function f_getCertificateValidityRestriction }// End of group certificateGetters group certificatesCaching { function f_createCertificatesCaching( in SequenceOfCertificate p_certificates, out CertificatesCaching p_certificatesCaching ) return boolean { p_certificatesCaching := { }; for (var integer v_counter := 0; v_counter < lengthof(p_certificates); v_counter := v_counter + 1) { var CertificatesCachingItem v_item; v_item.certificate := p_certificates[v_counter]; v_item.hashedId8 := f_calculateDigestSha256FromCertificate(v_item.certificate); p_certificatesCaching[v_counter] := v_item; } // End of 'for' statement return true; } function f_getCertificateFromCaching( in CertificatesCaching p_certificatesCaching, in HashedId8 p_hashedId8, out EtsiTs103097Certificate p_certificate ) return boolean { for (var integer v_counter := 0; v_counter < lengthof(p_certificatesCaching); v_counter := v_counter + 1) { if (match(p_certificatesCaching[v_counter].hashedId8, p_hashedId8) == true) { p_certificate := p_certificatesCaching[v_counter].certificate; return true; } } // End of 'for' statement return false; } function f_getCertificatesCachingItem( in CertificatesCaching p_certificatesCaching, in UInt8 p_index, out EtsiTs103097Certificate p_certificate ) return boolean { if (lengthof(p_certificatesCaching) < p_index) { p_certificate := p_certificatesCaching[p_index].certificate; return true; } return false; } function f_getCertificatesCachingItemSize( in CertificatesCaching p_certificatesCaching ) return UInt8 { return lengthof(p_certificatesCaching); } }// End of group certificatesCaching } // 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 384-bit (48-byte) hash value * @param p_toBeHashedData Data to be used to calculate the hash value * @return The hash value */ external function fx_hashWithSha384(in octetstring p_toBeHashedData) return Oct48; external function fx_hmac_sha256(in octetstring p_k, in octetstring p_m) return octetstring; /** * @desc This function validates AES128 CCM encryption based on IEEE Std 1609.2-20XX Annex D.6.1 AES-CCM-128 * @param[in] The symmetric AES 128 encryption key * @param[in] The initial vector (aka nonce) * @param[in] The raw payload * @return The encrypted payload */ external function fx_encrypt_aes_128_ccm_test(in octetstring p_k, in octetstring p_n, in octetstring p_pt) return octetstring; /** * @desc TThis function validates AES128 CCM encryption based on AES-GCM-256 * @param[in] The symmetric AES 128 encryption key * @param[in] The initial vector (aka nonce) * @param[in] The raw payload * @return The encrypted payload */ external function fx_encrypt_aes_128_gcm_test(in octetstring p_k, in octetstring p_n, in octetstring p_pt) return octetstring; /** * @desc This function validates AES128 CCM decryption based on IEEE Std 1609.2-20XX Annex D.6.1 AES-CCM-128 * @param[in] The symmetric AES 128 encryption key * @param[in] The initial vector (aka nonce) * @param[in] The cyphered payload * @return The raw payload */ external function fx_decrypt_aes_128_ccm_test(in octetstring p_k, in octetstring p_n, in octetstring p_pt) return octetstring; /** * @desc Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Nist-P256 algorithm * @param p_toBeEncryptedSecuredMessage The data to be encrypted * @param p_recipientsPublicKeyCompressed The Recipient's compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_publicEphemeralKeyCompressed The generated ephemeral compressed key * @param p_ephemeralKeyModeCompressed The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_encrypted_sym_key The encrypted AES 128 CCM symmetric key * @param p_authentication_vector The tag of the AES 128 CCM symmetric key encryption * @param p_nonce The nonce vector of the AES 128 CCM symmetric key encryption * @return The encrypted message */ external function fx_encryptWithEciesNistp256WithSha256(in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_recipientsPublicKeyCompressed, in integer p_compressed_mode, in octetstring p_salt, out Oct32 p_publicEphemeralKeyCompressed, out integer p_ephemeralKeyModeCompressed, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce, in boolean p_use_hardcoded_values := false) return octetstring; external function fx_test_encryptWithEciesNistp256WithSha256(in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_privateEphemeralKey, in Oct32 p_recipientPublicKeyX, in Oct32 p_recipientPublicKeyY, in octetstring p_salt, out Oct32 p_publicEphemeralKeyX, out Oct32 p_publicEphemeralKeyY, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce) return octetstring; /** * @desc Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Nist-P256 algorithm * @param p_encryptedSecuredMessage The data to be decrypted * @param p_publicEphemeralKeyCompressed The generated ephemeral compressed key * @param p_ephemeralKeyModeCompressed The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_encrypted_sym_key The encrypted AES 128 CCM symmetric key * @param p_authentication_vector The tag of the AES 128 CCM symmetric key encryption * @param p_nonce The nonce vector of the AES 128 CCM symmetric key encryption * @return The decrypted message */ external function fx_decryptWithEciesNistp256WithSha256(in octetstring p_encryptedSecuredMessage, in Oct32 p_privateEncKey, in Oct32 p_publicEphemeralKeyCompressed, in integer p_ephemeralKeyModeCompressed, in Oct16 p_encrypted_sym_key, in Oct16 p_authentication_vector, in Oct12 p_nonce, in Oct32 p_salt, out Oct16 p_aes_sym_enc_key) return octetstring; /** * @desc Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Brainpool-P256 algorithm * @param p_toBeEncryptedSecuredMessage The data to be encrypted * @param p_recipientsPublicKeyCompressed The Recipient's compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_publicEphemeralKeyCompressed The generated ephemeral compressed key * @param p_ephemeralKeyModeCompressed The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_encrypted_sym_key The encrypted AES 128 CCM symmetric key * @param p_authentication_vector The tag of the AES 128 CCM symmetric key encryption * @param p_nonce The nonce vector of the AES 128 CCM symmetric key encryption * @return The encrypted message */ external function fx_encryptWithEciesBrainpoolp256WithSha256(in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_recipientsPublicKeyCompressed, in integer p_compressed_mode, in octetstring p_salt, out Oct32 p_publicEphemeralKeyCompressed, out integer p_ephemeralKeyModeCompressed, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce, in boolean p_use_hardcoded_values := false) return octetstring; external function fx_test_encryptWithEciesBrainpoolp256WithSha256(in octetstring p_toBeEncryptedSecuredMessage, in Oct32 p_privateEphemeralKey, in Oct32 p_recipientPublicKeyX, in Oct32 p_recipientPublicKeyY, in octetstring p_salt, out Oct32 p_publicEphemeralKeyX, out Oct32 p_publicEphemeralKeyY, out Oct16 p_aes_sym_key, out Oct16 p_encrypted_sym_key, out Oct16 p_authentication_vector, out Oct12 p_nonce) return octetstring; /** * @desc Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Brainpool-P256 algorithm * @param p_encryptedSecuredMessage The data to be decrypted * @param p_publicEphemeralKeyCompressed The generated ephemeral compressed key * @param p_ephemeralKeyModeCompressed The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @param p_encrypted_sym_key The encrypted AES 128 CCM symmetric key * @param p_authentication_vector The tag of the AES 128 CCM symmetric key encryption * @param p_nonce The nonce vector of the AES 128 CCM symmetric key encryption * @return The decrypted message */ external function fx_decryptWithEciesBrainpoolp256WithSha256(in octetstring p_encryptedSecuredMessage, in Oct32 p_privateEncKey, in Oct32 p_publicEphemeralKeyCompressed, in integer p_ephemeralKeyModeCompressed, in Oct16 p_encrypted_sym_key, in Oct16 p_authentication_vector, in Oct12 p_nonce, in Oct32 p_salt, out Oct16 p_aes_sym_enc_key) return octetstring; /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature * @param p_toBeSignedSecuredMessage The data to be signed * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_privateKey The private key * @return The signature value */ external function fx_signWithEcdsaNistp256WithSha256(in octetstring p_toBeSignedSecuredMessage, in Oct32 p_certificateIssuer, in Oct32 p_privateKey) return octetstring; external function fx_test_signWithEcdsaNistp256WithSha256(in octetstring p_toBeSignedSecuredMessage, in Oct32 p_privateKey) return octetstring; /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature * @param p_toBeSignedSecuredMessage The data to be signed * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_privateKey The private key for signature * @return The signature value */ external function fx_signWithEcdsaBrainpoolp256WithSha256(in octetstring p_toBeSignedSecuredMessage, in Oct32 p_certificateIssuer, in Oct32 p_privateKey) return octetstring; /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_privateKey The private key for signature * @return The signature value */ external function fx_signWithEcdsaBrainpoolp384WithSha384(in octetstring p_toBeSignedSecuredMessage, in Oct48 p_certificateIssuer, in Oct48 p_privateKey) return octetstring; /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_signature The signature * @param p_ecdsaNistp256PublicKeyCompressed The compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ external function fx_verifyWithEcdsaNistp256WithSha256(in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in octetstring p_signature, in Oct32 p_ecdsaNistp256PublicKeyCompressed, in integer p_compressed_mode) return boolean; external function fx_test_verifyWithEcdsaNistp256WithSha256(in octetstring p_toBeVerifiedData, in octetstring p_signature, in Oct32 p_ecdsaNistp256PublicKeyCompressed, in integer p_compressed_mode) return boolean; /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @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_1(in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaNistp256PublicKeyX, in Oct32 p_ecdsaNistp256PublicKeyY) return boolean; /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * @param p_signature The signature * @param p_ecdsaBrainpoolp256PublicKeyCompressed The compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ external function fx_verifyWithEcdsaBrainpoolp256WithSha256(in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaBrainpoolp256PublicKeyCompressed, in integer p_compressed_mode) return boolean; /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The certificate issuer * @param p_signature The signature * @param p_ecdsaBrainpoolp256PublicKeyX The public key (x coordinate) * @param p_ecdsaBrainpoolp256PublicKeyY The public key (y coordinate) * @return true on success, false otherwise */ external function fx_verifyWithEcdsaBrainpoolp256WithSha256_1(in octetstring p_toBeVerifiedData, in Oct32 p_certificateIssuer, in Oct64 p_signature, in Oct32 p_ecdsaBrainpoolp256PublicKeyX, in Oct32 p_ecdsaBrainpoolp256PublicKeyY) return boolean; /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The certificate issuer * @param p_signature The signature * @param p_ecdsaBrainpoolp384PublicKeyCompressed The compressed public key * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ external function fx_verifyWithEcdsaBrainpoolp384WithSha384(in octetstring p_toBeVerifiedData, in Oct48 p_certificateIssuer, in Oct96 p_signature, in Oct48 p_ecdsaBrainpoolp384PublicKeyCompressed, in integer p_compressed_mode) return boolean; /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_certificateIssuer The hash of the canonical certificate issuer * @param p_signature The signature * @param p_ecdsaBrainpoolp384PublicKeyX The public key (x coordinate) * @param p_ecdsaBrainpoolp384PublicKeyY The public key (y coordinate) * @return true on success, false otherwise */ external function fx_verifyWithEcdsaBrainpoolp384WithSha384_1(in octetstring p_toBeVerifiedData, in Oct48 p_certificateIssuer, in Oct96 p_signature, in Oct48 p_ecdsaBrainpoolp384PublicKeyX, in Oct48 p_ecdsaBrainpoolp384PublicKeyY) 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) * @param p_publicKeyCompressed The compressed public keys * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ external function fx_generateKeyPair_nistp256(out Oct32 p_privateKey, out Oct32 p_publicKeyX, out Oct32 p_publicKeyY, out Oct32 p_publicKeyCompressed, out integer p_compressed_mode) 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) * @param p_publicKeyCompressed The compressed public keys * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ external function fx_generateKeyPair_brainpoolp256(out Oct32 p_privateKey, out Oct32 p_publicKeyX, out Oct32 p_publicKeyY, out Oct32 p_publicKeyCompressed, out integer p_compressed_mode) 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) * @param p_publicKeyCompressed The compressed public keys * @param p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * @return true on success, false otherwise */ external function fx_generateKeyPair_brainpoolp384(out Oct48 p_privateKey, out Oct48 p_publicKeyX, out Oct48 p_publicKeyY, out Oct48 p_publicKeyCompressed, out integer p_compressed_mode) 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; external function fx_store_certificate(in charstring p_cert_id, in octetstring p_cert, in octetstring p_private_key, in octetstring p_public_key_x, in octetstring p_public_key_y, in octetstring p_public_key_compressed, in integer p_public_key_compressed_mode, in octetstring p_hash, in octetstring p_hash_256, in octetstring p_hashid8, in octetstring p_issuer, in template (omit) octetstring p_private_enc_key, in template (omit) octetstring p_public_enc_key_x, in template (omit) octetstring p_public_enc_key_y, in template (omit) octetstring p_public_enc_compressed_key, in template (omit) integer p_public_enc_key_compressed_mode) 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_certificate_id the certificate identifier * @param p_certificate the expected certificate * @return true on success, false otherwise */ external function fx_readCertificate(in charstring p_certificate_id, out octetstring p_certificate) return boolean; /** * @desc Read the specified certificate digest * @param p_certificate_id the certificate identifier * @param p_digest the expected certificate * @return true on success, false otherwise */ external function fx_readCertificateDigest(in charstring p_certificate_id, out HashedId8 p_digest) return boolean; /** * @desc Read the whole-hash of the specified certificate * @param p_certificate_id the certificate identifier * @param p_hash the whole-hash of the certificate * @return true on success, false otherwise */ external function fx_readCertificateHash(in charstring p_certificate_id, out octetstring p_hash) return boolean; /** * @desc Read the whole-hash of the specified certificate using SHA 256 * @param p_certificate_id the certificate identifier * @param p_hash the whole-hash of the certificate * @return true on success, false otherwise */ external function fx_readCertificateHash256(in charstring p_certificate_id, out Oct32 p_hash) return boolean; external function fx_readCertificateFromDigest(in HashedId8 p_digest, out charstring p_certificate_id) return boolean; external function fx_readCertificateFromHashedId3(in HashedId3 p_digest, out charstring p_certificate_id) return boolean; /** * @desc Read the private keys for the specified certificate * @param p_keysId the keys identifier * @param p_signingPrivateKey the signing private key * @return true on success, false otherwise */ external function fx_readSigningKey(in charstring p_keysId, out Oct32 p_signingPrivateKey) return boolean; /** * @desc Read the private keys for the specified certificate * @param p_keysId the keys identifier * @param p_encryptPrivateKey the encrypt private key * @return true on success, false otherwise */ external function fx_readEncryptingKey(in charstring p_keysId, out Oct32 p_encryptingPrivateKey) return boolean; } // End of group certificatesLoader 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 region 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 SequenceOfRectangularRegion 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 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 */ external function fx_isLocationInsideOtherRegion(in octetstring p_region, in ThreeDLocation p_location) return boolean; /** * @desc Check that p_circular_region_1 circular region is included into p_circular_region_2 circular region * @param p_circular_region_1 Circular region 1 * @param p_circular_region_2 Circular region 2 * * @return true on success, false otherwise */ external function fx_areCirclesInside(in CircularRegion p_circular_region_1, in CircularRegion p_circular_region_2) return boolean; /** * @desc Check that p_rectanglar_region_1 rectangular region is included into p_rectanglar_region_2 rectangular region * @param p_rectanglar_region_1 Rectangular region 1 * @param p_rectanglar_region_2 Rectangular region 2 * * @return true on success, false otherwise */ external function fx_areRectanglesInside(in SequenceOfRectangularRegion p_rectanglar_region_1, in SequenceOfRectangularRegion p_rectanglar_region_2) return boolean; /** * @desc Check that p_polygonal_region_1 polygonal region is included into p_polygonal_region_2 polygonal region * @param p_polygonal_region_1 Polygonal region 1 * @param p_polygonal_region_2 Polygonal region 2 * * @return true on success, false otherwise */ external function fx_arePolygonsInside(in PolygonalRegion p_polygonal_region_1, in PolygonalRegion p_polygonal_region_2) 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 geodesic } // End of group externalFunctions group geometryFunctions { function f_checkRegionValidityRestiction( in EtsiTs103097Certificate p_cert, in EtsiTs103097Certificate p_cert_issuer ) return boolean { var ValidityPeriod v_cert_region, v_cert_issuer_region; var boolean v_cert_issuer_region_result; /* FIXME To be reviewed v_cert_issuer_region_result := f_getCertificateValidityRestriction(p_cert_issuer, e_region, v_cert_issuer_region); if (f_getCertificateValidityRestriction(p_cert, e_region, v_cert_region) == false) { if (v_cert_issuer_region_result == true) { if (v_cert_issuer_region.validity.region.region_type != e_none) { return false; } } } else if ( (v_cert_issuer_region_result == true) and (v_cert_issuer_region.validity.region.region_type != e_none) ) { if (v_cert_region.validity.region.region_type == e_circle) { if (v_cert_issuer_region.validity.region.region_type == e_circle) { // Check v_cert_region 'circle' is inside v_cert_issuer_region 'circle' if (f_areCirclesInside(v_cert_region.validity.region.region.circular_region, v_cert_issuer_region.validity.region.region.circular_region) == false) { log("*** " & testcasename() & ": FAIL: Issuer and issuing certificates circle area does not match ***"); return false; } } } else if (v_cert_region.validity.region.region_type == e_rectangle) { if (v_cert_issuer_region.validity.region.region_type == e_rectangle) { // Check v_cert_region 'rectangle' is inside v_cert_issuer_region 'rectangle' if (f_areRectanglesInside(v_cert_region.validity.region.region.rectangular_region, v_cert_issuer_region.validity.region.region.rectangular_region) == false) { log("*** " & testcasename() & ": FAIL: Issuer and issuing certificates rectangle area does not match ***"); return false; } } } else if (v_cert_region.validity.region.region_type == e_polygon) { if (v_cert_issuer_region.validity.region.region_type == e_polygon) { // Check v_cert_region 'polygon' is inside v_cert_issuer_region 'polygon' if (f_arePolygonsInside(v_cert_region.validity.region.region.polygonal_region, v_cert_issuer_region.validity.region.region.polygonal_region) == false) { log("*** " & testcasename() & ": FAIL: Issuer and issuing certificates polygon area does not match ***"); return false; } } } else if (v_cert_region.validity.region.region_type == e_id) { // Check id_region if (not match (v_cert_region.validity.region, mw_geographicRegion_identified(mw_identifiedRegion_iso3166_any))) { log("*** " & testcasename() & ": FAIL: Identified region is not conformed to ISO 3166-1 ***"); return false; } if (not match (v_cert_region.validity.region, mw_geographicRegion_identified(mw_identifiedRegion_un_stats_any))) { log("*** " & testcasename() & ": FAIL: Identified region is not conformed to United Nations Statistics Division ***"); return false; } // Check region_dictionary if (not match (v_cert_region.validity.region.region.id_region.region_dictionary, v_cert_issuer_region.validity.region.region.id_region.region_dictionary)) { log("*** " & testcasename() & ": FAIL: Issuer and issuing 'region_dictionary' field does not match ***"); return false; } // Check region_identifier if (not match (v_cert_region.validity.region.region.id_region.region_identifier, v_cert_issuer_region.validity.region.region.id_region.region_identifier)) { log("*** " & testcasename() & ": FAIL: Issuer and issuing 'region_identifier' field does not match ***"); return false; } // Check local_region if ( (not match (v_cert_issuer_region.validity.region.region.id_region.local_region, v_cert_region.validity.region.region.id_region.local_region)) or (not match (v_cert_issuer_region.validity.region.region.id_region.local_region, 0)) ) { log("*** " & testcasename() & ": FAIL: Issuer and issuing 'local_region' field does not match ***"); return false; } } }*/ return true; } // End of function f_checkRegionValidityRestiction /** * @desc Check that p_circular_region_1 circular region is included into p_circular_region_2 circular region * @param p_circular_region_1 Circular region 1 * @param p_circular_region_2 Circular region 2 * * @return true on success, false otherwise */ function f_areCirclesInside( in CircularRegion p_circular_region_1, in CircularRegion p_circular_region_2 ) return boolean { return fx_areCirclesInside(p_circular_region_1, p_circular_region_2); } /** * @desc Check that p_rectanglar_region_1 rectangular region is included into p_rectanglar_region_2 rectangular region * @param p_rectanglar_region_1 Rectangular region 1 * @param p_rectanglar_region_2 Rectangular region 2 * * @return true on success, false otherwise */ function f_areRectanglesInside( in SequenceOfRectangularRegion p_rectanglar_region_1, in SequenceOfRectangularRegion p_rectanglar_region_2 ) return boolean { return fx_areRectanglesInside(p_rectanglar_region_1, p_rectanglar_region_2); } /** * @desc Check that p_polygonal_region_1 polygonal region is included into p_polygonal_region_2 polygonal region * @param p_polygonal_region_1 Polygonal region 1 * @param p_polygonal_region_2 Polygonal region 2 * * @return true on success, false otherwise */ function f_arePolygonsInside( in PolygonalRegion p_polygonal_region_1, in PolygonalRegion p_polygonal_region_2 ) return boolean { return fx_arePolygonsInside(p_polygonal_region_1, p_polygonal_region_2); } /** * @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 //FIXME RGY Titan doesn't support dot notation after valueof at the moment // (valueof(p_location).longitude != c_maxLongitude + 1) and // (valueof(p_location).latitude != c_maxLatitude + 1); (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) * @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 ( //FIXME RGY Titan doesn't support dot notation after valueof at the moment // 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 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) SequenceOfRectangularRegion p_region ) return boolean { var integer v_i, v_j; var boolean v_found; for (v_i := 0; v_i < lengthof(p_region); v_i := v_i + 1) { var PolygonalRegion v_region_base; f_convertRectangularRegionIntoPolygonalRegion(valueof(p_region[v_i]), v_region_base); v_found := false; for (v_j := 0; v_j < lengthof(p_region); v_j := v_j + 1) { if (v_j != v_i) { var PolygonalRegion v_region; f_convertRectangularRegionIntoPolygonalRegion(valueof(p_region[v_j]), v_region); if (f_isPolygonalRegionInside(v_region, v_region_base) == true) { v_found := true; } } } // End of 'for' statement if (v_found == false) { return false; } } // End of 'for' statement return true; } // End of function f_isContinuousRectangularRegions /** * @desc Check if a polygonal region 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) SequenceOfRectangularRegion p_parent, in template (value) SequenceOfRectangularRegion p_region ) return boolean { var integer v_i, v_j; for (v_i := 0; v_i < lengthof(p_parent); v_i := v_i + 1) { var PolygonalRegion v_region_parent, v_region; f_convertRectangularRegionIntoPolygonalRegion(valueof(p_parent[v_i]), v_region_parent); for (v_j := 0; v_j < lengthof(p_parent); v_j := v_j + 1) { f_convertRectangularRegionIntoPolygonalRegion(valueof(p_region[v_j]), v_region); if (f_isPolygonalRegionInside(v_region, v_region_parent) == true) { return true; } } // End of 'for' statement } // End of 'for' statement return false; } // End of function f_isRectangularRegionsInside /** * @desc Convert a rectangular region into a polygonal region * @param p_region The rectangular regions to convert * @return * @verdict */ function f_convertRectangularRegionIntoPolygonalRegion( in template (value) RectangularRegion p_rectangular_region, out PolygonalRegion p_region ) return boolean { // Convert rectangular regions to polygons and check polygons p_region[0] := valueof(p_rectangular_region.northWest); p_region[1] := { valueof(p_rectangular_region.northWest.latitude) + valueof(p_rectangular_region.southEast.latitude), valueof(p_rectangular_region.northWest.longitude) }; p_region[2] := valueof(p_rectangular_region.southEast); p_region[3] := { valueof(p_rectangular_region.northWest.latitude), valueof(p_rectangular_region.northWest.longitude) + valueof(p_rectangular_region.southEast.longitude) }; log("f_convertRectangularRegionIntoPolygonalRegion: DEBUG: Northwest location is invalid in rect ", p_region); return true; } // End of function /** * @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 region 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 { // 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 /** * @desc */ function f_isIdentifiedRegionInside( in template (value) UInt16 p_parent, in template (value) UInt16 p_region ) return boolean { 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; if (ischosen(p_region.circularRegion)) { v_ret := f_isLocationInsideCircularRegion(valueof(p_region.circularRegion), p_location); } else if (ischosen(p_region.rectangularRegion)) { v_ret := f_isLocationInsideRectangularRegion(valueof(p_region.rectangularRegion), p_location); } else if (ischosen(p_region.polygonalRegion)) { v_ret := f_isLocationInsidePolygonalRegion(valueof(p_region.polygonalRegion), p_location); } else if (ischosen(p_region.identifiedRegion)) { for (var integer v_i := 0; v_i < lengthof(p_region.identifiedRegion); v_i := v_i + 1) { if (f_isLocationInsideIdentifiedRegion(valueof(p_region.identifiedRegion[v_i]), p_location) == true) { v_ret := true; break; } } // End of 'for' statement } 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) SequenceOfRectangularRegion 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; } // 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 ) return boolean { // 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 ) 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 { // Sanity check if (valueof(p_region) == ''O) { return false; } return fx_isLocationInsideOtherRegion(valueof(p_region), valueof(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 */ function f_dms2dd( in integer p_degrees, in integer p_minutes, in float p_seconds, in charstring p_latlon ) return float { var Oct1 v_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; } v_latlon := char2oct(p_latlon); 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 SecLatitude { 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 SecLongitude { return float2int(p_longitude * 1000000.0); // Significand length shall be 6 digits length } } // End of group geometryFunctions } // End of module LibItsSecurity_Functions