xref: /onnv-gate/usr/src/uts/common/fs/zfs/sha256.c (revision 5688:c0b02c8fd2c0)
1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
5*5688Sbonwick  * Common Development and Distribution License (the "License").
6*5688Sbonwick  * You may not use this file except in compliance with the License.
7789Sahrens  *
8789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens  * or http://www.opensolaris.org/os/licensing.
10789Sahrens  * See the License for the specific language governing permissions
11789Sahrens  * and limitations under the License.
12789Sahrens  *
13789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens  *
19789Sahrens  * CDDL HEADER END
20789Sahrens  */
21789Sahrens /*
22*5688Sbonwick  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23789Sahrens  * Use is subject to license terms.
24789Sahrens  */
25789Sahrens 
26789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
27789Sahrens 
28789Sahrens #include <sys/zfs_context.h>
29789Sahrens #include <sys/zio.h>
30789Sahrens #include <sys/zio_checksum.h>
31789Sahrens 
32789Sahrens /*
33*5688Sbonwick  * SHA-256 checksum, as specified in FIPS 180-3, available at:
34*5688Sbonwick  * http://csrc.nist.gov/publications/PubsFIPS.html
35789Sahrens  *
36789Sahrens  * This is a very compact implementation of SHA-256.
37789Sahrens  * It is designed to be simple and portable, not to be fast.
38789Sahrens  */
39789Sahrens 
40789Sahrens /*
41*5688Sbonwick  * The literal definitions of Ch() and Maj() according to FIPS 180-3 are:
42789Sahrens  *
43*5688Sbonwick  * 	Ch(x, y, z)     (x & y) ^ (~x & z)
44*5688Sbonwick  * 	Maj(x, y, z)    (x & y) ^ (x & z) ^ (y & z)
45789Sahrens  *
46*5688Sbonwick  * We use equivalent logical reductions here that require one less op.
47789Sahrens  */
48789Sahrens #define	Ch(x, y, z)	((z) ^ ((x) & ((y) ^ (z))))
49789Sahrens #define	Maj(x, y, z)	(((x) & (y)) ^ ((z) & ((x) ^ (y))))
50789Sahrens #define	Rot32(x, s)	(((x) >> s) | ((x) << (32 - s)))
51789Sahrens #define	SIGMA0(x)	(Rot32(x, 2) ^ Rot32(x, 13) ^ Rot32(x, 22))
52789Sahrens #define	SIGMA1(x)	(Rot32(x, 6) ^ Rot32(x, 11) ^ Rot32(x, 25))
53789Sahrens #define	sigma0(x)	(Rot32(x, 7) ^ Rot32(x, 18) ^ ((x) >> 3))
54789Sahrens #define	sigma1(x)	(Rot32(x, 17) ^ Rot32(x, 19) ^ ((x) >> 10))
55789Sahrens 
56789Sahrens static const uint32_t SHA256_K[64] = {
57789Sahrens 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
58789Sahrens 	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
59789Sahrens 	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
60789Sahrens 	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
61789Sahrens 	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
62789Sahrens 	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
63789Sahrens 	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
64789Sahrens 	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
65789Sahrens 	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
66789Sahrens 	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
67789Sahrens 	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
68789Sahrens 	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
69789Sahrens 	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
70789Sahrens 	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
71789Sahrens 	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
72789Sahrens 	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
73789Sahrens };
74789Sahrens 
75789Sahrens static void
76789Sahrens SHA256Transform(uint32_t *H, const uint8_t *cp)
77789Sahrens {
78789Sahrens 	uint32_t a, b, c, d, e, f, g, h, t, T1, T2, W[64];
79789Sahrens 
80789Sahrens 	for (t = 0; t < 16; t++, cp += 4)
81789Sahrens 		W[t] = (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3];
82789Sahrens 
83789Sahrens 	for (t = 16; t < 64; t++)
84789Sahrens 		W[t] = sigma1(W[t - 2]) + W[t - 7] +
85789Sahrens 		    sigma0(W[t - 15]) + W[t - 16];
86789Sahrens 
87789Sahrens 	a = H[0]; b = H[1]; c = H[2]; d = H[3];
88789Sahrens 	e = H[4]; f = H[5]; g = H[6]; h = H[7];
89789Sahrens 
90789Sahrens 	for (t = 0; t < 64; t++) {
91789Sahrens 		T1 = h + SIGMA1(e) + Ch(e, f, g) + SHA256_K[t] + W[t];
92789Sahrens 		T2 = SIGMA0(a) + Maj(a, b, c);
93789Sahrens 		h = g; g = f; f = e; e = d + T1;
94789Sahrens 		d = c; c = b; b = a; a = T1 + T2;
95789Sahrens 	}
96789Sahrens 
97789Sahrens 	H[0] += a; H[1] += b; H[2] += c; H[3] += d;
98789Sahrens 	H[4] += e; H[5] += f; H[6] += g; H[7] += h;
99789Sahrens }
100789Sahrens 
101789Sahrens void
102789Sahrens zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp)
103789Sahrens {
104789Sahrens 	uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
105789Sahrens 	    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
106789Sahrens 	uint8_t pad[128];
107*5688Sbonwick 	int i, padsize;
108789Sahrens 
109*5688Sbonwick 	for (i = 0; i < (size & ~63ULL); i += 64)
110789Sahrens 		SHA256Transform(H, (uint8_t *)buf + i);
111789Sahrens 
112*5688Sbonwick 	for (padsize = 0; i < size; i++)
113*5688Sbonwick 		pad[padsize++] = *((uint8_t *)buf + i);
114789Sahrens 
115789Sahrens 	for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++)
116789Sahrens 		pad[padsize] = 0;
117789Sahrens 
118*5688Sbonwick 	for (i = 56; i >= 0; i -= 8)
119*5688Sbonwick 		pad[padsize++] = (size << 3) >> i;
120789Sahrens 
121789Sahrens 	for (i = 0; i < padsize; i += 64)
122789Sahrens 		SHA256Transform(H, pad + i);
123789Sahrens 
124789Sahrens 	ZIO_SET_CHECKSUM(zcp,
125789Sahrens 	    (uint64_t)H[0] << 32 | H[1],
126789Sahrens 	    (uint64_t)H[2] << 32 | H[3],
127789Sahrens 	    (uint64_t)H[4] << 32 | H[5],
128789Sahrens 	    (uint64_t)H[6] << 32 | H[7]);
129789Sahrens }
130