From a1c9992692d9b5573a2ac5d9ceec3915618e1001 Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Tue, 7 Oct 2025 16:20:00 +0300 Subject: [PATCH 1/8] gitignore: add .cache to .gitignore Signed-off-by: Mykola Kobets Reviewed-by: Mykhailo Lohvynenko Reviewed-by: Oleksandr Grytsov Reviewed-by: Mykola Solianko --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bab6f8af3..0f4f1e8b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/* .vscode/* +.cache/* .*/*\!.github CMakeUserPresets.json From d4d06b7c5627c9cfa4b8be810e254fe0e85769ca Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Tue, 7 Oct 2025 16:23:07 +0300 Subject: [PATCH 2/8] crypto: split crypto.hpp on dedicated header files Signed-off-by: Mykola Kobets Reviewed-by: Mykhailo Lohvynenko Reviewed-by: Oleksandr Grytsov Reviewed-by: Mykola Solianko --- src/core/cm/storagestate/itf/storagestate.hpp | 2 - src/core/common/crypto/CMakeLists.txt | 16 +- src/core/common/crypto/crypto.hpp | 1276 ----------------- src/core/common/crypto/itf/aes.hpp | 94 ++ src/core/common/crypto/itf/asn1.hpp | 390 +++++ src/core/common/crypto/itf/certloader.hpp | 93 ++ src/core/common/crypto/itf/crypto.hpp | 38 + src/core/common/crypto/itf/cryptohelper.hpp | 221 +++ src/core/common/crypto/itf/hash.hpp | 133 ++ src/core/common/crypto/itf/privkey.hpp | 272 ++++ src/core/common/crypto/itf/rand.hpp | 64 + src/core/common/crypto/itf/uuid.hpp | 43 + src/core/common/crypto/itf/x509.hpp | 386 +++++ 13 files changed, 1748 insertions(+), 1280 deletions(-) delete mode 100644 src/core/common/crypto/crypto.hpp create mode 100644 src/core/common/crypto/itf/aes.hpp create mode 100644 src/core/common/crypto/itf/asn1.hpp create mode 100644 src/core/common/crypto/itf/certloader.hpp create mode 100644 src/core/common/crypto/itf/crypto.hpp create mode 100644 src/core/common/crypto/itf/cryptohelper.hpp create mode 100644 src/core/common/crypto/itf/hash.hpp create mode 100644 src/core/common/crypto/itf/privkey.hpp create mode 100644 src/core/common/crypto/itf/rand.hpp create mode 100644 src/core/common/crypto/itf/uuid.hpp create mode 100644 src/core/common/crypto/itf/x509.hpp diff --git a/src/core/cm/storagestate/itf/storagestate.hpp b/src/core/cm/storagestate/itf/storagestate.hpp index 8fd269b48..2de77d5ba 100644 --- a/src/core/cm/storagestate/itf/storagestate.hpp +++ b/src/core/cm/storagestate/itf/storagestate.hpp @@ -7,8 +7,6 @@ #ifndef AOS_CORE_CM_STORAGESTATE_ITF_STORAGESTATE_HPP_ #define AOS_CORE_CM_STORAGESTATE_ITF_STORAGESTATE_HPP_ -#include - namespace aos::cm::storagestate { /** @addtogroup cm Communication Manager diff --git a/src/core/common/crypto/CMakeLists.txt b/src/core/common/crypto/CMakeLists.txt index 78448edba..30d121bac 100644 --- a/src/core/common/crypto/CMakeLists.txt +++ b/src/core/common/crypto/CMakeLists.txt @@ -71,7 +71,7 @@ endif() # Sources # ###################################################################################################################### -set(SOURCES crypto.cpp cryptohelper.cpp cryptoutils.cpp) +set(SOURCES asn1.cpp cryptohelper.cpp certloader.cpp) if(WITH_MBEDTLS) list(APPEND SOURCES mbedtls/cryptoprovider.cpp mbedtls/driverwrapper.cpp) @@ -85,7 +85,19 @@ endif() # Headers # ###################################################################################################################### -set(HEADERS crypto.hpp cryptoprovider.hpp cryptoutils.hpp) +set(HEADERS + certloader.hpp + cryptoprovider.hpp + cryptohelper.hpp + itf/rand.hpp + itf/asn1.hpp + itf/certloader.hpp + itf/crypto.hpp + itf/cryptohelper.hpp + itf/hash.hpp + itf/privkey.hpp + itf/x509.hpp +) if(WITH_MBEDTLS) list(APPEND HEADERS mbedtls/cryptoprovider.hpp mbedtls/driverwrapper.hpp) diff --git a/src/core/common/crypto/crypto.hpp b/src/core/common/crypto/crypto.hpp deleted file mode 100644 index 2cfc40021..000000000 --- a/src/core/common/crypto/crypto.hpp +++ /dev/null @@ -1,1276 +0,0 @@ -/* - * Copyright (C) 2023 Renesas Electronics Corporation. - * Copyright (C) 2023 EPAM Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef AOS_CORE_COMMON_CRYPTO_CRYPTO_HPP_ -#define AOS_CORE_COMMON_CRYPTO_CRYPTO_HPP_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace aos::crypto { - -/** - * Certificate issuer name max length. - */ -constexpr auto cCertIssuerSize = AOS_CONFIG_CRYPTO_CERT_ISSUER_SIZE; - -/** - * Max length of a DNS name. - */ -constexpr auto cDNSNameLen = AOS_CONFIG_CRYPTO_DNS_NAME_LEN; - -/** - * Max number of alternative names for a module. - */ -constexpr auto cAltDNSNamesCount = AOS_CONFIG_CRYPTO_ALT_DNS_NAMES_MAX_COUNT; - -/** - * Certificate subject size. - */ -constexpr auto cCertSubjSize = AOS_CONFIG_CRYPTO_CERT_ISSUER_SIZE; - -/** - * Maximum length of distinguished name string representation. - */ -constexpr auto cCertDNStringSize = AOS_CONFIG_CRYPTO_DN_STRING_SIZE; - -/** - * Certificate extra extensions max number. - */ -constexpr auto cCertExtraExtCount = AOS_CONFIG_CRYPTO_EXTRA_EXTENSIONS_COUNT; - -/** - * Maximum length of numeric string representing ASN.1 Object Identifier. - */ -constexpr auto cASN1ObjIdLen = AOS_CONFIG_CRYPTO_ASN1_OBJECT_ID_LEN; - -/** - * Maximum size of a certificate ASN.1 Extension Value. - */ -constexpr auto cASN1ExtValueSize = AOS_CONFIG_CRYPTO_ASN1_EXTENSION_VALUE_SIZE; - -/** - * Maximum certificate key id size(in bytes). - */ -constexpr auto cCertKeyIdSize = AOS_CONFIG_CRYPTO_CERT_KEY_ID_SIZE; - -/** - * Maximum length of a PEM certificate. - */ -constexpr auto cCertPEMLen = AOS_CONFIG_CRYPTO_CERT_PEM_LEN; - -/** - * Maximum size of a DER certificate. - */ -constexpr auto cCertDERSize = AOS_CONFIG_CRYPTO_CERT_DER_SIZE; - -/** - * Maximum length of CSR in PEM format. - */ -constexpr auto cCSRPEMLen = AOS_CONFIG_CRYPTO_CSR_PEM_LEN; - -/** - * Maximum length of private key in PEM format. - */ -constexpr auto cPrivKeyPEMLen = AOS_CONFIG_CRYPTO_PRIVKEY_PEM_LEN; - -/** - * Serial number size(in bytes). - */ -constexpr auto cSerialNumSize = AOS_CONFIG_CRYPTO_SERIAL_NUM_SIZE; - -/** - * Length of serial number in string representation. - */ -constexpr auto cSerialNumStrLen = cSerialNumSize * 2; - -/** - * Maximum size of serial number encoded in DER format. - */ -constexpr auto cSerialNumDERSize = AOS_CONFIG_CRYPTO_SERIAL_NUM_DER_SIZE; - -/** - * Subject common name length. - */ -constexpr auto cSubjectCommonNameLen = AOS_CONFIG_CRYPTO_SUBJECT_COMMON_NAME_LEN; - -/** - * RSA modulus size. - */ -constexpr auto cRSAModulusSize = AOS_CONFIG_CRYPTO_RSA_MODULUS_SIZE; - -/** - * Size of RSA public exponent. - */ -constexpr auto cRSAPubExponentSize = AOS_CONFIG_CRYPTO_RSA_PUB_EXPONENT_SIZE; - -/** - * ECDSA params OID size. - */ -constexpr auto cECDSAParamsOIDSize = AOS_CONFIG_CRYPTO_ECDSA_PARAMS_OID_SIZE; - -/** - * DER-encoded X9.62 ECPoint. - */ -constexpr auto cECDSAPointDERSize = AOS_CONFIG_CRYPTO_ECDSA_POINT_DER_SIZE; - -/** - * Max expected number of certificates in a chain stored in PEM file. - */ -constexpr auto cCertChainSize = AOS_CONFIG_CRYPTO_CERTS_CHAIN_SIZE; - -/** - * Number of certificate chains to be stored in crypto::CertLoader. - */ -constexpr auto cCertChainsCount = AOS_CONFIG_CRYPTO_CERTIFICATE_CHAINS_COUNT; - -/** - * Certificate chain len. - */ -constexpr auto cCertChainPEMLen = cCertChainSize * cCertPEMLen; - -/** - * Maximum size of SHA2 digest. - */ -constexpr auto cSHA2DigestSize = AOS_CONFIG_CRYPTO_SHA2_DIGEST_SIZE; - -/** - * Maximum size of SHA1 digest. - */ -constexpr auto cSHA1DigestSize = AOS_CONFIG_CRYPTO_SHA1_DIGEST_SIZE; - -/** - * Maximum size of input data for SHA1 hash calculation. - */ -constexpr auto cSHA1InputDataSize = AOS_CONFIG_CRYPTO_SHA1_INPUT_SIZE; - -/** - * Maximum signature size. - */ -constexpr auto cSignatureSize = AOS_CONFIG_CRYPTO_SIGNATURE_SIZE; - -/** - * Max number of certificates. - */ -constexpr auto cMaxNumCertificates = AOS_CONFIG_CRYPTO_MAX_NUM_CERTIFICATES; - -/** - * SHA256 size. - */ -constexpr auto cSHA256Size = 32; - -/** - * SHA384 size. - */ -constexpr auto cSHA384Size = 48; - -/** - * SHA3-224 size. - */ -constexpr auto cSHA3_224Size = 28; - -/** - * Supported key types. - */ -class KeyAlgorithm { -public: - enum class Enum { eRSA, eECDSA }; - - static const Array GetStrings() - { - static const char* const sContentTypeStrings[] = {"RSA", "ECDSA"}; - return Array(sContentTypeStrings, ArraySize(sContentTypeStrings)); - }; -}; - -using KeyTypeEnum = KeyAlgorithm::Enum; -using KeyType = EnumStringer; - -/** - * Public key interface. - */ -class PublicKeyItf { -public: - /** - * Returns type of a public key. - * - * @return KeyType, - */ - virtual KeyType GetKeyType() const = 0; - - /** - * Tests whether current key is equal to the provided one. - * - * @param pubKey public key. - * @return bool. - */ - virtual bool IsEqual(const PublicKeyItf& pubKey) const = 0; - - /** - * Destroys object instance. - */ - virtual ~PublicKeyItf() = default; -}; - -/** - * Supported hash functions. - */ -class HashType { -public: - enum class Enum { - eSHA1, - eSHA224, - eSHA256, - eSHA384, - eSHA512, - eSHA512_224, - eSHA512_256, - eSHA3_224, - eSHA3_256, - eNone, - }; - - static const Array GetStrings() - { - static const char* const sContentTypeStrings[] = { - "SHA1", - "SHA224", - "SHA256", - "SHA384", - "SHA512", - "SHA512-224", - "SHA512-256", - "SHA3-224", - "SHA3-256", - "NONE", - }; - return Array(sContentTypeStrings, ArraySize(sContentTypeStrings)); - }; -}; - -using HashEnum = HashType::Enum; -using Hash = EnumStringer; - -/** - * Padding type. - */ -class PaddingType { -public: - enum class Enum { ePKCS1v1_5, ePSS, eNone }; - - static const Array GetStrings() - { - static const char* const sContentTypeStrings[] = {"PKCS1v1_5", "PSS", "Node"}; - return Array(sContentTypeStrings, ArraySize(sContentTypeStrings)); - }; -}; - -using PaddingEnum = PaddingType::Enum; -using Padding = EnumStringer; - -/** - * Verify options. - */ -struct VerifyOptions { - Time mCurrentTime; -}; - -/** - * Hash interface. - */ -class HashItf { -public: - /** - * Updates hash with input data. - * - * @param data input data. - * @return Error. - */ - virtual Error Update(const Array& data) = 0; - - /** - * Finalizes hash calculation. - * - * @param[out] hash result hash. - * @return Error. - */ - virtual Error Finalize(Array& hash) = 0; - - /** - * Destructor. - */ - virtual ~HashItf() = default; -}; - -/** - * Hasher interface. - */ -class HasherItf { -public: - /** - * Creates hash instance. - * - * @param algorithm hash algorithm. - * @return RetWithError>. - */ - virtual RetWithError> CreateHash(Hash algorithm) = 0; - - /** - * Destructor. - */ - virtual ~HasherItf() = default; -}; - -class RandomItf { -public: - /** - * Generates random integer value in range [0..maxValue]. - * - * @param maxValue maximum value. - * @return RetWithError. - */ - virtual RetWithError RandInt(uint64_t maxValue) = 0; - - /** - * Generates random buffer. - * - * @param[out] buffer result buffer. - * @param size buffer size. - * @return Error. - */ - virtual Error RandBuffer(Array& buffer, size_t size = 0) = 0; - - /** - * Destructor. - */ - virtual ~RandomItf() = default; -}; - -/*** - * UUID generator interface. - */ -class UUIDItf { -public: - /** - * Creates UUID v4. - * - * @return RetWithError. - */ - virtual RetWithError CreateUUIDv4() = 0; - - /** - * Creates UUID version 5 based on a given namespace identifier and name. - * - * @param space namespace identifier. - * @param name name. - * @result RetWithError. - */ - virtual RetWithError CreateUUIDv5(const uuid::UUID& space, const Array& name) = 0; - - /** - * Destructor. - */ - virtual ~UUIDItf() = default; -}; - -/** - * AES cipher interface for 16-byte block encryption/decryption. - */ -class AESCipherItf { -public: - /** - * AES block. - */ - using Block = StaticArray; - - /** - * Destructor. - */ - virtual ~AESCipherItf() = default; - - /** - * Encrypts a 16-byte block. - * - * @param input input block. - * @param[out] output encrypted block. - * @return Error. - */ - virtual Error EncryptBlock(const Block& input, Block& output) = 0; - - /** - * Decrypts a 16-byte block. - * - * @param input input block. - * @param[out] output decrypted block. - * @return Error. - */ - virtual Error DecryptBlock(const Block& input, Block& output) = 0; - - /** - * Finalizes encription/decryption. - * - * @param[out] output final block. - * @return Error. - */ - virtual Error Finalize(Block& output) = 0; -}; - -/** - * Interface for AES encoding/decoding. - */ -class AESEncoderDecoderItf { -public: - /** - * Destructor. - */ - virtual ~AESEncoderDecoderItf() = default; - - /** - * Creates a new AES encoder. - * - * @param mode AES mode: "CBC" supported only. - * @param key encryption key. - * @param iv initialization vector: must be 16 bytes for CBC mode. - * @return RetWithError>. - */ - virtual RetWithError> CreateAESEncoder( - const String& mode, const Array& key, const Array& iv) - = 0; - - /** - * Creates a new AES decoder. - * - * @param mode AES mode: "CBC" supported only. - * @param key decryption key. - * @param iv initialization vector: must be 16 bytes for CBC mode. - * @return RetWithError>. - */ - virtual RetWithError> CreateAESDecoder( - const String& mode, const Array& key, const Array& iv) - = 0; -}; - -/** - * Options being used while signing. - */ -struct SignOptions { - /** - * Hash function to be used when signing. - */ - Hash mHash; -}; - -/** - * PKCS1v15 decryption options. - */ -struct PKCS1v15DecryptionOptions { - int mKeySize = 0; -}; - -/** - * OAEP decryption options. - */ -struct OAEPDecryptionOptions { - Hash mHash; -}; - -/** - * Decryption options. - */ -using DecryptionOptions = Variant; - -/** - * Private key interface. - */ -class PrivateKeyItf { -public: - /** - * Returns public part of a private key. - * - * @return const PublicKeyItf&. - */ - virtual const PublicKeyItf& GetPublic() const = 0; - - /** - * Calculates a signature of a given digest. - * - * @param digest input hash digest. - * @param options signing options. - * @param[out] signature result signature. - * @return Error. - */ - virtual Error Sign(const Array& digest, const SignOptions& options, Array& signature) const = 0; - - /** - * Decrypts a cipher message. - * - * @param cipher encrypted message. - * @param options decryption options. - * @param[out] result decoded message. - * @return Error. - */ - virtual Error Decrypt(const Array& cipher, const DecryptionOptions& options, Array& result) const - = 0; - - /** - * Destroys object instance. - */ - virtual ~PrivateKeyItf() = default; -}; - -/** - * RSA public key. - */ -class RSAPublicKey : public PublicKeyItf { -public: - /** - * Constructs object instance. - * - * @param n modulus. - * @param e public exponent. - */ - RSAPublicKey(const Array& n, const Array& e) - : mN(n) - , mE(e) - { - } - - /** - * Returns type of a public key. - * - * @return KeyType, - */ - KeyType GetKeyType() const override { return KeyTypeEnum::eRSA; } - - /** - * Tests whether current key is equal to the provided one. - * - * @param pubKey public key. - * @return bool. - */ - bool IsEqual(const PublicKeyItf& pubKey) const override - { - if (pubKey.GetKeyType() != KeyTypeEnum::eRSA) { - return false; - } - - const auto& otherKey = static_cast(pubKey); - - return otherKey.mN == mN && otherKey.mE == mE; - } - - /** - * Returns RSA public modulus. - * - * @return const Array&. - */ - const Array& GetN() const { return mN; } - - /** - * Returns RSA public exponent. - * - * @return const Array&. - */ - const Array& GetE() const { return mE; } - -private: - StaticArray mN; - StaticArray mE; -}; - -/** - * ECDSA public key. - */ -class ECDSAPublicKey : public PublicKeyItf { -public: - /** - * Constructs object instance. - * - * @param n modulus. - * @param e public exponent. - */ - ECDSAPublicKey(const Array& params, const Array& point) - : mECParamsOID(params) - , mECPoint(point) - { - } - - /** - * Returns type of a public key. - * - * @return KeyType, - */ - KeyType GetKeyType() const override { return KeyTypeEnum::eECDSA; } - - /** - * Tests whether current key is equal to the provided one. - * - * @param pubKey public key. - * @return bool. - */ - bool IsEqual(const PublicKeyItf& pubKey) const override - { - if (pubKey.GetKeyType() != KeyTypeEnum::eECDSA) { - return false; - } - - const auto& otherKey = static_cast(pubKey); - - return otherKey.mECParamsOID == mECParamsOID && otherKey.mECPoint == mECPoint; - } - - /** - * Returns ECDSA params OID. - * - * @return const Array&. - */ - const Array& GetECParamsOID() const { return mECParamsOID; } - - /** - * Returns ECDSA point. - * - * @return const Array&. - */ - const Array& GetECPoint() const { return mECPoint; } - -private: - StaticArray mECParamsOID; - StaticArray mECPoint; -}; - -namespace asn1 { -/** - * ASN.1 OBJECT IDENTIFIER - */ -using ObjectIdentifier = StaticString; - -/** - * ASN1 value. - */ -struct ASN1Value { - int mTagClass {}; - int mTagNumber {}; - bool mIsConstructed {}; - Array mValue; - - /** - * Constructor. - */ - ASN1Value() = default; - - /** - * Constructor. - * - * @param tagClass ASN.1 tag class. - * @param tagNumber ASN.1 tag number. - * @param isConstructed indicates whether this value is a constructed type (true) or a primitive type (false). - * @param content raw content of the ASN.1 value. - */ - ASN1Value(int tagClass, int tagNumber, bool isConstructed, const Array& content) - : mTagClass(tagClass) - , mTagNumber(tagNumber) - , mIsConstructed(isConstructed) - , mValue(content) - { - } - - /** - * Constructor. - */ - ASN1Value(const ASN1Value& other) { *this = other; } - - /** - * Copy operator. - */ - ASN1Value& operator=(const ASN1Value& other) - { - mTagClass = other.mTagClass; - mTagNumber = other.mTagNumber; - mIsConstructed = other.mIsConstructed; - mValue.Rebind(other.mValue); - - return *this; - } - - /** - * Compares ASN1Value. - * - * @param other another ASN1Value to compare with. - * @return bool. - */ - bool operator==(const ASN1Value& other) const - { - return mTagClass == other.mTagClass && mTagNumber == other.mTagNumber && mIsConstructed == other.mIsConstructed - && mValue == other.mValue; - } - - /** - * Compares ASN1Value. - * - * @param other another ASN1Value to compare with. - * @return bool. - */ - bool operator!=(const ASN1Value& other) const { return !(*this == other); } -}; - -/** - * Represents an ASN.1 AlgorithmIdentifier type. - */ -struct AlgorithmIdentifier { - ObjectIdentifier mOID; - ASN1Value mParams; -}; - -/** - * ASN.1 structure extension. RFC 580, section 4.2 - */ -struct Extension { - ObjectIdentifier mID; - StaticArray mValue; - - /** - * Checks whether current object is equal the the given one. - * - * @param extension object to compare with. - * @return bool. - */ - bool operator==(const Extension& extension) const { return extension.mID == mID && extension.mValue == mValue; } - /** - * Checks whether current object is not equal the the given one. - * - * @param extension object to compare with. - * @return bool. - */ - bool operator!=(const Extension& extension) const { return !operator==(extension); } -}; - -/** - * Converts input time to ASN1 GeneralizedTime string. - * - * @param time time. - * @return RetWithError> - */ -RetWithError> ConvertTimeToASN1Str(const Time& time); - -/** - * ASN1 reader. - */ -class ASN1ReaderItf { -public: - /** - * Destructor. - */ - virtual ~ASN1ReaderItf() = default; - - /** - * Called once per parsed TLV element. - * - * @param value ASN1 value. - * @return Error. - */ - virtual Error OnASN1Element(const ASN1Value& value) = 0; -}; - -/** - * ASN.1 reader implementation that delegates parsing to a user-defined handler. - */ -template -class ASN1Reader : public ASN1ReaderItf { -public: - /** - * Constructor. - */ - explicit ASN1Reader(Handler&& handler) - : mHandler(Move(handler)) - { - } - - /** - * Processes a single ASN.1 element. - * - * @param value ASN.1 element value to process. - * @return Error. - */ - Error OnASN1Element(const ASN1Value& value) override { return mHandler(value); } - -private: - Handler mHandler; -}; - -/** - * Creates ASN1Reader instance based on the provided lambda. - * - * @param reader ASN1 reader. - * @return ASN1Reader. - */ -template -ASN1Reader MakeASN1Reader(Reader&& reader) -{ - return ASN1Reader(Move(reader)); -} - -/** - * Represents the result of an ASN.1 parsing operation. - */ -struct ASN1ParseResult { - Error mError; - Array mRemaining; - - /** - * Constructor. - */ - ASN1ParseResult() = default; - - /** - * Constructor. - * - * @param err error object. - * @param remaining not parsed content. - */ - ASN1ParseResult(const Error& err, const Array& remaining) - : mError(err) - , mRemaining(remaining) - { - } - - /** - * Copy constructor. - * - * @param other source parse result object. - */ - ASN1ParseResult(const ASN1ParseResult& other) { *this = other; } - - /** - * Copy operator. - * - * @param other source parse result object. - * @return ASN1ParseResult&. - */ - ASN1ParseResult& operator=(const ASN1ParseResult& other) - { - mError = other.mError; - mRemaining.Rebind(other.mRemaining); - - return *this; - } - - /** - * Compares ASN1 parse results. - * - * @param other another parse result to compare with. - * @return bool. - */ - bool operator==(const ASN1ParseResult& other) const - { - return mError == other.mError && mRemaining == other.mRemaining; - } - - /** - * Compares ASN1 parse results. - * - * @param other another parse result to compare with. - * @return bool. - */ - bool operator!=(const ASN1ParseResult& other) const { return !(*this == other); } -}; - -/** - * Options to control the behavior of ASN.1 parsing. - */ -struct ASN1ParseOptions { - /** - * Indicates whether the field is optional. - */ - bool mOptional = false; - - /** - * Optional tag to match during parsing. - */ - Optional mTag; -}; - -/** - * Interface for decoding ASN.1 structures. - */ -class ASN1DecoderItf { -public: - /** - * Destructor. - */ - virtual ~ASN1DecoderItf() = default; - - /** - * Discards an ASN.1 tag-length and invokes reader for its content. - * - * @param data input data buffer. - * @param opt parse options. - * @param asn1reader reader handles content of the structure. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadStruct( - const Array& data, const ASN1ParseOptions& opt, ASN1ReaderItf& asn1reader) - = 0; - - /** - * Reads an ASN.1 SET and invokes the reader for each element. - * - * @param data input data buffer. - * @param opt parse options. - * @param asn1reader reader callback to handle each element. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadSet(const Array& data, const ASN1ParseOptions& opt, ASN1ReaderItf& asn1reader) - = 0; - - /** - * Reads an ASN.1 SEQUENCE and invokes the reader for each element. - * - * @param data input data buffer. - * @param opt parse options. - * @param asn1reader reader callback to handle each element. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadSequence( - const Array& data, const ASN1ParseOptions& opt, ASN1ReaderItf& asn1reader) - = 0; - - /** - * Reads an ASN.1 INTEGER value. - * - * @param data input data buffer. - * @param opt parse options. - * @param[out] value result integer. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadInteger(const Array& data, const ASN1ParseOptions& opt, int& value) = 0; - - /** - * Reads a large ASN.1 INTEGER (BigInt) as a byte array. - * - * @param data input data buffer. - * @param opt parse options. - * @param[out] result result integer bytes. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadBigInt(const Array& data, const ASN1ParseOptions& opt, Array& result) - = 0; - - /** - * Reads an ASN.1 Object Identifier (OID). - * - * @param data input data buffer. - * @param opt parse options. - * @param[out] oid result OID. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadOID(const Array& data, const ASN1ParseOptions& opt, ObjectIdentifier& oid) = 0; - - /** - * Reads an ASN.1 AlgorithmIdentifier(AID). - * - * @param data input data buffer. - * @param opt parse options. - * @param[out] aid result AID. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadAID(const Array& data, const ASN1ParseOptions& opt, AlgorithmIdentifier& aid) - = 0; - - /** - * Reads an ASN.1 OCTET STRING. - * - * @param data input data buffer. - * @param opt parse options. - * @param[out] result result octet string. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadOctetString( - const Array& data, const ASN1ParseOptions& opt, Array& result) - = 0; - - /** - * Returns a raw ASN.1 value. - * - * @param data input data buffer. - * @param opt parse options. - * @param[out] result parsed ASN1 value. - * @return ASN1ParseResult. - */ - virtual ASN1ParseResult ReadRawValue(const Array& data, const ASN1ParseOptions& opt, ASN1Value& result) - = 0; -}; - -} // namespace asn1 - -namespace x509 { - -/** - * x509 Certificate. - */ -struct Certificate { - /** - * DER encoded certificate subject. - */ - StaticArray mSubject; - /** - * Certificate subject key id. - */ - StaticArray mSubjectKeyId; - /** - * Certificate authority key id. - */ - StaticArray mAuthorityKeyId; - /** - * DER encoded certificate subject issuer. - */ - StaticArray mIssuer; - /** - * Certificate serial number. - */ - StaticArray mSerial; - /** - * Issuer URLs. - */ - StaticArray, cMaxNumURLs> mIssuerURLs; - /** - * Certificate validity period. - */ - Time mNotBefore, mNotAfter; - /** - * Public key. - */ - Variant mPublicKey; - /** - * Complete ASN.1 DER content (certificate, signature algorithm and signature). - */ - StaticArray mRaw; -}; - -/** - * x509 Certificate request. - */ -struct CSR { - /** - * Certificate subject size. - */ - StaticArray mSubject; - /** - * Alternative DNS names. - */ - StaticArray, cAltDNSNamesCount> mDNSNames; - /** - * Contains extra extensions applied to CSR. - */ - StaticArray mExtraExtensions; -}; - -/** - * Provides interface to manage certificate requests. - */ -class ProviderItf { -public: - /** - * Creates a new certificate based on a template. - * - * @param templ a pattern for a new certificate. - * @param parent a parent certificate in a certificate chain. - * @param pubKey public key. - * @param privKey private key. - * @param[out] pemCert result certificate in PEM format. - * @result Error. - */ - virtual Error CreateCertificate( - const Certificate& templ, const Certificate& parent, const PrivateKeyItf& privKey, String& pemCert) - = 0; - - /** - * Creates certificate chain using client CSR & CA key/certificate as input. - * - * @param pemCSR client certificate request. - * @param pemCAKey CA private key in PEM. - * @param pemCACert CA certificate in PEM. - * @param serial serial number of certificate. - * @param[out] pemClientCert result certificate. - * @result Error. - */ - virtual Error CreateClientCert( - const String& csr, const String& caKey, const String& caCert, const Array& serial, String& clientCert) - = 0; - - /** - * Reads certificates from a PEM blob. - * - * @param pemBlob raw certificates in a PEM format. - * @param[out] resultCerts result certificate chain. - * @result Error. - */ - virtual Error PEMToX509Certs(const String& pemBlob, Array& resultCerts) = 0; - - /** - * Serializes input certificate object into a PEM blob. - * - * @param certificate input certificate object. - * @param[out] dst destination buffer. - * @result Error. - */ - virtual Error X509CertToPEM(const Certificate& certificate, String& dst) = 0; - - /** - * Reads private key from a PEM blob. - * - * @param pemBlob raw certificates in a PEM format. - * @result RetWithError>. - */ - virtual RetWithError> PEMToX509PrivKey(const String& pemBlob) = 0; - - /** - * Reads certificate from a DER blob. - * - * @param derBlob raw certificate in a DER format. - * @param[out] resultCert result certificate. - * @result Error. - */ - virtual Error DERToX509Cert(const Array& derBlob, Certificate& resultCert) = 0; - - /** - * Creates a new certificate request, based on a template. - * - * @param templ template for a new certificate request. - * @param privKey private key. - * @param[out] pemCSR result CSR in PEM format. - * @result Error. - */ - virtual Error CreateCSR(const CSR& templ, const PrivateKeyItf& privKey, String& pemCSR) = 0; - - /** - * Constructs x509 distinguished name(DN) from the argument list. - * - * @param comName common name. - * @param[out] result result DN. - * @result Error. - */ - virtual Error ASN1EncodeDN(const String& commonName, Array& result) = 0; - - /** - * Returns text representation of x509 distinguished name(DN). - * - * @param dn source binary representation of DN. - * @param[out] result DN text representation. - * @result Error. - */ - virtual Error ASN1DecodeDN(const Array& dn, String& result) = 0; - - /** - * Encodes array of object identifiers into ASN1 value. - * - * @param src array of object identifiers. - * @param asn1Value result ASN1 value. - */ - virtual Error ASN1EncodeObjectIds(const Array& src, Array& asn1Value) = 0; - - /** - * Encodes big integer in ASN1 format. - * - * @param number big integer. - * @param[out] asn1Value result ASN1 value. - * @result Error. - */ - virtual Error ASN1EncodeBigInt(const Array& number, Array& asn1Value) = 0; - - /** - * Creates ASN1 sequence from already encoded DER items. - * - * @param items DER encoded items. - * @param[out] asn1Value result ASN1 value. - * @result Error. - */ - virtual Error ASN1EncodeDERSequence(const Array>& items, Array& asn1Value) = 0; - - /** - * Returns value of the input ASN1 OCTETSTRING. - * - * @param src DER encoded OCTETSTRING value. - * @param[out] dst decoded value. - * @result Error. - */ - virtual Error ASN1DecodeOctetString(const Array& src, Array& dst) = 0; - - /** - * Decodes input ASN1 OID value. - * - * @param inOID input ASN1 OID value. - * @param[out] dst decoded value. - * @result Error. - */ - virtual Error ASN1DecodeOID(const Array& inOID, Array& dst) = 0; - - /** - * Verifies a digital signature using the provided public key and digest. - * - * @param pubKey public key. - * @param hashFunc hash function that was used to produce the digest. - * @param padding padding type. - * @param digest message digest to verify. - * @param signature signature to verify against the digest. - * @return Error. - */ - virtual Error Verify(const Variant& pubKey, Hash hashFunc, Padding padding, - const Array& digest, const Array& signature) - = 0; - - /** - * Verifies the certificate against a chain of intermediate and root certificates. - * - * @param rootCerts trusted root certificates. - * @param intermCerts intermediate certificate chain used to build the path to a trusted root. - * @param options verify options. - * @param cert certificate to verify. - * @return Error. - */ - virtual Error Verify(const Array& rootCerts, const Array& intermCerts, - const VerifyOptions& options, const Certificate& cert) - = 0; - - /** - * Destroys object instance. - */ - virtual ~ProviderItf() = default; -}; - -/** - * A chain of certificates. - */ -using CertificateChain = StaticArray; - -} // namespace x509 - -/** - * Crypto provider interface. - */ -class CryptoProviderItf : public x509::ProviderItf, - public HasherItf, - public RandomItf, - public UUIDItf, - public AESEncoderDecoderItf, - public asn1::ASN1DecoderItf { -public: - /** - * Destructor. - */ - virtual ~CryptoProviderItf() = default; -}; - -} // namespace aos::crypto - -#endif diff --git a/src/core/common/crypto/itf/aes.hpp b/src/core/common/crypto/itf/aes.hpp new file mode 100644 index 000000000..90d612ab2 --- /dev/null +++ b/src/core/common/crypto/itf/aes.hpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_AES_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_AES_HPP_ + +#include +#include + +namespace aos::crypto { + +/** + * AES cipher interface for 16-byte block encryption/decryption. + */ +class AESCipherItf { +public: + /** + * AES block. + */ + using Block = StaticArray; + + /** + * Destructor. + */ + virtual ~AESCipherItf() = default; + + /** + * Encrypts a 16-byte block. + * + * @param input input block. + * @param[out] output encrypted block. + * @return Error. + */ + virtual Error EncryptBlock(const Block& input, Block& output) = 0; + + /** + * Decrypts a 16-byte block. + * + * @param input input block. + * @param[out] output decrypted block. + * @return Error. + */ + virtual Error DecryptBlock(const Block& input, Block& output) = 0; + + /** + * Finalizes encription/decryption. + * + * @param[out] output final block. + * @return Error. + */ + virtual Error Finalize(Block& output) = 0; +}; + +/** + * Interface for AES encoding/decoding. + */ +class AESEncoderDecoderItf { +public: + /** + * Destructor. + */ + virtual ~AESEncoderDecoderItf() = default; + + /** + * Creates a new AES encoder. + * + * @param mode AES mode: "CBC" supported only. + * @param key encryption key. + * @param iv initialization vector: must be 16 bytes for CBC mode. + * @return RetWithError>. + */ + virtual RetWithError> CreateAESEncoder( + const String& mode, const Array& key, const Array& iv) + = 0; + + /** + * Creates a new AES decoder. + * + * @param mode AES mode: "CBC" supported only. + * @param key decryption key. + * @param iv initialization vector: must be 16 bytes for CBC mode. + * @return RetWithError>. + */ + virtual RetWithError> CreateAESDecoder( + const String& mode, const Array& key, const Array& iv) + = 0; +}; + +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_AES_HPP_ diff --git a/src/core/common/crypto/itf/asn1.hpp b/src/core/common/crypto/itf/asn1.hpp new file mode 100644 index 000000000..c6c022abf --- /dev/null +++ b/src/core/common/crypto/itf/asn1.hpp @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_ASN1_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_ASN1_HPP_ + +#include +#include +#include +#include + +namespace aos::crypto::asn1 { + +/** + * Maximum length of numeric string representing ASN.1 Object Identifier. + */ +constexpr auto cASN1ObjIdLen = AOS_CONFIG_CRYPTO_ASN1_OBJECT_ID_LEN; + +/** + * Maximum size of a certificate ASN.1 Extension Value. + */ +constexpr auto cASN1ExtValueSize = AOS_CONFIG_CRYPTO_ASN1_EXTENSION_VALUE_SIZE; + +/** + * ASN.1 OBJECT IDENTIFIER + */ +using ObjectIdentifier = StaticString; + +/** + * ASN1 value. + */ +struct ASN1Value { + int mTagClass {}; + int mTagNumber {}; + bool mIsConstructed {}; + Array mValue; + + /** + * Constructor. + */ + ASN1Value() = default; + + /** + * Constructor. + * + * @param tagClass ASN.1 tag class. + * @param tagNumber ASN.1 tag number. + * @param isConstructed indicates whether this value is a constructed type (true) or a primitive type (false). + * @param content raw content of the ASN.1 value. + */ + ASN1Value(int tagClass, int tagNumber, bool isConstructed, const Array& content) + : mTagClass(tagClass) + , mTagNumber(tagNumber) + , mIsConstructed(isConstructed) + , mValue(content) + { + } + + /** + * Constructor. + */ + ASN1Value(const ASN1Value& other) { *this = other; } + + /** + * Copy operator. + */ + ASN1Value& operator=(const ASN1Value& other) + { + mTagClass = other.mTagClass; + mTagNumber = other.mTagNumber; + mIsConstructed = other.mIsConstructed; + mValue.Rebind(other.mValue); + + return *this; + } + + /** + * Compares ASN1Value. + * + * @param other another ASN1Value to compare with. + * @return bool. + */ + bool operator==(const ASN1Value& other) const + { + return mTagClass == other.mTagClass && mTagNumber == other.mTagNumber && mIsConstructed == other.mIsConstructed + && mValue == other.mValue; + } + + /** + * Compares ASN1Value. + * + * @param other another ASN1Value to compare with. + * @return bool. + */ + bool operator!=(const ASN1Value& other) const { return !(*this == other); } +}; + +/** + * Represents an ASN.1 AlgorithmIdentifier type. + */ +struct AlgorithmIdentifier { + ObjectIdentifier mOID; + ASN1Value mParams; +}; + +/** + * ASN.1 structure extension. RFC 580, section 4.2 + */ +struct Extension { + ObjectIdentifier mID; + StaticArray mValue; + + /** + * Checks whether current object is equal the the given one. + * + * @param extension object to compare with. + * @return bool. + */ + bool operator==(const Extension& extension) const { return extension.mID == mID && extension.mValue == mValue; } + /** + * Checks whether current object is not equal the the given one. + * + * @param extension object to compare with. + * @return bool. + */ + bool operator!=(const Extension& extension) const { return !operator==(extension); } +}; + +/** + * Converts input time to ASN1 GeneralizedTime string. + * + * @param time time. + * @return RetWithError> + */ +RetWithError> ConvertTimeToASN1Str(const Time& time); + +/** + * ASN1 reader. + */ +class ASN1ReaderItf { +public: + /** + * Destructor. + */ + virtual ~ASN1ReaderItf() = default; + + /** + * Called once per parsed TLV element. + * + * @param value ASN1 value. + * @return Error. + */ + virtual Error OnASN1Element(const ASN1Value& value) = 0; +}; + +/** + * ASN.1 reader implementation that delegates parsing to a user-defined handler. + */ +template +class ASN1Reader : public ASN1ReaderItf { +public: + /** + * Constructor. + */ + explicit ASN1Reader(Handler&& handler) + : mHandler(Move(handler)) + { + } + + /** + * Processes a single ASN.1 element. + * + * @param value ASN.1 element value to process. + * @return Error. + */ + Error OnASN1Element(const ASN1Value& value) override { return mHandler(value); } + +private: + Handler mHandler; +}; + +/** + * Creates ASN1Reader instance based on the provided lambda. + * + * @param reader ASN1 reader. + * @return ASN1Reader. + */ +template +ASN1Reader MakeASN1Reader(Reader&& reader) +{ + return ASN1Reader(Move(reader)); +} + +/** + * Represents the result of an ASN.1 parsing operation. + */ +struct ASN1ParseResult { + Error mError; + Array mRemaining; + + /** + * Constructor. + */ + ASN1ParseResult() = default; + + /** + * Constructor. + * + * @param err error object. + * @param remaining not parsed content. + */ + ASN1ParseResult(const Error& err, const Array& remaining) + : mError(err) + , mRemaining(remaining) + { + } + + /** + * Copy constructor. + * + * @param other source parse result object. + */ + ASN1ParseResult(const ASN1ParseResult& other) { *this = other; } + + /** + * Copy operator. + * + * @param other source parse result object. + * @return ASN1ParseResult&. + */ + ASN1ParseResult& operator=(const ASN1ParseResult& other) + { + mError = other.mError; + mRemaining.Rebind(other.mRemaining); + + return *this; + } + + /** + * Compares ASN1 parse results. + * + * @param other another parse result to compare with. + * @return bool. + */ + bool operator==(const ASN1ParseResult& other) const + { + return mError == other.mError && mRemaining == other.mRemaining; + } + + /** + * Compares ASN1 parse results. + * + * @param other another parse result to compare with. + * @return bool. + */ + bool operator!=(const ASN1ParseResult& other) const { return !(*this == other); } +}; + +/** + * Options to control the behavior of ASN.1 parsing. + */ +struct ASN1ParseOptions { + /** + * Indicates whether the field is optional. + */ + bool mOptional = false; + + /** + * Optional tag to match during parsing. + */ + Optional mTag; +}; + +/** + * Interface for decoding ASN.1 structures. + */ +class ASN1DecoderItf { +public: + /** + * Destructor. + */ + virtual ~ASN1DecoderItf() = default; + + /** + * Discards an ASN.1 tag-length and invokes reader for its content. + * + * @param data input data buffer. + * @param opt parse options. + * @param asn1reader reader handles content of the structure. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadStruct( + const Array& data, const ASN1ParseOptions& opt, ASN1ReaderItf& asn1reader) + = 0; + + /** + * Reads an ASN.1 SET and invokes the reader for each element. + * + * @param data input data buffer. + * @param opt parse options. + * @param asn1reader reader callback to handle each element. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadSet(const Array& data, const ASN1ParseOptions& opt, ASN1ReaderItf& asn1reader) + = 0; + + /** + * Reads an ASN.1 SEQUENCE and invokes the reader for each element. + * + * @param data input data buffer. + * @param opt parse options. + * @param asn1reader reader callback to handle each element. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadSequence( + const Array& data, const ASN1ParseOptions& opt, ASN1ReaderItf& asn1reader) + = 0; + + /** + * Reads an ASN.1 INTEGER value. + * + * @param data input data buffer. + * @param opt parse options. + * @param[out] value result integer. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadInteger(const Array& data, const ASN1ParseOptions& opt, int& value) = 0; + + /** + * Reads a large ASN.1 INTEGER (BigInt) as a byte array. + * + * @param data input data buffer. + * @param opt parse options. + * @param[out] result result integer bytes. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadBigInt(const Array& data, const ASN1ParseOptions& opt, Array& result) + = 0; + + /** + * Reads an ASN.1 Object Identifier (OID). + * + * @param data input data buffer. + * @param opt parse options. + * @param[out] oid result OID. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadOID(const Array& data, const ASN1ParseOptions& opt, ObjectIdentifier& oid) = 0; + + /** + * Reads an ASN.1 AlgorithmIdentifier(AID). + * + * @param data input data buffer. + * @param opt parse options. + * @param[out] aid result AID. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadAID(const Array& data, const ASN1ParseOptions& opt, AlgorithmIdentifier& aid) + = 0; + + /** + * Reads an ASN.1 OCTET STRING. + * + * @param data input data buffer. + * @param opt parse options. + * @param[out] result result octet string. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadOctetString( + const Array& data, const ASN1ParseOptions& opt, Array& result) + = 0; + + /** + * Returns a raw ASN.1 value. + * + * @param data input data buffer. + * @param opt parse options. + * @param[out] result parsed ASN1 value. + * @return ASN1ParseResult. + */ + virtual ASN1ParseResult ReadRawValue(const Array& data, const ASN1ParseOptions& opt, ASN1Value& result) + = 0; +}; + +} // namespace aos::crypto::asn1 + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_ASN1_HPP_ diff --git a/src/core/common/crypto/itf/certloader.hpp b/src/core/common/crypto/itf/certloader.hpp new file mode 100644 index 000000000..c60720e17 --- /dev/null +++ b/src/core/common/crypto/itf/certloader.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_CERTLOADER_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_CERTLOADER_HPP_ + +#include "x509.hpp" + +namespace aos::crypto { + +/** + * Loads certificates and keys interface. + */ +class CertLoaderItf { +public: + /** + * Loads certificate chain by URL. + * + * @param url input url. + * @return RetWithError>. + */ + virtual RetWithError> LoadCertsChainByURL(const String& url) = 0; + + /** + * Loads private key by URL. + * + * @param url input url. + * @return RetWithError>. + */ + virtual RetWithError> LoadPrivKeyByURL(const String& url) = 0; + + /** + * Destroys cert loader instance. + */ + virtual ~CertLoaderItf() = default; +}; + +/** + * Parses scheme part of URL. + * + * @param url input url. + * @param[out] scheme url scheme. + * @return Error. + */ +Error ParseURLScheme(const String& url, String& scheme); + +/** + * Parses URL with file scheme. + * + * @param url input url. + * @param[out] path file path. + * @return Error. + */ +Error ParseFileURL(const String& url, String& path); + +/** + * Encodes PKCS11 ID to percent-encoded string. + * + * @param id PKCS11 ID. + * @param idStr percent-encoded string. + * @return Error. + */ +Error EncodePKCS11ID(const Array& id, String& idStr); + +/** + * Decodes PKCS11 ID from percent-encoded string. + * + * @param idStr percent-encoded string. + * @param id PKCS11 ID. + * @return Error. + */ +Error DecodeToPKCS11ID(const String& idStr, Array& id); + +/** + * Parses url with PKCS11 scheme. + * + * @param url input url. + * @param[out] library PKCS11 library. + * @param[out] token token label. + * @param[out] label certificate label. + * @param[out] id certificate id. + * @param[out] userPin user PIN. + * @return Error. + */ +Error ParsePKCS11URL( + const String& url, String& library, String& token, String& label, Array& id, String& userPin); + +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_CERTLOADER_HPP_ diff --git a/src/core/common/crypto/itf/crypto.hpp b/src/core/common/crypto/itf/crypto.hpp new file mode 100644 index 000000000..47e1fd179 --- /dev/null +++ b/src/core/common/crypto/itf/crypto.hpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 Renesas Electronics Corporation. + * Copyright (C) 2023 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_CRYPTO_HPP_ +#define AOS_CORE_COMMON_CRYPTO_CRYPTO_HPP_ + +#include "aes.hpp" +#include "asn1.hpp" +#include "hash.hpp" +#include "rand.hpp" +#include "uuid.hpp" +#include "x509.hpp" + +namespace aos::crypto { + +/** + * Crypto provider interface. + */ +class CryptoProviderItf : public x509::ProviderItf, + public HasherItf, + public RandomItf, + public UUIDItf, + public AESEncoderDecoderItf, + public asn1::ASN1DecoderItf { +public: + /** + * Destructor. + */ + virtual ~CryptoProviderItf() = default; +}; + +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_CRYPTO_HPP_ diff --git a/src/core/common/crypto/itf/cryptohelper.hpp b/src/core/common/crypto/itf/cryptohelper.hpp new file mode 100644 index 000000000..eeeb7c627 --- /dev/null +++ b/src/core/common/crypto/itf/cryptohelper.hpp @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_CRYPTOHELPER_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_CRYPTOHELPER_HPP_ + +#include + +namespace aos::crypto { + +/** + * Number of recipient info in envelope data. + */ +constexpr auto cRecipientsInEnvelopeData = AOS_CONFIG_CRYPTO_RECIPIENTS_IN_ENVELOPEDATA; + +/** + * Maximum size for cloud metadata. + */ +constexpr auto cCloudMetadataSize = AOS_CONFIG_CRYPTO_ENCRYPT_METADATA; + +/** + * Certificate fingerprint len. + */ +constexpr auto cCertFingerprintLen = AOS_CONFIG_CRYPTO_CERT_FINGERPRINT_LEN; + +/** + * Chain name len. + */ +constexpr auto cChainNameLen = AOS_CONFIG_CRYPTO_CHAIN_NAME_LEN; + +/** + * Algorithm len. + */ +constexpr auto cAlgLen = AOS_CONFIG_CRYPTO_ALG_LEN; + +/** + * IV size. + */ +constexpr auto cIVSize = AOS_CONFIG_CRYPTO_IV_SIZE; + +/** + * Key size. + */ +constexpr auto cKeySize = AOS_CONFIG_CRYPTO_KEY_SIZE; + +/** + * OCSP value len. + */ +constexpr auto cOCSPValueLen = AOS_CONFIG_CRYPTO_OCSP_VALUE_LEN; + +/** + * OCSP values count. + */ +constexpr auto cOCSPValuesCount = AOS_CONFIG_CRYPTO_OCSP_VALUES_COUNT; + +/** + * Certificate info. + */ +struct CertificateInfo { + StaticArray mCertificate; + StaticString mFingerprint; + + /** + * Compares certificate info. + * + * @param rhs certificate info to compare with. + * @return bool. + */ + bool operator==(const CertificateInfo& rhs) const + { + return mCertificate == rhs.mCertificate && mFingerprint == rhs.mFingerprint; + } + + /** + * Compares certificate info. + * + * @param rhs certificate info to compare with. + * @return bool. + */ + bool operator!=(const CertificateInfo& rhs) const { return !operator==(rhs); } +}; + +using CertificateInfoArray = StaticArray; + +/** + * Certificate chain info. + */ +struct CertificateChainInfo { + StaticString mName; + StaticArray, crypto::cCertChainSize> mFingerprints; + + /** + * Compares certificate chain info. + * + * @param rhs certificate chain info to compare with. + * @return bool. + */ + bool operator==(const CertificateChainInfo& rhs) const + { + return mName == rhs.mName && mFingerprints == rhs.mFingerprints; + } + + /** + * Compares certificate chain info. + * + * @param rhs certificate chain info to compare with. + * @return bool. + */ + bool operator!=(const CertificateChainInfo& rhs) const { return !operator==(rhs); } +}; + +using CertificateChainInfoArray = StaticArray; + +/** + * Decryption info. + */ +struct DecryptInfo { + StaticString mBlockAlg; + StaticArray mBlockIV; + StaticArray mBlockKey; + + /** + * Compares decryption info. + * + * @param rhs decryption info to compare with. + * @return bool. + */ + bool operator==(const DecryptInfo& rhs) const + { + return mBlockAlg == rhs.mBlockAlg && mBlockIV == rhs.mBlockIV && mBlockKey == rhs.mBlockKey; + } + + /** + * Compares decryption info. + * + * @param rhs decryption info to compare with. + * @return bool. + */ + bool operator!=(const DecryptInfo& rhs) const { return !operator==(rhs); } +}; + +/** + * Sign info. + */ +struct SignInfo { + StaticString mChainName; + StaticString mAlg; + StaticArray mValue; + Time mTrustedTimestamp {}; + StaticArray, cOCSPValuesCount> mOCSPValues; + /** + * Compares sign info. + * + * @param rhs sign info to compare with. + * @return bool. + */ + bool operator==(const SignInfo& rhs) const + { + return mChainName == rhs.mChainName && mAlg == rhs.mAlg && mValue == rhs.mValue + && mTrustedTimestamp == rhs.mTrustedTimestamp && mOCSPValues == rhs.mOCSPValues; + } + + /** + * Compares sign info. + * + * @param rhs sign info to compare with. + * @return bool. + */ + bool operator!=(const SignInfo& rhs) const { return !operator==(rhs); } +}; + +/** + * CryptoHelper interface for decrypting and validating cloud data. + */ +class CryptoHelperItf { +public: + /** + * Destructor. + */ + virtual ~CryptoHelperItf() = default; + + /** + * Decrypts a file using provided decryption information. + * + * @param encryptedPath path to the encrypted file. + * @param decryptedPath path where the decrypted file will be written. + * @param decryptionInfo decryption information. + * @return Error. + */ + virtual Error Decrypt(const String& encryptedPath, const String& decryptedPath, const DecryptInfo& decryptionInfo) + = 0; + + /** + * Validates digital signatures of a decrypted file against provided certificates and chains. + * + * @param decryptedPath path to the decrypted file to validate. + * @param signs signature information. + * @param chains certificate chains for validation. + * @param certs certificates used for validation. + * @return Error. + */ + virtual Error ValidateSigns(const String& decryptedPath, const SignInfo& signs, + const Array& chains, const Array& certs) + = 0; + + /** + * Decrypts metadata containing in a binary buffer. + * + * @param[in] input encrypted metadata buffer. + * @param[out] output buffer where the decrypted metadata will be stored. + * @return Error. + */ + virtual Error DecryptMetadata(const Array& input, Array& output) = 0; +}; + +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_CRYPTOHELPER_HPP_ diff --git a/src/core/common/crypto/itf/hash.hpp b/src/core/common/crypto/itf/hash.hpp new file mode 100644 index 000000000..9aea3bb88 --- /dev/null +++ b/src/core/common/crypto/itf/hash.hpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_HASH_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_HASH_HPP_ + +#include +#include +#include + +namespace aos::crypto { + +/** + * Maximum size of SHA2 digest. + */ +constexpr auto cSHA2DigestSize = AOS_CONFIG_CRYPTO_SHA2_DIGEST_SIZE; + +/** + * Maximum size of SHA1 digest. + */ +constexpr auto cSHA1DigestSize = AOS_CONFIG_CRYPTO_SHA1_DIGEST_SIZE; + +/** + * Maximum size of input data for SHA1 hash calculation. + */ +constexpr auto cSHA1InputDataSize = AOS_CONFIG_CRYPTO_SHA1_INPUT_SIZE; + +/** + * SHA256 size. + */ +constexpr auto cSHA256Size = 32; + +/** + * SHA384 size. + */ +constexpr auto cSHA384Size = 48; + +/** + * SHA3-224 size. + */ +constexpr auto cSHA3_224Size = 28; + +/** + * Supported hash functions. + */ +class HashType { +public: + enum class Enum { + eSHA1, + eSHA224, + eSHA256, + eSHA384, + eSHA512, + eSHA512_224, + eSHA512_256, + eSHA3_224, + eSHA3_256, + eNone, + }; + + static const Array GetStrings() + { + static const char* const sContentTypeStrings[] = { + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA512-224", + "SHA512-256", + "SHA3-224", + "SHA3-256", + "NONE", + }; + return Array(sContentTypeStrings, ArraySize(sContentTypeStrings)); + }; +}; + +using HashEnum = HashType::Enum; +using Hash = EnumStringer; + +/** + * Hash interface. + */ +class HashItf { +public: + /** + * Updates hash with input data. + * + * @param data input data. + * @return Error. + */ + virtual Error Update(const Array& data) = 0; + + /** + * Finalizes hash calculation. + * + * @param[out] hash result hash. + * @return Error. + */ + virtual Error Finalize(Array& hash) = 0; + + /** + * Destructor. + */ + virtual ~HashItf() = default; +}; + +/** + * Hasher interface. + */ +class HasherItf { +public: + /** + * Creates hash instance. + * + * @param algorithm hash algorithm. + * @return RetWithError>. + */ + virtual RetWithError> CreateHash(Hash algorithm) = 0; + + /** + * Destructor. + */ + virtual ~HasherItf() = default; +}; + +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_HASH_HPP_ diff --git a/src/core/common/crypto/itf/privkey.hpp b/src/core/common/crypto/itf/privkey.hpp new file mode 100644 index 000000000..ab3835aac --- /dev/null +++ b/src/core/common/crypto/itf/privkey.hpp @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_PRIVKEY_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_PRIVKEY_HPP_ + +#include +#include +#include +#include + +#include "hash.hpp" + +namespace aos::crypto { + +/** + * RSA modulus size. + */ +constexpr auto cRSAModulusSize = AOS_CONFIG_CRYPTO_RSA_MODULUS_SIZE; + +/** + * Size of RSA public exponent. + */ +constexpr auto cRSAPubExponentSize = AOS_CONFIG_CRYPTO_RSA_PUB_EXPONENT_SIZE; + +/** + * ECDSA params OID size. + */ +constexpr auto cECDSAParamsOIDSize = AOS_CONFIG_CRYPTO_ECDSA_PARAMS_OID_SIZE; + +/** + * DER-encoded X9.62 ECPoint. + */ +constexpr auto cECDSAPointDERSize = AOS_CONFIG_CRYPTO_ECDSA_POINT_DER_SIZE; + +/** + * Supported key types. + */ +class KeyAlgorithm { +public: + enum class Enum { eRSA, eECDSA }; + + static const Array GetStrings() + { + static const char* const sContentTypeStrings[] = {"RSA", "ECDSA"}; + return Array(sContentTypeStrings, ArraySize(sContentTypeStrings)); + }; +}; + +using KeyTypeEnum = KeyAlgorithm::Enum; +using KeyType = EnumStringer; + +/** + * Options being used while signing. + */ +struct SignOptions { + /** + * Hash function to be used when signing. + */ + Hash mHash; +}; + +/** + * PKCS1v15 decryption options. + */ +struct PKCS1v15DecryptionOptions { + int mKeySize = 0; +}; + +/** + * OAEP decryption options. + */ +struct OAEPDecryptionOptions { + Hash mHash; +}; + +/** + * Decryption options. + */ +using DecryptionOptions = Variant; + +/** + * Public key interface. + */ +class PublicKeyItf { +public: + /** + * Returns type of a public key. + * + * @return KeyType, + */ + virtual KeyType GetKeyType() const = 0; + + /** + * Tests whether current key is equal to the provided one. + * + * @param pubKey public key. + * @return bool. + */ + virtual bool IsEqual(const PublicKeyItf& pubKey) const = 0; + + /** + * Destroys object instance. + */ + virtual ~PublicKeyItf() = default; +}; + +/** + * Private key interface. + */ +class PrivateKeyItf { +public: + /** + * Returns public part of a private key. + * + * @return const PublicKeyItf&. + */ + virtual const PublicKeyItf& GetPublic() const = 0; + + /** + * Calculates a signature of a given digest. + * + * @param digest input hash digest. + * @param options signing options. + * @param[out] signature result signature. + * @return Error. + */ + virtual Error Sign(const Array& digest, const SignOptions& options, Array& signature) const = 0; + + /** + * Decrypts a cipher message. + * + * @param cipher encrypted message. + * @param options decryption options. + * @param[out] result decoded message. + * @return Error. + */ + virtual Error Decrypt(const Array& cipher, const DecryptionOptions& options, Array& result) const + = 0; + + /** + * Destroys object instance. + */ + virtual ~PrivateKeyItf() = default; +}; + +/** + * RSA public key. + */ +class RSAPublicKey : public PublicKeyItf { +public: + /** + * Constructs object instance. + * + * @param n modulus. + * @param e public exponent. + */ + RSAPublicKey(const Array& n, const Array& e) + : mN(n) + , mE(e) + { + } + + /** + * Returns type of a public key. + * + * @return KeyType, + */ + KeyType GetKeyType() const override { return KeyTypeEnum::eRSA; } + + /** + * Tests whether current key is equal to the provided one. + * + * @param pubKey public key. + * @return bool. + */ + bool IsEqual(const PublicKeyItf& pubKey) const override + { + if (pubKey.GetKeyType() != KeyTypeEnum::eRSA) { + return false; + } + + const auto& otherKey = static_cast(pubKey); + + return otherKey.mN == mN && otherKey.mE == mE; + } + + /** + * Returns RSA public modulus. + * + * @return const Array&. + */ + const Array& GetN() const { return mN; } + + /** + * Returns RSA public exponent. + * + * @return const Array&. + */ + const Array& GetE() const { return mE; } + +private: + StaticArray mN; + StaticArray mE; +}; + +/** + * ECDSA public key. + */ +class ECDSAPublicKey : public PublicKeyItf { +public: + /** + * Constructs object instance. + * + * @param n modulus. + * @param e public exponent. + */ + ECDSAPublicKey(const Array& params, const Array& point) + : mECParamsOID(params) + , mECPoint(point) + { + } + + /** + * Returns type of a public key. + * + * @return KeyType, + */ + KeyType GetKeyType() const override { return KeyTypeEnum::eECDSA; } + + /** + * Tests whether current key is equal to the provided one. + * + * @param pubKey public key. + * @return bool. + */ + bool IsEqual(const PublicKeyItf& pubKey) const override + { + if (pubKey.GetKeyType() != KeyTypeEnum::eECDSA) { + return false; + } + + const auto& otherKey = static_cast(pubKey); + + return otherKey.mECParamsOID == mECParamsOID && otherKey.mECPoint == mECPoint; + } + + /** + * Returns ECDSA params OID. + * + * @return const Array&. + */ + const Array& GetECParamsOID() const { return mECParamsOID; } + + /** + * Returns ECDSA point. + * + * @return const Array&. + */ + const Array& GetECPoint() const { return mECPoint; } + +private: + StaticArray mECParamsOID; + StaticArray mECPoint; +}; + +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_PRIVKEY_HPP_ diff --git a/src/core/common/crypto/itf/rand.hpp b/src/core/common/crypto/itf/rand.hpp new file mode 100644 index 000000000..4af37de53 --- /dev/null +++ b/src/core/common/crypto/itf/rand.hpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_RAND_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_RAND_HPP_ + +#include +#include + +namespace aos::crypto { + +/** + * Random generator interface. + */ +class RandomItf { +public: + /** + * Generates random integer value in range [0..maxValue]. + * + * @param maxValue maximum value. + * @return RetWithError. + */ + virtual RetWithError RandInt(uint64_t maxValue) = 0; + + /** + * Generates random buffer. + * + * @param[out] buffer result buffer. + * @param size buffer size. + * @return Error. + */ + virtual Error RandBuffer(Array& buffer, size_t size = 0) = 0; + + /** + * Destructor. + */ + virtual ~RandomItf() = default; +}; + +/** + * Generates random string. + * + * @param result result string. + * @param random random interface. + * @return Error. + */ +template +Error GenerateRandomString(String& result, RandomItf& random) +{ + StaticArray buffer; + + if (auto err = random.RandBuffer(buffer, size); !err.IsNone()) { + return err; + } + + return result.ByteArrayToHex(buffer); +} + +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_RAND_HPP_ diff --git a/src/core/common/crypto/itf/uuid.hpp b/src/core/common/crypto/itf/uuid.hpp new file mode 100644 index 000000000..dfe0ec658 --- /dev/null +++ b/src/core/common/crypto/itf/uuid.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_UUID_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_UUID_HPP_ + +#include + +namespace aos::crypto { + +/*** + * UUID generator interface. + */ +class UUIDItf { +public: + /** + * Creates UUID v4. + * + * @return RetWithError. + */ + virtual RetWithError CreateUUIDv4() = 0; + + /** + * Creates UUID version 5 based on a given namespace identifier and name. + * + * @param space namespace identifier. + * @param name name. + * @result RetWithError. + */ + virtual RetWithError CreateUUIDv5(const uuid::UUID& space, const Array& name) = 0; + + /** + * Destructor. + */ + virtual ~UUIDItf() = default; +}; + +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_UUID_HPP_ diff --git a/src/core/common/crypto/itf/x509.hpp b/src/core/common/crypto/itf/x509.hpp new file mode 100644 index 000000000..36aa052e4 --- /dev/null +++ b/src/core/common/crypto/itf/x509.hpp @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_ITF_X509_HPP_ +#define AOS_CORE_COMMON_CRYPTO_ITF_X509_HPP_ + +#include +#include +#include +#include + +#include "asn1.hpp" +#include "privkey.hpp" + +namespace aos::crypto { +/** + * Certificate issuer name max length. + */ +constexpr auto cCertIssuerSize = AOS_CONFIG_CRYPTO_CERT_ISSUER_SIZE; + +/** + * Max length of a DNS name. + */ +constexpr auto cDNSNameLen = AOS_CONFIG_CRYPTO_DNS_NAME_LEN; + +/** + * Max number of alternative names for a module. + */ +constexpr auto cAltDNSNamesCount = AOS_CONFIG_CRYPTO_ALT_DNS_NAMES_MAX_COUNT; + +/** + * Certificate subject size. + */ +constexpr auto cCertSubjSize = AOS_CONFIG_CRYPTO_CERT_ISSUER_SIZE; + +/** + * Maximum length of distinguished name string representation. + */ +constexpr auto cCertDNStringSize = AOS_CONFIG_CRYPTO_DN_STRING_SIZE; + +/** + * Certificate extra extensions max number. + */ +constexpr auto cCertExtraExtCount = AOS_CONFIG_CRYPTO_EXTRA_EXTENSIONS_COUNT; + +/** + * Maximum certificate key id size(in bytes). + */ +constexpr auto cCertKeyIdSize = AOS_CONFIG_CRYPTO_CERT_KEY_ID_SIZE; + +/** + * Maximum length of a PEM certificate. + */ +constexpr auto cCertPEMLen = AOS_CONFIG_CRYPTO_CERT_PEM_LEN; + +/** + * Maximum size of a DER certificate. + */ +constexpr auto cCertDERSize = AOS_CONFIG_CRYPTO_CERT_DER_SIZE; + +/** + * Maximum length of CSR in PEM format. + */ +constexpr auto cCSRPEMLen = AOS_CONFIG_CRYPTO_CSR_PEM_LEN; + +/** + * Maximum length of private key in PEM format. + */ +constexpr auto cPrivKeyPEMLen = AOS_CONFIG_CRYPTO_PRIVKEY_PEM_LEN; + +/** + * Serial number size(in bytes). + */ +constexpr auto cSerialNumSize = AOS_CONFIG_CRYPTO_SERIAL_NUM_SIZE; + +/** + * Length of serial number in string representation. + */ +constexpr auto cSerialNumStrLen = cSerialNumSize * 2; + +/** + * Maximum size of serial number encoded in DER format. + */ +constexpr auto cSerialNumDERSize = AOS_CONFIG_CRYPTO_SERIAL_NUM_DER_SIZE; + +/** + * Subject common name length. + */ +constexpr auto cSubjectCommonNameLen = AOS_CONFIG_CRYPTO_SUBJECT_COMMON_NAME_LEN; + +/** + * Max expected number of certificates in a chain stored in PEM file. + */ +constexpr auto cCertChainSize = AOS_CONFIG_CRYPTO_CERTS_CHAIN_SIZE; + +/** + * Number of certificate chains to be stored in crypto::CertLoader. + */ +constexpr auto cCertChainsCount = AOS_CONFIG_CRYPTO_CERTIFICATE_CHAINS_COUNT; + +/** + * PEM certificate chain length. + */ +constexpr auto cCertChainPEMLen = cCertChainSize * cCertPEMLen; + +/** + * Maximum signature size. + */ +constexpr auto cSignatureSize = AOS_CONFIG_CRYPTO_SIGNATURE_SIZE; + +/** + * Max number of certificates. + */ +constexpr auto cMaxNumCertificates = AOS_CONFIG_CRYPTO_MAX_NUM_CERTIFICATES; + +namespace x509 { + +/** + * Padding type. + */ +class PaddingType { +public: + enum class Enum { ePKCS1v1_5, ePSS, eNone }; + + static const Array GetStrings() + { + static const char* const sContentTypeStrings[] = {"PKCS1v1_5", "PSS", "Node"}; + return Array(sContentTypeStrings, ArraySize(sContentTypeStrings)); + }; +}; + +using PaddingEnum = PaddingType::Enum; +using Padding = EnumStringer; + +/** + * Verify options. + */ +struct VerifyOptions { + Time mCurrentTime; +}; + +/** + * x509 Certificate. + */ +struct Certificate { + /** + * DER encoded certificate subject. + */ + StaticArray mSubject; + /** + * Certificate subject key id. + */ + StaticArray mSubjectKeyId; + /** + * Certificate authority key id. + */ + StaticArray mAuthorityKeyId; + /** + * DER encoded certificate subject issuer. + */ + StaticArray mIssuer; + /** + * Certificate serial number. + */ + StaticArray mSerial; + /** + * Issuer URLs. + */ + StaticArray, cMaxNumURLs> mIssuerURLs; + /** + * Certificate validity period. + */ + Time mNotBefore, mNotAfter; + /** + * Public key. + */ + Variant mPublicKey; + /** + * Complete ASN.1 DER content (certificate, signature algorithm and signature). + */ + StaticArray mRaw; +}; + +/** + * x509 Certificate request. + */ +struct CSR { + /** + * Certificate subject size. + */ + StaticArray mSubject; + /** + * Alternative DNS names. + */ + StaticArray, cAltDNSNamesCount> mDNSNames; + /** + * Contains extra extensions applied to CSR. + */ + StaticArray mExtraExtensions; +}; + +/** + * Provides interface to manage certificate requests. + */ +class ProviderItf { +public: + /** + * Creates a new certificate based on a template. + * + * @param templ a pattern for a new certificate. + * @param parent a parent certificate in a certificate chain. + * @param pubKey public key. + * @param privKey private key. + * @param[out] pemCert result certificate in PEM format. + * @result Error. + */ + virtual Error CreateCertificate( + const Certificate& templ, const Certificate& parent, const PrivateKeyItf& privKey, String& pemCert) + = 0; + + /** + * Creates certificate chain using client CSR & CA key/certificate as input. + * + * @param pemCSR client certificate request. + * @param pemCAKey CA private key in PEM. + * @param pemCACert CA certificate in PEM. + * @param serial serial number of certificate. + * @param[out] pemClientCert result certificate. + * @result Error. + */ + virtual Error CreateClientCert( + const String& csr, const String& caKey, const String& caCert, const Array& serial, String& clientCert) + = 0; + + /** + * Reads certificates from a PEM blob. + * + * @param pemBlob raw certificates in a PEM format. + * @param[out] resultCerts result certificate chain. + * @result Error. + */ + virtual Error PEMToX509Certs(const String& pemBlob, Array& resultCerts) = 0; + + /** + * Serializes input certificate object into a PEM blob. + * + * @param certificate input certificate object. + * @param[out] dst destination buffer. + * @result Error. + */ + virtual Error X509CertToPEM(const Certificate& certificate, String& dst) = 0; + + /** + * Reads private key from a PEM blob. + * + * @param pemBlob raw certificates in a PEM format. + * @result RetWithError>. + */ + virtual RetWithError> PEMToX509PrivKey(const String& pemBlob) = 0; + + /** + * Reads certificate from a DER blob. + * + * @param derBlob raw certificate in a DER format. + * @param[out] resultCert result certificate. + * @result Error. + */ + virtual Error DERToX509Cert(const Array& derBlob, Certificate& resultCert) = 0; + + /** + * Creates a new certificate request, based on a template. + * + * @param templ template for a new certificate request. + * @param privKey private key. + * @param[out] pemCSR result CSR in PEM format. + * @result Error. + */ + virtual Error CreateCSR(const CSR& templ, const PrivateKeyItf& privKey, String& pemCSR) = 0; + + /** + * Constructs x509 distinguished name(DN) from the argument list. + * + * @param comName common name. + * @param[out] result result DN. + * @result Error. + */ + virtual Error ASN1EncodeDN(const String& commonName, Array& result) = 0; + + /** + * Returns text representation of x509 distinguished name(DN). + * + * @param dn source binary representation of DN. + * @param[out] result DN text representation. + * @result Error. + */ + virtual Error ASN1DecodeDN(const Array& dn, String& result) = 0; + + /** + * Encodes array of object identifiers into ASN1 value. + * + * @param src array of object identifiers. + * @param asn1Value result ASN1 value. + */ + virtual Error ASN1EncodeObjectIds(const Array& src, Array& asn1Value) = 0; + + /** + * Encodes big integer in ASN1 format. + * + * @param number big integer. + * @param[out] asn1Value result ASN1 value. + * @result Error. + */ + virtual Error ASN1EncodeBigInt(const Array& number, Array& asn1Value) = 0; + + /** + * Creates ASN1 sequence from already encoded DER items. + * + * @param items DER encoded items. + * @param[out] asn1Value result ASN1 value. + * @result Error. + */ + virtual Error ASN1EncodeDERSequence(const Array>& items, Array& asn1Value) = 0; + + /** + * Returns value of the input ASN1 OCTETSTRING. + * + * @param src DER encoded OCTETSTRING value. + * @param[out] dst decoded value. + * @result Error. + */ + virtual Error ASN1DecodeOctetString(const Array& src, Array& dst) = 0; + + /** + * Decodes input ASN1 OID value. + * + * @param inOID input ASN1 OID value. + * @param[out] dst decoded value. + * @result Error. + */ + virtual Error ASN1DecodeOID(const Array& inOID, Array& dst) = 0; + + /** + * Verifies a digital signature using the provided public key and digest. + * + * @param pubKey public key. + * @param hashFunc hash function that was used to produce the digest. + * @param padding padding type. + * @param digest message digest to verify. + * @param signature signature to verify against the digest. + * @return Error. + */ + virtual Error Verify(const Variant& pubKey, Hash hashFunc, Padding padding, + const Array& digest, const Array& signature) + = 0; + + /** + * Verifies the certificate against a chain of intermediate and root certificates. + * + * @param rootCerts trusted root certificates. + * @param intermCerts intermediate certificate chain used to build the path to a trusted root. + * @param options verify options. + * @param cert certificate to verify. + * @return Error. + */ + virtual Error Verify(const Array& rootCerts, const Array& intermCerts, + const VerifyOptions& options, const Certificate& cert) + = 0; + + /** + * Destroys object instance. + */ + virtual ~ProviderItf() = default; +}; + +/** + * A chain of certificates. + */ +using CertificateChain = StaticArray; + +} // namespace x509 +} // namespace aos::crypto + +#endif // AOS_CORE_COMMON_CRYPTO_ITF_X509_HPP_ From 0cf6565148aa64942f10ff97310e5bc8955977f9 Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Tue, 7 Oct 2025 16:23:33 +0300 Subject: [PATCH 3/8] crypto: rename crypto.cpp to asn1.cpp Signed-off-by: Mykola Kobets Reviewed-by: Mykhailo Lohvynenko Reviewed-by: Oleksandr Grytsov Reviewed-by: Mykola Solianko --- src/core/common/crypto/{crypto.cpp => asn1.cpp} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/core/common/crypto/{crypto.cpp => asn1.cpp} (97%) diff --git a/src/core/common/crypto/crypto.cpp b/src/core/common/crypto/asn1.cpp similarity index 97% rename from src/core/common/crypto/crypto.cpp rename to src/core/common/crypto/asn1.cpp index 59d9b409f..3e3aab2b9 100644 --- a/src/core/common/crypto/crypto.cpp +++ b/src/core/common/crypto/asn1.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "crypto.hpp" +#include "itf/asn1.hpp" namespace aos::crypto::asn1 { From 87586f5e17c1dc716b903398bc8c9b90aa83f2c0 Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Tue, 7 Oct 2025 16:23:57 +0300 Subject: [PATCH 4/8] crypto: rename cryptoutils to certloader Signed-off-by: Mykola Kobets Reviewed-by: Mykhailo Lohvynenko Reviewed-by: Oleksandr Grytsov Reviewed-by: Mykola Solianko --- .../{cryptoutils.cpp => certloader.cpp} | 16 +- src/core/common/crypto/certloader.hpp | 76 ++++++++ src/core/common/crypto/cryptoutils.hpp | 173 ------------------ 3 files changed, 84 insertions(+), 181 deletions(-) rename src/core/common/crypto/{cryptoutils.cpp => certloader.cpp} (94%) create mode 100644 src/core/common/crypto/certloader.hpp delete mode 100644 src/core/common/crypto/cryptoutils.hpp diff --git a/src/core/common/crypto/cryptoutils.cpp b/src/core/common/crypto/certloader.cpp similarity index 94% rename from src/core/common/crypto/cryptoutils.cpp rename to src/core/common/crypto/certloader.cpp index dea836d32..d2cbf2627 100644 --- a/src/core/common/crypto/cryptoutils.cpp +++ b/src/core/common/crypto/certloader.cpp @@ -8,7 +8,7 @@ #include #include -#include "cryptoutils.hpp" +#include "certloader.hpp" namespace aos::crypto { @@ -24,7 +24,7 @@ constexpr auto cSchemeMaxLength = Max(sizeof(cSchemeFile), sizeof(cSchemePKCS11) * CertLoader **********************************************************************************************************************/ -Error CertLoader::Init(crypto::x509::ProviderItf& cryptoProvider, pkcs11::PKCS11Manager& pkcs11Manager) +Error CertLoader::Init(x509::ProviderItf& cryptoProvider, pkcs11::PKCS11Manager& pkcs11Manager) { LOG_DBG() << "Init cert loader"; @@ -34,7 +34,7 @@ Error CertLoader::Init(crypto::x509::ProviderItf& cryptoProvider, pkcs11::PKCS11 return ErrorEnum::eNone; } -RetWithError> CertLoader::LoadCertsChainByURL(const String& url) +RetWithError> CertLoader::LoadCertsChainByURL(const String& url) { LOG_DBG() << "Load certs chain by URL: url=" << url; @@ -79,7 +79,7 @@ RetWithError> CertLoader::LoadCertsCha return {nullptr, ErrorEnum::eInvalidArgument}; } -RetWithError> CertLoader::LoadPrivKeyByURL(const String& url) +RetWithError> CertLoader::LoadPrivKeyByURL(const String& url) { LOG_DBG() << "Load private key by URL: url=" << url; @@ -186,7 +186,7 @@ RetWithError CertLoader::FindToken(const pkcs11::LibraryContext& return {0, ErrorEnum::eNotFound}; } -RetWithError> CertLoader::LoadCertsFromFile(const String& fileName) +RetWithError> CertLoader::LoadCertsFromFile(const String& fileName) { LOG_DBG() << "Load certs chain from file: fileName=" << fileName; @@ -197,18 +197,18 @@ RetWithError> CertLoader::LoadCertsFro return {nullptr, err}; } - auto certificates = MakeShared(&mAllocator); + auto certificates = MakeShared(&mAllocator); err = mCryptoProvider->PEMToX509Certs(*buff, *certificates); return {certificates, err}; } -RetWithError> CertLoader::LoadPrivKeyFromFile(const String& fileName) +RetWithError> CertLoader::LoadPrivKeyFromFile(const String& fileName) { LOG_DBG() << "Load private key from file: fileName=" << fileName; - auto buff = MakeUnique>(&mAllocator); + auto buff = MakeUnique>(&mAllocator); auto err = fs::ReadFileToString(fileName, *buff); if (!err.IsNone()) { diff --git a/src/core/common/crypto/certloader.hpp b/src/core/common/crypto/certloader.hpp new file mode 100644 index 000000000..efdbf3989 --- /dev/null +++ b/src/core/common/crypto/certloader.hpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023 Renesas Electronics Corporation. + * Copyright (C) 2023 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CORE_COMMON_CRYPTO_CRYPTOUTILS_HPP_ +#define AOS_CORE_COMMON_CRYPTO_CRYPTOUTILS_HPP_ + +#include +#include + +#include "itf/certoloader.hpp" +#include "itf/crypto.hpp" + +namespace aos::crypto { + +/** + * Loads certificates and keys by URL. + */ +class CertLoader : public CertLoaderItf { +public: + /** + * Initializes object instance. + * + * @param cryptoProvider crypto provider interface. + * @param pkcs11Manager PKCS11 library manager. + * @return Error. + */ + Error Init(x509::ProviderItf& cryptoProvider, pkcs11::PKCS11Manager& pkcs11Manager); + + /** + * Loads certificate chain by URL. + * + * @param url input url. + * @return RetWithError>. + */ + RetWithError> LoadCertsChainByURL(const String& url) override; + + /** + * Loads private key by URL. + * + * @param url input url. + * @return RetWithError>. + */ + RetWithError> LoadPrivKeyByURL(const String& url) override; + +private: + using PEMCertChainBlob = StaticString; + + static constexpr auto cCertAllocatorSize + = cCertChainsCount * cCertChainSize * sizeof(x509::Certificate) + sizeof(PEMCertChainBlob); + static constexpr auto cKeyAllocatorSize + = AOS_CONFIG_CRYPTO_PRIV_KEYS_COUNT * pkcs11::cPrivateKeyMaxSize + sizeof(cPrivKeyPEMLen); + static constexpr auto cNumAllocation = AOS_CONFIG_CRYPTO_NUM_ALLOCATIONS; + + static constexpr auto cDefaultPKCS11Library = AOS_CONFIG_CRYPTO_DEFAULT_PKCS11_LIB; + + RetWithError> OpenSession( + const String& libraryPath, const String& token, const String& userPIN); + RetWithError FindToken(const pkcs11::LibraryContext& library, const String& token); + + RetWithError> LoadCertsFromFile(const String& fileName); + RetWithError> LoadPrivKeyFromFile(const String& fileName); + + x509::ProviderItf* mCryptoProvider = nullptr; + pkcs11::PKCS11Manager* mPKCS11 = nullptr; + + StaticAllocator + mAllocator; +}; + +} // namespace aos::crypto + +#endif diff --git a/src/core/common/crypto/cryptoutils.hpp b/src/core/common/crypto/cryptoutils.hpp deleted file mode 100644 index 1a4ecf2c8..000000000 --- a/src/core/common/crypto/cryptoutils.hpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2023 Renesas Electronics Corporation. - * Copyright (C) 2023 EPAM Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef AOS_CORE_COMMON_CRYPTO_CRYPTOUTILS_HPP_ -#define AOS_CORE_COMMON_CRYPTO_CRYPTOUTILS_HPP_ - -#include -#include -#include - -#include "crypto.hpp" - -namespace aos::crypto { - -/** - * Loads certificates and keys interface. - */ -class CertLoaderItf { -public: - /** - * Loads certificate chain by URL. - * - * @param url input url. - * @return RetWithError>. - */ - virtual RetWithError> LoadCertsChainByURL(const String& url) = 0; - - /** - * Loads private key by URL. - * - * @param url input url. - * @return RetWithError>. - */ - virtual RetWithError> LoadPrivKeyByURL(const String& url) = 0; - - /** - * Destroys cert loader instance. - */ - virtual ~CertLoaderItf() = default; -}; - -/** - * Loads certificates and keys by URL. - */ -class CertLoader : public CertLoaderItf { -public: - /** - * Initializes object instance. - * - * @param cryptoProvider crypto provider interface. - * @param pkcs11Manager PKCS11 library manager. - * @return Error. - */ - Error Init(crypto::x509::ProviderItf& cryptoProvider, pkcs11::PKCS11Manager& pkcs11Manager); - - /** - * Loads certificate chain by URL. - * - * @param url input url. - * @return RetWithError>. - */ - RetWithError> LoadCertsChainByURL(const String& url) override; - - /** - * Loads private key by URL. - * - * @param url input url. - * @return RetWithError>. - */ - RetWithError> LoadPrivKeyByURL(const String& url) override; - -private: - using PEMCertChainBlob = StaticString; - - static constexpr auto cCertAllocatorSize - = crypto::cCertChainsCount * crypto::cCertChainSize * sizeof(crypto::x509::Certificate) - + sizeof(PEMCertChainBlob); - static constexpr auto cKeyAllocatorSize - = AOS_CONFIG_CRYPTO_PRIV_KEYS_COUNT * pkcs11::cPrivateKeyMaxSize + sizeof(crypto::cPrivKeyPEMLen); - static constexpr auto cNumAllocation = AOS_CONFIG_CRYPTO_NUM_ALLOCATIONS; - - static constexpr auto cDefaultPKCS11Library = AOS_CONFIG_CRYPTO_DEFAULT_PKCS11_LIB; - - RetWithError> OpenSession( - const String& libraryPath, const String& token, const String& userPIN); - RetWithError FindToken(const pkcs11::LibraryContext& library, const String& token); - - RetWithError> LoadCertsFromFile(const String& fileName); - RetWithError> LoadPrivKeyFromFile(const String& fileName); - - crypto::x509::ProviderItf* mCryptoProvider = nullptr; - pkcs11::PKCS11Manager* mPKCS11 = nullptr; - - StaticAllocator - mAllocator; -}; - -/** - * Parses scheme part of URL. - * - * @param url input url. - * @param[out] scheme url scheme. - * @return Error. - */ -Error ParseURLScheme(const String& url, String& scheme); - -/** - * Parses URL with file scheme. - * - * @param url input url. - * @param[out] path file path. - * @return Error. - */ -Error ParseFileURL(const String& url, String& path); - -/** - * Encodes PKCS11 ID to percent-encoded string. - * - * @param id PKCS11 ID. - * @param idStr percent-encoded string. - * @return Error. - */ -Error EncodePKCS11ID(const Array& id, String& idStr); - -/** - * Decodes PKCS11 ID from percent-encoded string. - * - * @param idStr percent-encoded string. - * @param id PKCS11 ID. - * @return Error. - */ -Error DecodeToPKCS11ID(const String& idStr, Array& id); - -/** - * Parses url with PKCS11 scheme. - * - * @param url input url. - * @param[out] library PKCS11 library. - * @param[out] token token label. - * @param[out] label certificate label. - * @param[out] id certificate id. - * @param[out] userPin user PIN. - * @return Error. - */ -Error ParsePKCS11URL( - const String& url, String& library, String& token, String& label, Array& id, String& userPin); - -/** - * Generates random string. - * - * @param result result string. - * @param random random interface. - * @return Error. - */ -template -Error GenerateRandomString(String& result, RandomItf& random) -{ - StaticArray buffer; - - if (auto err = random.RandBuffer(buffer, size); !err.IsNone()) { - return err; - } - - return result.ByteArrayToHex(buffer); -} - -} // namespace aos::crypto - -#endif From 4314cb11975a07cb36b319eb07b799dd700ee945 Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Tue, 7 Oct 2025 16:31:47 +0300 Subject: [PATCH 5/8] all: fix crypto includes Signed-off-by: Mykola Kobets Reviewed-by: Mykhailo Lohvynenko Reviewed-by: Oleksandr Grytsov Reviewed-by: Mykola Solianko --- src/core/cm/storagestate/itf/sender.hpp | 1 - src/core/cm/storagestate/itf/storage.hpp | 2 +- src/core/cm/storagestate/storagestate.cpp | 16 ++++----- src/core/cm/storagestate/storagestate.hpp | 6 ++-- src/core/cm/storagestate/storagestate.md | 2 +- src/core/common/crypto/tests/crypto.cpp | 2 +- src/core/common/crypto/tests/cryptohelper.cpp | 34 +++++++++---------- src/core/common/pkcs11/pkcs11.hpp | 2 +- .../crypto/providers/cryptofactoryitf.hpp | 2 +- src/core/common/tools/fs.hpp | 3 +- src/core/common/types/certificates.hpp | 2 +- src/core/common/types/instance.hpp | 2 +- src/core/common/types/obsolete.hpp | 6 ++-- src/core/common/types/state.hpp | 4 +-- .../certhandler/certmodules/pkcs11/pkcs11.cpp | 3 +- src/core/iam/certhandler/certprovider.hpp | 2 -- src/core/iam/certhandler/hsm.hpp | 2 +- src/core/iam/permhandler/permhandler.hpp | 2 +- src/core/iam/tests/mocks/certloadermock.hpp | 7 ++-- src/core/sm/networkmanager/networkmanager.cpp | 1 - src/core/sm/networkmanager/networkmanager.hpp | 2 +- 21 files changed, 50 insertions(+), 53 deletions(-) diff --git a/src/core/cm/storagestate/itf/sender.hpp b/src/core/cm/storagestate/itf/sender.hpp index a02eb29b6..bd1c99ad8 100644 --- a/src/core/cm/storagestate/itf/sender.hpp +++ b/src/core/cm/storagestate/itf/sender.hpp @@ -7,7 +7,6 @@ #ifndef AOS_CORE_CM_STORAGESTATE_ITF_SENDER_HPP_ #define AOS_CORE_CM_STORAGESTATE_ITF_SENDER_HPP_ -#include #include namespace aos::cm::storagestate { diff --git a/src/core/cm/storagestate/itf/storage.hpp b/src/core/cm/storagestate/itf/storage.hpp index 0c074aeb1..2a24c5ecf 100644 --- a/src/core/cm/storagestate/itf/storage.hpp +++ b/src/core/cm/storagestate/itf/storage.hpp @@ -7,7 +7,7 @@ #ifndef AOS_CORE_CM_STORAGESTATE_ITF_STORAGE_HPP_ #define AOS_CORE_CM_STORAGESTATE_ITF_STORAGE_HPP_ -#include +#include namespace aos::cm::storagestate { diff --git a/src/core/cm/storagestate/storagestate.cpp b/src/core/cm/storagestate/storagestate.cpp index 4bb1fb043..7ba9f0fd0 100644 --- a/src/core/cm/storagestate/storagestate.cpp +++ b/src/core/cm/storagestate/storagestate.cpp @@ -45,16 +45,16 @@ Error ToRelativePath(const String& base, const String& full, String& result) **********************************************************************************************************************/ Error StorageState::Init(const Config& config, StorageItf& storage, SenderItf& sender, fs::FSPlatformItf& fsPlatform, - fs::FSWatcherItf& fsWatcher, crypto::CryptoProviderItf& cryptoProvider) + fs::FSWatcherItf& fsWatcher, crypto::HasherItf& hasher) { LOG_INF() << "Initialize storage state"; - mConfig = config; - mStorage = &storage; - mMessageSender = &sender; - mFSPlatform = &fsPlatform; - mFSWatcher = &fsWatcher; - mCryptoProvider = &cryptoProvider; + mConfig = config; + mStorage = &storage; + mMessageSender = &sender; + mFSPlatform = &fsPlatform; + mFSWatcher = &fsWatcher; + mHasher = &hasher; if (auto err = fs::MakeDirAll(mConfig.mStateDir); !err.IsNone()) { return AOS_ERROR_WRAP(err); @@ -660,7 +660,7 @@ StaticString StorageState::GetStoragePath(const InstanceIdent& ins Error StorageState::CalculateChecksum(const String& data, String& checksum) { - auto [hasher, err] = mCryptoProvider->CreateHash(cHashAlgorithm); + auto [hasher, err] = mHasher->CreateHash(cHashAlgorithm); if (!err.IsNone()) { return AOS_ERROR_WRAP(err); } diff --git a/src/core/cm/storagestate/storagestate.hpp b/src/core/cm/storagestate/storagestate.hpp index 55481bbad..1ae3f6921 100644 --- a/src/core/cm/storagestate/storagestate.hpp +++ b/src/core/cm/storagestate/storagestate.hpp @@ -7,7 +7,7 @@ #ifndef AOS_CORE_CM_STORAGESTATE_STORAGESTATE_HPP_ #define AOS_CORE_CM_STORAGESTATE_STORAGESTATE_HPP_ -#include +#include #include #include #include @@ -41,7 +41,7 @@ class StorageState : public StateItf, public StorageStateItf, private fs::FSEven * @return Error. */ Error Init(const Config& config, StorageItf& storage, SenderItf& sender, fs::FSPlatformItf& fsPlatform, - fs::FSWatcherItf& fsWatcher, crypto::CryptoProviderItf& cryptoProvider); + fs::FSWatcherItf& fsWatcher, crypto::HasherItf& hasher); /** * Starts storage state instance. @@ -200,7 +200,7 @@ class StorageState : public StateItf, public StorageStateItf, private fs::FSEven SenderItf* mMessageSender = {}; fs::FSPlatformItf* mFSPlatform = {}; fs::FSWatcherItf* mFSWatcher = {}; - crypto::CryptoProviderItf* mCryptoProvider = {}; + crypto::HasherItf* mHasher = {}; bool mStateAndStorageOnSamePartition = {}; StaticArray mStates; }; diff --git a/src/core/cm/storagestate/storagestate.md b/src/core/cm/storagestate/storagestate.md index b2deb447e..0095d7dd1 100644 --- a/src/core/cm/storagestate/storagestate.md +++ b/src/core/cm/storagestate/storagestate.md @@ -15,7 +15,7 @@ It requires the following interfaces: * [aos::cm::storagestate::StorageItf](itf/storage.hpp) - manages metadata about storage/state partitions; * [aos::fs::FSPlatformItf](../../common/tools/fs.hpp) - handle filesystem operations; * [aos::fs::FSWatcherItf](../../common/tools/fs.hpp) - subscribes to file change events. -* [aos::crypto::CryptoProviderItf](../../common/crypto/crypto.hpp) - computes state file checksum; +* [aos::crypto::HasherItf](../../common/crypto/itf/hasher.hpp) - computes state file checksum; ```mermaid classDiagram diff --git a/src/core/common/crypto/tests/crypto.cpp b/src/core/common/crypto/tests/crypto.cpp index cdd85802e..54b4c9b39 100644 --- a/src/core/common/crypto/tests/crypto.cpp +++ b/src/core/common/crypto/tests/crypto.cpp @@ -6,7 +6,7 @@ #include -#include +#include namespace aos::crypto::asn1 { diff --git a/src/core/common/crypto/tests/cryptohelper.cpp b/src/core/common/crypto/tests/cryptohelper.cpp index bfe68e71c..a51075e29 100644 --- a/src/core/common/crypto/tests/cryptohelper.cpp +++ b/src/core/common/crypto/tests/cryptohelper.cpp @@ -54,10 +54,10 @@ std::vector ReadFileFromCrtDir(const String& fileName) return {content.begin(), content.end()}; } -DecryptInfo CreateDecryptionInfo( +cloudprotocol::DecryptInfo CreateDecryptionInfo( const char* blockAlg, const std::vector& blockIV, const std::vector& blockKey) { - DecryptInfo decryptInfo; + cloudprotocol::DecryptInfo decryptInfo; decryptInfo.mBlockAlg = blockAlg; decryptInfo.mBlockIV = Array(blockIV.data(), blockIV.size()); @@ -68,7 +68,7 @@ DecryptInfo CreateDecryptionInfo( return decryptInfo; } -CertificateInfo CreateCert(CryptoProviderItf& provider, const char* name) +cloudprotocol::CertificateInfo CreateCert(CryptoProviderItf& provider, const char* name) { auto fullPath = CRYPTOHELPER_CERTS_DIR "/" + std::string(name) + ".pem"; @@ -78,7 +78,7 @@ CertificateInfo CreateCert(CryptoProviderItf& provider, const char* name) AssertOK(fs::ReadFileToString(fullPath.c_str(), pem)); AssertOK(provider.PEMToX509Certs(pem, chain)); - CertificateInfo cert; + cloudprotocol::CertificateInfo cert; cert.mFingerprint = name; cert.mCertificate = chain[0].mRaw; @@ -86,9 +86,9 @@ CertificateInfo CreateCert(CryptoProviderItf& provider, const char* name) return cert; } -CertificateChainInfo CreateCertChain(const char* name, const std::vector fingerprints) +cloudprotocol::CertificateChainInfo CreateCertChain(const char* name, const std::vector fingerprints) { - CertificateChainInfo chain; + cloudprotocol::CertificateChainInfo chain; chain.mName = name; @@ -99,9 +99,9 @@ CertificateChainInfo CreateCertChain(const char* name, const std::vector mDecryptedContent; + const char* mEncryptedFile; + cloudprotocol::DecryptInfo mDecryptInfo; + std::vector mDecryptedContent; }; std::vector testData = { @@ -203,9 +203,9 @@ TEST_F(CryptoHelperTest, Decrypt) TEST_F(CryptoHelperTest, ValidateSigns) { struct TestData { - std::vector mCerts; - CertificateChainInfo mChain; - SignInfo mSigns; + std::vector mCerts; + cloudprotocol::CertificateChainInfo mChain; + cloudprotocol::SignInfo mSigns; }; constexpr auto cDecryptedFile = CRYPTOHELPER_CERTS_DIR "/hello-world.txt"; @@ -237,10 +237,10 @@ TEST_F(CryptoHelperTest, ValidateSigns) CreateSigns("onlineTest2", "RSA/SHA256/PKCS1v1_5")}}; for (const auto& item : testData) { - StaticArray certs; - certs = Array(item.mCerts.data(), item.mCerts.size()); + StaticArray certs; + certs = Array(item.mCerts.data(), item.mCerts.size()); - StaticArray chains; + StaticArray chains; chains.PushBack(item.mChain); ASSERT_TRUE(mCryptoHelper.ValidateSigns(cDecryptedFile, item.mSigns, chains, certs).IsNone()); diff --git a/src/core/common/pkcs11/pkcs11.hpp b/src/core/common/pkcs11/pkcs11.hpp index a7c7c8a33..c84ca6bfd 100644 --- a/src/core/common/pkcs11/pkcs11.hpp +++ b/src/core/common/pkcs11/pkcs11.hpp @@ -8,7 +8,7 @@ #ifndef AOS_CORE_COMMON_PKCS11_PKCS11_HPP_ #define AOS_CORE_COMMON_PKCS11_PKCS11_HPP_ -#include +#include #include #include #include diff --git a/src/core/common/tests/crypto/providers/cryptofactoryitf.hpp b/src/core/common/tests/crypto/providers/cryptofactoryitf.hpp index 734a9a4d9..8260181f3 100644 --- a/src/core/common/tests/crypto/providers/cryptofactoryitf.hpp +++ b/src/core/common/tests/crypto/providers/cryptofactoryitf.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include namespace aos::crypto { diff --git a/src/core/common/tools/fs.hpp b/src/core/common/tools/fs.hpp index 4404872f1..a85a8f321 100644 --- a/src/core/common/tools/fs.hpp +++ b/src/core/common/tools/fs.hpp @@ -10,7 +10,8 @@ #include -#include +#include +#include #include "config.hpp" #include "noncopyable.hpp" diff --git a/src/core/common/types/certificates.hpp b/src/core/common/types/certificates.hpp index ab0a44026..bcb73f7f3 100644 --- a/src/core/common/types/certificates.hpp +++ b/src/core/common/types/certificates.hpp @@ -7,7 +7,7 @@ #ifndef AOS_CORE_COMMON_TYPES_CERTIFICATES_HPP_ #define AOS_CORE_COMMON_TYPES_CERTIFICATES_HPP_ -#include +#include #include #include "common.hpp" diff --git a/src/core/common/types/instance.hpp b/src/core/common/types/instance.hpp index 18631c308..8765d5e22 100644 --- a/src/core/common/types/instance.hpp +++ b/src/core/common/types/instance.hpp @@ -7,7 +7,7 @@ #ifndef AOS_CORE_COMMON_TYPES_INSTANCE_HPP_ #define AOS_CORE_COMMON_TYPES_INSTANCE_HPP_ -#include +#include #include "common.hpp" #include "network.hpp" diff --git a/src/core/common/types/obsolete.hpp b/src/core/common/types/obsolete.hpp index 8c041bc51..888b6155f 100644 --- a/src/core/common/types/obsolete.hpp +++ b/src/core/common/types/obsolete.hpp @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2023 Renesas Electronics Corporation. * Copyright (C) 2023 EPAM Systems, Inc. * @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -24,7 +24,7 @@ namespace aos { -/* +/** * Layer digest len. */ constexpr auto cLayerDigestLen = AOS_CONFIG_TYPES_LAYER_DIGEST_LEN; diff --git a/src/core/common/types/state.hpp b/src/core/common/types/state.hpp index bb47247e4..87c145fd2 100644 --- a/src/core/common/types/state.hpp +++ b/src/core/common/types/state.hpp @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2025 EPAM Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 @@ -7,7 +7,7 @@ #ifndef AOS_CORE_COMMON_TYPES_STATE_HPP_ #define AOS_CORE_COMMON_TYPES_STATE_HPP_ -#include +#include namespace aos { diff --git a/src/core/iam/certhandler/certmodules/pkcs11/pkcs11.cpp b/src/core/iam/certhandler/certmodules/pkcs11/pkcs11.cpp index ded0ed126..c65f1df2d 100644 --- a/src/core/iam/certhandler/certmodules/pkcs11/pkcs11.cpp +++ b/src/core/iam/certhandler/certmodules/pkcs11/pkcs11.cpp @@ -5,7 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include #include #include #include diff --git a/src/core/iam/certhandler/certprovider.hpp b/src/core/iam/certhandler/certprovider.hpp index c571c6d4e..9d7dce29b 100644 --- a/src/core/iam/certhandler/certprovider.hpp +++ b/src/core/iam/certhandler/certprovider.hpp @@ -7,8 +7,6 @@ #ifndef AOS_CORE_IAM_CERTHANDLER_CERTPROVIDER_HPP_ #define AOS_CORE_IAM_CERTHANDLER_CERTPROVIDER_HPP_ -#include - #include "certhandler.hpp" namespace aos::iam::certhandler { diff --git a/src/core/iam/certhandler/hsm.hpp b/src/core/iam/certhandler/hsm.hpp index a930677c5..9cf793138 100644 --- a/src/core/iam/certhandler/hsm.hpp +++ b/src/core/iam/certhandler/hsm.hpp @@ -8,7 +8,7 @@ #ifndef AOS_CORE_IAM_CERTHANDLER_HSM_HPP_ #define AOS_CORE_IAM_CERTHANDLER_HSM_HPP_ -#include +#include #include #include #include diff --git a/src/core/iam/permhandler/permhandler.hpp b/src/core/iam/permhandler/permhandler.hpp index 36cd98baf..9f825eb5e 100644 --- a/src/core/iam/permhandler/permhandler.hpp +++ b/src/core/iam/permhandler/permhandler.hpp @@ -8,7 +8,7 @@ #ifndef AOS_CORE_IAM_PERMHANDLER_PERMHANDLER_HPP_ #define AOS_CORE_IAM_PERMHANDLER_PERMHANDLER_HPP_ -#include +#include #include #include #include diff --git a/src/core/iam/tests/mocks/certloadermock.hpp b/src/core/iam/tests/mocks/certloadermock.hpp index b47f4428e..9b432cde8 100644 --- a/src/core/iam/tests/mocks/certloadermock.hpp +++ b/src/core/iam/tests/mocks/certloadermock.hpp @@ -9,7 +9,7 @@ #include -#include +#include namespace aos::crypto { @@ -19,9 +19,8 @@ namespace aos::crypto { class CertLoaderMock : public CertLoaderItf { public: - MOCK_METHOD( - RetWithError>, LoadCertsChainByURL, (const String&), (override)); - MOCK_METHOD(RetWithError>, LoadPrivKeyByURL, (const String&), (override)); + MOCK_METHOD(RetWithError>, LoadCertsChainByURL, (const String&), (override)); + MOCK_METHOD(RetWithError>, LoadPrivKeyByURL, (const String&), (override)); }; } // namespace aos::crypto diff --git a/src/core/sm/networkmanager/networkmanager.cpp b/src/core/sm/networkmanager/networkmanager.cpp index fff908889..43bf2d2f7 100644 --- a/src/core/sm/networkmanager/networkmanager.cpp +++ b/src/core/sm/networkmanager/networkmanager.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include diff --git a/src/core/sm/networkmanager/networkmanager.hpp b/src/core/sm/networkmanager/networkmanager.hpp index 3f90f387c..20116c5a9 100644 --- a/src/core/sm/networkmanager/networkmanager.hpp +++ b/src/core/sm/networkmanager/networkmanager.hpp @@ -7,7 +7,7 @@ #ifndef AOS_CORE_SM_NETWORKMANAGER_NETWORKMANAGER_HPP_ #define AOS_CORE_SM_NETWORKMANAGER_NETWORKMANAGER_HPP_ -#include +#include #include #include #include From 8dd0b17b6bdcc2652445a5f379b2c7c70b7d3fe1 Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Tue, 7 Oct 2025 16:41:19 +0300 Subject: [PATCH 6/8] crypto: adapt crypto module to interface reloacations VerifyOptions, Padding moved to crypto::x509 namespace Also removed redundant namespace qualifiers Signed-off-by: Mykola Kobets Reviewed-by: Mykhailo Lohvynenko Reviewed-by: Oleksandr Grytsov Reviewed-by: Mykola Solianko --- src/core/common/crypto/certloader.hpp | 2 +- src/core/common/crypto/cryptohelper.cpp | 9 +- src/core/common/crypto/cryptohelper.hpp | 236 ++---------------- .../common/crypto/mbedtls/cryptoprovider.cpp | 18 +- .../common/crypto/mbedtls/cryptoprovider.hpp | 6 +- .../common/crypto/mbedtls/driverwrapper.hpp | 2 +- .../common/crypto/openssl/cryptoprovider.cpp | 14 +- .../common/crypto/openssl/cryptoprovider.hpp | 6 +- .../common/crypto/openssl/opensslprovider.hpp | 2 +- src/core/common/crypto/tests/CMakeLists.txt | 2 +- .../crypto/tests/{crypto.cpp => asn1.cpp} | 2 +- src/core/common/crypto/tests/cryptohelper.cpp | 35 +-- .../common/crypto/tests/cryptoprovider.cpp | 18 +- src/core/common/crypto/tests/cryptoutils.cpp | 41 +-- src/core/common/tests/mocks/cryptomock.hpp | 5 +- 15 files changed, 100 insertions(+), 298 deletions(-) rename src/core/common/crypto/tests/{crypto.cpp => asn1.cpp} (92%) diff --git a/src/core/common/crypto/certloader.hpp b/src/core/common/crypto/certloader.hpp index efdbf3989..fa63febe6 100644 --- a/src/core/common/crypto/certloader.hpp +++ b/src/core/common/crypto/certloader.hpp @@ -11,7 +11,7 @@ #include #include -#include "itf/certoloader.hpp" +#include "itf/certloader.hpp" #include "itf/crypto.hpp" namespace aos::crypto { diff --git a/src/core/common/crypto/cryptohelper.cpp b/src/core/common/crypto/cryptohelper.cpp index d18833c83..3370f85d1 100644 --- a/src/core/common/crypto/cryptohelper.cpp +++ b/src/core/common/crypto/cryptohelper.cpp @@ -13,6 +13,7 @@ namespace aos::crypto { /*********************************************************************************************************************** * Public **********************************************************************************************************************/ + CryptoHelper::CryptoHelper() : mSemaphore(cMaxNumConcurrentItems) { @@ -476,11 +477,11 @@ Error CryptoHelper::VerifySigns(const String& file, const SignInfo& signs, SignC return AOS_ERROR_WRAP(ErrorEnum::eNotSupported); } - Padding padding; + x509::Padding padding; if (paddingName == "PKCS1V1_5") { - padding = PaddingEnum::ePKCS1v1_5; + padding = x509::PaddingEnum::ePKCS1v1_5; } else if (paddingName == "PSS") { - padding = PaddingEnum::ePSS; + padding = x509::PaddingEnum::ePSS; } else { AOS_ERROR_WRAP(Error(ErrorEnum::eNotSupported, "unknown padding for RSA")); } @@ -497,7 +498,7 @@ Error CryptoHelper::VerifySigns(const String& file, const SignInfo& signs, SignC return err; } - VerifyOptions options; + x509::VerifyOptions options; options.mCurrentTime = signs.mTrustedTimestamp; // Assume any key usages. diff --git a/src/core/common/crypto/cryptohelper.hpp b/src/core/common/crypto/cryptohelper.hpp index 14acc7411..a5eac7123 100644 --- a/src/core/common/crypto/cryptohelper.hpp +++ b/src/core/common/crypto/cryptohelper.hpp @@ -7,194 +7,13 @@ #ifndef AOS_AOS_COMMON_CRYPTO_CRYPTOHELPER_HPP_ #define AOS_AOS_COMMON_CRYPTO_CRYPTOHELPER_HPP_ -#include #include -namespace aos::crypto { - -/** - * Number of recipient info in envelope data. - */ -constexpr auto cRecipientsInEnvelopeData = AOS_CONFIG_CRYPTO_RECIPIENTS_IN_ENVELOPEDATA; - -/** - * Maximum size for cloud metadata. - */ -constexpr auto cCloudMetadataSize = AOS_CONFIG_CRYPTO_ENCRYPT_METADATA; - -/** - * Certificate fingerprint len. - */ -constexpr auto cCertFingerprintLen = AOS_CONFIG_CRYPTO_CERT_FINGERPRINT_LEN; - -/** - * Chain name len. - */ -constexpr auto cChainNameLen = AOS_CONFIG_CRYPTO_CHAIN_NAME_LEN; - -/** - * Algorithm len. - */ -constexpr auto cAlgLen = AOS_CONFIG_CRYPTO_ALG_LEN; - -/** - * IV size. - */ -constexpr auto cIVSize = AOS_CONFIG_CRYPTO_IV_SIZE; - -/** - * Key size. - */ -constexpr auto cKeySize = AOS_CONFIG_CRYPTO_KEY_SIZE; - -/** - * OCSP value len. - */ -constexpr auto cOCSPValueLen = AOS_CONFIG_CRYPTO_OCSP_VALUE_LEN; - -/** - * OCSP values count. - */ -constexpr auto cOCSPValuesCount = AOS_CONFIG_CRYPTO_OCSP_VALUES_COUNT; - -/** - * Certificate info. - */ -struct CertificateInfo { - StaticArray mCertificate; - StaticString mFingerprint; - - /** - * Compares certificate info. - * - * @param rhs certificate info to compare with. - * @return bool. - */ - bool operator==(const CertificateInfo& rhs) const - { - return mCertificate == rhs.mCertificate && mFingerprint == rhs.mFingerprint; - } +#include "itf/certloader.hpp" +#include "itf/crypto.hpp" +#include "itf/cryptohelper.hpp" - /** - * Compares certificate info. - * - * @param rhs certificate info to compare with. - * @return bool. - */ - bool operator!=(const CertificateInfo& rhs) const { return !operator==(rhs); } -}; - -using CertificateInfoArray = StaticArray; - -/** - * Certificate chain info. - */ -struct CertificateChainInfo { - StaticString mName; - StaticArray, crypto::cCertChainSize> mFingerprints; - - /** - * Compares certificate chain info. - * - * @param rhs certificate chain info to compare with. - * @return bool. - */ - bool operator==(const CertificateChainInfo& rhs) const - { - return mName == rhs.mName && mFingerprints == rhs.mFingerprints; - } - - /** - * Compares certificate chain info. - * - * @param rhs certificate chain info to compare with. - * @return bool. - */ - bool operator!=(const CertificateChainInfo& rhs) const { return !operator==(rhs); } -}; - -using CertificateChainInfoArray = StaticArray; - -/** - * Decryption info. - */ -struct DecryptInfo { - StaticString mBlockAlg; - StaticArray mBlockIV; - StaticArray mBlockKey; - - /** - * Compares decryption info. - * - * @param rhs decryption info to compare with. - * @return bool. - */ - bool operator==(const DecryptInfo& rhs) const - { - return mBlockAlg == rhs.mBlockAlg && mBlockIV == rhs.mBlockIV && mBlockKey == rhs.mBlockKey; - } - - /** - * Compares decryption info. - * - * @param rhs decryption info to compare with. - * @return bool. - */ - bool operator!=(const DecryptInfo& rhs) const { return !operator==(rhs); } -}; - -/** - * Sign info. - */ -struct SignInfo { - StaticString mChainName; - StaticString mAlg; - StaticArray mValue; - Time mTrustedTimestamp {}; - StaticArray, cOCSPValuesCount> mOCSPValues; - /** - * Compares sign info. - * - * @param rhs sign info to compare with. - * @return bool. - */ - bool operator==(const SignInfo& rhs) const - { - return mChainName == rhs.mChainName && mAlg == rhs.mAlg && mValue == rhs.mValue - && mTrustedTimestamp == rhs.mTrustedTimestamp && mOCSPValues == rhs.mOCSPValues; - } - - /** - * Compares sign info. - * - * @param rhs sign info to compare with. - * @return bool. - */ - bool operator!=(const SignInfo& rhs) const { return !operator==(rhs); } -}; - -/** - * Certificate info in x509 format. - */ -struct X509CertificateInfo { - /** - * Certificate. - */ - x509::Certificate mCertificate; - - /** - * Certificate fingerprint. - */ - StaticString mFingerprint; -}; - -/** - * Signing context. - */ -struct SignContext { - StaticArray mCerts; - CertificateChainInfoArray mChains; -}; +namespace aos::crypto { /** * CMS recipient identity info. @@ -243,47 +62,26 @@ struct ContentInfo { }; /** - * CryptoHelper interface. + * Certificate info in x509 format. */ -class CryptoHelperItf { -public: - /** - * Destructor. - */ - virtual ~CryptoHelperItf() = default; - +struct X509CertificateInfo { /** - * Decrypts a file using provided decryption information. - * - * @param encryptedPath path to the encrypted file. - * @param decryptedPath path where the decrypted file will be written. - * @param decryptionInfo decryption information. - * @return Error. + * Certificate. */ - virtual Error Decrypt(const String& encryptedPath, const String& decryptedPath, const DecryptInfo& decryptionInfo) - = 0; + x509::Certificate mCertificate; /** - * Validates digital signatures of a decrypted file against provided certificates and chains. - * - * @param decryptedPath path to the decrypted file to validate. - * @param signs signature information. - * @param chains certificate chains for validation. - * @param certs certificates used for validation. - * @return Error. + * Certificate fingerprint. */ - virtual Error ValidateSigns(const String& decryptedPath, const SignInfo& signs, - const Array& chains, const Array& certs) - = 0; + StaticString mFingerprint; +}; - /** - * Decrypts metadata containing in a binary buffer. - * - * @param[in] input encrypted metadata buffer. - * @param[out] output buffer where the decrypted metadata will be stored. - * @return Error. - */ - virtual Error DecryptMetadata(const Array& input, Array& output) = 0; +/** + * Signing context. + */ +struct SignContext { + StaticArray mCerts; + CertificateChainInfoArray mChains; }; /** diff --git a/src/core/common/crypto/mbedtls/cryptoprovider.cpp b/src/core/common/crypto/mbedtls/cryptoprovider.cpp index c7d97cfc9..d889f5cce 100644 --- a/src/core/common/crypto/mbedtls/cryptoprovider.cpp +++ b/src/core/common/crypto/mbedtls/cryptoprovider.cpp @@ -407,7 +407,7 @@ asn1::ASN1ParseResult ReadASN1Container(const Array& data, const asn1:: return {ErrorEnum::eNone, remaining}; } -Error VerifyRSASignature(const RSAPublicKey& pubKey, mbedtls_md_type_t hash, Padding padding, +Error VerifyRSASignature(const RSAPublicKey& pubKey, mbedtls_md_type_t hash, x509::Padding padding, const Array& digest, const Array& signature) { mbedtls_rsa_context rsa; @@ -428,14 +428,14 @@ Error VerifyRSASignature(const RSAPublicKey& pubKey, mbedtls_md_type_t hash, Pad } // Choose padding mode - if (padding == PaddingEnum::ePKCS1v1_5) { + if (padding == x509::PaddingEnum::ePKCS1v1_5) { ret = mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V15, hash); if (ret != 0) { return AOS_ERROR_WRAP(ret); } ret = mbedtls_rsa_rsassa_pkcs1_v15_verify(&rsa, hash, digest.Size(), digest.Get(), signature.Get()); - } else if (padding == PaddingEnum::ePSS) { + } else if (padding == x509::PaddingEnum::ePSS) { ret = mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, hash); if (ret != 0) { return AOS_ERROR_WRAP(ret); @@ -1082,8 +1082,8 @@ RetWithError> MbedTLSCryptoProvider::CreateAESDecoder( return {UniquePtr(Move(cipher)), ErrorEnum::eNone}; } -Error MbedTLSCryptoProvider::Verify(const Variant& pubKey, Hash hashFunc, Padding padding, - const Array& digest, const Array& signature) +Error MbedTLSCryptoProvider::Verify(const Variant& pubKey, Hash hashFunc, + x509::Padding padding, const Array& digest, const Array& signature) { if (digest.IsEmpty() || signature.IsEmpty()) { return AOS_ERROR_WRAP(ErrorEnum::eInvalidArgument); @@ -1091,8 +1091,8 @@ Error MbedTLSCryptoProvider::Verify(const Variant& struct SignatureVerifier : StaticVisitor { public: - SignatureVerifier( - mbedtls_md_type_t hash, Padding padding, const Array& digest, const Array& signature) + SignatureVerifier(mbedtls_md_type_t hash, x509::Padding padding, const Array& digest, + const Array& signature) : mHash(hash) , mPadding(padding) , mDigest(&digest) @@ -1109,7 +1109,7 @@ Error MbedTLSCryptoProvider::Verify(const Variant& private: mbedtls_md_type_t mHash; - Padding mPadding; + x509::Padding mPadding; const Array* mDigest = nullptr; const Array* mSignature = nullptr; }; @@ -1120,7 +1120,7 @@ Error MbedTLSCryptoProvider::Verify(const Variant& } Error MbedTLSCryptoProvider::Verify(const Array& rootCerts, - const Array& intermCerts, const VerifyOptions& options, const x509::Certificate& cert) + const Array& intermCerts, const x509::VerifyOptions& options, const x509::Certificate& cert) { Time curTime; if (!options.mCurrentTime.IsZero()) { diff --git a/src/core/common/crypto/mbedtls/cryptoprovider.hpp b/src/core/common/crypto/mbedtls/cryptoprovider.hpp index 2104b7dbd..5eae4577c 100644 --- a/src/core/common/crypto/mbedtls/cryptoprovider.hpp +++ b/src/core/common/crypto/mbedtls/cryptoprovider.hpp @@ -14,7 +14,7 @@ #include #include -#include "../crypto.hpp" +#include "../itf/crypto.hpp" #include "driverwrapper.hpp" namespace aos::crypto { @@ -237,7 +237,7 @@ class MbedTLSCryptoProvider : public CryptoProviderItf { * @param signature signature to verify against the digest. * @return Error. */ - Error Verify(const Variant& pubKey, Hash hashFunc, Padding padding, + Error Verify(const Variant& pubKey, Hash hashFunc, x509::Padding padding, const Array& digest, const Array& signature) override; /** @@ -250,7 +250,7 @@ class MbedTLSCryptoProvider : public CryptoProviderItf { * @return Error. */ Error Verify(const Array& rootCerts, const Array& intermCerts, - const VerifyOptions& options, const x509::Certificate& cert) override; + const x509::VerifyOptions& options, const x509::Certificate& cert) override; /** * Discards an ASN.1 tag-length and invokes reader for its content. diff --git a/src/core/common/crypto/mbedtls/driverwrapper.hpp b/src/core/common/crypto/mbedtls/driverwrapper.hpp index ed4b8aee4..b0c8646ab 100644 --- a/src/core/common/crypto/mbedtls/driverwrapper.hpp +++ b/src/core/common/crypto/mbedtls/driverwrapper.hpp @@ -10,7 +10,7 @@ #include -#include "../crypto.hpp" +#include "../itf/crypto.hpp" /** * Key description. diff --git a/src/core/common/crypto/openssl/cryptoprovider.cpp b/src/core/common/crypto/openssl/cryptoprovider.cpp index d148ca77a..995bf7c68 100644 --- a/src/core/common/crypto/openssl/cryptoprovider.cpp +++ b/src/core/common/crypto/openssl/cryptoprovider.cpp @@ -1116,7 +1116,7 @@ Error Sign(const PrivateKeyItf& privKey, X509_REQ* req, OSSL_LIB_CTX* libCtx) return ErrorEnum::eNone; } -Error SetVerificationOptions(const VerifyOptions& opts, X509_STORE_CTX* store) +Error SetVerificationOptions(const x509::VerifyOptions& opts, X509_STORE_CTX* store) { if (!opts.mCurrentTime.IsZero()) { auto curTime = DeferRelease(ASN1_UTCTIME_new(), ASN1_TIME_free); @@ -1879,8 +1879,8 @@ RetWithError> OpenSSLCryptoProvider::CreateAESDecoder( return {UniquePtr(Move(cipher)), ErrorEnum::eNone}; } -Error OpenSSLCryptoProvider::Verify(const Variant& pubKey, Hash hashFunc, Padding padding, - const Array& digest, const Array& signature) +Error OpenSSLCryptoProvider::Verify(const Variant& pubKey, Hash hashFunc, + x509::Padding padding, const Array& digest, const Array& signature) { auto [pkey, err] = GetEvpPublicKey(pubKey, mLibCtx); if (!err.IsNone()) { @@ -1910,9 +1910,9 @@ Error OpenSSLCryptoProvider::Verify(const Variant& auto keyType = EVP_PKEY_base_id(pkey); if (keyType == EVP_PKEY_RSA) { int opensslPadding = -1; - if (padding == PaddingEnum::ePKCS1v1_5) { + if (padding == x509::PaddingEnum::ePKCS1v1_5) { opensslPadding = RSA_PKCS1_PADDING; - } else if (padding == PaddingEnum::ePSS) { + } else if (padding == x509::PaddingEnum::ePSS) { opensslPadding = RSA_PKCS1_PSS_PADDING; } else { return AOS_ERROR_WRAP(ErrorEnum::eInvalidArgument); @@ -1928,7 +1928,7 @@ Error OpenSSLCryptoProvider::Verify(const Variant& } } else if (keyType == EVP_PKEY_EC) { // ECDSA doesn't use padding - if (padding != PaddingEnum::eNone) { + if (padding != x509::PaddingEnum::eNone) { return AOS_ERROR_WRAP(ErrorEnum::eInvalidArgument); } } else { @@ -1944,7 +1944,7 @@ Error OpenSSLCryptoProvider::Verify(const Variant& } Error OpenSSLCryptoProvider::Verify(const Array& rootCerts, - const Array& intermCerts, const VerifyOptions& options, const x509::Certificate& cert) + const Array& intermCerts, const x509::VerifyOptions& options, const x509::Certificate& cert) { if (rootCerts.IsEmpty()) { return AOS_ERROR_WRAP(Error(ErrorEnum::eInvalidArgument, "no root certificates")); diff --git a/src/core/common/crypto/openssl/cryptoprovider.hpp b/src/core/common/crypto/openssl/cryptoprovider.hpp index c9c110f8e..c053d5d35 100644 --- a/src/core/common/crypto/openssl/cryptoprovider.hpp +++ b/src/core/common/crypto/openssl/cryptoprovider.hpp @@ -9,7 +9,7 @@ #include -#include "../crypto.hpp" +#include "../itf/crypto.hpp" #include "opensslprovider.hpp" namespace aos::crypto { @@ -237,7 +237,7 @@ class OpenSSLCryptoProvider : public CryptoProviderItf { * @param signature signature to verify against the digest. * @return Error. */ - Error Verify(const Variant& pubKey, Hash hashFunc, Padding padding, + Error Verify(const Variant& pubKey, Hash hashFunc, x509::Padding padding, const Array& digest, const Array& signature) override; /** @@ -250,7 +250,7 @@ class OpenSSLCryptoProvider : public CryptoProviderItf { * @return Error. */ Error Verify(const Array& rootCerts, const Array& intermCerts, - const VerifyOptions& options, const x509::Certificate& cert) override; + const x509::VerifyOptions& options, const x509::Certificate& cert) override; /** * Discards an ASN.1 tag-length and invokes reader for its content. diff --git a/src/core/common/crypto/openssl/opensslprovider.hpp b/src/core/common/crypto/openssl/opensslprovider.hpp index a7de47b58..5fc38e66b 100644 --- a/src/core/common/crypto/openssl/opensslprovider.hpp +++ b/src/core/common/crypto/openssl/opensslprovider.hpp @@ -9,7 +9,7 @@ #include -#include "../crypto.hpp" +#include "../itf/crypto.hpp" /** * Returns OpenSSL error. diff --git a/src/core/common/crypto/tests/CMakeLists.txt b/src/core/common/crypto/tests/CMakeLists.txt index 3af5d0280..0039b5936 100644 --- a/src/core/common/crypto/tests/CMakeLists.txt +++ b/src/core/common/crypto/tests/CMakeLists.txt @@ -10,7 +10,7 @@ set(TARGET_NAME crypto_test) # Sources # ###################################################################################################################### -set(SOURCES crypto.cpp) +set(SOURCES asn1.cpp) if(WITH_MBEDTLS OR WITH_OPENSSL) list(APPEND SOURCES cryptohelper.cpp cryptoprovider.cpp cryptoutils.cpp) diff --git a/src/core/common/crypto/tests/crypto.cpp b/src/core/common/crypto/tests/asn1.cpp similarity index 92% rename from src/core/common/crypto/tests/crypto.cpp rename to src/core/common/crypto/tests/asn1.cpp index 54b4c9b39..1d4aae6d7 100644 --- a/src/core/common/crypto/tests/crypto.cpp +++ b/src/core/common/crypto/tests/asn1.cpp @@ -10,7 +10,7 @@ namespace aos::crypto::asn1 { -TEST(CryptoTest, ConvertTimeToASN1Str) +TEST(ASN1Test, ConvertTimeToASN1Str) { auto t = Time::Unix(1706702400); diff --git a/src/core/common/crypto/tests/cryptohelper.cpp b/src/core/common/crypto/tests/cryptohelper.cpp index a51075e29..f636271cb 100644 --- a/src/core/common/crypto/tests/cryptohelper.cpp +++ b/src/core/common/crypto/tests/cryptohelper.cpp @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -54,10 +55,10 @@ std::vector ReadFileFromCrtDir(const String& fileName) return {content.begin(), content.end()}; } -cloudprotocol::DecryptInfo CreateDecryptionInfo( +DecryptInfo CreateDecryptionInfo( const char* blockAlg, const std::vector& blockIV, const std::vector& blockKey) { - cloudprotocol::DecryptInfo decryptInfo; + DecryptInfo decryptInfo; decryptInfo.mBlockAlg = blockAlg; decryptInfo.mBlockIV = Array(blockIV.data(), blockIV.size()); @@ -68,7 +69,7 @@ cloudprotocol::DecryptInfo CreateDecryptionInfo( return decryptInfo; } -cloudprotocol::CertificateInfo CreateCert(CryptoProviderItf& provider, const char* name) +CertificateInfo CreateCert(CryptoProviderItf& provider, const char* name) { auto fullPath = CRYPTOHELPER_CERTS_DIR "/" + std::string(name) + ".pem"; @@ -78,7 +79,7 @@ cloudprotocol::CertificateInfo CreateCert(CryptoProviderItf& provider, const cha AssertOK(fs::ReadFileToString(fullPath.c_str(), pem)); AssertOK(provider.PEMToX509Certs(pem, chain)); - cloudprotocol::CertificateInfo cert; + CertificateInfo cert; cert.mFingerprint = name; cert.mCertificate = chain[0].mRaw; @@ -86,9 +87,9 @@ cloudprotocol::CertificateInfo CreateCert(CryptoProviderItf& provider, const cha return cert; } -cloudprotocol::CertificateChainInfo CreateCertChain(const char* name, const std::vector fingerprints) +CertificateChainInfo CreateCertChain(const char* name, const std::vector fingerprints) { - cloudprotocol::CertificateChainInfo chain; + CertificateChainInfo chain; chain.mName = name; @@ -99,9 +100,9 @@ cloudprotocol::CertificateChainInfo CreateCertChain(const char* name, const std: return chain; } -cloudprotocol::SignInfo CreateSigns(const char* chainName, const char* algName) +SignInfo CreateSigns(const char* chainName, const char* algName) { - cloudprotocol::SignInfo signs; + SignInfo signs; signs.mChainName = chainName; signs.mAlg = algName; @@ -176,9 +177,9 @@ TEST_F(CryptoHelperTest, ServiceDiscoveryURLs) TEST_F(CryptoHelperTest, Decrypt) { struct TestData { - const char* mEncryptedFile; - cloudprotocol::DecryptInfo mDecryptInfo; - std::vector mDecryptedContent; + const char* mEncryptedFile; + DecryptInfo mDecryptInfo; + std::vector mDecryptedContent; }; std::vector testData = { @@ -203,9 +204,9 @@ TEST_F(CryptoHelperTest, Decrypt) TEST_F(CryptoHelperTest, ValidateSigns) { struct TestData { - std::vector mCerts; - cloudprotocol::CertificateChainInfo mChain; - cloudprotocol::SignInfo mSigns; + std::vector mCerts; + CertificateChainInfo mChain; + SignInfo mSigns; }; constexpr auto cDecryptedFile = CRYPTOHELPER_CERTS_DIR "/hello-world.txt"; @@ -237,10 +238,10 @@ TEST_F(CryptoHelperTest, ValidateSigns) CreateSigns("onlineTest2", "RSA/SHA256/PKCS1v1_5")}}; for (const auto& item : testData) { - StaticArray certs; - certs = Array(item.mCerts.data(), item.mCerts.size()); + StaticArray certs; + certs = Array(item.mCerts.data(), item.mCerts.size()); - StaticArray chains; + StaticArray chains; chains.PushBack(item.mChain); ASSERT_TRUE(mCryptoHelper.ValidateSigns(cDecryptedFile, item.mSigns, chains, certs).IsNone()); diff --git a/src/core/common/crypto/tests/cryptoprovider.cpp b/src/core/common/crypto/tests/cryptoprovider.cpp index 0d8d7a705..0cb895bb4 100644 --- a/src/core/common/crypto/tests/cryptoprovider.cpp +++ b/src/core/common/crypto/tests/cryptoprovider.cpp @@ -6,7 +6,6 @@ #include -#include #include #include #include @@ -295,8 +294,8 @@ TEST_P(CryptoProviderTest, CreateSelfSignedCert) TEST_P(CryptoProviderTest, CreateCSRUsingECKey) { - aos::crypto::x509::CSR templ; - const char* subjectName = "CN=Test Subject, O=Org, C=GB"; + x509::CSR templ; + const char* subjectName = "CN=Test Subject, O=Org, C=GB"; ASSERT_EQ(mCryptoProvider->ASN1EncodeDN(subjectName, templ.mSubject), aos::ErrorEnum::eNone); templ.mDNSNames.Resize(2); @@ -819,7 +818,7 @@ TEST_P(CryptoProviderTest, VerifyRSASignature) pubKey.SetValue(static_cast(privKey->GetPublic())); EXPECT_TRUE( - mCryptoProvider->Verify(pubKey, HashEnum::eSHA256, PaddingEnum::ePKCS1v1_5, digest, signature).IsNone()); + mCryptoProvider->Verify(pubKey, HashEnum::eSHA256, x509::PaddingEnum::ePKCS1v1_5, digest, signature).IsNone()); } TEST_P(CryptoProviderTest, VerifyECDSASignature) @@ -849,12 +848,13 @@ TEST_P(CryptoProviderTest, VerifyECDSASignature) Variant pubKey; pubKey.SetValue(static_cast(privKey->GetPublic())); - EXPECT_TRUE(mCryptoProvider->Verify(pubKey, HashEnum::eSHA384, PaddingEnum::eNone, digest, signature).IsNone()); + EXPECT_TRUE( + mCryptoProvider->Verify(pubKey, HashEnum::eSHA384, x509::PaddingEnum::eNone, digest, signature).IsNone()); } TEST_P(CryptoProviderTest, VerifyCertChain) { - StaticString buff; + StaticString buff; StaticArray rootCerts; ASSERT_TRUE(fs::ReadFileToString(TEST_CERTIFICATES_DIR "/ca.cer", buff).IsNone()); @@ -870,7 +870,7 @@ TEST_P(CryptoProviderTest, VerifyCertChain) ASSERT_TRUE(fs::ReadFileToString(TEST_CERTIFICATES_DIR "/client.cer", buff).IsNone()); ASSERT_TRUE(mCryptoProvider->PEMToX509Certs(buff, leafCerts).IsNone()); - VerifyOptions opts; + x509::VerifyOptions opts; opts.mCurrentTime = Time(); ASSERT_TRUE(mCryptoProvider->Verify(rootCerts, intermCerts, opts, leafCerts[0]).IsNone()); @@ -878,7 +878,7 @@ TEST_P(CryptoProviderTest, VerifyCertChain) TEST_P(CryptoProviderTest, VerifyCertChainCurTimeExceeds) { - StaticString buff; + StaticString buff; StaticArray rootCerts; ASSERT_TRUE(fs::ReadFileToString(TEST_CERTIFICATES_DIR "/ca.cer", buff).IsNone()); @@ -894,7 +894,7 @@ TEST_P(CryptoProviderTest, VerifyCertChainCurTimeExceeds) ASSERT_TRUE(fs::ReadFileToString(TEST_CERTIFICATES_DIR "/client.cer", buff).IsNone()); ASSERT_TRUE(mCryptoProvider->PEMToX509Certs(buff, leafCerts).IsNone()); - VerifyOptions opts; + x509::VerifyOptions opts; opts.mCurrentTime = Time::Now().Add(Years(2)); ASSERT_FALSE(mCryptoProvider->Verify(rootCerts, intermCerts, opts, leafCerts[0]).IsNone()); diff --git a/src/core/common/crypto/tests/cryptoutils.cpp b/src/core/common/crypto/tests/cryptoutils.cpp index 51f03c368..81a812566 100644 --- a/src/core/common/crypto/tests/cryptoutils.cpp +++ b/src/core/common/crypto/tests/cryptoutils.cpp @@ -7,7 +7,7 @@ #include -#include +#include #include #include #include @@ -51,8 +51,8 @@ class CryptoutilsTest : public Test { ASSERT_TRUE(err.IsNone()); // read certificates - StaticArray derBlob; - crypto::x509::Certificate caCert, clientCert; + StaticArray derBlob; + x509::Certificate caCert, clientCert; ASSERT_TRUE(fs::ReadFile(CERTIFICATES_DIR "/ca.cer.der", derBlob).IsNone()); ASSERT_TRUE(mCryptoProvider->DERToX509Cert(derBlob, caCert).IsNone()); @@ -93,11 +93,12 @@ class CryptoutilsTest : public Test { pkcs11::SlotID mSlotID = 0; SharedPtr mLibrary; - crypto::CertLoader mCertLoader; + CertLoader mCertLoader; StaticAllocator + 2 * sizeof(x509::Certificate) + sizeof(x509::CertificateChain) + + 2 * sizeof(pkcs11::PKCS11RSAPrivateKey)) + + sizeof(CertLoader)> mAllocator; }; @@ -238,8 +239,8 @@ TEST_F(CryptoutilsTest, FindPKCS11CertificateChain) "path=" SOFTHSM2_LIB "&pin-source=" + std::string(mPINSource); - SharedPtr chain; - Error error = ErrorEnum::eNone; + SharedPtr chain; + Error error = ErrorEnum::eNone; Tie(chain, error) = mCertLoader.LoadCertsChainByURL(url.c_str()); ASSERT_TRUE(error.IsNone()); @@ -247,11 +248,11 @@ TEST_F(CryptoutilsTest, FindPKCS11CertificateChain) ASSERT_EQ(chain->Size(), 2); // check client certificate - aos::StaticString subject; + StaticString subject; ASSERT_TRUE(mCryptoProvider->ASN1DecodeDN((*chain)[0].mSubject, subject).IsNone()); EXPECT_EQ(std::string(subject.CStr()), std::string("CN=Aos Core")); - aos::StaticString issuer; + StaticString issuer; ASSERT_TRUE(mCryptoProvider->ASN1DecodeDN((*chain)[0].mIssuer, issuer).IsNone()); EXPECT_EQ(std::string(issuer.CStr()), std::string("CN=Aos Cloud")); @@ -273,8 +274,8 @@ TEST_F(CryptoutilsTest, FindPKCS11CertificateChainBadURL) "path=" SOFTHSM2_LIB "&pin-source=" + std::string(mPINSource); - SharedPtr chain; - Error error = ErrorEnum::eNone; + SharedPtr chain; + Error error = ErrorEnum::eNone; Tie(chain, error) = mCertLoader.LoadCertsChainByURL(url.c_str()); ASSERT_TRUE(error.Is(ErrorEnum::eNotFound)); @@ -290,8 +291,8 @@ TEST_F(CryptoutilsTest, FindPKCS11PrivateKey) "path=" SOFTHSM2_LIB "&pin-source=" + std::string(mPINSource); - SharedPtr privKey; - Error error = ErrorEnum::eNone; + SharedPtr privKey; + Error error = ErrorEnum::eNone; Tie(privKey, error) = mCertLoader.LoadPrivKeyByURL(url.c_str()); ASSERT_TRUE(error.IsNone()); @@ -308,8 +309,8 @@ TEST_F(CryptoutilsTest, FindPKCS11PrivateKeyBadURL) "path=" SOFTHSM2_LIB "&pin-source=" + std::string(mPINSource); - SharedPtr privKey; - Error error = ErrorEnum::eNone; + SharedPtr privKey; + Error error = ErrorEnum::eNone; Tie(privKey, error) = mCertLoader.LoadPrivKeyByURL(url.c_str()); ASSERT_TRUE(error.Is(ErrorEnum::eNotFound)); @@ -319,8 +320,8 @@ TEST_F(CryptoutilsTest, FindCertificatesFromFile) { const char* url = "file:" CERTIFICATES_DIR "/client-ca-chain.pem"; - SharedPtr chain; - Error error = ErrorEnum::eNone; + SharedPtr chain; + Error error = ErrorEnum::eNone; Tie(chain, error) = mCertLoader.LoadCertsChainByURL(url); ASSERT_TRUE(error.IsNone()); @@ -328,11 +329,11 @@ TEST_F(CryptoutilsTest, FindCertificatesFromFile) ASSERT_EQ(chain->Size(), 2); // check client certificate - aos::StaticString subject; + StaticString subject; ASSERT_TRUE(mCryptoProvider->ASN1DecodeDN((*chain)[0].mSubject, subject).IsNone()); EXPECT_EQ(std::string(subject.CStr()), std::string("CN=Aos Core")); - aos::StaticString issuer; + StaticString issuer; ASSERT_TRUE(mCryptoProvider->ASN1DecodeDN((*chain)[0].mIssuer, issuer).IsNone()); EXPECT_EQ(std::string(issuer.CStr()), std::string("CN=Aos Cloud")); diff --git a/src/core/common/tests/mocks/cryptomock.hpp b/src/core/common/tests/mocks/cryptomock.hpp index c8c6f0c94..fa53897d0 100644 --- a/src/core/common/tests/mocks/cryptomock.hpp +++ b/src/core/common/tests/mocks/cryptomock.hpp @@ -10,8 +10,8 @@ #include -#include #include +#include namespace aos::crypto { @@ -54,7 +54,8 @@ class ProviderMock : public ProviderItf { MOCK_METHOD(Error, ASN1DecodeOctetString, (const Array&, Array&), (override)); MOCK_METHOD(Error, ASN1DecodeOID, (const Array&, Array&), (override)); MOCK_METHOD(Error, Verify, - ((const Variant&), Hash, Padding, const Array&, const Array&), + ((const Variant&), Hash, x509::Padding, const Array&, + const Array&), (override)); MOCK_METHOD(Error, Verify, (const Array&, const Array&, const VerifyOptions&, const Certificate&), (override)); From 35d8dc6de75878e6b47002852e236990e94bd71e Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Thu, 9 Oct 2025 16:47:41 +0300 Subject: [PATCH 7/8] common: add WITH_TEST_TOOLS to provide test tools with disabled tests Signed-off-by: Mykola Kobets Reviewed-by: Mykhailo Lohvynenko Reviewed-by: Oleksandr Grytsov Reviewed-by: Mykola Solianko --- CMakeLists.txt | 2 ++ src/core/common/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d479eb26..794a9c036 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,8 @@ set(CMAKE_CXX_STANDARD 17) set(VERSION_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +set(WITH_TEST_TOOLS ${WITH_TEST}) + if(WITH_TEST) find_package(GTest REQUIRED) diff --git a/src/core/common/CMakeLists.txt b/src/core/common/CMakeLists.txt index bcb2e370e..13834a784 100644 --- a/src/core/common/CMakeLists.txt +++ b/src/core/common/CMakeLists.txt @@ -64,7 +64,7 @@ add_subdirectory(tools) add_subdirectory(types) add_subdirectory(version) -if(WITH_TEST) +if(WITH_TEST_TOOLS) add_subdirectory(tests) endif() From 7b8815c912d0f1f84bf1da1b617f121385528cf7 Mon Sep 17 00:00:00 2001 From: Mykola Kobets Date: Sun, 12 Oct 2025 01:23:21 +0300 Subject: [PATCH 8/8] crypto: add crypto documentation Signed-off-by: Mykola Kobets Reviewed-by: Mykhailo Lohvynenko Reviewed-by: Oleksandr Grytsov Reviewed-by: Mykola Solianko --- src/core/common/crypto/crypto.md | 268 +++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 src/core/common/crypto/crypto.md diff --git a/src/core/common/crypto/crypto.md b/src/core/common/crypto/crypto.md new file mode 100644 index 000000000..d29258527 --- /dev/null +++ b/src/core/common/crypto/crypto.md @@ -0,0 +1,268 @@ +# Crypto Module Documentation + +This document describes the crypto module in the AOS Core Library, including its interfaces, architecture, and usage. + +## Overview + +The crypto module provides a comprehensive set of interfaces for cryptographic operations including hashing, encryption, digital signatures, certificate handling, ASN.1 parsing, and random number generation. + +### Crypto Module Implementations + +The crypto module implements a dual-backend architecture, providing two complete implementations: + +- **MbedTLS Implementation**: lightweight, embedded-focused cryptographic library +- **OpenSSL Implementation**: full-featured, enterprise-grade cryptographic library + +### Build Configuration + +The implementation is selected at build time using CMake flags: + +- `WITH_MBEDTLS=ON` (default): Enables MbedTLS implementation +- `WITH_OPENSSL=ON`: Enables OpenSSL implementation +- Both can be enabled simultaneously for testing/comparison purposes + +### Default CryptoProvider + +The module provides a unified `CryptoProviderItf` that abstracts the underlying implementation. The `DefaultCryptoProvider` alias is used to instantiate the interface with the same name regardless of the build configuration. + +## Interface Descriptions + +### UUIDItf + +UUID generation interface for creating unique identifiers. + +**Methods:** + +- `CreateUUIDv4()`: Creates a UUID version 4 +- `CreateUUIDv5(space, name)`: Creates a UUID version 5 based on namespace and name + +### AES Interfaces + +AES encryption and decryption interfaces for AES cryptographic operations. + +#### AESCipherItf + +AES cipher interface for encrypting and decrypting data blocks using the AES algorithm. + +**Methods:** + +- `EncryptBlock(input, output)`: Encrypts a data block +- `DecryptBlock(input, output)`: Decrypts a data block +- `Finalize(output)`: Finalizes encryption/decryption + +#### AESEncoderDecoderItf + +Factory interface for creating AES encoders and decoders. + +**Methods:** + +- `CreateAESEncoder(mode, key, iv)`: Creates a new AES encoder +- `CreateAESDecoder(mode, key, iv)`: Creates a new AES decoder + +### Hash Interfaces + +Hash computation interfaces for cryptographic hashing operations. + +#### HashItf + +Interface for hash computation operations. + +**Methods:** + +- `Update(data)`: Updates hash with input data +- `Finalize(hash)`: Finalizes hash computation and returns result + +#### HasherItf + +Hash factory interface for creating hash instances. + +**Methods:** + +- `CreateHash(algorithm)`: Creates a hash instance for specified algorithm + +**Types:** + +- `Hash`: Hash algorithm type used to specify which hash function to use. Supported algorithms: `eSHA1`, `eSHA224`, `eSHA256`, `eSHA384`, `eSHA512`, `eSHA512_224`, `eSHA512_256`, `eSHA3_224`, `eSHA3_256`, `eNONE` + +### Private/Public Key Interfaces + +Private/Public key interfaces for asymmetric cryptographic operations. Currently supports RSA and ECDSA keys. + +#### PublicKeyItf + +Public key interface for key type identification and comparison. + +**Methods:** + +- `GetKeyType()`: Returns the type of the public key +- `IsEqual(pubKey)`: Tests whether current key is equal to the provided one + +#### PrivateKeyItf + +Private key operations interface for signing and decryption. + +**Methods:** + +- `GetPublic()`: Returns public part of a private key +- `Sign(digest, options, signature)`: Calculates a signature of a given digest +- `Decrypt(cipher, options, result)`: Decrypts a cipher message + +**Types:** + +- `SignOptions`: Signature options contain optional hash algorithm to be used +- `DecryptionOptions`: Decryption options that can be either `PKCS1v15DecryptionOptions` or `OAEPDecryptionOptions` (used with RSA keys only) + +#### RSAPublicKey + +RSA public key structure containing modulus and exponent. + +**Methods:** + +- `GetN()`: Returns RSA modulus +- `GetE()`: Returns RSA public exponent + +#### ECDSAPublicKey + +ECDSA public key structure containing curve parameters and point. + +**Methods:** + +- `GetECParamsOID()`: Returns ECDSA parameters OID +- `GetECPoint()`: Returns ECDSA point + +### ASN.1 Interfaces + +ASN.1 interfaces for parsing and encoding ASN.1 data structures. + +#### ASN1HandlerItf + +ASN.1 element handler interface for processing ASN.1 elements. + +**Methods:** + +- `OnASN1Element(value)`: Handles ASN.1 element + +#### ASN1DecoderItf + +ASN.1 decoder interface for parsing ASN.1 structures. + +**Methods:** + +- `ReadStruct(data, opt, asn1reader)`: Reads ASN.1 SEQUENCE +- `ReadSet(data, opt, asn1reader)`: Reads ASN.1 SET +- `ReadSequence(data, opt, asn1reader)`: Reads ASN.1 SEQUENCE +- `ReadInteger(data, opt, value)`: Reads ASN.1 INTEGER +- `ReadBigInt(data, opt, result)`: Reads ASN.1 big integer +- `ReadOID(data, opt, oid)`: Reads ASN.1 object identifier +- `ReadAID(data, opt, aid)`: Reads algorithm identifier +- `ReadOctetString(data, opt, result)`: Reads ASN.1 octet string +- `ReadRawValue(data, opt, result)`: Reads raw ASN.1 value + +**Types:** + +- `ASN1Value`: ASN.1 value structure +- `ASN1ParseResult`: ASN.1 parsing result +- `ASN1ParseOptions`: ASN.1 parsing options +- `ObjectIdentifier`: ASN.1 object identifier type +- `Extension`: ASN.1 extension structure + +### RandomItf + +Random number generator interface for generating random data. + +**Methods:** + +- `RandInt(maxValue)`: Generates random integer in range [0..maxValue] +- `RandBuffer(buffer, size)`: Generates random buffer + +### CertLoaderItf + +Interface for loading certificates and private keys from URLs. Currently supports file URLs (file: prefix) and PKCS#11 URLs (pkcs11: prefix). + +**Methods:** + +- `LoadCertsChainByURL(url)`: Loads certificate chain by URL +- `LoadPrivKeyByURL(url)`: Loads private key by URL + +### CryptoHelperItf + +Interface for decrypting and validating cloud data. + +**Methods:** + +- `Decrypt(encryptedPath, decryptedPath, decryptionInfo)`: Decrypts file using decryption information +- `ValidateSigns(decryptedPath, signs, chains, certs)`: Validates digital signatures +- `DecryptMetadata(input, output)`: Decrypts metadata from binary buffer + +### ProviderItf (x509) + +X.509 certificate provider interface for certificate operations. + +**Methods:** + +- `CreateCertificate(templ, parent, privKey, pemCert)`: Creates certificate from template +- `CreateClientCert(csr, caKey, caCert, serial, clientCert)`: Creates client certificate +- `PEMToX509Certs(pemBlob, resultCerts)`: Reads certificates from PEM +- `X509CertToPEM(certificate, dst)`: Serializes certificate to PEM +- `PEMToX509PrivKey(pemBlob)`: Reads private key from PEM +- `DERToX509Cert(derBlob, resultCert)`: Reads certificate from DER +- `CreateCSR(templ, privKey, pemCSR)`: Creates certificate signing request +- `ASN1EncodeDN(commonName, result)`: Constructs distinguished name +- `ASN1DecodeDN(dn, result)`: Returns text representation of DN +- `ASN1EncodeObjectIds(src, asn1Value)`: Encodes object identifiers +- `ASN1EncodeBigInt(number, asn1Value)`: Encodes big integer +- `ASN1EncodeDERSequence(items, asn1Value)`: Creates ASN.1 sequence +- `ASN1DecodeOctetString(src, dst)`: Decodes octet string +- `ASN1DecodeOID(inOID, dst)`: Decodes object identifier +- `Verify(pubKey, hashFunc, padding, digest, signature)`: Verifies digital signature +- `Verify(rootCerts, intermCerts, options, cert)`: Verifies certificate chain + +**Note:** Methods starting with "ASN1" will be relocated to a dedicated ASN1 interface in future versions. + +**Types:** + +- `Certificate`: X.509 certificate structure +- `CSR`: Certificate signing request structure +- `CertificateChain`: Certificate chain type +- `PaddingType`: Padding types (PKCS1v1.5, PSS, None) +- `VerifyOptions`: Certificate verification options + +## Utility Functions + +### URL Parsing Functions + +- `ParseURLScheme(url, scheme)`: Parses scheme part of URL +- `ParseFileURL(url, path)`: Parses URL with file scheme +- `ParsePKCS11URL(url, library, token, label, id, userPin)`: Parses PKCS#11 URL + +### PKCS#11 Functions + +- `EncodePKCS11ID(id, idStr)`: Encodes PKCS#11 ID to percent-encoded string +- `DecodeToPKCS11ID(idStr, id)`: Decodes PKCS#11 ID from percent-encoded string + +### ASN.1 Utility Functions + +- `ConvertTimeToASN1Str(time)`: Converts time to ASN.1 GeneralizedTime string + +## Summary + +This document provided information about all the crypto interfaces available in the AOS Core Library crypto module: + +`UUIDItf`, `AESCipherItf`, `AESEncoderDecoderItf`, `HashItf`, `HasherItf`, `PublicKeyItf`, `PrivateKeyItf`, `RSAPublicKey`, `ECDSAPublicKey`, `ProviderItf` (x509), `ASN1HandlerItf`, `ASN1DecoderItf`, `RandomItf`, `CertLoaderItf`, `CryptoHelperItf` + +### Example Usage + +```cpp +// Create crypto provider +auto cryptoProvider = DefaultCryptoProvider(); + +// Get random number generator +auto randomItf = cryptoProvider->GetRandom(); + +// Generate random integer +auto randomValue = randomItf->RandInt(100); + +// Generate random buffer +Array buffer; +randomItf->RandBuffer(buffer, 32); +```