1ad767ee8SHans de Goede // SPDX-License-Identifier: GPL-2.0-or-later
2ad767ee8SHans de Goede /*
3ad767ee8SHans de Goede * SHA-256, as specified in
4ad767ee8SHans de Goede * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
5ad767ee8SHans de Goede *
6ad767ee8SHans de Goede * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
7ad767ee8SHans de Goede *
8ad767ee8SHans de Goede * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
9ad767ee8SHans de Goede * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
10ad767ee8SHans de Goede * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
11ad767ee8SHans de Goede * Copyright (c) 2014 Red Hat Inc.
12ad767ee8SHans de Goede */
13ad767ee8SHans de Goede
14*6c19f3bfSHerbert Xu #include <asm/unaligned.h>
15*6c19f3bfSHerbert Xu #include <crypto/sha256_base.h>
16*6c19f3bfSHerbert Xu #include <linux/kernel.h>
179ecf5ad5SHans de Goede #include <linux/module.h>
18ad767ee8SHans de Goede #include <linux/string.h>
19ad767ee8SHans de Goede
2063642d5cSArvind Sankar static const u32 SHA256_K[] = {
2163642d5cSArvind Sankar 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
2263642d5cSArvind Sankar 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
2363642d5cSArvind Sankar 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
2463642d5cSArvind Sankar 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
2563642d5cSArvind Sankar 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
2663642d5cSArvind Sankar 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
2763642d5cSArvind Sankar 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
2863642d5cSArvind Sankar 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
2963642d5cSArvind Sankar 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
3063642d5cSArvind Sankar 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
3163642d5cSArvind Sankar 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
3263642d5cSArvind Sankar 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
3363642d5cSArvind Sankar 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
3463642d5cSArvind Sankar 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
3563642d5cSArvind Sankar 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
3663642d5cSArvind Sankar 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
3763642d5cSArvind Sankar };
3863642d5cSArvind Sankar
Ch(u32 x,u32 y,u32 z)39ad767ee8SHans de Goede static inline u32 Ch(u32 x, u32 y, u32 z)
40ad767ee8SHans de Goede {
41ad767ee8SHans de Goede return z ^ (x & (y ^ z));
42ad767ee8SHans de Goede }
43ad767ee8SHans de Goede
Maj(u32 x,u32 y,u32 z)44ad767ee8SHans de Goede static inline u32 Maj(u32 x, u32 y, u32 z)
45ad767ee8SHans de Goede {
46ad767ee8SHans de Goede return (x & y) | (z & (x | y));
47ad767ee8SHans de Goede }
48ad767ee8SHans de Goede
49ad767ee8SHans de Goede #define e0(x) (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22))
50ad767ee8SHans de Goede #define e1(x) (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25))
51ad767ee8SHans de Goede #define s0(x) (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3))
52ad767ee8SHans de Goede #define s1(x) (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10))
53ad767ee8SHans de Goede
LOAD_OP(int I,u32 * W,const u8 * input)54ad767ee8SHans de Goede static inline void LOAD_OP(int I, u32 *W, const u8 *input)
55ad767ee8SHans de Goede {
56906a4bb9SHans de Goede W[I] = get_unaligned_be32((__u32 *)input + I);
57ad767ee8SHans de Goede }
58ad767ee8SHans de Goede
BLEND_OP(int I,u32 * W)59ad767ee8SHans de Goede static inline void BLEND_OP(int I, u32 *W)
60ad767ee8SHans de Goede {
61ad767ee8SHans de Goede W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
62ad767ee8SHans de Goede }
63ad767ee8SHans de Goede
6463642d5cSArvind Sankar #define SHA256_ROUND(i, a, b, c, d, e, f, g, h) do { \
6563642d5cSArvind Sankar u32 t1, t2; \
6663642d5cSArvind Sankar t1 = h + e1(e) + Ch(e, f, g) + SHA256_K[i] + W[i]; \
6763642d5cSArvind Sankar t2 = e0(a) + Maj(a, b, c); \
6863642d5cSArvind Sankar d += t1; \
6963642d5cSArvind Sankar h = t1 + t2; \
7063642d5cSArvind Sankar } while (0)
7163642d5cSArvind Sankar
sha256_transform(u32 * state,const u8 * input,u32 * W)72b8399819SArvind Sankar static void sha256_transform(u32 *state, const u8 *input, u32 *W)
73ad767ee8SHans de Goede {
7463642d5cSArvind Sankar u32 a, b, c, d, e, f, g, h;
75ad767ee8SHans de Goede int i;
76ad767ee8SHans de Goede
77ad767ee8SHans de Goede /* load the input */
7818d05ca4SArvind Sankar for (i = 0; i < 16; i += 8) {
7918d05ca4SArvind Sankar LOAD_OP(i + 0, W, input);
8018d05ca4SArvind Sankar LOAD_OP(i + 1, W, input);
8118d05ca4SArvind Sankar LOAD_OP(i + 2, W, input);
8218d05ca4SArvind Sankar LOAD_OP(i + 3, W, input);
8318d05ca4SArvind Sankar LOAD_OP(i + 4, W, input);
8418d05ca4SArvind Sankar LOAD_OP(i + 5, W, input);
8518d05ca4SArvind Sankar LOAD_OP(i + 6, W, input);
8618d05ca4SArvind Sankar LOAD_OP(i + 7, W, input);
8718d05ca4SArvind Sankar }
88ad767ee8SHans de Goede
89ad767ee8SHans de Goede /* now blend */
9018d05ca4SArvind Sankar for (i = 16; i < 64; i += 8) {
9118d05ca4SArvind Sankar BLEND_OP(i + 0, W);
9218d05ca4SArvind Sankar BLEND_OP(i + 1, W);
9318d05ca4SArvind Sankar BLEND_OP(i + 2, W);
9418d05ca4SArvind Sankar BLEND_OP(i + 3, W);
9518d05ca4SArvind Sankar BLEND_OP(i + 4, W);
9618d05ca4SArvind Sankar BLEND_OP(i + 5, W);
9718d05ca4SArvind Sankar BLEND_OP(i + 6, W);
9818d05ca4SArvind Sankar BLEND_OP(i + 7, W);
9918d05ca4SArvind Sankar }
100ad767ee8SHans de Goede
101ad767ee8SHans de Goede /* load the state into our registers */
102ad767ee8SHans de Goede a = state[0]; b = state[1]; c = state[2]; d = state[3];
103ad767ee8SHans de Goede e = state[4]; f = state[5]; g = state[6]; h = state[7];
104ad767ee8SHans de Goede
105ad767ee8SHans de Goede /* now iterate */
10663642d5cSArvind Sankar for (i = 0; i < 64; i += 8) {
10763642d5cSArvind Sankar SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h);
10863642d5cSArvind Sankar SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g);
10963642d5cSArvind Sankar SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f);
11063642d5cSArvind Sankar SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e);
11163642d5cSArvind Sankar SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d);
11263642d5cSArvind Sankar SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c);
11363642d5cSArvind Sankar SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b);
11463642d5cSArvind Sankar SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a);
11563642d5cSArvind Sankar }
116ad767ee8SHans de Goede
117ad767ee8SHans de Goede state[0] += a; state[1] += b; state[2] += c; state[3] += d;
118ad767ee8SHans de Goede state[4] += e; state[5] += f; state[6] += g; state[7] += h;
119ad767ee8SHans de Goede }
120ad767ee8SHans de Goede
sha256_transform_blocks(struct sha256_state * sctx,const u8 * input,int blocks)121*6c19f3bfSHerbert Xu static void sha256_transform_blocks(struct sha256_state *sctx,
122*6c19f3bfSHerbert Xu const u8 *input, int blocks)
123ad767ee8SHans de Goede {
124b8399819SArvind Sankar u32 W[64];
125ad767ee8SHans de Goede
126ad767ee8SHans de Goede do {
127*6c19f3bfSHerbert Xu sha256_transform(sctx->state, input, W);
128*6c19f3bfSHerbert Xu input += SHA256_BLOCK_SIZE;
129*6c19f3bfSHerbert Xu } while (--blocks);
130ad767ee8SHans de Goede
131b8399819SArvind Sankar memzero_explicit(W, sizeof(W));
132ad767ee8SHans de Goede }
133*6c19f3bfSHerbert Xu
sha256_update(struct sha256_state * sctx,const u8 * data,unsigned int len)134*6c19f3bfSHerbert Xu void sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
135*6c19f3bfSHerbert Xu {
136*6c19f3bfSHerbert Xu lib_sha256_base_do_update(sctx, data, len, sha256_transform_blocks);
137ad767ee8SHans de Goede }
13801d3aee8SHans de Goede EXPORT_SYMBOL(sha256_update);
139ad767ee8SHans de Goede
__sha256_final(struct sha256_state * sctx,u8 * out,int digest_size)140*6c19f3bfSHerbert Xu static void __sha256_final(struct sha256_state *sctx, u8 *out, int digest_size)
141ad767ee8SHans de Goede {
142*6c19f3bfSHerbert Xu lib_sha256_base_do_finalize(sctx, sha256_transform_blocks);
143*6c19f3bfSHerbert Xu lib_sha256_base_finish(sctx, out, digest_size);
144ad767ee8SHans de Goede }
1457d2f5b0cSHans de Goede
sha256_final(struct sha256_state * sctx,u8 * out)14613855fd8SEric Biggers void sha256_final(struct sha256_state *sctx, u8 *out)
1477d2f5b0cSHans de Goede {
148*6c19f3bfSHerbert Xu __sha256_final(sctx, out, 32);
1497d2f5b0cSHans de Goede }
15001d3aee8SHans de Goede EXPORT_SYMBOL(sha256_final);
1517d2f5b0cSHans de Goede
sha224_final(struct sha256_state * sctx,u8 * out)15213855fd8SEric Biggers void sha224_final(struct sha256_state *sctx, u8 *out)
1537d2f5b0cSHans de Goede {
154*6c19f3bfSHerbert Xu __sha256_final(sctx, out, 28);
1557d2f5b0cSHans de Goede }
1567d2f5b0cSHans de Goede EXPORT_SYMBOL(sha224_final);
1579ecf5ad5SHans de Goede
sha256(const u8 * data,unsigned int len,u8 * out)1589ea9c58bSEric Biggers void sha256(const u8 *data, unsigned int len, u8 *out)
1599ea9c58bSEric Biggers {
1609ea9c58bSEric Biggers struct sha256_state sctx;
1619ea9c58bSEric Biggers
1629ea9c58bSEric Biggers sha256_init(&sctx);
1639ea9c58bSEric Biggers sha256_update(&sctx, data, len);
1649ea9c58bSEric Biggers sha256_final(&sctx, out);
1659ea9c58bSEric Biggers }
1669ea9c58bSEric Biggers EXPORT_SYMBOL(sha256);
1679ea9c58bSEric Biggers
1689ecf5ad5SHans de Goede MODULE_LICENSE("GPL");
169