zfs_sha256.c revision 8044:b3af80bbf173
1238438Sdteske/*
2238438Sdteske *  GRUB  --  GRand Unified Bootloader
3238438Sdteske *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
4245106Sdteske *
5238438Sdteske *  This program is free software; you can redistribute it and/or modify
6238438Sdteske *  it under the terms of the GNU General Public License as published by
7238438Sdteske *  the Free Software Foundation; either version 2 of the License, or
8238438Sdteske *  (at your option) any later version.
9238438Sdteske *
10238438Sdteske *  This program is distributed in the hope that it will be useful,
11238438Sdteske *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12238438Sdteske *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13238438Sdteske *  GNU General Public License for more details.
14238438Sdteske *
15238438Sdteske *  You should have received a copy of the GNU General Public License
16238438Sdteske *  along with this program; if not, write to the Free Software
17238438Sdteske *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18238438Sdteske */
19238438Sdteske/*
20238438Sdteske * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
21238438Sdteske * Use is subject to license terms.
22238438Sdteske */
23238438Sdteske
24238438Sdteske#pragma ident	"%Z%%M%	%I%	%E% SMI"
25238438Sdteske
26238438Sdteske#include "fsys_zfs.h"
27238438Sdteske
28238438Sdteske/*
29238438Sdteske * SHA-256 checksum, as specified in FIPS 180-2, available at:
30238438Sdteske * http://csrc.nist.gov/cryptval
31238438Sdteske *
32251265Sdteske * This is a very compact implementation of SHA-256.
33251265Sdteske * It is designed to be simple and portable, not to be fast.
34251265Sdteske */
35251265Sdteske
36251265Sdteske/*
37251265Sdteske * The literal definitions according to FIPS180-2 would be:
38251265Sdteske *
39251265Sdteske * 	Ch(x, y, z)     (((x) & (y)) ^ ((~(x)) & (z)))
40251265Sdteske * 	Maj(x, y, z)    (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
41251265Sdteske *
42251265Sdteske * We use logical equivalents which require one less op.
43251265Sdteske */
44251265Sdteske#define	Ch(x, y, z)	((z) ^ ((x) & ((y) ^ (z))))
45251265Sdteske#define	Maj(x, y, z)	(((x) & (y)) ^ ((z) & ((x) ^ (y))))
46251265Sdteske#define	Rot32(x, s)	(((x) >> s) | ((x) << (32 - s)))
47240684Sdteske#define	SIGMA0(x)	(Rot32(x, 2) ^ Rot32(x, 13) ^ Rot32(x, 22))
48240684Sdteske#define	SIGMA1(x)	(Rot32(x, 6) ^ Rot32(x, 11) ^ Rot32(x, 25))
49244675Sdteske#define	sigma0(x)	(Rot32(x, 7) ^ Rot32(x, 18) ^ ((x) >> 3))
50240684Sdteske#define	sigma1(x)	(Rot32(x, 17) ^ Rot32(x, 19) ^ ((x) >> 10))
51240684Sdteske
52240684Sdteskestatic const uint32_t SHA256_K[64] = {
53240684Sdteske	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
54238438Sdteske	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
55238438Sdteske	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
56238438Sdteske	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
57242107Sdteske	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
58242107Sdteske	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
59242107Sdteske	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
60238438Sdteske	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
61238438Sdteske	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
62238438Sdteske	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
63238438Sdteske	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
64238438Sdteske	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
65238438Sdteske	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
66238438Sdteske	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
67238438Sdteske	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
68251264Sdteske	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
69251264Sdteske};
70238438Sdteske
71238438Sdteskestatic void
72249746SdteskeSHA256Transform(uint32_t *H, const uint8_t *cp)
73238438Sdteske{
74238438Sdteske	uint32_t a, b, c, d, e, f, g, h, t, T1, T2, W[64];
75238438Sdteske
76238438Sdteske	for (t = 0; t < 16; t++, cp += 4)
77238438Sdteske		W[t] = (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3];
78238438Sdteske
79238438Sdteske	for (t = 16; t < 64; t++)
80238438Sdteske		W[t] = sigma1(W[t - 2]) + W[t - 7] +
81238438Sdteske		    sigma0(W[t - 15]) + W[t - 16];
82238438Sdteske
83238438Sdteske	a = H[0]; b = H[1]; c = H[2]; d = H[3];
84238438Sdteske	e = H[4]; f = H[5]; g = H[6]; h = H[7];
85238438Sdteske
86238438Sdteske	for (t = 0; t < 64; t++) {
87238438Sdteske		T1 = h + SIGMA1(e) + Ch(e, f, g) + SHA256_K[t] + W[t];
88238438Sdteske		T2 = SIGMA0(a) + Maj(a, b, c);
89238438Sdteske		h = g; g = f; f = e; e = d + T1;
90238438Sdteske		d = c; c = b; b = a; a = T1 + T2;
91244550Sdteske	}
92238438Sdteske
93238438Sdteske	H[0] += a; H[1] += b; H[2] += c; H[3] += d;
94238438Sdteske	H[4] += e; H[5] += f; H[6] += g; H[7] += h;
95238438Sdteske}
96251270Sdteske
97238438Sdteskevoid
98251270Sdteskezio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp)
99244550Sdteske{
100238438Sdteske	uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
101238438Sdteske	    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
102238438Sdteske	uint8_t pad[128];
103238438Sdteske	int padsize = size & 63;
104238438Sdteske	int i;
105238438Sdteske
106238438Sdteske	for (i = 0; i < size - padsize; i += 64)
107238438Sdteske		SHA256Transform(H, (uint8_t *)buf + i);
108238438Sdteske
109238438Sdteske	for (i = 0; i < padsize; i++)
110238438Sdteske		pad[i] = ((uint8_t *)buf)[i];
111238438Sdteske
112244550Sdteske	for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++)
113238438Sdteske		pad[padsize] = 0;
114238438Sdteske
115238438Sdteske	for (i = 0; i < 8; i++)
116238438Sdteske		pad[padsize++] = (size << 3) >> (56 - 8 * i);
117238438Sdteske
118238438Sdteske	for (i = 0; i < padsize; i += 64)
119238438Sdteske		SHA256Transform(H, pad + i);
120238438Sdteske
121238438Sdteske	ZIO_SET_CHECKSUM(zcp,
122238438Sdteske	    (uint64_t)H[0] << 32 | H[1],
123238438Sdteske	    (uint64_t)H[2] << 32 | H[3],
124238438Sdteske	    (uint64_t)H[4] << 32 | H[5],
125238438Sdteske	    (uint64_t)H[6] << 32 | H[7]);
126238438Sdteske}
127238438Sdteske