@@ -480,6 +480,99 @@ static void run_plug_sha256_compression_tests(void) {
480480 secp256k1_context_destroy (ctx_cloned );
481481}
482482
483+ static void run_sha256_multi_block_compression_tests (void ) {
484+ secp256k1_hash_ctx hash_ctx ;
485+ secp256k1_sha256 sha256_one ;
486+ secp256k1_sha256 sha256_two ;
487+ unsigned char out_one [32 ], out_two [32 ];
488+
489+ hash_ctx .fn_sha256_compression = secp256k1_sha256_transform ;
490+
491+ { /* 1) Writing one 64-byte full block vs two 32-byte blocks */
492+ const unsigned char data [64 ] = "totally serious test message to hash, definitely no random data" ;
493+ unsigned char data32 [32 ];
494+
495+ secp256k1_sha256_initialize (& sha256_one );
496+ secp256k1_sha256_initialize (& sha256_two );
497+
498+ /* Write the 64-byte block */
499+ secp256k1_sha256_write (& hash_ctx , & sha256_one , data , 64 );
500+ secp256k1_sha256_finalize (& hash_ctx , & sha256_one , out_one );
501+
502+ /* Write the two 32-byte blocks */
503+ memcpy (data32 , data , 32 );
504+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data32 , 32 );
505+ memcpy (data32 , data + 32 , 32 );
506+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data32 , 32 );
507+ secp256k1_sha256_finalize (& hash_ctx , & sha256_two , out_two );
508+
509+ CHECK (secp256k1_memcmp_var (out_one , out_two , 32 ) == 0 );
510+ }
511+
512+ { /* 2) Writing one 80-byte block vs two 40-byte blocks */
513+ const unsigned char data [80 ] = "Genesis: The Times 03/Jan/2009 Chancellor on brink of second bailout for banks " ;
514+ unsigned char data40 [40 ];
515+
516+ secp256k1_sha256_initialize (& sha256_one );
517+ secp256k1_sha256_initialize (& sha256_two );
518+
519+ /* Write the 80-byte block */
520+ secp256k1_sha256_write (& hash_ctx , & sha256_one , data , 80 );
521+ secp256k1_sha256_finalize (& hash_ctx , & sha256_one , out_one );
522+
523+ /* Write the two 40-byte blocks */
524+ memcpy (data40 , data , 40 );
525+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data40 , 40 );
526+ memcpy (data40 , data + 40 , 40 );
527+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data40 , 40 );
528+ secp256k1_sha256_finalize (& hash_ctx , & sha256_two , out_two );
529+
530+ CHECK (secp256k1_memcmp_var (out_one , out_two , 32 ) == 0 );
531+ }
532+
533+ { /* 3) Writing multiple consecutive full blocks in one write (128 bytes) */
534+ unsigned char data [128 ];
535+ unsigned char i ;
536+ for (i = 0 ; i < 128 ; i ++ ) data [i ] = i ;
537+
538+ secp256k1_sha256_initialize (& sha256_one );
539+ secp256k1_sha256_initialize (& sha256_two );
540+
541+ /* Single write of 128 bytes (two full 64-byte blocks) */
542+ secp256k1_sha256_write (& hash_ctx , & sha256_one , data , 128 );
543+ secp256k1_sha256_finalize (& hash_ctx , & sha256_one , out_one );
544+
545+ /* Two separate writes of 64 bytes each */
546+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data , 64 );
547+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data + 64 , 64 );
548+ secp256k1_sha256_finalize (& hash_ctx , & sha256_two , out_two );
549+
550+ CHECK (secp256k1_memcmp_var (out_one , out_two , 32 ) == 0 );
551+ }
552+
553+ { /* 4) Mixed small + large writes in sequence */
554+ unsigned char data [150 ];
555+ unsigned char i ;
556+ for (i = 0 ; i < 150 ; i ++ ) data [i ] = i ;
557+
558+ secp256k1_sha256_initialize (& sha256_one );
559+ secp256k1_sha256_initialize (& sha256_two );
560+
561+ /* Single write of 150 bytes */
562+ secp256k1_sha256_write (& hash_ctx , & sha256_one , data , 150 );
563+ secp256k1_sha256_finalize (& hash_ctx , & sha256_one , out_one );
564+
565+ /* Split writes: 10, 64, 64, 12 bytes */
566+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data , 10 );
567+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data + 10 , 64 );
568+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data + 74 , 64 );
569+ secp256k1_sha256_write (& hash_ctx , & sha256_two , data + 138 , 12 );
570+ secp256k1_sha256_finalize (& hash_ctx , & sha256_two , out_two );
571+
572+ CHECK (secp256k1_memcmp_var (out_one , out_two , 32 ) == 0 );
573+ }
574+ }
575+
483576static void run_ctz_tests (void ) {
484577 static const uint32_t b32 [] = {1 , 0xffffffff , 0x5e56968f , 0xe0d63129 };
485578 static const uint64_t b64 [] = {1 , 0xffffffffffffffff , 0xbcd02462139b3fc3 , 0x98b5f80c769693ef };
@@ -7764,6 +7857,7 @@ static const struct tf_test_entry tests_general[] = {
77647857 CASE (deprecated_context_flags_test ),
77657858 CASE (scratch_tests ),
77667859 CASE (plug_sha256_compression_tests ),
7860+ CASE (sha256_multi_block_compression_tests ),
77677861};
77687862
77697863static const struct tf_test_entry tests_integer [] = {
0 commit comments