@@ -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
451462CHIP_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
461478CHIP_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
471492CHIP_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
487517CHIP_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
499536void 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