From 21b2f65d3f69d1f0c0a5b40650a8f6f29cf21dfe Mon Sep 17 00:00:00 2001 From: cheatfate Date: Mon, 29 Dec 2025 17:21:48 +0200 Subject: [PATCH 1/2] Fix sha2 update() function crashes on uninitialized context. Add tests. --- nimcrypto/sha2/sha2.nim | 7 +++++++ tests/testsha2.nim | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/nimcrypto/sha2/sha2.nim b/nimcrypto/sha2/sha2.nim index 033df7e..2578439 100644 --- a/nimcrypto/sha2/sha2.nim +++ b/nimcrypto/sha2/sha2.nim @@ -81,6 +81,10 @@ func reset*(ctx: var Sha2Context) {.noinit.} = ctx.state[6] = 0x2B0199FC2C85B8AA'u64 ctx.state[7] = 0x0EB72DDC81C52CA2'u64 +template checkContext(ctx: var Sha2Context) = + doAssert(not(isNil(ctx.compressFunc)), + "Context should be initialized first!") + func getCompressFunction( Sha2ContextType: typedesc[sha224|sha256], implementation: Sha2Implementation, @@ -226,6 +230,8 @@ func clear*(ctx: var Sha2Context) {.noinit.} = burnMem(ctx) func update*[T: bchar](ctx: var Sha2Context, data: openArray[T]) {.noinit.} = + ctx.checkContext() + var pos = 0 bytesLeft = len(data) @@ -313,6 +319,7 @@ func finalize512(ctx: var Sha2Context) {.inline, noinit.} = func finish*(ctx: var Sha2Context, data: var openArray[byte]): uint {.noinit, discardable.} = + ctx.checkContext() when ctx.bits == 224 and ctx.bsize == 64: if len(data) >= 28: finalize256(ctx) diff --git a/tests/testsha2.nim b/tests/testsha2.nim index a873f18..1572f28 100644 --- a/tests/testsha2.nim +++ b/tests/testsha2.nim @@ -915,3 +915,31 @@ suite "SHA2 Tests": skip() else: check sha512.millionAtest2() == stripSpaces(digest1ma512) + + test "Uninitialized context crash test": + var + ctx1: sha224 + ctx2: sha256 + ctx3: sha384 + ctx4: sha512 + ctx5: sha512_224 + ctx6: sha512_256 + + template doCheck(a: untyped): untyped = + try: + a.update([0x00'u8]) + false + except AssertionDefect: + true + except CatchableError: + false + except Defect: + false + + check: + ctx1.doCheck() == true + ctx2.doCheck() == true + ctx3.doCheck() == true + ctx4.doCheck() == true + ctx5.doCheck() == true + ctx6.doCheck() == true From 3af8ad3c0b1cf3b404bd017a2875f0f97dd996e4 Mon Sep 17 00:00:00 2001 From: cheatfate Date: Tue, 30 Dec 2025 01:26:15 +0200 Subject: [PATCH 2/2] Add test for finish() operation. --- tests/testsha2.nim | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/testsha2.nim b/tests/testsha2.nim index 1572f28..f034115 100644 --- a/tests/testsha2.nim +++ b/tests/testsha2.nim @@ -916,7 +916,7 @@ suite "SHA2 Tests": else: check sha512.millionAtest2() == stripSpaces(digest1ma512) - test "Uninitialized context crash test": + test "Uninitialized context update()/finish() crash test": var ctx1: sha224 ctx2: sha256 @@ -925,7 +925,7 @@ suite "SHA2 Tests": ctx5: sha512_224 ctx6: sha512_256 - template doCheck(a: untyped): untyped = + template doCheckUpdate(a: untyped): untyped = try: a.update([0x00'u8]) false @@ -936,10 +936,29 @@ suite "SHA2 Tests": except Defect: false + template doCheckFinish(a: untyped): untyped = + try: + var digest: array[64, byte] + let count {.used.} = a.finish(digest) + false + except AssertionDefect: + true + except CatchableError: + false + except Defect: + false + + check: + ctx1.doCheckUpdate() == true + ctx2.doCheckUpdate() == true + ctx3.doCheckUpdate() == true + ctx4.doCheckUpdate() == true + ctx5.doCheckUpdate() == true + ctx6.doCheckUpdate() == true check: - ctx1.doCheck() == true - ctx2.doCheck() == true - ctx3.doCheck() == true - ctx4.doCheck() == true - ctx5.doCheck() == true - ctx6.doCheck() == true + ctx1.doCheckFinish() == true + ctx2.doCheckFinish() == true + ctx3.doCheckFinish() == true + ctx4.doCheckFinish() == true + ctx5.doCheckFinish() == true + ctx6.doCheckFinish() == true