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