Skip to content

Commit 44499b4

Browse files
authored
Migrate from deprecated OpenSSL SHA256_* APIs to EVP APIs (project-chip#36386)
* Migrate from deprecated OpenSSL SHA256_* APIs to EVP APIs * Integrating comments
1 parent 5e101e0 commit 44499b4

File tree

2 files changed

+67
-18
lines changed

2 files changed

+67
-18
lines changed

src/crypto/CHIPCryptoPAL.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,9 @@ class Hash_SHA256_stream
942942

943943
private:
944944
HashSHA256OpaqueContext mContext;
945+
#if CHIP_CRYPTO_BORINGSSL || CHIP_CRYPTO_OPENSSL
946+
bool mInitialized = false;
947+
#endif
945948
};
946949

947950
class HKDF_sha

src/crypto/CHIPCryptoPALOpenSSL.cpp

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -433,71 +433,115 @@ CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * o
433433
return CHIP_NO_ERROR;
434434
}
435435

436-
Hash_SHA256_stream::Hash_SHA256_stream() {}
436+
// For OpenSSL, we store a pointer to the digest context (EVP_MD_CTX) since EVP_MD_CTX is Opaque.
437+
static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(void *),
438+
"kMAX_Hash_SHA256_Context_Size needs to at least be able to store a pointer");
437439

438-
Hash_SHA256_stream::~Hash_SHA256_stream()
440+
// Storing a pointer to EVP_MD_CTX in HashSHA256OpaqueContext instead of the actual EVP_MD_CTX structure, as EVP_MD_CTX was made
441+
// opaque by OpenSSL and is dynamically allocated.
442+
static inline void set_inner_hash_evp_md_ctx(HashSHA256OpaqueContext * context, EVP_MD_CTX * evp_ctx)
439443
{
440-
Clear();
444+
*SafePointerCast<EVP_MD_CTX **>(context) = evp_ctx;
441445
}
442446

443-
static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(SHA256_CTX),
444-
"kMAX_Hash_SHA256_Context_Size is too small for the size of underlying SHA256_CTX");
447+
static inline EVP_MD_CTX * to_inner_hash_evp_md_ctx(HashSHA256OpaqueContext * context)
448+
{
449+
return *SafePointerCast<EVP_MD_CTX **>(context);
450+
}
445451

446-
static inline SHA256_CTX * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context)
452+
Hash_SHA256_stream::Hash_SHA256_stream() : mInitialized(false)
447453
{
448-
return SafePointerCast<SHA256_CTX *>(context);
454+
set_inner_hash_evp_md_ctx(&mContext, nullptr);
455+
}
456+
457+
Hash_SHA256_stream::~Hash_SHA256_stream()
458+
{
459+
Clear();
449460
}
450461

451462
CHIP_ERROR Hash_SHA256_stream::Begin()
452463
{
453-
SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext);
454464

455-
const int result = SHA256_Init(context);
465+
EVP_MD_CTX * mdctx = EVP_MD_CTX_new();
466+
VerifyOrReturnError(mdctx != nullptr, CHIP_ERROR_INTERNAL);
467+
468+
set_inner_hash_evp_md_ctx(&mContext, mdctx);
469+
470+
const int result = EVP_DigestInit_ex(mdctx, _digestForType(DigestType::SHA256), nullptr);
471+
456472
VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
473+
mInitialized = true;
457474

458475
return CHIP_NO_ERROR;
459476
}
460477

461478
CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data)
462479
{
463-
SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext);
480+
VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED);
481+
482+
EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
483+
VerifyOrReturnError(mdctx != nullptr, CHIP_ERROR_INTERNAL);
484+
485+
const int result = EVP_DigestUpdate(mdctx, data.data(), data.size());
464486

465-
const int result = SHA256_Update(context, Uint8::to_const_uchar(data.data()), data.size());
466487
VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
467488

468489
return CHIP_NO_ERROR;
469490
}
470491

471492
CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer)
472493
{
473-
SHA256_CTX * context = to_inner_hash_sha256_context(&mContext);
474494

475-
// Back-up context as we are about to finalize the hash to extract digest.
476-
SHA256_CTX previous_ctx = *context;
495+
VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED);
496+
497+
EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
498+
499+
// Back-up the context as we are about to finalize the hash to extract digest.
500+
EVP_MD_CTX * previous_mdctx = EVP_MD_CTX_new();
501+
VerifyOrReturnError(previous_mdctx != nullptr, CHIP_ERROR_INTERNAL);
502+
const int copy_result = EVP_MD_CTX_copy_ex(previous_mdctx, mdctx);
503+
VerifyOrReturnError(copy_result == 1, CHIP_ERROR_INTERNAL);
477504

478505
// Pad + compute digest, then finalize context. It is restored next line to continue.
479506
CHIP_ERROR result = Finish(out_buffer);
480507

481-
// Restore context prior to finalization.
482-
*context = previous_ctx;
508+
// free the finalized context.
509+
EVP_MD_CTX_free(mdctx);
510+
511+
// Restore the backed up context, to be able to get intermediate digest again if needed
512+
set_inner_hash_evp_md_ctx(&mContext, previous_mdctx);
483513

484514
return result;
485515
}
486516

487517
CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer)
488518
{
519+
unsigned int size;
520+
489521
VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
522+
VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED);
523+
524+
EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
525+
526+
const int result = EVP_DigestFinal_ex(mdctx, out_buffer.data(), &size);
490527

491-
SHA256_CTX * const context = to_inner_hash_sha256_context(&mContext);
492-
const int result = SHA256_Final(Uint8::to_uchar(out_buffer.data()), context);
493528
VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
529+
VerifyOrReturnError(size == kSHA256_Hash_Length, CHIP_ERROR_INTERNAL);
530+
494531
out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length);
495532

496533
return CHIP_NO_ERROR;
497534
}
498535

499536
void Hash_SHA256_stream::Clear()
500537
{
538+
EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
539+
540+
// EVP_MD_CTX_free does nothing if a nullptr is passed to it
541+
EVP_MD_CTX_free(mdctx);
542+
set_inner_hash_evp_md_ctx(&mContext, nullptr);
543+
544+
mInitialized = false;
501545
OPENSSL_cleanse(this, sizeof(*this));
502546
}
503547

@@ -1405,6 +1449,8 @@ void Spake2p_P256_SHA256_HKDF_HMAC::Clear()
14051449
BN_CTX_free(context->bn_ctx);
14061450
}
14071451

1452+
sha256_hash_ctx.Clear();
1453+
14081454
free_point(M);
14091455
free_point(N);
14101456
free_point(X);

0 commit comments

Comments
 (0)