From b33ec1364214476359a5dae300df9daf977b4864 Mon Sep 17 00:00:00 2001 From: Ryan McConnell Date: Sat, 29 Nov 2025 16:58:17 -0500 Subject: [PATCH 1/4] init --- nimcrypto/bcmode.nim | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/nimcrypto/bcmode.nim b/nimcrypto/bcmode.nim index 0cca060..02eccc5 100644 --- a/nimcrypto/bcmode.nim +++ b/nimcrypto/bcmode.nim @@ -70,8 +70,10 @@ type y: array[16, byte] basectr: array[16, byte] buf: array[16, byte] + ectr: array[16, byte] aadlen: uint64 datalen: uint64 + ectrUsed: int ## ECB (Electronic Code Book) Mode @@ -1083,6 +1085,12 @@ template sizeKey*[T](ctx: GCM[T]): int = mixin sizeKey sizeKey(ctx.cipher) +func refillEctr[T](ctx: var GCM[T]) {.inline.} = + ## Refresh keystream block and reset offset. + inc128(ctx.y) + ctx.cipher.encrypt(ctx.y, ctx.ectr) + ctx.ectrUsed = 0 + func init*[T]( ctx: var GCM[T], key: openArray[byte], @@ -1121,6 +1129,7 @@ func init*[T]( ctx.datalen = 0 if len(aad) > 0: ghash(ctx.buf, ctx.h, aad) + ctx.refillEctr() func encrypt*[T]( ctx: var GCM[T], @@ -1133,19 +1142,20 @@ func encrypt*[T]( ## Note that length of ``input`` must be less or equal to length of ## ``output``. Length of ``input`` must not be zero. mixin encrypt - var ectr: array[16, byte] assert(len(input) <= len(output)) var length = len(input) var offset = 0 ctx.datalen += uint64(length) while length > 0: - let uselen = if length < 16: length else: 16 - inc128(ctx.y) - ctx.cipher.encrypt(ctx.y, ectr) + if ctx.ectrUsed == 16: + ctx.refillEctr() + let available = 16 - ctx.ectrUsed + let uselen = if length < available: length else: available for i in 0.. 0: - let uselen = if length < 16: length else: 16 - inc128(ctx.y) - ctx.cipher.encrypt(ctx.y, ectr) + if ctx.ectrUsed == 16: + ctx.refillEctr() + let available = 16 - ctx.ectrUsed + let uselen = if length < available: length else: available for i in 0.. Date: Sat, 29 Nov 2025 18:18:37 -0500 Subject: [PATCH 2/4] chunked ghash --- nimcrypto/bcmode.nim | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/nimcrypto/bcmode.nim b/nimcrypto/bcmode.nim index 02eccc5..d1c36d6 100644 --- a/nimcrypto/bcmode.nim +++ b/nimcrypto/bcmode.nim @@ -74,6 +74,8 @@ type aadlen: uint64 datalen: uint64 ectrUsed: int + ghashPending: array[16, byte] + ghashUsed: int ## ECB (Electronic Code Book) Mode @@ -1091,6 +1093,31 @@ func refillEctr[T](ctx: var GCM[T]) {.inline.} = ctx.cipher.encrypt(ctx.y, ctx.ectr) ctx.ectrUsed = 0 +func updateGhash[T](ctx: var GCM[T], data: openArray[byte]) {.inline.} = + ## Process data into GHASH, buffering partial blocks until full. + var offset = 0 + var length = len(data) + + if ctx.ghashUsed > 0 and length > 0: + let toCopy = min(16 - ctx.ghashUsed, length) + copyMem(addr ctx.ghashPending[ctx.ghashUsed], unsafeAddr data[offset], toCopy) + ctx.ghashUsed += toCopy + offset += toCopy + length -= toCopy + if ctx.ghashUsed == 16: + ghash(ctx.buf, ctx.h, ctx.ghashPending) + ctx.ghashUsed = 0 + + let alignedLen = (length shr 4) shl 4 + if alignedLen > 0: + ghash(ctx.buf, ctx.h, data.toOpenArray(offset, offset + alignedLen - 1)) + offset += alignedLen + length -= alignedLen + + if length > 0: + copyMem(addr ctx.ghashPending[0], unsafeAddr data[offset], length) + ctx.ghashUsed = length + func init*[T]( ctx: var GCM[T], key: openArray[byte], @@ -1154,7 +1181,7 @@ func encrypt*[T]( let uselen = if length < available: length else: available for i in 0.. 0: copyMem(tag, 0, ctx.basectr, 0, uselen) + if ctx.ghashUsed > 0: + zeroMem(addr ctx.ghashPending[ctx.ghashUsed], 16 - ctx.ghashUsed) + ghash(ctx.buf, ctx.h, ctx.ghashPending) + ctx.ghashUsed = 0 beStore64(workbuf, 0, ctx.aadlen shl 3) beStore64(workbuf, 8, ctx.datalen shl 3) ghash(ctx.buf, ctx.h, workbuf) From 6dc34c65d8c20a9046d204c79300b96b8b2c376e Mon Sep 17 00:00:00 2001 From: Ryan McConnell Date: Sat, 29 Nov 2025 18:30:54 -0500 Subject: [PATCH 3/4] support in place --- nimcrypto/bcmode.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimcrypto/bcmode.nim b/nimcrypto/bcmode.nim index d1c36d6..2f083c0 100644 --- a/nimcrypto/bcmode.nim +++ b/nimcrypto/bcmode.nim @@ -1179,9 +1179,9 @@ func encrypt*[T]( ctx.refillEctr() let available = 16 - ctx.ectrUsed let uselen = if length < available: length else: available + ctx.updateGhash(output.toOpenArray(offset, offset + uselen - 1)) for i in 0.. Date: Sat, 29 Nov 2025 22:21:02 -0500 Subject: [PATCH 4/4] woops :) --- nimcrypto/bcmode.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimcrypto/bcmode.nim b/nimcrypto/bcmode.nim index 2f083c0..da225bd 100644 --- a/nimcrypto/bcmode.nim +++ b/nimcrypto/bcmode.nim @@ -1179,9 +1179,9 @@ func encrypt*[T]( ctx.refillEctr() let available = 16 - ctx.ectrUsed let uselen = if length < available: length else: available - ctx.updateGhash(output.toOpenArray(offset, offset + uselen - 1)) for i in 0..