xref: /freebsd/sys/cddl/boot/zfs/sha256.c (revision 1ba4a712dde6e6c613fc411a96958b4ade67de4c)
11ba4a712SPawel Jakub Dawidek /*
21ba4a712SPawel Jakub Dawidek  * CDDL HEADER START
31ba4a712SPawel Jakub Dawidek  *
41ba4a712SPawel Jakub Dawidek  * The contents of this file are subject to the terms of the
51ba4a712SPawel Jakub Dawidek  * Common Development and Distribution License, Version 1.0 only
61ba4a712SPawel Jakub Dawidek  * (the "License").  You may not use this file except in compliance
71ba4a712SPawel Jakub Dawidek  * with the License.
81ba4a712SPawel Jakub Dawidek  *
91ba4a712SPawel Jakub Dawidek  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
101ba4a712SPawel Jakub Dawidek  * or http://www.opensolaris.org/os/licensing.
111ba4a712SPawel Jakub Dawidek  * See the License for the specific language governing permissions
121ba4a712SPawel Jakub Dawidek  * and limitations under the License.
131ba4a712SPawel Jakub Dawidek  *
141ba4a712SPawel Jakub Dawidek  * When distributing Covered Code, include this CDDL HEADER in each
151ba4a712SPawel Jakub Dawidek  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
161ba4a712SPawel Jakub Dawidek  * If applicable, add the following below this CDDL HEADER, with the
171ba4a712SPawel Jakub Dawidek  * fields enclosed by brackets "[]" replaced with your own identifying
181ba4a712SPawel Jakub Dawidek  * information: Portions Copyright [yyyy] [name of copyright owner]
191ba4a712SPawel Jakub Dawidek  *
201ba4a712SPawel Jakub Dawidek  * CDDL HEADER END
211ba4a712SPawel Jakub Dawidek  */
221ba4a712SPawel Jakub Dawidek /*
231ba4a712SPawel Jakub Dawidek  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
241ba4a712SPawel Jakub Dawidek  * Use is subject to license terms.
251ba4a712SPawel Jakub Dawidek  */
261ba4a712SPawel Jakub Dawidek 
271ba4a712SPawel Jakub Dawidek /*#pragma ident	"%Z%%M%	%I%	%E% SMI"*/
281ba4a712SPawel Jakub Dawidek 
291ba4a712SPawel Jakub Dawidek /*
301ba4a712SPawel Jakub Dawidek  * SHA-256 checksum, as specified in FIPS 180-2, available at:
311ba4a712SPawel Jakub Dawidek  * http://csrc.nist.gov/cryptval
321ba4a712SPawel Jakub Dawidek  *
331ba4a712SPawel Jakub Dawidek  * This is a very compact implementation of SHA-256.
341ba4a712SPawel Jakub Dawidek  * It is designed to be simple and portable, not to be fast.
351ba4a712SPawel Jakub Dawidek  */
361ba4a712SPawel Jakub Dawidek 
371ba4a712SPawel Jakub Dawidek /*
381ba4a712SPawel Jakub Dawidek  * The literal definitions according to FIPS180-2 would be:
391ba4a712SPawel Jakub Dawidek  *
401ba4a712SPawel Jakub Dawidek  * 	Ch(x, y, z)     (((x) & (y)) ^ ((~(x)) & (z)))
411ba4a712SPawel Jakub Dawidek  * 	Maj(x, y, z)    (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
421ba4a712SPawel Jakub Dawidek  *
431ba4a712SPawel Jakub Dawidek  * We use logical equivalents which require one less op.
441ba4a712SPawel Jakub Dawidek  */
451ba4a712SPawel Jakub Dawidek #define	Ch(x, y, z)	((z) ^ ((x) & ((y) ^ (z))))
461ba4a712SPawel Jakub Dawidek #define	Maj(x, y, z)	(((x) & (y)) ^ ((z) & ((x) ^ (y))))
471ba4a712SPawel Jakub Dawidek #define	Rot32(x, s)	(((x) >> s) | ((x) << (32 - s)))
481ba4a712SPawel Jakub Dawidek #define	SIGMA0(x)	(Rot32(x, 2) ^ Rot32(x, 13) ^ Rot32(x, 22))
491ba4a712SPawel Jakub Dawidek #define	SIGMA1(x)	(Rot32(x, 6) ^ Rot32(x, 11) ^ Rot32(x, 25))
501ba4a712SPawel Jakub Dawidek #define	sigma0(x)	(Rot32(x, 7) ^ Rot32(x, 18) ^ ((x) >> 3))
511ba4a712SPawel Jakub Dawidek #define	sigma1(x)	(Rot32(x, 17) ^ Rot32(x, 19) ^ ((x) >> 10))
521ba4a712SPawel Jakub Dawidek 
531ba4a712SPawel Jakub Dawidek static const uint32_t SHA256_K[64] = {
541ba4a712SPawel Jakub Dawidek 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
551ba4a712SPawel Jakub Dawidek 	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
561ba4a712SPawel Jakub Dawidek 	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
571ba4a712SPawel Jakub Dawidek 	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
581ba4a712SPawel Jakub Dawidek 	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
591ba4a712SPawel Jakub Dawidek 	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
601ba4a712SPawel Jakub Dawidek 	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
611ba4a712SPawel Jakub Dawidek 	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
621ba4a712SPawel Jakub Dawidek 	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
631ba4a712SPawel Jakub Dawidek 	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
641ba4a712SPawel Jakub Dawidek 	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
651ba4a712SPawel Jakub Dawidek 	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
661ba4a712SPawel Jakub Dawidek 	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
671ba4a712SPawel Jakub Dawidek 	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
681ba4a712SPawel Jakub Dawidek 	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
691ba4a712SPawel Jakub Dawidek 	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
701ba4a712SPawel Jakub Dawidek };
711ba4a712SPawel Jakub Dawidek 
721ba4a712SPawel Jakub Dawidek static void
731ba4a712SPawel Jakub Dawidek SHA256Transform(uint32_t *H, const uint8_t *cp)
741ba4a712SPawel Jakub Dawidek {
751ba4a712SPawel Jakub Dawidek 	uint32_t a, b, c, d, e, f, g, h, t, T1, T2, W[64];
761ba4a712SPawel Jakub Dawidek 
771ba4a712SPawel Jakub Dawidek 	for (t = 0; t < 16; t++, cp += 4)
781ba4a712SPawel Jakub Dawidek 		W[t] = (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3];
791ba4a712SPawel Jakub Dawidek 
801ba4a712SPawel Jakub Dawidek 	for (t = 16; t < 64; t++)
811ba4a712SPawel Jakub Dawidek 		W[t] = sigma1(W[t - 2]) + W[t - 7] +
821ba4a712SPawel Jakub Dawidek 		    sigma0(W[t - 15]) + W[t - 16];
831ba4a712SPawel Jakub Dawidek 
841ba4a712SPawel Jakub Dawidek 	a = H[0]; b = H[1]; c = H[2]; d = H[3];
851ba4a712SPawel Jakub Dawidek 	e = H[4]; f = H[5]; g = H[6]; h = H[7];
861ba4a712SPawel Jakub Dawidek 
871ba4a712SPawel Jakub Dawidek 	for (t = 0; t < 64; t++) {
881ba4a712SPawel Jakub Dawidek 		T1 = h + SIGMA1(e) + Ch(e, f, g) + SHA256_K[t] + W[t];
891ba4a712SPawel Jakub Dawidek 		T2 = SIGMA0(a) + Maj(a, b, c);
901ba4a712SPawel Jakub Dawidek 		h = g; g = f; f = e; e = d + T1;
911ba4a712SPawel Jakub Dawidek 		d = c; c = b; b = a; a = T1 + T2;
921ba4a712SPawel Jakub Dawidek 	}
931ba4a712SPawel Jakub Dawidek 
941ba4a712SPawel Jakub Dawidek 	H[0] += a; H[1] += b; H[2] += c; H[3] += d;
951ba4a712SPawel Jakub Dawidek 	H[4] += e; H[5] += f; H[6] += g; H[7] += h;
961ba4a712SPawel Jakub Dawidek }
971ba4a712SPawel Jakub Dawidek 
981ba4a712SPawel Jakub Dawidek static void
991ba4a712SPawel Jakub Dawidek zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp)
1001ba4a712SPawel Jakub Dawidek {
1011ba4a712SPawel Jakub Dawidek 	uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
1021ba4a712SPawel Jakub Dawidek 	    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
1031ba4a712SPawel Jakub Dawidek 	uint8_t pad[128];
1041ba4a712SPawel Jakub Dawidek 	int padsize = size & 63;
1051ba4a712SPawel Jakub Dawidek 	int i;
1061ba4a712SPawel Jakub Dawidek 
1071ba4a712SPawel Jakub Dawidek 	for (i = 0; i < size - padsize; i += 64)
1081ba4a712SPawel Jakub Dawidek 		SHA256Transform(H, (uint8_t *)buf + i);
1091ba4a712SPawel Jakub Dawidek 
1101ba4a712SPawel Jakub Dawidek 	for (i = 0; i < padsize; i++)
1111ba4a712SPawel Jakub Dawidek 		pad[i] = ((uint8_t *)buf)[i];
1121ba4a712SPawel Jakub Dawidek 
1131ba4a712SPawel Jakub Dawidek 	for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++)
1141ba4a712SPawel Jakub Dawidek 		pad[padsize] = 0;
1151ba4a712SPawel Jakub Dawidek 
1161ba4a712SPawel Jakub Dawidek 	for (i = 0; i < 8; i++)
1171ba4a712SPawel Jakub Dawidek 		pad[padsize++] = (size << 3) >> (56 - 8 * i);
1181ba4a712SPawel Jakub Dawidek 
1191ba4a712SPawel Jakub Dawidek 	for (i = 0; i < padsize; i += 64)
1201ba4a712SPawel Jakub Dawidek 		SHA256Transform(H, pad + i);
1211ba4a712SPawel Jakub Dawidek 
1221ba4a712SPawel Jakub Dawidek 	ZIO_SET_CHECKSUM(zcp,
1231ba4a712SPawel Jakub Dawidek 	    (uint64_t)H[0] << 32 | H[1],
1241ba4a712SPawel Jakub Dawidek 	    (uint64_t)H[2] << 32 | H[3],
1251ba4a712SPawel Jakub Dawidek 	    (uint64_t)H[4] << 32 | H[5],
1261ba4a712SPawel Jakub Dawidek 	    (uint64_t)H[6] << 32 | H[7]);
1271ba4a712SPawel Jakub Dawidek }
128