573 lines
21 KiB
Nim
573 lines
21 KiB
Nim
#
|
|
#
|
|
# NimCrypto
|
|
# (c) Copyright 2016 Eugene Kabanov
|
|
#
|
|
# See the file "LICENSE", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
## This module implements SHA2 (Secure Hash Algorithm 2) set of cryptographic
|
|
## hash functions designed by National Security Agency, version FIPS-180-4.
|
|
## [http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf]
|
|
##
|
|
## Tests made according to official test vectors
|
|
## [http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf].
|
|
|
|
import hash, utils
|
|
|
|
{.deadCodeElim:on.}
|
|
|
|
const
|
|
## Compile with ``-d:smallcode`` to generate smaller code footprint
|
|
smallCode = defined(smallcode)
|
|
|
|
K0 = [
|
|
0x428a2f98'u32, 0x71374491'u32, 0xb5c0fbcf'u32, 0xe9b5dba5'u32,
|
|
0x3956c25b'u32, 0x59f111f1'u32, 0x923f82a4'u32, 0xab1c5ed5'u32,
|
|
0xd807aa98'u32, 0x12835b01'u32, 0x243185be'u32, 0x550c7dc3'u32,
|
|
0x72be5d74'u32, 0x80deb1fe'u32, 0x9bdc06a7'u32, 0xc19bf174'u32,
|
|
0xe49b69c1'u32, 0xefbe4786'u32, 0x0fc19dc6'u32, 0x240ca1cc'u32,
|
|
0x2de92c6f'u32, 0x4a7484aa'u32, 0x5cb0a9dc'u32, 0x76f988da'u32,
|
|
0x983e5152'u32, 0xa831c66d'u32, 0xb00327c8'u32, 0xbf597fc7'u32,
|
|
0xc6e00bf3'u32, 0xd5a79147'u32, 0x06ca6351'u32, 0x14292967'u32,
|
|
0x27b70a85'u32, 0x2e1b2138'u32, 0x4d2c6dfc'u32, 0x53380d13'u32,
|
|
0x650a7354'u32, 0x766a0abb'u32, 0x81c2c92e'u32, 0x92722c85'u32,
|
|
0xa2bfe8a1'u32, 0xa81a664b'u32, 0xc24b8b70'u32, 0xc76c51a3'u32,
|
|
0xd192e819'u32, 0xd6990624'u32, 0xf40e3585'u32, 0x106aa070'u32,
|
|
0x19a4c116'u32, 0x1e376c08'u32, 0x2748774c'u32, 0x34b0bcb5'u32,
|
|
0x391c0cb3'u32, 0x4ed8aa4a'u32, 0x5b9cca4f'u32, 0x682e6ff3'u32,
|
|
0x748f82ee'u32, 0x78a5636f'u32, 0x84c87814'u32, 0x8cc70208'u32,
|
|
0x90befffa'u32, 0xa4506ceb'u32, 0xbef9a3f7'u32, 0xc67178f2'u32
|
|
]
|
|
|
|
K1 = [
|
|
0x428a2f98d728ae22'u64, 0x7137449123ef65cd'u64, 0xb5c0fbcfec4d3b2f'u64,
|
|
0xe9b5dba58189dbbc'u64, 0x3956c25bf348b538'u64, 0x59f111f1b605d019'u64,
|
|
0x923f82a4af194f9b'u64, 0xab1c5ed5da6d8118'u64, 0xd807aa98a3030242'u64,
|
|
0x12835b0145706fbe'u64, 0x243185be4ee4b28c'u64, 0x550c7dc3d5ffb4e2'u64,
|
|
0x72be5d74f27b896f'u64, 0x80deb1fe3b1696b1'u64, 0x9bdc06a725c71235'u64,
|
|
0xc19bf174cf692694'u64, 0xe49b69c19ef14ad2'u64, 0xefbe4786384f25e3'u64,
|
|
0x0fc19dc68b8cd5b5'u64, 0x240ca1cc77ac9c65'u64, 0x2de92c6f592b0275'u64,
|
|
0x4a7484aa6ea6e483'u64, 0x5cb0a9dcbd41fbd4'u64, 0x76f988da831153b5'u64,
|
|
0x983e5152ee66dfab'u64, 0xa831c66d2db43210'u64, 0xb00327c898fb213f'u64,
|
|
0xbf597fc7beef0ee4'u64, 0xc6e00bf33da88fc2'u64, 0xd5a79147930aa725'u64,
|
|
0x06ca6351e003826f'u64, 0x142929670a0e6e70'u64, 0x27b70a8546d22ffc'u64,
|
|
0x2e1b21385c26c926'u64, 0x4d2c6dfc5ac42aed'u64, 0x53380d139d95b3df'u64,
|
|
0x650a73548baf63de'u64, 0x766a0abb3c77b2a8'u64, 0x81c2c92e47edaee6'u64,
|
|
0x92722c851482353b'u64, 0xa2bfe8a14cf10364'u64, 0xa81a664bbc423001'u64,
|
|
0xc24b8b70d0f89791'u64, 0xc76c51a30654be30'u64, 0xd192e819d6ef5218'u64,
|
|
0xd69906245565a910'u64, 0xf40e35855771202a'u64, 0x106aa07032bbd1b8'u64,
|
|
0x19a4c116b8d2d0c8'u64, 0x1e376c085141ab53'u64, 0x2748774cdf8eeb99'u64,
|
|
0x34b0bcb5e19b48a8'u64, 0x391c0cb3c5c95a63'u64, 0x4ed8aa4ae3418acb'u64,
|
|
0x5b9cca4f7763e373'u64, 0x682e6ff3d6b2b8a3'u64, 0x748f82ee5defb2fc'u64,
|
|
0x78a5636f43172f60'u64, 0x84c87814a1f0ab72'u64, 0x8cc702081a6439ec'u64,
|
|
0x90befffa23631e28'u64, 0xa4506cebde82bde9'u64, 0xbef9a3f7b2c67915'u64,
|
|
0xc67178f2e372532b'u64, 0xca273eceea26619c'u64, 0xd186b8c721c0c207'u64,
|
|
0xeada7dd6cde0eb1e'u64, 0xf57d4f7fee6ed178'u64, 0x06f067aa72176fba'u64,
|
|
0x0a637dc5a2c898a6'u64, 0x113f9804bef90dae'u64, 0x1b710b35131c471b'u64,
|
|
0x28db77f523047d84'u64, 0x32caab7b40c72493'u64, 0x3c9ebe0a15c9bebc'u64,
|
|
0x431d67c49c100d4c'u64, 0x4cc5d4becb3e42b6'u64, 0x597f299cfc657e2a'u64,
|
|
0x5fcb6fab3ad6faec'u64, 0x6c44198c4a475817'u64
|
|
]
|
|
|
|
template CH0(x, y, z): uint32 =
|
|
((x) and (y)) xor (not(x) and (z))
|
|
template MAJ0(x, y, z): uint32 =
|
|
((x) and (y)) xor ((x) and (z)) xor ((y) and (z))
|
|
template CH1(x, y, z): uint64 =
|
|
((x) and (y)) xor (not(x) and (z))
|
|
template MAJ1(x, y, z): uint64 =
|
|
((x) and (y)) xor ((x) and (z)) xor ((y) and (z))
|
|
template TAU0(x: uint32): uint32 =
|
|
(ROR(x, 2) xor ROR(x, 13) xor ROR(x, 22))
|
|
template TAU1(x: uint32): uint32 =
|
|
(ROR(x, 6) xor ROR(x, 11) xor ROR(x, 25))
|
|
template SIG0(x): uint32 =
|
|
ROR(x, 7) xor ROR(x, 18) xor (x shr 3)
|
|
template SIG1(x): uint32 =
|
|
ROR(x, 17) xor ROR(x, 19) xor (x shr 10)
|
|
template PHI0(x): uint64 =
|
|
ROR(x, 28) xor ROR(x, 34) xor ROR(x, 39)
|
|
template PHI1(x): uint64 =
|
|
ROR(x, 14) xor ROR(x, 18) xor ROR(x, 41)
|
|
template RHO0(x): uint64 =
|
|
ROR(x, 1) xor ROR(x, 8) xor (x shr 7)
|
|
template RHO1(x): uint64 =
|
|
ROR(x, 19) xor ROR(x, 61) xor (x shr 6)
|
|
|
|
type
|
|
Sha2Context*[bits: static[int],
|
|
bsize: static[int],
|
|
T: uint32|uint64] = object
|
|
count: array[2, T]
|
|
state: array[8, T]
|
|
buffer: array[bsize, byte]
|
|
|
|
sha224* = Sha2Context[224, 64, uint32]
|
|
sha256* = Sha2Context[256, 64, uint32]
|
|
sha384* = Sha2Context[384, 128, uint64]
|
|
sha512* = Sha2Context[512, 128, uint64]
|
|
sha512_224* = Sha2Context[224, 128, uint64]
|
|
sha512_256* = Sha2Context[256, 128, uint64]
|
|
sha2* = sha224 | sha256 | sha384 | sha512 | sha512_224 | sha512_256
|
|
|
|
template sizeDigest*(ctx: Sha2Context): uint =
|
|
(ctx.bits div 8)
|
|
|
|
template sizeBlock*(ctx: Sha2Context): uint =
|
|
(ctx.bsize)
|
|
|
|
template sizeDigest*(r: typedesc[sha2]): int =
|
|
when r is sha224 or r is sha512_224:
|
|
(28)
|
|
elif r is sha256 or r is sha512_256:
|
|
(32)
|
|
elif r is sha384:
|
|
(48)
|
|
elif r is sha512:
|
|
(64)
|
|
|
|
template sizeBlock*(r: typedesc[sha2]): int =
|
|
when r is sha224 or r is sha256:
|
|
(64)
|
|
else:
|
|
(128)
|
|
|
|
proc init*(ctx: var Sha2Context) =
|
|
ctx.count[0] = 0
|
|
ctx.count[1] = 0
|
|
when ctx.bits == 224 and ctx.bsize == 64:
|
|
ctx.state[0] = 0xC1059ED8'u32
|
|
ctx.state[1] = 0x367CD507'u32
|
|
ctx.state[2] = 0x3070DD17'u32
|
|
ctx.state[3] = 0xF70E5939'u32
|
|
ctx.state[4] = 0xFFC00B31'u32
|
|
ctx.state[5] = 0x68581511'u32
|
|
ctx.state[6] = 0x64F98FA7'u32
|
|
ctx.state[7] = 0xBEFA4FA4'u32
|
|
elif ctx.bits == 256 and ctx.bsize == 64:
|
|
ctx.state[0] = 0x6A09E667'u32
|
|
ctx.state[1] = 0xBB67AE85'u32
|
|
ctx.state[2] = 0x3C6EF372'u32
|
|
ctx.state[3] = 0xA54FF53A'u32
|
|
ctx.state[4] = 0x510E527F'u32
|
|
ctx.state[5] = 0x9B05688C'u32
|
|
ctx.state[6] = 0x1F83D9AB'u32
|
|
ctx.state[7] = 0x5BE0CD19'u32
|
|
elif ctx.bits == 384 and ctx.bsize == 128:
|
|
ctx.state[0] = 0xCBBB9D5DC1059ED8'u64
|
|
ctx.state[1] = 0x629A292A367CD507'u64
|
|
ctx.state[2] = 0x9159015A3070DD17'u64
|
|
ctx.state[3] = 0x152FECD8F70E5939'u64
|
|
ctx.state[4] = 0x67332667FFC00B31'u64
|
|
ctx.state[5] = 0x8EB44A8768581511'u64
|
|
ctx.state[6] = 0xDB0C2E0D64F98FA7'u64
|
|
ctx.state[7] = 0x47B5481DBEFA4FA4'u64
|
|
elif ctx.bits == 512 and ctx.bsize == 128:
|
|
ctx.state[0] = 0x6A09E667F3BCC908'u64
|
|
ctx.state[1] = 0xBB67AE8584CAA73B'u64
|
|
ctx.state[2] = 0x3C6EF372FE94F82B'u64
|
|
ctx.state[3] = 0xA54FF53A5F1D36F1'u64
|
|
ctx.state[4] = 0x510E527FADE682D1'u64
|
|
ctx.state[5] = 0x9B05688C2B3E6C1F'u64
|
|
ctx.state[6] = 0x1F83D9ABFB41BD6B'u64
|
|
ctx.state[7] = 0x5BE0CD19137E2179'u64
|
|
elif ctx.bits == 224 and ctx.bsize == 128:
|
|
ctx.state[0] = 0x8C3D37C819544DA2'u64
|
|
ctx.state[1] = 0x73E1996689DCD4D6'u64
|
|
ctx.state[2] = 0x1DFAB7AE32FF9C82'u64
|
|
ctx.state[3] = 0x679DD514582F9FCF'u64
|
|
ctx.state[4] = 0x0F6D2B697BD44DA8'u64
|
|
ctx.state[5] = 0x77E36F7304C48942'u64
|
|
ctx.state[6] = 0x3F9D85A86A1D36C8'u64
|
|
ctx.state[7] = 0x1112E6AD91D692A1'u64
|
|
elif ctx.bits == 256 and ctx.bsize == 128:
|
|
ctx.state[0] = 0x22312194FC2BF72C'u64
|
|
ctx.state[1] = 0x9F555FA3C84C64C2'u64
|
|
ctx.state[2] = 0x2393B86B6F53B151'u64
|
|
ctx.state[3] = 0x963877195940EABD'u64
|
|
ctx.state[4] = 0x96283EE2A88EFFE3'u64
|
|
ctx.state[5] = 0xBE5E1E2553863992'u64
|
|
ctx.state[6] = 0x2B0199FC2C85B8AA'u64
|
|
ctx.state[7] = 0x0EB72DDC81C52CA2'u64
|
|
|
|
proc clear*(ctx: var Sha2Context) {.inline.} =
|
|
burnMem(ctx)
|
|
|
|
when not smallCode:
|
|
template ROUND256(a, b, c, d, e, f, g, h, z) =
|
|
t0 = h + TAU1(e) + CH0(e, f, g) + K0[z] + W[z]
|
|
t1 = TAU0(a) + MAJ0(a, b, c)
|
|
d = d + t0
|
|
h = t0 + t1
|
|
|
|
template ROUND512(a, b, c, d, e, f, g, h, z) =
|
|
t0 = h + PHI1(e) + CH1(e, f, g) + K1[z] + W[z]
|
|
t1 = PHI0(a) + MAJ1(a, b, c)
|
|
d = d + t0
|
|
h = t0 + t1
|
|
|
|
proc sha256Transform(state: var array[8, uint32], data: ptr byte) =
|
|
var t0, t1: uint32
|
|
var W: array[64, uint32]
|
|
|
|
var i = 0
|
|
while i < 16:
|
|
W[i] = LSWAP(GET_DWORD(data, i))
|
|
inc(i)
|
|
while i < 64:
|
|
W[i] = SIG1(W[i - 2]) + W[i - 7] + SIG0(W[i - 15]) + W[i - 16]
|
|
inc(i)
|
|
|
|
var s0 = state[0]
|
|
var s1 = state[1]
|
|
var s2 = state[2]
|
|
var s3 = state[3]
|
|
var s4 = state[4]
|
|
var s5 = state[5]
|
|
var s6 = state[6]
|
|
var s7 = state[7]
|
|
|
|
when smallCode:
|
|
i = 0
|
|
while i < 64:
|
|
t0 = s7 + TAU1(s4) + CH0(s4, s5, s6) + K0[i] + W[i]
|
|
t1 = TAU0(s0) + MAJ0(s0, s1, s2)
|
|
s7 = s6
|
|
s6 = s5
|
|
s5 = s4
|
|
s4 = s3 + t0
|
|
s3 = s2
|
|
s2 = s1
|
|
s1 = s0
|
|
s0 = t0 + t1
|
|
inc(i)
|
|
else:
|
|
ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 0)
|
|
ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 1)
|
|
ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 2)
|
|
ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 3)
|
|
ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 4)
|
|
ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 5)
|
|
ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 6)
|
|
ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 7)
|
|
ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 8)
|
|
ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 9)
|
|
ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 10)
|
|
ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 11)
|
|
ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 12)
|
|
ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 13)
|
|
ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 14)
|
|
ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 15)
|
|
|
|
ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 16)
|
|
ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 17)
|
|
ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 18)
|
|
ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 19)
|
|
ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 20)
|
|
ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 21)
|
|
ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 22)
|
|
ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 23)
|
|
ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 24)
|
|
ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 25)
|
|
ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 26)
|
|
ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 27)
|
|
ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 28)
|
|
ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 29)
|
|
ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 30)
|
|
ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 31)
|
|
|
|
ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 32)
|
|
ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 33)
|
|
ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 34)
|
|
ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 35)
|
|
ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 36)
|
|
ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 37)
|
|
ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 38)
|
|
ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 39)
|
|
ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 40)
|
|
ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 41)
|
|
ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 42)
|
|
ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 43)
|
|
ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 44)
|
|
ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 45)
|
|
ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 46)
|
|
ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 47)
|
|
|
|
ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 48)
|
|
ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 49)
|
|
ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 50)
|
|
ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 51)
|
|
ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 52)
|
|
ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 53)
|
|
ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 54)
|
|
ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 55)
|
|
ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 56)
|
|
ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 57)
|
|
ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 58)
|
|
ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 59)
|
|
ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 60)
|
|
ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 61)
|
|
ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 62)
|
|
ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 63)
|
|
|
|
state[0] += s0
|
|
state[1] += s1
|
|
state[2] += s2
|
|
state[3] += s3
|
|
state[4] += s4
|
|
state[5] += s5
|
|
state[6] += s6
|
|
state[7] += s7
|
|
|
|
proc sha512Transform(state: var array[8, uint64], data: ptr byte) =
|
|
var t0, t1: uint64
|
|
var W: array[80, uint64]
|
|
|
|
var i = 0
|
|
while i < 16:
|
|
W[i] = LSWAP(GET_QWORD(data, i))
|
|
inc(i)
|
|
while i < 80:
|
|
W[i] = RHO1(W[i - 2]) + W[i - 7] + RHO0(W[i - 15]) + W[i - 16]
|
|
inc(i)
|
|
|
|
var s0 = state[0]
|
|
var s1 = state[1]
|
|
var s2 = state[2]
|
|
var s3 = state[3]
|
|
var s4 = state[4]
|
|
var s5 = state[5]
|
|
var s6 = state[6]
|
|
var s7 = state[7]
|
|
|
|
when smallCode:
|
|
i = 0
|
|
while i < 80:
|
|
t0 = s7 + PHI1(s4) + CH1(s4, s5, s6) + K1[i] + W[i]
|
|
t1 = PHI0(s0) + MAJ1(s0, s1, s2)
|
|
s7 = s6
|
|
s6 = s5
|
|
s5 = s4
|
|
s4 = s3 + t0
|
|
s3 = s2
|
|
s2 = s1
|
|
s1 = s0
|
|
s0 = t0 + t1
|
|
inc(i)
|
|
else:
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 0)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 1)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 2)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 3)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 4)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 5)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 6)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 7)
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 8)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 9)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 10)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 11)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 12)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 13)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 14)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 15)
|
|
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 16)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 17)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 18)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 19)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 20)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 21)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 22)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 23)
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 24)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 25)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 26)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 27)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 28)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 29)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 30)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 31)
|
|
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 32)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 33)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 34)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 35)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 36)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 37)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 38)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 39)
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 40)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 41)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 42)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 43)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 44)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 45)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 46)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 47)
|
|
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 48)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 49)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 50)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 51)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 52)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 53)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 54)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 55)
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 56)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 57)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 58)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 59)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 60)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 61)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 62)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 63)
|
|
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 64)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 65)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 66)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 67)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 68)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 69)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 70)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 71)
|
|
ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 72)
|
|
ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 73)
|
|
ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 74)
|
|
ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 75)
|
|
ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 76)
|
|
ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 77)
|
|
ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 78)
|
|
ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 79)
|
|
|
|
state[0] += s0
|
|
state[1] += s1
|
|
state[2] += s2
|
|
state[3] += s3
|
|
state[4] += s4
|
|
state[5] += s5
|
|
state[6] += s6
|
|
state[7] += s7
|
|
|
|
proc update*(ctx: var Sha2Context, data: ptr byte, inlen: uint) =
|
|
var pos = 0'u
|
|
var length = inlen
|
|
|
|
when ctx.bsize == 64:
|
|
while length > 0'u:
|
|
let offset = cast[uint](ctx.count[0] and 0x3F)
|
|
let size = min(64'u - offset, length)
|
|
copyMem(addr(ctx.buffer[offset]),
|
|
cast[pointer](cast[uint](data) + pos), size)
|
|
pos = pos + size
|
|
length = length - size
|
|
ctx.count[0] += cast[uint32](size)
|
|
if ctx.count[0] < cast[uint32](size):
|
|
ctx.count[1] += 1'u32
|
|
if (ctx.count[0] and 0x3F) == 0:
|
|
sha256Transform(ctx.state, addr(ctx.buffer[0]))
|
|
elif ctx.bsize == 128:
|
|
while length > 0'u:
|
|
let offset = cast[uint](ctx.count[0] and 0x7F)
|
|
let size = min(128'u - offset, length)
|
|
copyMem(addr(ctx.buffer[offset]),
|
|
cast[pointer](cast[uint](data) + pos), size)
|
|
pos = pos + size
|
|
length = length - size
|
|
ctx.count[0] += cast[uint64](size)
|
|
if ctx.count[0] < cast[uint64](size):
|
|
ctx.count[1] += 1'u64
|
|
if (ctx.count[0] and 0x7F) == 0:
|
|
sha512Transform(ctx.state, addr(ctx.buffer[0]))
|
|
|
|
proc update*[T: bchar](ctx: var Sha2Context, data: openarray[T]) =
|
|
if len(data) == 0:
|
|
ctx.update(nil, 0)
|
|
else:
|
|
ctx.update(cast[ptr byte](unsafeAddr data[0]), cast[uint](len(data)))
|
|
|
|
proc finalize256(ctx: var Sha2Context) =
|
|
var buffer = addr(ctx.buffer[0])
|
|
var j = int(ctx.count[0] and 0x3F)
|
|
ctx.buffer[j] = 0x80
|
|
inc(j)
|
|
while j != 56:
|
|
if j == 64:
|
|
sha256Transform(ctx.state, buffer)
|
|
j = 0
|
|
ctx.buffer[j] = 0x00
|
|
inc(j)
|
|
ctx.count[1] = (ctx.count[1] shl 3) + (ctx.count[0] shr 29)
|
|
ctx.count[0] = ctx.count[0] shl 3
|
|
SET_DWORD(buffer, 14, LSWAP(ctx.count[1]))
|
|
SET_DWORD(buffer, 15, LSWAP(ctx.count[0]))
|
|
sha256Transform(ctx.state, buffer)
|
|
|
|
proc finalize512(ctx: var Sha2Context) =
|
|
var buffer = addr(ctx.buffer[0])
|
|
var j = int(ctx.count[0] and 0x7F)
|
|
ctx.buffer[j] = 0x80
|
|
inc(j)
|
|
while j != 112:
|
|
if j == 128:
|
|
sha512Transform(ctx.state, buffer)
|
|
j = 0
|
|
ctx.buffer[j] = 0x00
|
|
inc(j)
|
|
ctx.count[1] = (ctx.count[1] shl 3) + (ctx.count[0] shr 29)
|
|
ctx.count[0] = ctx.count[0] shl 3
|
|
SET_QWORD(buffer, 14, LSWAP(ctx.count[1]))
|
|
SET_QWORD(buffer, 15, LSWAP(ctx.count[0]))
|
|
sha512Transform(ctx.state, buffer)
|
|
|
|
proc finish*(ctx: var Sha2Context, pBytes: ptr byte, nBytes: uint): uint =
|
|
result = 0
|
|
when ctx.bits == 224 and ctx.bsize == 64:
|
|
finalize256(ctx)
|
|
if nBytes >= 28'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..6:
|
|
SET_DWORD(pBytes, i, LSWAP(ctx.state[i]))
|
|
elif ctx.bits == 256 and ctx.bsize == 64:
|
|
finalize256(ctx)
|
|
if nBytes >= 32'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..7:
|
|
SET_DWORD(pBytes, i, LSWAP(ctx.state[i]))
|
|
elif ctx.bits == 384 and ctx.bsize == 128:
|
|
finalize512(ctx)
|
|
if nBytes >= 48'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..5:
|
|
SET_QWORD(pBytes, i, LSWAP(ctx.state[i]))
|
|
elif ctx.bits == 512 and ctx.bsize == 128:
|
|
finalize512(ctx)
|
|
if nBytes >= 64'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..7:
|
|
SET_QWORD(pBytes, i, LSWAP(ctx.state[i]))
|
|
elif ctx.bits == 256 and ctx.bsize == 128:
|
|
finalize512(ctx)
|
|
if nBytes >= 32'u:
|
|
result = sizeDigest(ctx)
|
|
for i in 0..3:
|
|
SET_QWORD(pBytes, i, LSWAP(ctx.state[i]))
|
|
elif ctx.bits == 224 and ctx.bsize == 128:
|
|
finalize512(ctx)
|
|
if nBytes >= 28'u:
|
|
result = sizeDigest(ctx)
|
|
SET_QWORD(pBytes, 0, LSWAP(ctx.state[0]))
|
|
SET_QWORD(pBytes, 1, LSWAP(ctx.state[1]))
|
|
SET_QWORD(pBytes, 2, LSWAP(ctx.state[2]))
|
|
SET_DWORD(pBytes, 6, cast[uint32](LSWAP(ctx.state[3])))
|
|
|
|
proc finish*(ctx: var Sha2Context): MDigest[ctx.bits] =
|
|
discard finish(ctx, cast[ptr byte](addr result.data[0]),
|
|
cast[uint](len(result.data)))
|
|
|
|
proc finish*[T: bchar](ctx: var Sha2Context, data: var openarray[T]) =
|
|
assert(cast[uint](len(data)) >= ctx.sizeDigest)
|
|
discard ctx.finish(cast[ptr byte](addr data[0]), cast[uint](len(data)))
|