/*- * Copyright 2005,2007,2009 Colin Percival * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include "sysendian.h" #include "sha256_p.h" #include "compat.h" /* Elementary functions used by SHA256 */ #define Ch(x, y, z) ((x & (y ^ z)) ^ z) #define Maj(x, y, z) ((x & (y | z)) | (y & z)) #define SHR(x, n) (x >> n) #define ROTR(x, n) ((x >> n) | (x << (32 - n))) #define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) #define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) /* SHA256 round function */ #define RND(a, b, c, d, e, f, g, h, k) \ t0 = h + S1(e) + Ch(e, f, g) + k; \ t1 = S0(a) + Maj(a, b, c); \ d += t0; \ h = t0 + t1; /* Adjusted round function for rotating state */ #define RNDr(S, W, i, k) \ RND(S[(64 - i) % 8], S[(65 - i) % 8], \ S[(66 - i) % 8], S[(67 - i) % 8], \ S[(68 - i) % 8], S[(69 - i) % 8], \ S[(70 - i) % 8], S[(71 - i) % 8], \ W[i] + k) /* static unsigned char PAD[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; */ /** * SHA256_Buf(in, len, digest): * Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}. */ void SHA256_Buf( const void * in, size_t len, uint8_t digest[32] ) { SHA256_CTX ctx; SHA256_Init( &ctx ); SHA256_Update( &ctx, in, len ); SHA256_Final( digest, &ctx ); } /** * HMAC_SHA256_Buf(K, Klen, in, len, digest): * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of * length ${Klen}, and write the result to ${digest}. */ void HMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len, uint8_t digest[32]) { HMAC_SHA256_CTX ctx; HMAC_SHA256_Init( &ctx, K, Klen ); HMAC_SHA256_Update( &ctx, in, len ); HMAC_SHA256_Final( digest, &ctx ); } /* Initialize an HMAC-SHA256 operation with the given key. */ void HMAC_SHA256_Init( HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen ) { unsigned char pad[64]; unsigned char khash[32]; const unsigned char * K = _K; size_t i; /* If Klen > 64, the key is really SHA256(K). */ if (Klen > 64) { SHA256_Init( &ctx->ictx ); SHA256_Update( &ctx->ictx, K, Klen ); SHA256_Final( khash, &ctx->ictx ); K = khash; Klen = 32; } /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ SHA256_Init( &ctx->ictx ); memset( pad, 0x36, 64 ); for ( i = 0; i < Klen; i++ ) pad[i] ^= K[i]; SHA256_Update( &ctx->ictx, pad, 64 ); /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ SHA256_Init( &ctx->octx ); memset(pad, 0x5c, 64); for ( i = 0; i < Klen; i++ ) pad[i] ^= K[i]; SHA256_Update( &ctx->octx, pad, 64 ); /* Clean the stack. */ //memset(khash, 0, 32); } /* Add bytes to the HMAC-SHA256 operation. */ void HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) { /* Feed data to the inner SHA256 operation. */ SHA256_Update( &ctx->ictx, in, len ); } /* Finish an HMAC-SHA256 operation. */ void HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx ) { unsigned char ihash[32]; /* Finish the inner SHA256 operation. */ SHA256_Final( ihash, &ctx->ictx ); /* Feed the inner hash to the outer SHA256 operation. */ SHA256_Update( &ctx->octx, ihash, 32 ); /* Finish the outer SHA256 operation. */ SHA256_Final( digest, &ctx->octx ); /* Clean the stack. */ //memset(ihash, 0, 32); } /** * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). */ void PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) { HMAC_SHA256_CTX PShctx, hctx; uint8_t _ALIGN(128) T[32]; uint8_t _ALIGN(128) U[32]; uint8_t ivec[4]; size_t i, clen; uint64_t j; int k; /* Compute HMAC state after processing P and S. */ HMAC_SHA256_Init(&PShctx, passwd, passwdlen); HMAC_SHA256_Update(&PShctx, salt, saltlen); /* Iterate through the blocks. */ for (i = 0; i * 32 < dkLen; i++) { /* Generate INT(i + 1). */ be32enc(ivec, (uint32_t)(i + 1)); /* Compute U_1 = PRF(P, S || INT(i)). */ memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); HMAC_SHA256_Update(&hctx, ivec, 4); HMAC_SHA256_Final(U, &hctx); /* T_i = U_1 ... */ memcpy(T, U, 32); for (j = 2; j <= c; j++) { /* Compute U_j. */ HMAC_SHA256_Init(&hctx, passwd, passwdlen); HMAC_SHA256_Update(&hctx, U, 32); HMAC_SHA256_Final(U, &hctx); /* ... xor U_j ... */ for (k = 0; k < 32; k++) T[k] ^= U[k]; } /* Copy as many bytes as necessary into buf. */ clen = dkLen - i * 32; if (clen > 32) clen = 32; memcpy(&buf[i * 32], T, clen); } /* Clean PShctx, since we never called _Final on it. */ //memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX_Y)); }