1160814Ssimon/* crypto/sha/sha256.c */
2160814Ssimon/* ====================================================================
3160814Ssimon * Copyright (c) 2004 The OpenSSL Project.  All rights reserved
4160814Ssimon * according to the OpenSSL license [found in ../../LICENSE].
5160814Ssimon * ====================================================================
6160814Ssimon */
7160814Ssimon#include <openssl/opensslconf.h>
8160814Ssimon#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA256)
9160814Ssimon
10296341Sdelphij# include <stdlib.h>
11296341Sdelphij# include <string.h>
12160814Ssimon
13296341Sdelphij# include <openssl/crypto.h>
14296341Sdelphij# include <openssl/sha.h>
15296341Sdelphij# include <openssl/opensslv.h>
16160814Ssimon
17296341Sdelphijconst char SHA256_version[] = "SHA-256" OPENSSL_VERSION_PTEXT;
18160814Ssimon
19238405Sjkimfips_md_init_ctx(SHA224, SHA256)
20296341Sdelphij{
21296341Sdelphij    memset(c, 0, sizeof(*c));
22296341Sdelphij    c->h[0] = 0xc1059ed8UL;
23296341Sdelphij    c->h[1] = 0x367cd507UL;
24296341Sdelphij    c->h[2] = 0x3070dd17UL;
25296341Sdelphij    c->h[3] = 0xf70e5939UL;
26296341Sdelphij    c->h[4] = 0xffc00b31UL;
27296341Sdelphij    c->h[5] = 0x68581511UL;
28296341Sdelphij    c->h[6] = 0x64f98fa7UL;
29296341Sdelphij    c->h[7] = 0xbefa4fa4UL;
30296341Sdelphij    c->md_len = SHA224_DIGEST_LENGTH;
31296341Sdelphij    return 1;
32296341Sdelphij}
33160814Ssimon
34238405Sjkimfips_md_init(SHA256)
35296341Sdelphij{
36296341Sdelphij    memset(c, 0, sizeof(*c));
37296341Sdelphij    c->h[0] = 0x6a09e667UL;
38296341Sdelphij    c->h[1] = 0xbb67ae85UL;
39296341Sdelphij    c->h[2] = 0x3c6ef372UL;
40296341Sdelphij    c->h[3] = 0xa54ff53aUL;
41296341Sdelphij    c->h[4] = 0x510e527fUL;
42296341Sdelphij    c->h[5] = 0x9b05688cUL;
43296341Sdelphij    c->h[6] = 0x1f83d9abUL;
44296341Sdelphij    c->h[7] = 0x5be0cd19UL;
45296341Sdelphij    c->md_len = SHA256_DIGEST_LENGTH;
46296341Sdelphij    return 1;
47296341Sdelphij}
48160814Ssimon
49160814Ssimonunsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md)
50296341Sdelphij{
51296341Sdelphij    SHA256_CTX c;
52296341Sdelphij    static unsigned char m[SHA224_DIGEST_LENGTH];
53160814Ssimon
54296341Sdelphij    if (md == NULL)
55296341Sdelphij        md = m;
56296341Sdelphij    SHA224_Init(&c);
57296341Sdelphij    SHA256_Update(&c, d, n);
58296341Sdelphij    SHA256_Final(md, &c);
59296341Sdelphij    OPENSSL_cleanse(&c, sizeof(c));
60296341Sdelphij    return (md);
61296341Sdelphij}
62160814Ssimon
63160814Ssimonunsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md)
64296341Sdelphij{
65296341Sdelphij    SHA256_CTX c;
66296341Sdelphij    static unsigned char m[SHA256_DIGEST_LENGTH];
67160814Ssimon
68296341Sdelphij    if (md == NULL)
69296341Sdelphij        md = m;
70296341Sdelphij    SHA256_Init(&c);
71296341Sdelphij    SHA256_Update(&c, d, n);
72296341Sdelphij    SHA256_Final(md, &c);
73296341Sdelphij    OPENSSL_cleanse(&c, sizeof(c));
74296341Sdelphij    return (md);
75296341Sdelphij}
76160814Ssimon
77160814Ssimonint SHA224_Update(SHA256_CTX *c, const void *data, size_t len)
78296341Sdelphij{
79296341Sdelphij    return SHA256_Update(c, data, len);
80296341Sdelphij}
81160814Ssimon
82296341Sdelphijint SHA224_Final(unsigned char *md, SHA256_CTX *c)
83296341Sdelphij{
84296341Sdelphij    return SHA256_Final(md, c);
85296341Sdelphij}
86160814Ssimon
87296341Sdelphij# define DATA_ORDER_IS_BIG_ENDIAN
88296341Sdelphij
89296341Sdelphij# define HASH_LONG               SHA_LONG
90296341Sdelphij# define HASH_CTX                SHA256_CTX
91296341Sdelphij# define HASH_CBLOCK             SHA_CBLOCK
92160814Ssimon/*
93160814Ssimon * Note that FIPS180-2 discusses "Truncation of the Hash Function Output."
94160814Ssimon * default: case below covers for it. It's not clear however if it's
95160814Ssimon * permitted to truncate to amount of bytes not divisible by 4. I bet not,
96160814Ssimon * but if it is, then default: case shall be extended. For reference.
97160814Ssimon * Idea behind separate cases for pre-defined lenghts is to let the
98160814Ssimon * compiler decide if it's appropriate to unroll small loops.
99160814Ssimon */
100296341Sdelphij# define HASH_MAKE_STRING(c,s)   do {    \
101296341Sdelphij        unsigned long ll;               \
102296341Sdelphij        unsigned int  nn;               \
103296341Sdelphij        switch ((c)->md_len)            \
104296341Sdelphij        {   case SHA224_DIGEST_LENGTH:  \
105296341Sdelphij                for (nn=0;nn<SHA224_DIGEST_LENGTH/4;nn++)       \
106296341Sdelphij                {   ll=(c)->h[nn]; (void)HOST_l2c(ll,(s));   }  \
107296341Sdelphij                break;                  \
108296341Sdelphij            case SHA256_DIGEST_LENGTH:  \
109296341Sdelphij                for (nn=0;nn<SHA256_DIGEST_LENGTH/4;nn++)       \
110296341Sdelphij                {   ll=(c)->h[nn]; (void)HOST_l2c(ll,(s));   }  \
111296341Sdelphij                break;                  \
112296341Sdelphij            default:                    \
113296341Sdelphij                if ((c)->md_len > SHA256_DIGEST_LENGTH) \
114296341Sdelphij                    return 0;                           \
115296341Sdelphij                for (nn=0;nn<(c)->md_len/4;nn++)                \
116296341Sdelphij                {   ll=(c)->h[nn]; (void)HOST_l2c(ll,(s));   }  \
117296341Sdelphij                break;                  \
118296341Sdelphij        }                               \
119296341Sdelphij        } while (0)
120160814Ssimon
121296341Sdelphij# define HASH_UPDATE             SHA256_Update
122296341Sdelphij# define HASH_TRANSFORM          SHA256_Transform
123296341Sdelphij# define HASH_FINAL              SHA256_Final
124296341Sdelphij# define HASH_BLOCK_DATA_ORDER   sha256_block_data_order
125296341Sdelphij# ifndef SHA256_ASM
126194206Ssimonstatic
127296341Sdelphij# endif
128296341Sdelphijvoid sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num);
129160814Ssimon
130296341Sdelphij# include "md32_common.h"
131160814Ssimon
132296341Sdelphij# ifndef SHA256_ASM
133160814Ssimonstatic const SHA_LONG K256[64] = {
134296341Sdelphij    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
135296341Sdelphij    0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
136296341Sdelphij    0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
137296341Sdelphij    0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
138296341Sdelphij    0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
139296341Sdelphij    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
140296341Sdelphij    0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
141296341Sdelphij    0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
142296341Sdelphij    0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
143296341Sdelphij    0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
144296341Sdelphij    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
145296341Sdelphij    0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
146296341Sdelphij    0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
147296341Sdelphij    0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
148296341Sdelphij    0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
149296341Sdelphij    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
150296341Sdelphij};
151160814Ssimon
152160814Ssimon/*
153160814Ssimon * FIPS specification refers to right rotations, while our ROTATE macro
154160814Ssimon * is left one. This is why you might notice that rotation coefficients
155160814Ssimon * differ from those observed in FIPS document by 32-N...
156160814Ssimon */
157296341Sdelphij#  define Sigma0(x)       (ROTATE((x),30) ^ ROTATE((x),19) ^ ROTATE((x),10))
158296341Sdelphij#  define Sigma1(x)       (ROTATE((x),26) ^ ROTATE((x),21) ^ ROTATE((x),7))
159296341Sdelphij#  define sigma0(x)       (ROTATE((x),25) ^ ROTATE((x),14) ^ ((x)>>3))
160296341Sdelphij#  define sigma1(x)       (ROTATE((x),15) ^ ROTATE((x),13) ^ ((x)>>10))
161160814Ssimon
162296341Sdelphij#  define Ch(x,y,z)       (((x) & (y)) ^ ((~(x)) & (z)))
163296341Sdelphij#  define Maj(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
164160814Ssimon
165296341Sdelphij#  ifdef OPENSSL_SMALL_FOOTPRINT
166160814Ssimon
167296341Sdelphijstatic void sha256_block_data_order(SHA256_CTX *ctx, const void *in,
168296341Sdelphij                                    size_t num)
169296341Sdelphij{
170296341Sdelphij    unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1, T2;
171296341Sdelphij    SHA_LONG X[16], l;
172296341Sdelphij    int i;
173296341Sdelphij    const unsigned char *data = in;
174160814Ssimon
175296341Sdelphij    while (num--) {
176160814Ssimon
177296341Sdelphij        a = ctx->h[0];
178296341Sdelphij        b = ctx->h[1];
179296341Sdelphij        c = ctx->h[2];
180296341Sdelphij        d = ctx->h[3];
181296341Sdelphij        e = ctx->h[4];
182296341Sdelphij        f = ctx->h[5];
183296341Sdelphij        g = ctx->h[6];
184296341Sdelphij        h = ctx->h[7];
185160814Ssimon
186296341Sdelphij        for (i = 0; i < 16; i++) {
187296341Sdelphij            HOST_c2l(data, l);
188296341Sdelphij            T1 = X[i] = l;
189296341Sdelphij            T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i];
190296341Sdelphij            T2 = Sigma0(a) + Maj(a, b, c);
191296341Sdelphij            h = g;
192296341Sdelphij            g = f;
193296341Sdelphij            f = e;
194296341Sdelphij            e = d + T1;
195296341Sdelphij            d = c;
196296341Sdelphij            c = b;
197296341Sdelphij            b = a;
198296341Sdelphij            a = T1 + T2;
199296341Sdelphij        }
200160814Ssimon
201296341Sdelphij        for (; i < 64; i++) {
202296341Sdelphij            s0 = X[(i + 1) & 0x0f];
203296341Sdelphij            s0 = sigma0(s0);
204296341Sdelphij            s1 = X[(i + 14) & 0x0f];
205296341Sdelphij            s1 = sigma1(s1);
206160814Ssimon
207296341Sdelphij            T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf];
208296341Sdelphij            T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i];
209296341Sdelphij            T2 = Sigma0(a) + Maj(a, b, c);
210296341Sdelphij            h = g;
211296341Sdelphij            g = f;
212296341Sdelphij            f = e;
213296341Sdelphij            e = d + T1;
214296341Sdelphij            d = c;
215296341Sdelphij            c = b;
216296341Sdelphij            b = a;
217296341Sdelphij            a = T1 + T2;
218296341Sdelphij        }
219160814Ssimon
220296341Sdelphij        ctx->h[0] += a;
221296341Sdelphij        ctx->h[1] += b;
222296341Sdelphij        ctx->h[2] += c;
223296341Sdelphij        ctx->h[3] += d;
224296341Sdelphij        ctx->h[4] += e;
225296341Sdelphij        ctx->h[5] += f;
226296341Sdelphij        ctx->h[6] += g;
227296341Sdelphij        ctx->h[7] += h;
228160814Ssimon
229296341Sdelphij    }
230160814Ssimon}
231160814Ssimon
232296341Sdelphij#  else
233160814Ssimon
234296341Sdelphij#   define ROUND_00_15(i,a,b,c,d,e,f,g,h)          do {    \
235296341Sdelphij        T1 += h + Sigma1(e) + Ch(e,f,g) + K256[i];      \
236296341Sdelphij        h = Sigma0(a) + Maj(a,b,c);                     \
237296341Sdelphij        d += T1;        h += T1;                } while (0)
238160814Ssimon
239296341Sdelphij#   define ROUND_16_63(i,a,b,c,d,e,f,g,h,X)        do {    \
240296341Sdelphij        s0 = X[(i+1)&0x0f];     s0 = sigma0(s0);        \
241296341Sdelphij        s1 = X[(i+14)&0x0f];    s1 = sigma1(s1);        \
242296341Sdelphij        T1 = X[(i)&0x0f] += s0 + s1 + X[(i+9)&0x0f];    \
243296341Sdelphij        ROUND_00_15(i,a,b,c,d,e,f,g,h);         } while (0)
244160814Ssimon
245296341Sdelphijstatic void sha256_block_data_order(SHA256_CTX *ctx, const void *in,
246296341Sdelphij                                    size_t num)
247296341Sdelphij{
248296341Sdelphij    unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1;
249296341Sdelphij    SHA_LONG X[16];
250296341Sdelphij    int i;
251296341Sdelphij    const unsigned char *data = in;
252296341Sdelphij    const union {
253296341Sdelphij        long one;
254296341Sdelphij        char little;
255296341Sdelphij    } is_endian = {
256296341Sdelphij        1
257296341Sdelphij    };
258160814Ssimon
259296341Sdelphij    while (num--) {
260160814Ssimon
261296341Sdelphij        a = ctx->h[0];
262296341Sdelphij        b = ctx->h[1];
263296341Sdelphij        c = ctx->h[2];
264296341Sdelphij        d = ctx->h[3];
265296341Sdelphij        e = ctx->h[4];
266296341Sdelphij        f = ctx->h[5];
267296341Sdelphij        g = ctx->h[6];
268296341Sdelphij        h = ctx->h[7];
269160814Ssimon
270296341Sdelphij        if (!is_endian.little && sizeof(SHA_LONG) == 4
271296341Sdelphij            && ((size_t)in % 4) == 0) {
272296341Sdelphij            const SHA_LONG *W = (const SHA_LONG *)data;
273160814Ssimon
274296341Sdelphij            T1 = X[0] = W[0];
275296341Sdelphij            ROUND_00_15(0, a, b, c, d, e, f, g, h);
276296341Sdelphij            T1 = X[1] = W[1];
277296341Sdelphij            ROUND_00_15(1, h, a, b, c, d, e, f, g);
278296341Sdelphij            T1 = X[2] = W[2];
279296341Sdelphij            ROUND_00_15(2, g, h, a, b, c, d, e, f);
280296341Sdelphij            T1 = X[3] = W[3];
281296341Sdelphij            ROUND_00_15(3, f, g, h, a, b, c, d, e);
282296341Sdelphij            T1 = X[4] = W[4];
283296341Sdelphij            ROUND_00_15(4, e, f, g, h, a, b, c, d);
284296341Sdelphij            T1 = X[5] = W[5];
285296341Sdelphij            ROUND_00_15(5, d, e, f, g, h, a, b, c);
286296341Sdelphij            T1 = X[6] = W[6];
287296341Sdelphij            ROUND_00_15(6, c, d, e, f, g, h, a, b);
288296341Sdelphij            T1 = X[7] = W[7];
289296341Sdelphij            ROUND_00_15(7, b, c, d, e, f, g, h, a);
290296341Sdelphij            T1 = X[8] = W[8];
291296341Sdelphij            ROUND_00_15(8, a, b, c, d, e, f, g, h);
292296341Sdelphij            T1 = X[9] = W[9];
293296341Sdelphij            ROUND_00_15(9, h, a, b, c, d, e, f, g);
294296341Sdelphij            T1 = X[10] = W[10];
295296341Sdelphij            ROUND_00_15(10, g, h, a, b, c, d, e, f);
296296341Sdelphij            T1 = X[11] = W[11];
297296341Sdelphij            ROUND_00_15(11, f, g, h, a, b, c, d, e);
298296341Sdelphij            T1 = X[12] = W[12];
299296341Sdelphij            ROUND_00_15(12, e, f, g, h, a, b, c, d);
300296341Sdelphij            T1 = X[13] = W[13];
301296341Sdelphij            ROUND_00_15(13, d, e, f, g, h, a, b, c);
302296341Sdelphij            T1 = X[14] = W[14];
303296341Sdelphij            ROUND_00_15(14, c, d, e, f, g, h, a, b);
304296341Sdelphij            T1 = X[15] = W[15];
305296341Sdelphij            ROUND_00_15(15, b, c, d, e, f, g, h, a);
306160814Ssimon
307296341Sdelphij            data += SHA256_CBLOCK;
308296341Sdelphij        } else {
309296341Sdelphij            SHA_LONG l;
310160814Ssimon
311296341Sdelphij            HOST_c2l(data, l);
312296341Sdelphij            T1 = X[0] = l;
313296341Sdelphij            ROUND_00_15(0, a, b, c, d, e, f, g, h);
314296341Sdelphij            HOST_c2l(data, l);
315296341Sdelphij            T1 = X[1] = l;
316296341Sdelphij            ROUND_00_15(1, h, a, b, c, d, e, f, g);
317296341Sdelphij            HOST_c2l(data, l);
318296341Sdelphij            T1 = X[2] = l;
319296341Sdelphij            ROUND_00_15(2, g, h, a, b, c, d, e, f);
320296341Sdelphij            HOST_c2l(data, l);
321296341Sdelphij            T1 = X[3] = l;
322296341Sdelphij            ROUND_00_15(3, f, g, h, a, b, c, d, e);
323296341Sdelphij            HOST_c2l(data, l);
324296341Sdelphij            T1 = X[4] = l;
325296341Sdelphij            ROUND_00_15(4, e, f, g, h, a, b, c, d);
326296341Sdelphij            HOST_c2l(data, l);
327296341Sdelphij            T1 = X[5] = l;
328296341Sdelphij            ROUND_00_15(5, d, e, f, g, h, a, b, c);
329296341Sdelphij            HOST_c2l(data, l);
330296341Sdelphij            T1 = X[6] = l;
331296341Sdelphij            ROUND_00_15(6, c, d, e, f, g, h, a, b);
332296341Sdelphij            HOST_c2l(data, l);
333296341Sdelphij            T1 = X[7] = l;
334296341Sdelphij            ROUND_00_15(7, b, c, d, e, f, g, h, a);
335296341Sdelphij            HOST_c2l(data, l);
336296341Sdelphij            T1 = X[8] = l;
337296341Sdelphij            ROUND_00_15(8, a, b, c, d, e, f, g, h);
338296341Sdelphij            HOST_c2l(data, l);
339296341Sdelphij            T1 = X[9] = l;
340296341Sdelphij            ROUND_00_15(9, h, a, b, c, d, e, f, g);
341296341Sdelphij            HOST_c2l(data, l);
342296341Sdelphij            T1 = X[10] = l;
343296341Sdelphij            ROUND_00_15(10, g, h, a, b, c, d, e, f);
344296341Sdelphij            HOST_c2l(data, l);
345296341Sdelphij            T1 = X[11] = l;
346296341Sdelphij            ROUND_00_15(11, f, g, h, a, b, c, d, e);
347296341Sdelphij            HOST_c2l(data, l);
348296341Sdelphij            T1 = X[12] = l;
349296341Sdelphij            ROUND_00_15(12, e, f, g, h, a, b, c, d);
350296341Sdelphij            HOST_c2l(data, l);
351296341Sdelphij            T1 = X[13] = l;
352296341Sdelphij            ROUND_00_15(13, d, e, f, g, h, a, b, c);
353296341Sdelphij            HOST_c2l(data, l);
354296341Sdelphij            T1 = X[14] = l;
355296341Sdelphij            ROUND_00_15(14, c, d, e, f, g, h, a, b);
356296341Sdelphij            HOST_c2l(data, l);
357296341Sdelphij            T1 = X[15] = l;
358296341Sdelphij            ROUND_00_15(15, b, c, d, e, f, g, h, a);
359296341Sdelphij        }
360160814Ssimon
361296341Sdelphij        for (i = 16; i < 64; i += 8) {
362296341Sdelphij            ROUND_16_63(i + 0, a, b, c, d, e, f, g, h, X);
363296341Sdelphij            ROUND_16_63(i + 1, h, a, b, c, d, e, f, g, X);
364296341Sdelphij            ROUND_16_63(i + 2, g, h, a, b, c, d, e, f, X);
365296341Sdelphij            ROUND_16_63(i + 3, f, g, h, a, b, c, d, e, X);
366296341Sdelphij            ROUND_16_63(i + 4, e, f, g, h, a, b, c, d, X);
367296341Sdelphij            ROUND_16_63(i + 5, d, e, f, g, h, a, b, c, X);
368296341Sdelphij            ROUND_16_63(i + 6, c, d, e, f, g, h, a, b, X);
369296341Sdelphij            ROUND_16_63(i + 7, b, c, d, e, f, g, h, a, X);
370296341Sdelphij        }
371160814Ssimon
372296341Sdelphij        ctx->h[0] += a;
373296341Sdelphij        ctx->h[1] += b;
374296341Sdelphij        ctx->h[2] += c;
375296341Sdelphij        ctx->h[3] += d;
376296341Sdelphij        ctx->h[4] += e;
377296341Sdelphij        ctx->h[5] += f;
378296341Sdelphij        ctx->h[6] += g;
379296341Sdelphij        ctx->h[7] += h;
380160814Ssimon
381296341Sdelphij    }
382296341Sdelphij}
383160814Ssimon
384296341Sdelphij#  endif
385296341Sdelphij# endif                         /* SHA256_ASM */
386160814Ssimon
387296341Sdelphij#endif                          /* OPENSSL_NO_SHA256 */
388