Skip to content

Commit

Permalink
Stream based implementation of SHA256 hash for openSSL and mbedTLS li…
Browse files Browse the repository at this point in the history
…braries. (project-chip#1252)

* Implemented SHA256 hash function based on openSSL and mbedTLS libraries.

* Added stream based implementation of SHA256 hash for openSSL and mbedTLS libraries.

* Generalized all functions in the CHIPCryptoPAL files belong to chip::Crypto namespace.
  • Loading branch information
emargolis authored Jun 25, 2020
1 parent c567d83 commit 1fd80b8
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 45 deletions.
31 changes: 31 additions & 0 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
#include <core/CHIPError.h>
#include <stddef.h>

#if CHIP_CRYPTO_OPENSSL
#include <openssl/sha.h>
#elif CHIP_CRYPTO_MBEDTLS
#include <mbedtls/sha256.h>
#endif

namespace chip {
namespace Crypto {

Expand Down Expand Up @@ -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
Expand Down
94 changes: 71 additions & 23 deletions src/crypto/CHIPCryptoPALOpenSSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@

#include <string.h>

namespace chip {
namespace Crypto {

#define kKeyLengthInBits 256

enum class DigestType
Expand All @@ -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");

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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();

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -700,3 +745,6 @@ CHIP_ERROR chip::Crypto::ECDH_derive_secret(const unsigned char * remote_public_
_logSSLError();
return error;
}

} // namespace Crypto
} // namespace chip
94 changes: 72 additions & 22 deletions src/crypto/CHIPCryptoPALmbedTLS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@

#include <string.h>

namespace chip {
namespace Crypto {

#define MAX_ERROR_STR_LEN 128
#define NUM_BYTES_IN_SHA256_HASH 32

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Loading

0 comments on commit 1fd80b8

Please sign in to comment.