/* This file is distributed under the following terms: * Copyright 2005-2014 Colin Percival. All rights reserved. * Copyright 2014 Sean Kelly. 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 #include "pbkdf2.h" /* Function which does the zeroing. */ static void insecure_memzero_func(volatile void * buf, size_t len) { volatile uint8_t * _buf = (volatile uint8_t *)buf; size_t i; for (i = 0; i < len; i++) _buf[i] = 0; } /* Pointer to memory-zeroing function. */ void (* volatile insecure_memzero_ptr)(volatile void *, size_t) = insecure_memzero_func; /** * HMAC_SHA256_Init(ctx, K, Klen): * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from * ${K}. */ void HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) { uint8_t pad[64]; uint8_t khash[32]; const uint8_t * K = (const uint8_t *)_K; size_t i; /* If Klen > 64, the key is really SHA256(K). */ if (Klen > 64) { ctx->ictx.Init(); ctx->ictx.Update(K, Klen); memcpy(khash, ctx->ictx.Digest(), 32); K = khash; Klen = 32; } /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ ctx->ictx.Init(); memset(pad, 0x36, 64); for (i = 0; i < Klen; i++) pad[i] ^= K[i]; ctx->ictx.Update(pad, 64); /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ ctx->octx.Init(); memset(pad, 0x5c, 64); for (i = 0; i < Klen; i++) pad[i] ^= K[i]; ctx->octx.Update(pad, 64); /* Clean the stack. */ insecure_memzero(khash, 32); insecure_memzero(pad, 64); } /** * HMAC_SHA256_Update(ctx, in, len): * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}. */ void HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len) { /* Feed data to the inner SHA256 operation. */ ctx->ictx.Update(in, len); } /** * HMAC_SHA256_Final(digest, ctx): * Output the HMAC-SHA256 of the data input to the context ${ctx} into the * buffer ${digest}. */ void HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx) { uint8_t ihash[32]; /* Finish the inner SHA256 operation. */ memcpy(ihash, ctx->ictx.Digest(), 32); /* Feed the inner hash to the outer SHA256 operation. */ ctx->octx.Update(ihash, 32); /* Finish the outer SHA256 operation. */ memcpy(digest, ctx->octx.Digest(), 32); /* Clean the stack. */ insecure_memzero(ihash, 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; size_t i; uint32_t ivec; uint8_t U[32]; uint8_t T[32]; uint64_t j; int k; size_t clen; /* Sanity-check. */ assert(dkLen <= 32 * (size_t)(UINT32_MAX)); /* 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). */ ivec = B_HOST_TO_BENDIAN_INT32((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. */ insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX)); }