diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 4339fd70f8aa4e..7b0b4c13eced44 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -26,6 +26,12 @@ #include #include +#if CHIP_CRYPTO_OPENSSL +#include +#elif CHIP_CRYPTO_MBEDTLS +#include +#endif + namespace chip { namespace Crypto { @@ -82,6 +88,31 @@ CHIP_ERROR AES_CCM_decrypt(const unsigned char * ciphertext, size_t ciphertext_l CHIP_ERROR Hash_SHA256(const unsigned char * data, const size_t data_length, unsigned char * out_buffer); +/** + * @brief A class that defines stream based implementation of SHA-256 hash + **/ + +class Hash_SHA256_stream +{ +public: + Hash_SHA256_stream(void); + ~Hash_SHA256_stream(void); + + CHIP_ERROR Begin(void); + CHIP_ERROR AddData(const unsigned char * data, const size_t data_length); + CHIP_ERROR Finish(unsigned char * out_buffer); + void Clear(void); + +private: +#if CHIP_CRYPTO_OPENSSL + SHA256_CTX context; +#elif CHIP_CRYPTO_MBEDTLS + mbedtls_sha256_context context; +#else + SHA256_CTX_PLATFORM context; // To be defined by the platform specific implementation of sha256. +#endif +}; + /** * @brief A function that implements SHA-256 based HKDF * @param secret The secret to use as the key to the HKDF diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index 0cbc76bc6daf7f..1ad43b1be1a75d 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -36,6 +36,9 @@ #include +namespace chip { +namespace Crypto { + #define kKeyLengthInBits 256 enum class DigestType @@ -48,8 +51,6 @@ enum class ECName P256v1 }; -using namespace chip::Crypto; - static_assert(kMax_ECDH_Secret_Length >= 32, "ECDH shared secret is too short"); static_assert(kMax_ECDSA_Signature_Length >= 72, "ECDSA signature buffer length is too short"); @@ -116,9 +117,9 @@ static const EVP_MD * _digestForType(DigestType digestType) } } -CHIP_ERROR chip::Crypto::AES_CCM_encrypt(const unsigned char * plaintext, size_t plaintext_length, const unsigned char * aad, - size_t aad_length, const unsigned char * key, size_t key_length, const unsigned char * iv, - size_t iv_length, unsigned char * ciphertext, unsigned char * tag, size_t tag_length) +CHIP_ERROR AES_CCM_encrypt(const unsigned char * plaintext, size_t plaintext_length, const unsigned char * aad, size_t aad_length, + const unsigned char * key, size_t key_length, const unsigned char * iv, size_t iv_length, + unsigned char * ciphertext, unsigned char * tag, size_t tag_length) { EVP_CIPHER_CTX * context = NULL; int bytesWritten = 0; @@ -193,9 +194,9 @@ CHIP_ERROR chip::Crypto::AES_CCM_encrypt(const unsigned char * plaintext, size_t return error; } -CHIP_ERROR chip::Crypto::AES_CCM_decrypt(const unsigned char * ciphertext, size_t ciphertext_length, const unsigned char * aad, - size_t aad_length, const unsigned char * tag, size_t tag_length, const unsigned char * key, - size_t key_length, const unsigned char * iv, size_t iv_length, unsigned char * plaintext) +CHIP_ERROR AES_CCM_decrypt(const unsigned char * ciphertext, size_t ciphertext_length, const unsigned char * aad, size_t aad_length, + const unsigned char * tag, size_t tag_length, const unsigned char * key, size_t key_length, + const unsigned char * iv, size_t iv_length, unsigned char * plaintext) { EVP_CIPHER_CTX * context = NULL; CHIP_ERROR error = CHIP_NO_ERROR; @@ -259,7 +260,7 @@ CHIP_ERROR chip::Crypto::AES_CCM_decrypt(const unsigned char * ciphertext, size_ return error; } -CHIP_ERROR chip::Crypto::Hash_SHA256(const unsigned char * data, const size_t data_length, unsigned char * out_buffer) +CHIP_ERROR Hash_SHA256(const unsigned char * data, const size_t data_length, unsigned char * out_buffer) { CHIP_ERROR error = CHIP_NO_ERROR; @@ -273,9 +274,54 @@ CHIP_ERROR chip::Crypto::Hash_SHA256(const unsigned char * data, const size_t da return error; } -CHIP_ERROR chip::Crypto::HKDF_SHA256(const unsigned char * secret, const size_t secret_length, const unsigned char * salt, - const size_t salt_length, const unsigned char * info, const size_t info_length, - unsigned char * out_buffer, size_t out_length) +Hash_SHA256_stream::Hash_SHA256_stream(void) {} + +Hash_SHA256_stream::~Hash_SHA256_stream(void) {} + +CHIP_ERROR Hash_SHA256_stream::Begin(void) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + result = SHA256_Init(&context); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + +exit: + return error; +} + +CHIP_ERROR Hash_SHA256_stream::AddData(const unsigned char * data, const size_t data_length) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + result = SHA256_Update(&context, data, data_length); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + +exit: + return error; +} + +CHIP_ERROR Hash_SHA256_stream::Finish(unsigned char * out_buffer) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + result = SHA256_Final(out_buffer, &context); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + +exit: + return error; +} + +void Hash_SHA256_stream::Clear(void) +{ + memset(this, 0, sizeof(*this)); +} + +CHIP_ERROR HKDF_SHA256(const unsigned char * secret, const size_t secret_length, const unsigned char * salt, + const size_t salt_length, const unsigned char * info, const size_t info_length, unsigned char * out_buffer, + size_t out_length) { EVP_PKEY_CTX * context; CHIP_ERROR error = CHIP_NO_ERROR; @@ -334,12 +380,12 @@ CHIP_ERROR chip::Crypto::HKDF_SHA256(const unsigned char * secret, const size_t return error; } -CHIP_ERROR chip::Crypto::add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold) +CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold) { return CHIP_NO_ERROR; } -CHIP_ERROR chip::Crypto::DRBG_get_bytes(unsigned char * out_buffer, const size_t out_length) +CHIP_ERROR DRBG_get_bytes(unsigned char * out_buffer, const size_t out_length) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; @@ -354,9 +400,8 @@ CHIP_ERROR chip::Crypto::DRBG_get_bytes(unsigned char * out_buffer, const size_t return error; } -CHIP_ERROR chip::Crypto::ECDSA_sign_msg(const unsigned char * msg, const size_t msg_length, const unsigned char * private_key, - const size_t private_key_length, unsigned char * out_signature, - size_t & out_signature_length) +CHIP_ERROR ECDSA_sign_msg(const unsigned char * msg, const size_t msg_length, const unsigned char * private_key, + const size_t private_key_length, unsigned char * out_signature, size_t & out_signature_length) { ERR_clear_error(); @@ -455,9 +500,9 @@ CHIP_ERROR chip::Crypto::ECDSA_sign_msg(const unsigned char * msg, const size_t return error; } -CHIP_ERROR chip::Crypto::ECDSA_validate_msg_signature(const unsigned char * msg, const size_t msg_length, - const unsigned char * public_key, const size_t public_key_length, - const unsigned char * signature, const size_t signature_length) +CHIP_ERROR ECDSA_validate_msg_signature(const unsigned char * msg, const size_t msg_length, const unsigned char * public_key, + const size_t public_key_length, const unsigned char * signature, + const size_t signature_length) { ERR_clear_error(); CHIP_ERROR error = CHIP_ERROR_INTERNAL; @@ -637,9 +682,9 @@ static CHIP_ERROR _create_evp_key_from_binary_p256_key(const unsigned char * key return error; } -CHIP_ERROR chip::Crypto::ECDH_derive_secret(const unsigned char * remote_public_key, const size_t remote_public_key_length, - const unsigned char * local_private_key, const size_t local_private_key_length, - unsigned char * out_secret, size_t & out_secret_length) +CHIP_ERROR ECDH_derive_secret(const unsigned char * remote_public_key, const size_t remote_public_key_length, + const unsigned char * local_private_key, const size_t local_private_key_length, + unsigned char * out_secret, size_t & out_secret_length) { ERR_clear_error(); CHIP_ERROR error = CHIP_NO_ERROR; @@ -700,3 +745,6 @@ CHIP_ERROR chip::Crypto::ECDH_derive_secret(const unsigned char * remote_public_ _logSSLError(); return error; } + +} // namespace Crypto +} // namespace chip diff --git a/src/crypto/CHIPCryptoPALmbedTLS.cpp b/src/crypto/CHIPCryptoPALmbedTLS.cpp index 00ef01d5641ca7..2be9cf40d835e4 100644 --- a/src/crypto/CHIPCryptoPALmbedTLS.cpp +++ b/src/crypto/CHIPCryptoPALmbedTLS.cpp @@ -38,6 +38,9 @@ #include +namespace chip { +namespace Crypto { + #define MAX_ERROR_STR_LEN 128 #define NUM_BYTES_IN_SHA256_HASH 32 @@ -79,9 +82,9 @@ static bool _isValidKeyLength(size_t length) return false; } -CHIP_ERROR chip::Crypto::AES_CCM_encrypt(const unsigned char * plaintext, size_t plaintext_length, const unsigned char * aad, - size_t aad_length, const unsigned char * key, size_t key_length, const unsigned char * iv, - size_t iv_length, unsigned char * ciphertext, unsigned char * tag, size_t tag_length) +CHIP_ERROR AES_CCM_encrypt(const unsigned char * plaintext, size_t plaintext_length, const unsigned char * aad, size_t aad_length, + const unsigned char * key, size_t key_length, const unsigned char * iv, size_t iv_length, + unsigned char * ciphertext, unsigned char * tag, size_t tag_length) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 1; @@ -117,9 +120,9 @@ CHIP_ERROR chip::Crypto::AES_CCM_encrypt(const unsigned char * plaintext, size_t return error; } -CHIP_ERROR chip::Crypto::AES_CCM_decrypt(const unsigned char * ciphertext, size_t ciphertext_len, const unsigned char * aad, - size_t aad_len, const unsigned char * tag, size_t tag_length, const unsigned char * key, - size_t key_length, const unsigned char * iv, size_t iv_length, unsigned char * plaintext) +CHIP_ERROR AES_CCM_decrypt(const unsigned char * ciphertext, size_t ciphertext_len, const unsigned char * aad, size_t aad_len, + const unsigned char * tag, size_t tag_length, const unsigned char * key, size_t key_length, + const unsigned char * iv, size_t iv_length, unsigned char * plaintext) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 1; @@ -155,10 +158,10 @@ CHIP_ERROR chip::Crypto::AES_CCM_decrypt(const unsigned char * ciphertext, size_ return error; } -CHIP_ERROR chip::Crypto::Hash_SHA256(const unsigned char * data, const size_t data_length, unsigned char * out_buffer) +CHIP_ERROR Hash_SHA256(const unsigned char * data, const size_t data_length, unsigned char * out_buffer) { CHIP_ERROR error = CHIP_NO_ERROR; - int result = 1; + int result = 0; // zero data length hash is supported. @@ -171,9 +174,54 @@ CHIP_ERROR chip::Crypto::Hash_SHA256(const unsigned char * data, const size_t da return error; } -CHIP_ERROR chip::Crypto::HKDF_SHA256(const unsigned char * secret, const size_t secret_length, const unsigned char * salt, - const size_t salt_length, const unsigned char * info, const size_t info_length, - unsigned char * out_buffer, size_t out_length) +Hash_SHA256_stream::Hash_SHA256_stream(void) {} + +Hash_SHA256_stream::~Hash_SHA256_stream(void) {} + +CHIP_ERROR Hash_SHA256_stream::Begin(void) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + result = mbedtls_sha256_starts_ret(&context, 0); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + return error; +} + +CHIP_ERROR Hash_SHA256_stream::AddData(const unsigned char * data, const size_t data_length) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + result = mbedtls_sha256_update_ret(&context, data, data_length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + return error; +} + +CHIP_ERROR Hash_SHA256_stream::Finish(unsigned char * out_buffer) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + result = mbedtls_sha256_finish_ret(&context, out_buffer); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + return error; +} + +void Hash_SHA256_stream::Clear(void) +{ + memset(this, 0, sizeof(*this)); +} + +CHIP_ERROR HKDF_SHA256(const unsigned char * secret, const size_t secret_length, const unsigned char * salt, + const size_t salt_length, const unsigned char * info, const size_t info_length, unsigned char * out_buffer, + size_t out_length) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 1; @@ -225,7 +273,7 @@ static EntropyContext * get_entropy_context() return context; } -CHIP_ERROR chip::Crypto::add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold) +CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; @@ -242,7 +290,7 @@ CHIP_ERROR chip::Crypto::add_entropy_source(entropy_source fn_source, void * p_s return error; } -CHIP_ERROR chip::Crypto::DRBG_get_bytes(unsigned char * out_buffer, const size_t out_length) +CHIP_ERROR DRBG_get_bytes(unsigned char * out_buffer, const size_t out_length) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; @@ -266,9 +314,8 @@ static int ECDSA_sign_rng(void * ctxt, unsigned char * out_buffer, size_t out_le return (chip::Crypto::DRBG_get_bytes(out_buffer, out_length) == CHIP_NO_ERROR) ? 0 : 1; } -CHIP_ERROR chip::Crypto::ECDSA_sign_msg(const unsigned char * msg, const size_t msg_length, const unsigned char * private_key, - const size_t private_key_length, unsigned char * out_signature, - size_t & out_signature_length) +CHIP_ERROR ECDSA_sign_msg(const unsigned char * msg, const size_t msg_length, const unsigned char * private_key, + const size_t private_key_length, unsigned char * out_signature, size_t & out_signature_length) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; @@ -310,9 +357,9 @@ CHIP_ERROR chip::Crypto::ECDSA_sign_msg(const unsigned char * msg, const size_t return error; } -CHIP_ERROR chip::Crypto::ECDSA_validate_msg_signature(const unsigned char * msg, const size_t msg_length, - const unsigned char * public_key, const size_t public_key_length, - const unsigned char * signature, const size_t signature_length) +CHIP_ERROR ECDSA_validate_msg_signature(const unsigned char * msg, const size_t msg_length, const unsigned char * public_key, + const size_t public_key_length, const unsigned char * signature, + const size_t signature_length) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; @@ -353,9 +400,9 @@ CHIP_ERROR chip::Crypto::ECDSA_validate_msg_signature(const unsigned char * msg, return error; } -CHIP_ERROR chip::Crypto::ECDH_derive_secret(const unsigned char * remote_public_key, const size_t remote_public_key_length, - const unsigned char * local_private_key, const size_t local_private_key_length, - unsigned char * out_secret, size_t & out_secret_length) +CHIP_ERROR ECDH_derive_secret(const unsigned char * remote_public_key, const size_t remote_public_key_length, + const unsigned char * local_private_key, const size_t local_private_key_length, + unsigned char * out_secret, size_t & out_secret_length) { CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; @@ -406,3 +453,6 @@ CHIP_ERROR chip::Crypto::ECDH_derive_secret(const unsigned char * remote_public_ _log_mbedTLS_error(result); return error; } + +} // namespace Crypto +} // namespace chip diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 19fa55697f1ff3..237a89a520ef59 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -505,6 +505,48 @@ static void TestHash_SHA256(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, numOfTestsExecuted == ArraySize(hash_sha256_test_vectors)); } +static void TestHash_SHA256_Stream(nlTestSuite * inSuite, void * inContext) +{ + int numOfTestCases = ArraySize(hash_sha256_test_vectors); + int numOfTestsExecuted = 0; + CHIP_ERROR error = CHIP_NO_ERROR; + + for (numOfTestsExecuted = 0; numOfTestsExecuted < numOfTestCases; numOfTestsExecuted++) + { + hash_sha256_vector v = hash_sha256_test_vectors[numOfTestsExecuted]; + const unsigned char * data = v.data; + size_t data_length = v.data_length; + unsigned char out_buffer[kSHA256_Hash_Length]; + + Hash_SHA256_stream sha256; + + error = sha256.Begin(); + NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); + + // Split data into 3 random streams. + for (int i = 0; i < 2; ++i) + { + size_t rand_data_length = rand() % (data_length + 1); + + error = sha256.AddData(data, rand_data_length); + NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); + + data += rand_data_length; + data_length -= rand_data_length; + } + + error = sha256.AddData(data, data_length); + NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); + + error = sha256.Finish(out_buffer); + NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR); + + bool success = memcmp(v.hash, out_buffer, sizeof(out_buffer)) == 0; + NL_TEST_ASSERT(inSuite, success); + } + NL_TEST_ASSERT(inSuite, numOfTestsExecuted == ArraySize(hash_sha256_test_vectors)); +} + static void TestHKDF_SHA256(nlTestSuite * inSuite, void * inContext) { int numOfTestCases = ArraySize(hkdf_sha256_test_vectors); @@ -864,6 +906,7 @@ static const nlTest sTests[] = { NL_TEST_DEF("Test ECDSA sign msg invalid parameters", TestECDSA_SigningInvalidParams), NL_TEST_DEF("Test ECDSA signature validation invalid parameters", TestECDSA_ValidationInvalidParam), NL_TEST_DEF("Test Hash SHA 256", TestHash_SHA256), + NL_TEST_DEF("Test Hash SHA 256 Stream", TestHash_SHA256_Stream), NL_TEST_DEF("Test HKDF SHA 256", TestHKDF_SHA256), NL_TEST_DEF("Test DRBG invalid inputs", TestDRBG_InvalidInputs), NL_TEST_DEF("Test DRBG output", TestDRBG_Output),