/*! * \file LibItsSecurity_Functions.cc * \brief Source file for Security externl functions. * \author ETSI STF525 * \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. * \version 0.1 */ #include "LibItsSecurity_Functions.hh" #include "sha256.hh" #include "sha384.hh" #include "hmac.hh" #include "security_ecc.hh" #include "security_services.hh" #include #include #include "loggers.hh" namespace LibItsSecurity__Functions { // FIXME Unify code with security_services /** * \fn OCTETSTRING fx_hashWithSha256(const OCTETSTRING& p__toBeHashedData); * \brief Produces a 256-bit (32-bytes) hash value * \param[in] p__toBeHashedData The data to be used to calculate the hash value * \return The hash value */ OCTETSTRING fx__hashWithSha256( const OCTETSTRING& p__toBeHashedData ) { loggers::get_instance().log_msg(">>> fx__hashWithSha256: p__toBeHashedData= ", p__toBeHashedData); sha256 hash; OCTETSTRING hashData; hash.generate(p__toBeHashedData, hashData); loggers::get_instance().log_msg("fx__hashWithSha256: hashData= ", hashData); return hashData; } // End of function fx__hashWithSha256 /** * \fn OCTETSTRING fx_hashWithSha384(const OCTETSTRING& p__toBeHashedData); * \brief Produces a 384-bit (48-bytes) hash value * \param[in] p__toBeHashedData Data to be used to calculate the hash value * \return The hash value */ OCTETSTRING fx__hashWithSha384( const OCTETSTRING& p__toBeHashedData ) { sha384 hash; OCTETSTRING hashData; hash.generate(p__toBeHashedData, hashData); loggers::get_instance().log_msg("fx__hashWithSha384: hashData= ", hashData); return hashData; } // End of function fx__hashWithSha384 /** * \fn OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature * \param[in] p__toBeSignedSecuredMessage The data to be signed * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__privateKey The private key * \return The signature value */ OCTETSTRING fx__signWithEcdsaNistp256WithSha256( const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__privateKey ) { loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: data=", p__toBeSignedSecuredMessage); loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: issuer=", p__certificateIssuer); loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: private key=", p__privateKey); // Sanity checks if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) { loggers::get_instance().log("fx__signWithEcdsaNistp256WithSha256: Wrong parameters"); return OCTETSTRING(0, nullptr); } // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha256 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeSignedSecuredMessage, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha256_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Data input) || Hash (Signer identifier input)=", hashData1); OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Calculate the signature security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey); OCTETSTRING r_sig; OCTETSTRING s_sig; if (k.sign(hashData, r_sig, s_sig) == 0) { OCTETSTRING os = r_sig + s_sig; loggers::get_instance().log_msg("r_sig= ", r_sig); loggers::get_instance().log_msg("s_sig= ", s_sig); loggers::get_instance().log_msg("sig= ", os); return os; } return OCTETSTRING(0, nullptr); } /** * \fn OCTETSTRING fx__signWithEcdsaBrainpoolp256WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature * \param[in] p__toBeSignedSecuredMessage The data to be signed * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__privateKey The private key * \return The signature value */ OCTETSTRING fx__signWithEcdsaBrainpoolp256WithSha256( const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__privateKey ) { // Sanity checks if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) { loggers::get_instance().log("fx__signWithEcdsaBrainpoolp256WithSha256: Wrong parameters"); return OCTETSTRING(0, nullptr); } // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha256 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeSignedSecuredMessage, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha256_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256WithSha256: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256WithSha256: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Calculate the signature security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__privateKey); OCTETSTRING r_sig; OCTETSTRING s_sig; if (k.sign(hashData, r_sig, s_sig) == 0) { OCTETSTRING os = r_sig + s_sig; loggers::get_instance().log_msg("r_sig= ", r_sig); loggers::get_instance().log_msg("s_sig= ", s_sig); loggers::get_instance().log_msg("sig= ", os); return os; } return OCTETSTRING(0, nullptr); } /** * \fn OCTETSTRING fx__signWithEcdsaBrainpoolp384WithSha384(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature * \param[in] p__toBeSignedSecuredMessage The data to be signed * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__privateKey The private key * \return The signature value */ OCTETSTRING fx__signWithEcdsaBrainpoolp384WithSha384( const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__privateKey ) { // Sanity checks if ((p__certificateIssuer.lengthof() != 48) || (p__privateKey.lengthof() != 48)) { loggers::get_instance().log("fx__signWithEcdsaBrainpoolp384WithSha384: Wrong parameters"); return OCTETSTRING(0, nullptr); } // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha384 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeSignedSecuredMessage, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha384_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384WithSha384: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384WithSha384: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Calculate the signature security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__privateKey); OCTETSTRING r_sig; OCTETSTRING s_sig; if (k.sign(hashData, r_sig, s_sig) == 0) { OCTETSTRING os = r_sig + s_sig; loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384WithSha384: r_sig= ", r_sig); loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384WithSha384: s_sig= ", s_sig); loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384WithSha384: sig= ", os); return os; } return OCTETSTRING(0, nullptr); } /** * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaNistp256PublicKeyCompressed); * \brief Verify the signature of the specified data * \param[in] p__toBeVerifiedData The data to be verified * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__signature The signature * \param[in] p__ecdsaNistp256PublicKeyCompressed The compressed public key (x coordinate only) * \return true on success, false otherwise */ BOOLEAN fx__verifyWithEcdsaNistp256WithSha256( const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaNistp256PublicKeyCompressed, const INTEGER& p__compressedMode ) { // Sanity checks if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyCompressed.lengthof() != 32)) { loggers::get_instance().log("fx__verifyWithEcdsaNistp256WithSha256: Wrong parameters"); return FALSE; } // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha256 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeVerifiedData, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha256_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Check the signature security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyCompressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); if (k.sign_verif(hashData, p__signature) == 0) { return TRUE; } return FALSE; } /** * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaNistp256PublicKeyX, const OCTETSTRING& p__ecdsaNistp256PublicKeyY); * \brief Verify the signature of the specified data * \param[in] p__toBeVerifiedData The data to be verified * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__signature The signature * \param[in] p__ecdsaNistp256PublicKeyX The public key (x coordinate) * \param[in] p__ecdsaNistp256PublicKeyY The public key (y coordinate) * \return true on success, false otherwise */ BOOLEAN fx__verifyWithEcdsaNistp256WithSha256__1( const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaNistp256PublicKeyX, const OCTETSTRING& p__ecdsaNistp256PublicKeyY ) { // Sanity checks if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64)) { loggers::get_instance().log("fx__verifyWithEcdsaNistp256WithSha256__1: Wrong parameters"); return FALSE; } // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha256 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeVerifiedData, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha256_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Check the signature security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyX, p__ecdsaNistp256PublicKeyY); //security_ecc k(ec_elliptic_curves::nist_p_256); if (k.sign_verif(hashData, p__signature) == 0) { return TRUE; } return FALSE; } /** * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp256WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyCompressed); * \brief Verify the signature of the specified data * \param[in] p__toBeVerifiedData The data to be verified * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__signature The signature * \param[in] p__ecdsaBrainpoolp256PublicKeyCompressed The compressed public key (x coordinate only) * \return true on success, false otherwise */ BOOLEAN fx__verifyWithEcdsaBrainpoolp256WithSha256( const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyCompressed, const INTEGER& p__compressedMode ) { // Sanity checks if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaBrainpoolp256PublicKeyCompressed.lengthof() != 32)) { loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp256WithSha256: Wrong parameters"); return FALSE; } // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha256 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeVerifiedData, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha256_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256WithSha256: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256WithSha256: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Check the signature security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__ecdsaBrainpoolp256PublicKeyCompressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); if (k.sign_verif(hashData, p__signature) == 0) { return TRUE; } return FALSE; } /** * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp256WithSha256_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyY); * \brief Verify the signature of the specified data * \param[in] p__toBeVerifiedData The data to be verified * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__signature The signature * \param[in] p__ecdsaBrainpoolp256PublicKeyX The public key (x coordinate) * \param[in] p__ecdsaBrainpoolp256PublicKeyY The public key (y coordinate) * \return true on success, false otherwise */ BOOLEAN fx__verifyWithEcdsaBrainpoolp256WithSha256__1( const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyY ) { // Sanity checks if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64)) { loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp256WithSha256__1: Wrong parameters"); return FALSE; } // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha256 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeVerifiedData, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha256_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256WithSha256__1: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256WithSha256__1: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256WithSha256__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Check the signature security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__ecdsaBrainpoolp256PublicKeyX, p__ecdsaBrainpoolp256PublicKeyY); if (k.sign_verif(hashData, p__signature) == 0) { return TRUE; } return FALSE; } /** * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384WithSha384(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyCompressed); * \brief Verify the signature of the specified data * \param[in] p__toBeVerifiedData The data to be verified * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__signature The signature * \param[in] p__ecdsaBrainpoolp384PublicKeyCompressed The compressed public key (x coordinate only) * \return true on success, false otherwise */ BOOLEAN fx__verifyWithEcdsaBrainpoolp384WithSha384( const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyCompressed, const INTEGER& p__compressedMode ) { // Sanity checks if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaBrainpoolp384PublicKeyCompressed.lengthof() != 48)) { loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp384WithSha384: Wrong parameters"); return FALSE; } // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha384 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeVerifiedData, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha384_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384WithSha384: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384WithSha384: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Check the signature security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__ecdsaBrainpoolp384PublicKeyCompressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); if (k.sign_verif(hashData, p__signature) == 0) { return TRUE; } return FALSE; } /** * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384WithSha384_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY); * \brief Verify the signature of the specified data * \param[in] p__toBeVerifiedData The data to be verified * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate * \param[in] p__signature The signature * \param[in] p__ecdsaBrainpoolp384PublicKeyX The public key (x coordinate) * \param[in] p__ecdsaBrainpoolp384PublicKeyY The public key (y coordinate) * \return true on success, false otherwise */ BOOLEAN fx__verifyWithEcdsaBrainpoolp384WithSha384__1( const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__certificateIssuer, const OCTETSTRING& p__signature, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY ) { // Sanity checks if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96)) { loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp384WithSha384__1: Wrong parameters"); return FALSE; } // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) sha384 hash; OCTETSTRING hashData1; // Hash (Data input) hash.generate(p__toBeVerifiedData, hashData1); OCTETSTRING hashData2; // Hash (Signer identifier input) if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) hashData2 = p__certificateIssuer; } else { hashData2 = hash.get_sha384_empty_string(); // Hash of empty string } loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384WithSha384: Hash (Data input)=", hashData1); loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384WithSha384: Hash (Signer identifier input)=", hashData2); hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) hash.generate(hashData1, hashData); loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); // Check the signature security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__ecdsaBrainpoolp384PublicKeyX, p__ecdsaBrainpoolp384PublicKeyY); if (k.sign_verif(hashData, p__signature) == 0) { return TRUE; } return FALSE; } /** * \fn OCTETSTRING fx__test__hmac__sha256(const OCTETSTRING& p__k, const OCTETSTRING& p__m); * \brief Generate a HMAC-SHA256 value based on the provided secret key * \param[in] p__k The secret key used for the HMAC calculation * \param[in] p__m The message * \return The HMAC value resized to 16-byte */ OCTETSTRING fx__test__hmac__sha256(const OCTETSTRING& p__k, const OCTETSTRING& p__m) { loggers::get_instance().log(">>> fx__test__hmac__sha256"); hmac h(hash_algorithms::sha_256); // TODO Use ec_encryption_algorithm OCTETSTRING t; if (h.generate(p__m, p__k, t) == -1) { loggers::get_instance().warning("fx__test__hmac__sha256: Failed to generate HMAC"); return OCTETSTRING(0, nullptr); } loggers::get_instance().log_msg("fx__test__hmac__sha256: HMAC: ", t); return t; } /** * \fn OCTETSTRING fx__test__encrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt); * \brief Encrypt the message using AES 128 CCM algorithm * \param[in] p__k The symmetric encryption key * \param[in] p__n The initial vector, nonce vector * \param[in] p__pt The message to encrypt * \return The encrypted message concatenated to the AES 128 CCM tag */ OCTETSTRING fx__test__encrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt) { loggers::get_instance().log(">>> fx__test__encrypt__aes__128__ccm__test"); security_ecc ec(ec_elliptic_curves::nist_p_256); OCTETSTRING enc_message; if (ec.encrypt(encryption_algotithm::aes_128_ccm, p__k, p__n, p__pt, enc_message) == -1) { loggers::get_instance().warning("fx__test__encrypt__aes__128__ccm__test: Failed to encrypt message"); return OCTETSTRING(0, nullptr); } OCTETSTRING os(enc_message + ec.tag()); loggers::get_instance().log_msg("fx__test__encrypt__aes__128__ccm__test: encrypted message: ", os); return os; } /** * \fn OCTETSTRING fx__test__decrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__ct); * \brief Encrypt the message using AES 128 CCM algorithm * \param[in] p__k The symmetric encryption key * \param[in] p__n The initial vector, nonce vector * \param[in] p__ct The encrypted message concatenated to the AES 128 CCM tag * \return The original message */ OCTETSTRING fx__test__decrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__ct) { loggers::get_instance().log(">>> fx__test__decrypt__aes__128__ccm__test"); security_ecc ec(ec_elliptic_curves::nist_p_256); // Extract the tag OCTETSTRING tag(16, p__ct.lengthof() - 16 + static_cast(p__ct)); loggers::get_instance().log_msg("fx__test__decrypt__aes__128__ccm__test: tag: ", tag); // Remove the tag from the end of the encrypted message OCTETSTRING ct(p__ct.lengthof() - 16, static_cast(p__ct)); loggers::get_instance().log_msg("fx__test__decrypt__aes__128__ccm__test: ct: ", ct); OCTETSTRING message; if (ec.decrypt(encryption_algotithm::aes_128_ccm, p__k, p__n, tag, ct, message) == -1) { loggers::get_instance().warning("fx__test__decrypt__aes__128__ccm__test: Failed to decrypt message"); return OCTETSTRING(0, nullptr); } loggers::get_instance().log_to_hexa("fx__test__decrypt__aes__128__ccm__test: decrypted message: ", message); return message; } /** * \fn OCTETSTRING fx__encryptWithEciesNistp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyX, const OCTETSTRING& p__recipientsPublicKeyY, OCTETSTRING& p__publicEphemeralKeyX, OCTETSTRING& p__publicEphemeralKeyY, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce); * \brief Encrypt the message using ECIES algorithm to encrypt AES 128 CCM symmetric key, as defined in IEEE Std 1609.2-2017 * \param[in] p__toBeEncryptedSecuredMessage The message to be encrypted * \param[in] p__recipientsPublicKeyCompressed The Recipient's compressed public key * \param[in] p__compressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * \param[out] p__publicEphemeralKeyCompressed The public ephemeral compressed key * \param[out] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * \param[out] p__encrypted__sym__key The encrypted AES 128 symmetric key * \param[out] p__authentication__vector The tag of the encrypted AES 128 symmetric key * \param[out] p__nonce The nonce vector * \return The original 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 */ // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function OCTETSTRING fx__encryptWithEciesNistp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyCompressed, const INTEGER& p__compressedMode, OCTETSTRING& p__publicEphemeralKeyCompressed, INTEGER& p__ephemeralCompressedMode, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce) { loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage); loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__recipientsPublicKeyX: ", p__recipientsPublicKeyCompressed); loggers::get_instance().log(">>> fx__encryptWithEciesNistp256WithSha256: p__compressedMode: %d", static_cast(p__compressedMode)); // 1. Generate new Private/Public key security_ecc ec(ec_elliptic_curves::nist_p_256); if (ec.generate() == -1) { loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to generate ephemeral keys"); return OCTETSTRING(0, nullptr); } // 2. Generate and derive shared secret security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__recipientsPublicKeyCompressed, (static_cast(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y()) == -1) { loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to generate and derive secret key"); return OCTETSTRING(0, nullptr); } // Set the encrypted symmetric key p__encrypted__sym__key = ec.encrypted_symmetric_key(); loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: Encrypted symmetric key: ", p__encrypted__sym__key); // Set the tag of the symmetric key encryption p__authentication__vector = ec.tag(); loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector); // Set ephemeral public keys p__publicEphemeralKeyCompressed = ec.public_key_compressed(); loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed); p__ephemeralCompressedMode = (ec.public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1; loggers::get_instance().log("fx__encryptWithEciesNistp256WithSha256: Ephemeral public compressed mode: %d: ", p__ephemeralCompressedMode); // 3. Retrieve AES 128 parameters p__nonce = ec.nonce(); loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce); OCTETSTRING enc_symm_key = ec.symmetric_encryption_key(); loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: enc_symm_key: ", enc_symm_key); // 4. Encrypt the data using AES-128 CCM OCTETSTRING enc_message; if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to encrypt message"); return OCTETSTRING(0, nullptr); } enc_message += ec.tag(); loggers::get_instance().log_to_hexa("fx__encryptWithEciesNistp256WithSha256: enc message||Tag: ", enc_message); return enc_message; } /** * \fn OCTETSTRING fx__decryptWithEciesNistp256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const OCTETSTRING& p__publicEphemeralKeyX, const OCTETSTRING& p__publicEphemeralKeyY, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& p__authentication__vector, const OCTETSTRING& p__nonce); * \brief Decrypt the message using ECIES algorithm to decrypt AES 128 CCM symmetric key, as defined in IEEE Std 1609.2-2017 * \param[in] p__encryptedSecuredMessage The encrypted message * \param[in] p__privateEncKey The private encryption key * \param[in] p__publicEphemeralKeyCompressed The public ephemeral compressed key * \param[in] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise * \param[in] p__encrypted__sym__key The encrypted AES 128 symmetric key * \param[in] p__authentication__vector The tag of the encrypted AES 128 symmetric key * \param[in] p__nonce The nonce vector * \return The original 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 */ // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function OCTETSTRING fx__decryptWithEciesNistp256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const OCTETSTRING& p__publicEphemeralKeyCompressed, const INTEGER& p__ephemeralCompressedMode, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& p__authentication__vector, const OCTETSTRING& p__nonce) { loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage); loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__privateEncKey: ", p__privateEncKey); loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__publicEphemeralKeyCompressed: ", p__publicEphemeralKeyCompressed); loggers::get_instance().log(">>> fx__decryptWithEciesNistp256WithSha256: p__ephemeralCompressedMode: %d", static_cast(p__ephemeralCompressedMode)); loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce); loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector); loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); // 1. Create security_ecc instance security_ecc ec(ec_elliptic_curves::nist_p_256, p__privateEncKey); security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__publicEphemeralKeyCompressed, (static_cast(p__ephemeralCompressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); // 2. Generate the shared secret value based on recipient's public ephemeral keys will be required if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, p__privateEncKey, ec_comp.public_key_x(), ec_comp.public_key_y(), p__encrypted__sym__key, p__nonce, p__authentication__vector) == -1) { loggers::get_instance().warning("fx__decryptWithEciesNistp256WithSha256: Failed to generate shared secret"); return OCTETSTRING(0, nullptr); } // Decrypt the message OCTETSTRING enc_message(p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof(), static_cast(p__encryptedSecuredMessage)); // Extract the encrypted message loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: enc_message: ", enc_message); // Extract the ctag value OCTETSTRING tag(ec.tag().lengthof(), static_cast(p__encryptedSecuredMessage) + p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof()); loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: tag: ", tag); OCTETSTRING message; if (ec.decrypt(tag, enc_message, message) == -1) { loggers::get_instance().warning("fx__decryptWithEciesNistp256WithSha256: Failed to generate shared secret"); return OCTETSTRING(0, nullptr); } loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: dec message: ", message); return message; } OCTETSTRING fx__encryptWithEciesBrainpoolp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyCompressed, const INTEGER& p__compressedMode, OCTETSTRING& p__publicEphemeralKeyCompressed, INTEGER& p__ephemeralCompressedMode, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce) { loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage); loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed); loggers::get_instance().log(">>> fx__encryptWithEciesBrainpoolp256WithSha256: p__compressedMode: %d", static_cast(p__compressedMode)); // 1. Generate new Private/Public key security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1); if (ec.generate() == -1) { loggers::get_instance().warning(": Failed to generate ephemeral keys"); return OCTETSTRING(0, nullptr); } // 2. Generate and derive shared secret security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientsPublicKeyCompressed, (static_cast(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y()) == -1) { loggers::get_instance().warning(": Failed to generate and derive secret key"); return OCTETSTRING(0, nullptr); } // Set the encrypted symmetric key p__encrypted__sym__key = ec.encrypted_symmetric_key(); loggers::get_instance().log_msg(": Encrypted symmetric key: ", p__encrypted__sym__key); // Set the tag of the symmetric key encryption p__authentication__vector = ec.tag(); loggers::get_instance().log_msg(": p__authentication__vector: ", p__authentication__vector); // Set ephemeral public keys p__publicEphemeralKeyCompressed = ec.public_key_compressed(); loggers::get_instance().log_msg(": Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed); p__ephemeralCompressedMode = (ec.public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1; loggers::get_instance().log(": Ephemeral public compressed mode: %d: ", p__ephemeralCompressedMode); // 3. Retrieve AES 128 parameters p__nonce = ec.nonce(); loggers::get_instance().log_msg(": p__nonce: ", p__nonce); OCTETSTRING enc_symm_key = ec.symmetric_encryption_key(); loggers::get_instance().log_msg(": enc_symm_key: ", enc_symm_key); // 4. Encrypt the data using AES-128 CCM OCTETSTRING enc_message; if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { loggers::get_instance().warning(": Failed to encrypt message"); return OCTETSTRING(0, nullptr); } enc_message += ec.tag(); loggers::get_instance().log_to_hexa(": enc message||Tag: ", enc_message); return enc_message; } OCTETSTRING fx__decryptWithEciesBrainpoolp256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const OCTETSTRING& p__publicEphemeralKeyCompressed, const INTEGER& p__ephemeralCompressedMode, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& p__authentication__vector, const OCTETSTRING& p__nonce) { loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage); loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__privateEncKey: ", p__privateEncKey); loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__publicEphemeralKeyCompressed: ", p__publicEphemeralKeyCompressed); loggers::get_instance().log(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__ephemeralCompressedMode: %d", static_cast(p__ephemeralCompressedMode)); loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__nonce: ", p__nonce); loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__authentication__vector: ", p__authentication__vector); loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); // 1. Create security_ecc instance security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1, p__privateEncKey); security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__publicEphemeralKeyCompressed, (static_cast(p__ephemeralCompressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); // 2. Generate the shared secret value based on recipient's public ephemeral keys will be required if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, p__privateEncKey, ec_comp.public_key_x(), ec_comp.public_key_y(), p__encrypted__sym__key, p__nonce, p__authentication__vector) == -1) { loggers::get_instance().warning("fx__decryptWithEciesBrainpoolp256WithSha256: Failed to generate shared secret"); return OCTETSTRING(0, nullptr); } // Decrypt the message OCTETSTRING enc_message(p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof(), static_cast(p__encryptedSecuredMessage)); // Extract the encrypted message loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256WithSha256: enc_message: ", enc_message); // Extract the ctag value OCTETSTRING tag(ec.tag().lengthof(), static_cast(p__encryptedSecuredMessage) + p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof()); loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256WithSha256: tag: ", tag); OCTETSTRING message; if (ec.decrypt(tag, enc_message, message) == -1) { loggers::get_instance().warning("fx__decryptWithEciesBrainpoolp256WithSha256: Failed to generate shared secret"); return OCTETSTRING(0, nullptr); } loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256WithSha256: dec message: ", message); return message; } /** * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. * This function should not be used by the ATS * \param p_privateKey The new private key value * \param p_publicKeyX The new public key value (x coordinate) * \param p_publicKeyX The new public key value (y coordinate) * \return true on success, false otherwise fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; */ BOOLEAN fx__generateKeyPair__nistp256( OCTETSTRING& p__privateKey, OCTETSTRING& p__publicKeyX, OCTETSTRING& p__publicKeyY, OCTETSTRING& p__publicKeyCompressed, INTEGER& p__compressedMode ) { security_ecc k(ec_elliptic_curves::nist_p_256); if (k.generate() != 0) { p__privateKey = OCTETSTRING(0, nullptr); p__publicKeyX = OCTETSTRING(0, nullptr); p__publicKeyY = OCTETSTRING(0, nullptr); p__publicKeyCompressed = OCTETSTRING(0, nullptr); return FALSE; } // Sanity checks if (k.private_key().lengthof() != 32) { loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid private key size"); return FALSE; } if (k.public_key_x().lengthof() != 32) { loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public key X-coordonate size"); return FALSE; } if (k.public_key_y().lengthof() != 32) { loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public key Y-coordonate size"); return FALSE; } if (k.public_key_compressed().lengthof() != 32) { loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public compressed key size"); return FALSE; } p__privateKey = k.private_key(); p__publicKeyX = k.public_key_x(); p__publicKeyY = k.public_key_y(); p__publicKeyCompressed = k.public_key_compressed(); p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); return TRUE; } /** * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. * This function should not be used by the ATS * \param p_privateKey The new private key value * \param p_publicKeyX The new public key value (x coordinate) * \param p_publicKeyX The new public key value (y coordinate) * \return true on success, false otherwise fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; */ BOOLEAN fx__generateKeyPair__brainpoolp256( OCTETSTRING& p__privateKey, OCTETSTRING& p__publicKeyX, OCTETSTRING& p__publicKeyY, OCTETSTRING& p__publicKeyCompressed, INTEGER& p__compressedMode ) { security_ecc k(ec_elliptic_curves::brainpool_p_256_r1); if (k.generate() != 0) { p__privateKey = OCTETSTRING(0, nullptr); p__publicKeyX = OCTETSTRING(0, nullptr); p__publicKeyY = OCTETSTRING(0, nullptr); p__publicKeyCompressed = OCTETSTRING(0, nullptr); return FALSE; } // Sanity checks if (k.private_key().lengthof() != 32) { loggers::get_instance().error("fx__generateKeyPair__brainpoolp256: Invalid private key size"); return FALSE; } if (k.public_key_x().lengthof() != 32) { loggers::get_instance().error("fx__generateKeyPair__brainpoolp256: Invalid public key X-coordonate size"); return FALSE; } if (k.public_key_y().lengthof() != 32) { loggers::get_instance().error("fx__generateKeyPair__brainpoolp256: Invalid public key Y-coordonate size"); return FALSE; } if (k.public_key_compressed().lengthof() != 32) { loggers::get_instance().error("fx__generateKeyPair__brainpoolp256: Invalid public compressed key size"); return FALSE; } p__privateKey = k.private_key(); p__publicKeyX = k.public_key_x(); p__publicKeyY = k.public_key_y(); p__publicKeyCompressed = k.public_key_compressed(); p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); return TRUE; } /** * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. * This function should not be used by the ATS * \param p_privateKey The new private key value * \param p_publicKeyX The new public key value (x coordinate) * \param p_publicKeyX The new public key value (y coordinate) * \return true on success, false otherwise fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; */ BOOLEAN fx__generateKeyPair__brainpoolp384( OCTETSTRING& p__privateKey, OCTETSTRING& p__publicKeyX, OCTETSTRING& p__publicKeyY, OCTETSTRING& p__publicKeyCompressed, INTEGER& p__compressedMode ) { security_ecc k(ec_elliptic_curves::brainpool_p_384_r1); if (k.generate() != 0) { p__privateKey = OCTETSTRING(0, nullptr); p__publicKeyX = OCTETSTRING(0, nullptr); p__publicKeyY = OCTETSTRING(0, nullptr); p__publicKeyCompressed = OCTETSTRING(0, nullptr); return FALSE; } // Sanity checks if (k.private_key().lengthof() != 48) { loggers::get_instance().error("fx__generateKeyPair__brainpoolp384: Invalid private key size"); return FALSE; } if (k.public_key_x().lengthof() != 48) { loggers::get_instance().error("fx__generateKeyPair__brainpoolp384: Invalid public key X-coordonate size"); return FALSE; } if (k.public_key_y().lengthof() != 48) { loggers::get_instance().error("fx__generateKeyPair__brainpoolp384: Invalid public key Y-coordonate size"); return FALSE; } if (k.public_key_compressed().lengthof() != 48) { loggers::get_instance().error("fx__generateKeyPair__brainpoolp384: Invalid public compressed key size"); return FALSE; } p__privateKey = k.private_key(); p__publicKeyX = k.public_key_x(); p__publicKeyY = k.public_key_y(); p__publicKeyCompressed = k.public_key_compressed(); p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); return TRUE; } // group encryption // group certificatesLoader /** * \brief 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 fx_loadCertificates(in charstring p_rootDirectory, in charstring p_configId) return boolean; */ BOOLEAN fx__loadCertificates( const CHARSTRING& p__rootDirectory, const CHARSTRING& p__configId ) { loggers::get_instance().log(">>> fx__loadCertificates: '%s', '%s'", static_cast(p__rootDirectory), static_cast(p__configId)); std::string str(static_cast(p__rootDirectory)); if (p__configId.lengthof() != 0) { str += "/"; str += std::string(static_cast(p__configId)); } params params; params.insert(std::pair(std::string("sec_db_path"), str)); if (security_services::get_instance().setup(params) == -1) { return FALSE; } return TRUE; } BOOLEAN fx__store__certificate(const CHARSTRING& p__cert__id, const OCTETSTRING& p__cert, const OCTETSTRING& p__private__key, const OCTETSTRING& p__public__key__x, const OCTETSTRING& p__public__key__y, const OCTETSTRING& p__public__key__compressed, const INTEGER& p__public__key__compressed__mode, const OCTETSTRING& p__hash, const OCTETSTRING& p__hashid8, const OCTETSTRING& p__issuer, const OCTETSTRING_template& p__private__enc__key, const OCTETSTRING_template& p__public__enc__key__x, const OCTETSTRING_template& p__public__enc__key__y, const OCTETSTRING_template& p__public__enc__compressed__key, const INTEGER_template& p__public__enc__key__compressed__mode) { loggers::get_instance().log(">>> fx__store__certificate: '%s'", static_cast(p__cert__id)); int result; if (!p__private__enc__key.is_omit()) { const OCTETSTRING private_enc_key = p__private__enc__key.valueof(); const OCTETSTRING public_enc_key_x = p__public__enc__key__x.valueof(); const OCTETSTRING public_enc_key_y = p__public__enc__key__y.valueof(); result = security_services::get_instance().store_certificate(p__cert__id, p__cert, p__private__key, p__public__key__x, p__public__key__y, p__public__key__compressed, p__public__key__compressed__mode, p__hash, p__hashid8, p__issuer, p__private__enc__key.valueof(), p__public__enc__key__x.valueof(), p__public__enc__key__y.valueof(), p__public__enc__compressed__key.valueof(), p__public__enc__key__compressed__mode.valueof()); } else { result = security_services::get_instance().store_certificate(p__cert__id, p__cert, p__private__key, p__public__key__x, p__public__key__y, p__public__key__compressed, p__public__key__compressed__mode, p__hash, p__hashid8, p__issuer, OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), INTEGER(-1)); } return (result == 0); } /** * \brief Unload from memory cache the certificates * \return true on success, false otherwise */ BOOLEAN fx__unloadCertificates( ) { return TRUE; } /** * \brief Read the specified certificate * \param p_certificateId the certificate identifier * \param p_certificate the expected certificate * \return true on success, false otherwise */ BOOLEAN fx__readCertificate( const CHARSTRING& p__certificateId, OCTETSTRING& p__certificate ) { loggers::get_instance().log(">>> fx__readCertificate: '%s'", static_cast(p__certificateId)); if (security_services::get_instance().read_certificate(p__certificateId, p__certificate) == -1) { return FALSE; } return TRUE; } BOOLEAN fx__readCertificateFromDigest( const OCTETSTRING& p__digest, CHARSTRING& p__certificateId) { loggers::get_instance().log_msg(">>> fx__readCertificateFromDigest: ", p__digest); if (security_services::get_instance().read_certificate_from_digest(p__digest, p__certificateId) == -1) { return FALSE; } loggers::get_instance().log_msg("fx__readCertificateFromDigest: ", p__certificateId); return TRUE; } /** * \brief Read the specified certificate digest * \param p_certificateId the certificate identifier * \param p_digest the expected certificate * \return true on success, false otherwise */ BOOLEAN fx__readCertificateDigest( const CHARSTRING& p__certificateId, OCTETSTRING& p__digest ) { loggers::get_instance().log(">>> fx__readCertificateDigest: '%s'", static_cast(p__certificateId)); if (security_services::get_instance().read_certificate_digest(p__certificateId, p__digest) == -1) { return FALSE; } return TRUE; } /** * \brief Read the whole-hash of the certificate * \param p_certificateId the certificate identifier * \param p_hash the expected certificate * \return true on success, false otherwise */ BOOLEAN fx__readCertificateHash( const CHARSTRING& p__certificateId, OCTETSTRING& p__hash ) { loggers::get_instance().log(">>> fx__readCertificateHash: '%s'", static_cast(p__certificateId)); if (security_services::get_instance().read_certificate_hash(p__certificateId, p__hash) == -1) { return FALSE; } return TRUE; } /** * \brief Read the private keys for the specified certificate * \param p_certificateId the keys identifier * \param p_signingPrivateKey the signing private key * \return true on success, false otherwise */ BOOLEAN fx__readSigningKey( const CHARSTRING& p__certificateId, OCTETSTRING& p__signingPrivateKey ) { loggers::get_instance().log(">>> fx__readSigningKey: '%s'", static_cast(p__certificateId)); if (security_services::get_instance().read_private_key(p__certificateId, p__signingPrivateKey) == -1) { return FALSE; } return TRUE; } /** * \brief 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 fx_readEncryptingKey(in charstring p_keysId, out Oct32 p_encryptingPrivateKey) return boolean; */ BOOLEAN fx__readEncryptingKey( const CHARSTRING& p__certificateId, OCTETSTRING& p__encryptingPrivateKey ) { loggers::get_instance().log(">>> fx__readSigningKey: '%s'", static_cast(p__certificateId)); if (security_services::get_instance().read_private_enc_key(p__certificateId, p__encryptingPrivateKey) == -1) { return FALSE; } return TRUE; } // group geodesic /* * \brief 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 fx_isValidPolygonalRegion(in PolygonalRegion p_region) return boolean; */ BOOLEAN fx__isValidPolygonalRegion( const IEEE1609dot2BaseTypes::PolygonalRegion& p__region ) { return TRUE; } /* * \brief 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 fx_isPolygonalRegionInside(in PolygonalRegion p_parent, in PolygonalRegion p_region) return boolean; */ BOOLEAN fx__isPolygonalRegionInside( const IEEE1609dot2BaseTypes::PolygonalRegion& p__parent, const IEEE1609dot2BaseTypes::PolygonalRegion& p__region ) { return TRUE; } /* * \brief 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 fx_isLocationInsideCircularRegion(in CircularRegion p_region, in ThreeDLocation p_location) return boolean; */ BOOLEAN fx__isLocationInsideCircularRegion( const IEEE1609dot2BaseTypes::CircularRegion& p__region, const IEEE1609dot2BaseTypes::ThreeDLocation& p__location ) { return TRUE; } /* * \brief 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 fx_isLocationInsideRectangularRegion(in SequenceOfRectangularRegion p_region, in ThreeDLocation p_location) return boolean; */ BOOLEAN fx__isLocationInsideRectangularRegion( const IEEE1609dot2BaseTypes::SequenceOfRectangularRegion& p__region, const IEEE1609dot2BaseTypes::ThreeDLocation& p__location ) { return TRUE; } /* * \brief 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 fx_isLocationInsidePolygonalRegion(in PolygonalRegion p_region, in ThreeDLocation p_location) return boolean; */ BOOLEAN fx__isLocationInsidePolygonalRegion( const IEEE1609dot2BaseTypes::PolygonalRegion& p__region, const IEEE1609dot2BaseTypes::ThreeDLocation& p__location ) { return TRUE; } /* * \brief 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 fx_isLocationInsideIdentifiedRegion(in IdentifiedRegion p_region, in ThreeDLocation p_location) return boolean; */ BOOLEAN fx__isLocationInsideIdentifiedRegion( const IEEE1609dot2BaseTypes::IdentifiedRegion& p__region, const IEEE1609dot2BaseTypes::ThreeDLocation& p__location ) { return TRUE; } /* * \brief 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 fx_isLocationInsideOtherRegion(in octetstring p_region, in ThreeDLocation p_location) return boolean; */ BOOLEAN fx__isLocationInsideOtherRegion( const OCTETSTRING& p_region, const IEEE1609dot2BaseTypes::ThreeDLocation& p_location ) { return TRUE; } /* * \brief 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 fx_areCirclesInside(in CircularRegion p_circular_region_1, in CircularRegion p_circular_region_2) return boolean; */ BOOLEAN fx__areCirclesInside( const IEEE1609dot2BaseTypes::CircularRegion& p_circular_region_1, const IEEE1609dot2BaseTypes::CircularRegion& p_circular_region_2 ) { return TRUE; } /* * \brief 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 fx_areRectanglesInside(in SequenceOfRectangularRegion p_rectanglar_region_1, in SequenceOfRectangularRegion p_rectanglar_region_2) return boolean; */ BOOLEAN fx__areRectanglesInside( const IEEE1609dot2BaseTypes::SequenceOfRectangularRegion& p_rectanglar_region_1, const IEEE1609dot2BaseTypes::SequenceOfRectangularRegion& p_rectanglar_region_2 ) { return TRUE; } /* * \brief 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 fx_arePolygonsInside(in PolygonalRegion p_polygonal_region_1, in PolygonalRegion p_polygonal_region_2) return boolean; */ BOOLEAN fx__arePolygonsInside( const IEEE1609dot2BaseTypes::PolygonalRegion& p_polygonal_region_1, const IEEE1609dot2BaseTypes::PolygonalRegion& p_polygonal_region_2 ) { return TRUE; } /** * \brief 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 fx_dms2dd(in Int p_degrees, in Int p_minutes, in float p_seconds, in Oct1 p_latlon) return float; */ FLOAT fx__dms2dd( const INTEGER& p__degrees, const INTEGER& p__minutes, const FLOAT& p__seconds, const OCTETSTRING& p__latlon ) { return 0.0; } } // end of namespace