Line data Source code
1 : /*
2 : * Code originally from LibTomCrypt -- Licensed under the Public Domain/WTFPL2.0
3 : */
4 :
5 : #include "sha512.h"
6 : #include "sha.h"
7 :
8 : /* the K array */
9 : static const uint64_t K[80] = {
10 : CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
11 : CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
12 : CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
13 : CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
14 : CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
15 : CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
16 : CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
17 : CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
18 : CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
19 : CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
20 : CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
21 : CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
22 : CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
23 : CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
24 : CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
25 : CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
26 : CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
27 : CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
28 : CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
29 : CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
30 : CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
31 : CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
32 : CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
33 : CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
34 : CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
35 : CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
36 : CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
37 : CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
38 : CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
39 : CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
40 : CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
41 : CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
42 : CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
43 : CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
44 : CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
45 : CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
46 : CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
47 : CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
48 : CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
49 : CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)};
50 :
51 : /* Various logical functions */
52 : #define Ch(x, y, z) (z ^ (x & (y ^ z)))
53 : #define Maj(x, y, z) (((x | y) & z) | (x & y))
54 : #define S(x, n) ROR64c(x, n)
55 : #define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF)) >> ((uint64_t)n))
56 : #define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
57 : #define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
58 : #define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
59 : #define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
60 :
61 : /* compress 1024-bits */
62 0 : static void sha512_compress(sha512_context *md, const uint8_t *buf)
63 : {
64 0 : uint64_t S[8], W[80], t0, t1;
65 0 : int i;
66 :
67 : /* copy state into S */
68 0 : for (i = 0; i < 8; i++) {
69 0 : S[i] = md->state[i];
70 : }
71 :
72 : /* copy the state into 1024-bits into W[0..15] */
73 0 : for (i = 0; i < 16; i++) {
74 0 : LOAD64H(W[i], buf + (8 * i));
75 : }
76 :
77 : /* fill W[16..79] */
78 0 : for (i = 16; i < 80; i++) {
79 0 : W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
80 : }
81 :
82 : /* Compress */
83 : #define RND(a, b, c, d, e, f, g, h, i) \
84 : t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
85 : t1 = Sigma0(a) + Maj(a, b, c); \
86 : d += t0; \
87 : h = t0 + t1;
88 :
89 0 : for (i = 0; i < 80; i += 8) {
90 0 : RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i + 0);
91 0 : RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], i + 1);
92 0 : RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], i + 2);
93 0 : RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], i + 3);
94 0 : RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], i + 4);
95 0 : RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], i + 5);
96 0 : RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], i + 6);
97 0 : RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], i + 7);
98 : }
99 :
100 : /* feedback */
101 0 : for (i = 0; i < 8; i++) {
102 0 : md->state[i] = md->state[i] + S[i];
103 : }
104 0 : }
105 :
106 0 : void sha512_init(sha512_context *md)
107 : {
108 0 : md->curlen = 0;
109 0 : md->length = 0;
110 0 : md->state[0] = CONST64(0x6a09e667f3bcc908);
111 0 : md->state[1] = CONST64(0xbb67ae8584caa73b);
112 0 : md->state[2] = CONST64(0x3c6ef372fe94f82b);
113 0 : md->state[3] = CONST64(0xa54ff53a5f1d36f1);
114 0 : md->state[4] = CONST64(0x510e527fade682d1);
115 0 : md->state[5] = CONST64(0x9b05688c2b3e6c1f);
116 0 : md->state[6] = CONST64(0x1f83d9abfb41bd6b);
117 0 : md->state[7] = CONST64(0x5be0cd19137e2179);
118 0 : }
119 :
120 0 : void sha512_process(sha512_context *md, const uint8_t *in, size_t inlen)
121 : {
122 0 : size_t n;
123 0 : if (md->curlen > sizeof(md->buf)) {
124 : return;
125 : }
126 0 : if ((md->length + inlen) < md->length) {
127 : return;
128 : }
129 0 : while (inlen > 0) {
130 0 : if (md->curlen == 0 && inlen >= 128) {
131 0 : sha512_compress(md, in);
132 0 : md->length += 128 * 8;
133 0 : in += 128;
134 0 : inlen -= 128;
135 : } else {
136 0 : n = (((inlen) < ((128u - md->curlen))) ? (inlen)
137 : : ((128u - md->curlen)));
138 0 : memcpy(md->buf + md->curlen, in, (size_t)n);
139 0 : md->curlen += n;
140 0 : in += n;
141 0 : inlen -= n;
142 0 : if (md->curlen == 128) {
143 0 : sha512_compress(md, md->buf);
144 0 : md->length += 8 * 128;
145 0 : md->curlen = 0;
146 : }
147 : }
148 : }
149 : }
150 :
151 0 : void sha512_done(sha512_context *md, uint8_t *out)
152 : {
153 0 : int i;
154 :
155 0 : if (md->curlen >= sizeof(md->buf)) {
156 : return;
157 : }
158 :
159 : /* increase the length of the message */
160 0 : md->length += md->curlen * CONST64(8);
161 :
162 : /* append the '1' bit */
163 0 : md->buf[md->curlen++] = (uint8_t)0x80;
164 :
165 : /* if the length is currently above 112 bytes we append zeros
166 : * then compress. Then we can fall back to padding zeros and length
167 : * encoding like normal.
168 : */
169 0 : if (md->curlen > 112) {
170 0 : while (md->curlen < 128) {
171 0 : md->buf[md->curlen++] = (uint8_t)0;
172 : }
173 0 : sha512_compress(md, md->buf);
174 0 : md->curlen = 0;
175 : }
176 :
177 : /* pad upto 120 bytes of zeroes
178 : * note: that from 112 to 120 is the 64 MSB of the length. We assume that
179 : * you won't hash > 2^64 bits of data... :-)
180 : */
181 0 : while (md->curlen < 120) {
182 0 : md->buf[md->curlen++] = (uint8_t)0;
183 : }
184 :
185 : /* store length */
186 0 : STORE64H(md->length, md->buf + 120);
187 0 : sha512_compress(md, md->buf);
188 :
189 : /* copy output */
190 0 : for (i = 0; i < 8; i++) {
191 0 : STORE64H(md->state[i], out + (8 * i));
192 : }
193 : }
194 :
195 0 : void sha512_hash(const uint8_t *data, size_t len, uint8_t *digest)
196 : {
197 0 : sha512_context md;
198 0 : sha512_init(&md);
199 0 : sha512_process(&md, data, len);
200 0 : sha512_done(&md, digest);
201 0 : }
|