From 8a6f89be881a447bdbfabda94f3dbff9c2610955 Mon Sep 17 00:00:00 2001 From: wangyu- Date: Sat, 23 Jun 2018 20:00:03 -0500 Subject: [PATCH] add missing files --- lib/pbkdf2-sha1.c | 865 +++++++++++++++++++++++++++++++++++++++++++ lib/pbkdf2-sha1.h | 14 + lib/pbkdf2-sha256.c | 871 ++++++++++++++++++++++++++++++++++++++++++++ lib/pbkdf2-sha256.h | 13 + 4 files changed, 1763 insertions(+) create mode 100644 lib/pbkdf2-sha1.c create mode 100644 lib/pbkdf2-sha1.h create mode 100644 lib/pbkdf2-sha256.c create mode 100644 lib/pbkdf2-sha256.h diff --git a/lib/pbkdf2-sha1.c b/lib/pbkdf2-sha1.c new file mode 100644 index 0000000..a8ce77b --- /dev/null +++ b/lib/pbkdf2-sha1.c @@ -0,0 +1,865 @@ +/* + this file is from https://github.com/kholia/PKCS5_PBKDF2 + +* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + * + * Copyright 2012 Mathias Olsson mathias@kompetensum.com + * + * This file is dual licensed as either GPL version 2 or Apache License 2.0 at your choice + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * http://www.apache.org/licenses/ + * + * Note that PolarSSL uses GPL with a FOSS License Exception */ + +#include +#include +#include + +#if defined(TEST) ||defined(DEBUG) +#undef TEST +#undef DEBUG +#warning "undefined TEST/DEBUG" +#endif + +typedef struct { + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} sha1_context; + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-1 context setup + */ +void sha1_starts(sha1_context * ctx) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +static void sha1_process(sha1_context * ctx, const unsigned char data[64]) +{ + unsigned long temp, W[16], A, B, C, D, E; + + GET_ULONG_BE(W[0], data, 0); + GET_ULONG_BE(W[1], data, 4); + GET_ULONG_BE(W[2], data, 8); + GET_ULONG_BE(W[3], data, 12); + GET_ULONG_BE(W[4], data, 16); + GET_ULONG_BE(W[5], data, 20); + GET_ULONG_BE(W[6], data, 24); + GET_ULONG_BE(W[7], data, 28); + GET_ULONG_BE(W[8], data, 32); + GET_ULONG_BE(W[9], data, 36); + GET_ULONG_BE(W[10], data, 40); + GET_ULONG_BE(W[11], data, 44); + GET_ULONG_BE(W[12], data, 48); + GET_ULONG_BE(W[13], data, 52); + GET_ULONG_BE(W[14], data, 56); + GET_ULONG_BE(W[15], data, 60); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ + W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P(A, B, C, D, E, W[0]); + P(E, A, B, C, D, W[1]); + P(D, E, A, B, C, W[2]); + P(C, D, E, A, B, W[3]); + P(B, C, D, E, A, W[4]); + P(A, B, C, D, E, W[5]); + P(E, A, B, C, D, W[6]); + P(D, E, A, B, C, W[7]); + P(C, D, E, A, B, W[8]); + P(B, C, D, E, A, W[9]); + P(A, B, C, D, E, W[10]); + P(E, A, B, C, D, W[11]); + P(D, E, A, B, C, W[12]); + P(C, D, E, A, B, W[13]); + P(B, C, D, E, A, W[14]); + P(A, B, C, D, E, W[15]); + P(E, A, B, C, D, R(16)); + P(D, E, A, B, C, R(17)); + P(C, D, E, A, B, R(18)); + P(B, C, D, E, A, R(19)); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P(A, B, C, D, E, R(20)); + P(E, A, B, C, D, R(21)); + P(D, E, A, B, C, R(22)); + P(C, D, E, A, B, R(23)); + P(B, C, D, E, A, R(24)); + P(A, B, C, D, E, R(25)); + P(E, A, B, C, D, R(26)); + P(D, E, A, B, C, R(27)); + P(C, D, E, A, B, R(28)); + P(B, C, D, E, A, R(29)); + P(A, B, C, D, E, R(30)); + P(E, A, B, C, D, R(31)); + P(D, E, A, B, C, R(32)); + P(C, D, E, A, B, R(33)); + P(B, C, D, E, A, R(34)); + P(A, B, C, D, E, R(35)); + P(E, A, B, C, D, R(36)); + P(D, E, A, B, C, R(37)); + P(C, D, E, A, B, R(38)); + P(B, C, D, E, A, R(39)); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P(A, B, C, D, E, R(40)); + P(E, A, B, C, D, R(41)); + P(D, E, A, B, C, R(42)); + P(C, D, E, A, B, R(43)); + P(B, C, D, E, A, R(44)); + P(A, B, C, D, E, R(45)); + P(E, A, B, C, D, R(46)); + P(D, E, A, B, C, R(47)); + P(C, D, E, A, B, R(48)); + P(B, C, D, E, A, R(49)); + P(A, B, C, D, E, R(50)); + P(E, A, B, C, D, R(51)); + P(D, E, A, B, C, R(52)); + P(C, D, E, A, B, R(53)); + P(B, C, D, E, A, R(54)); + P(A, B, C, D, E, R(55)); + P(E, A, B, C, D, R(56)); + P(D, E, A, B, C, R(57)); + P(C, D, E, A, B, R(58)); + P(B, C, D, E, A, R(59)); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P(A, B, C, D, E, R(60)); + P(E, A, B, C, D, R(61)); + P(D, E, A, B, C, R(62)); + P(C, D, E, A, B, R(63)); + P(B, C, D, E, A, R(64)); + P(A, B, C, D, E, R(65)); + P(E, A, B, C, D, R(66)); + P(D, E, A, B, C, R(67)); + P(C, D, E, A, B, R(68)); + P(B, C, D, E, A, R(69)); + P(A, B, C, D, E, R(70)); + P(E, A, B, C, D, R(71)); + P(D, E, A, B, C, R(72)); + P(C, D, E, A, B, R(73)); + P(B, C, D, E, A, R(74)); + P(A, B, C, D, E, R(75)); + P(E, A, B, C, D, R(76)); + P(D, E, A, B, C, R(77)); + P(C, D, E, A, B, R(78)); + P(B, C, D, E, A, R(79)); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update(sha1_context * ctx, const unsigned char *input, int ilen) +{ + int fill; + unsigned long left; + + if (ilen <= 0) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (unsigned long) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if (ctx->total[0] < (unsigned long) ilen) + ctx->total[1]++; + + if (left && ilen >= fill) { + memcpy((void *) (ctx->buffer + left), (void *) input, fill); + sha1_process(ctx, ctx->buffer); + input += fill; + ilen -= fill; + left = 0; + } + + while (ilen >= 64) { + sha1_process(ctx, input); + input += 64; + ilen -= 64; + } + + if (ilen > 0) { + memcpy((void *) (ctx->buffer + left), (void *) input, ilen); + } +} + +static const unsigned char sha1_padding[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 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish(sha1_context * ctx, unsigned char output[20]) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = (ctx->total[0] >> 29) + | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); + + PUT_ULONG_BE(high, msglen, 0); + PUT_ULONG_BE(low, msglen, 4); + + last = ctx->total[0] & 0x3F; + padn = (last < 56) ? (56 - last) : (120 - last); + + sha1_update(ctx, (unsigned char *) sha1_padding, padn); + sha1_update(ctx, msglen, 8); + + PUT_ULONG_BE(ctx->state[0], output, 0); + PUT_ULONG_BE(ctx->state[1], output, 4); + PUT_ULONG_BE(ctx->state[2], output, 8); + PUT_ULONG_BE(ctx->state[3], output, 12); + PUT_ULONG_BE(ctx->state[4], output, 16); +} + +/* + * output = SHA-1( input buffer ) + */ +void sha1(const unsigned char *input, int ilen, unsigned char output[20]) +{ + sha1_context ctx; + + sha1_starts(&ctx); + sha1_update(&ctx, input, ilen); + sha1_finish(&ctx, output); + +} + + +/* + * SHA-1 HMAC context setup + */ +void sha1_hmac_starts(sha1_context * ctx, const unsigned char *key, int keylen) +{ + int i; + unsigned char sum[20]; + + if (keylen > 64) { + sha1(key, keylen, sum); + keylen = 20; + key = sum; + } + + memset(ctx->ipad, 0x36, 64); + memset(ctx->opad, 0x5C, 64); + + for (i = 0; i < keylen; i++) { + ctx->ipad[i] = (unsigned char) (ctx->ipad[i] ^ key[i]); + ctx->opad[i] = (unsigned char) (ctx->opad[i] ^ key[i]); + } + + sha1_starts(ctx); + sha1_update(ctx, ctx->ipad, 64); + +} + +/* + * SHA-1 HMAC process buffer + */ +void sha1_hmac_update(sha1_context * ctx, const unsigned char *input, int ilen) +{ + sha1_update(ctx, input, ilen); +} + +/* + * SHA-1 HMAC final digest + */ +void sha1_hmac_finish(sha1_context * ctx, unsigned char output[20]) +{ + unsigned char tmpbuf[20]; + + sha1_finish(ctx, tmpbuf); + sha1_starts(ctx); + sha1_update(ctx, ctx->opad, 64); + sha1_update(ctx, tmpbuf, 20); + sha1_finish(ctx, output); + +} + +/* + * SHA1 HMAC context reset + */ +void sha1_hmac_reset(sha1_context * ctx) +{ + sha1_starts(ctx); + sha1_update(ctx, ctx->ipad, 64); +} + +/* + * output = HMAC-SHA-1( hmac key, input buffer ) + */ +void sha1_hmac(const unsigned char *key, int keylen, + const unsigned char *input, int ilen, unsigned char output[20]) +{ + sha1_context ctx; + + sha1_hmac_starts(&ctx, key, keylen); + sha1_hmac_update(&ctx, input, ilen); + sha1_hmac_finish(&ctx, output); + +} + + + + + + + +#ifndef min +#define min( a, b ) ( ((a) < (b)) ? (a) : (b) ) +#endif + +void PKCS5_PBKDF2_HMAC_SHA1(const unsigned char *password, size_t plen, + const unsigned char *salt, size_t slen, + const unsigned long iteration_count, const unsigned long key_length, + unsigned char *output) +{ + sha1_context ctx; + sha1_starts(&ctx); + + // Size of the generated digest + unsigned char md_size = 20; + unsigned char md1[20]; + unsigned char work[20]; + + unsigned long counter = 1; + unsigned long generated_key_length = 0; + while (generated_key_length < key_length) { + // U1 ends up in md1 and work + unsigned char c[4]; + c[0] = (counter >> 24) & 0xff; + c[1] = (counter >> 16) & 0xff; + c[2] = (counter >> 8) & 0xff; + c[3] = (counter >> 0) & 0xff; + + sha1_hmac_starts(&ctx, password, plen); + sha1_hmac_update(&ctx, salt, slen); + sha1_hmac_update(&ctx, c, 4); + sha1_hmac_finish(&ctx, md1); + memcpy(work, md1, md_size); + + unsigned long ic = 1; + for (ic = 1; ic < iteration_count; ic++) { + // U2 ends up in md1 + sha1_hmac_starts(&ctx, password, plen); + sha1_hmac_update(&ctx, md1, md_size); + sha1_hmac_finish(&ctx, md1); + // U1 xor U2 + unsigned long i = 0; + for (i = 0; i < md_size; i++) { + work[i] ^= md1[i]; + } + // and so on until iteration_count + } + + // Copy the generated bytes to the key + unsigned long bytes_to_write = + min((key_length - generated_key_length), md_size); + memcpy(output + generated_key_length, work, bytes_to_write); + generated_key_length += bytes_to_write; + ++counter; + } +} + + +#if defined(TEST) +/* + * FIPS-180-1 test vectors + */ +static unsigned char sha1_test_buf[3][57] = { + {"abc"}, + {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, + {""} +}; + +static const int sha1_test_buflen[3] = { + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = { + {0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D}, + {0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1}, + {0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F} +}; + +/* + * RFC 2202 test vectors + */ +static unsigned char sha1_hmac_test_key[7][26] = { + {"\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B"}, + {"Jefe"}, + {"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA"}, + {"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19"}, + {"\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C"}, + {""}, /* 0xAA 80 times */ + {""} +}; + +static const int sha1_hmac_test_keylen[7] = { + 20, 4, 20, 25, 20, 80, 80 +}; + +static unsigned char sha1_hmac_test_buf[7][74] = { + {"Hi There"}, + {"what do ya want for nothing?"}, + {"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"}, + {"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"}, + {"Test With Truncation"}, + {"Test Using Larger Than Block-Size Key - Hash Key First"}, + {"Test Using Larger Than Block-Size Key and Larger" + " Than One Block-Size Data"} +}; + +static const int sha1_hmac_test_buflen[7] = { + 8, 28, 50, 50, 20, 54, 73 +}; + +static const unsigned char sha1_hmac_test_sum[7][20] = { + {0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B, + 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00}, + {0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74, + 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79}, + {0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3, + 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3}, + {0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84, + 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA}, + {0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2, + 0x7B, 0xE1}, + {0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70, + 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12}, + {0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B, + 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91} +}; + +typedef struct { + char *t; + char *p; + int plen; + char *s; + int slen; + int c; + int dkLen; + char dk[1024]; // Remember to set this to max dkLen +} testvector; + +int do_test(testvector * tv) +{ + printf("Started %s\n", tv->t); + fflush(stdout); + char *key = malloc(tv->dkLen); + if (key == 0) { + return -1; + } + + PKCS5_PBKDF2_HMAC(tv->p, tv->plen, tv->s, tv->slen, tv->c, + tv->dkLen, key); + + if (memcmp(tv->dk, key, tv->dkLen) != 0) { + // Failed + return -1; + } + + return 0; +} + +#ifdef DEBUG +static void print_hex(unsigned char *str, int len) +{ + int i; + for (i = 0; i < len; ++i) + printf("%02x", str[i]); + printf("\n"); +} +#endif + +/* + * Checkup routine + */ +int main(int argc,char * argv[]) +{ + int verbose = 1; + int i, j, buflen; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + + sha1_context ctx; + + /* + * SHA-1 + */ + for (i = 0; i < 3; i++) { + if (verbose != 0) + printf(" SHA-1 test #%d: ", i + 1); + + sha1_starts(&ctx); + + if (i == 2) { + memset(buf, 'a', buflen = 1000); + + for (j = 0; j < 1000; j++) + sha1_update(&ctx, buf, buflen); + } else + sha1_update(&ctx, sha1_test_buf[i], + sha1_test_buflen[i]); + + sha1_finish(&ctx, sha1sum); + + if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) { + if (verbose != 0) + printf("failed\n"); + + return (1); + } + + if (verbose != 0) + printf("passed\n"); + } + + if (verbose != 0) + printf("\n"); + + for (i = 0; i < 7; i++) { + if (verbose != 0) + printf(" HMAC-SHA-1 test #%d: ", i + 1); + + if (i == 5 || i == 6) { + memset(buf, '\xAA', buflen = 80); + sha1_hmac_starts(&ctx, buf, buflen); + } else + sha1_hmac_starts(&ctx, sha1_hmac_test_key[i], + sha1_hmac_test_keylen[i]); + + sha1_hmac_update(&ctx, sha1_hmac_test_buf[i], + sha1_hmac_test_buflen[i]); + + sha1_hmac_finish(&ctx, sha1sum); + + buflen = (i == 4) ? 12 : 20; + + if (memcmp(sha1sum, sha1_hmac_test_sum[i], buflen) != 0) { + if (verbose != 0) + printf("failed\n"); + + return (1); + } + + if (verbose != 0) + printf("passed\n"); + } + + if (verbose != 0) + printf("\n"); + + // Test vectors from RFC 6070 + + testvector *tv = 0; + int res = 0; + +/* + Input: + P = "password" (8 octets) + S = "salt" (4 octets) + c = 1 + dkLen = 20 + + Output: + DK = 0c 60 c8 0f 96 1f 0e 71 + f3 a9 b5 24 af 60 12 06 + 2f e0 37 a6 (20 octets) + +*/ + testvector t1 = { + "Test 1", + "password", 8, "salt", 4, 1, 20, + .dk = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6} + }; + + tv = &t1; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + +/* + Input: + P = "password" (8 octets) + S = "salt" (4 octets) + c = 2 + dkLen = 20 + + Output: + DK = ea 6c 01 4d c7 2d 6f 8c + cd 1e d9 2a ce 1d 41 f0 + d8 de 89 57 (20 octets) + +*/ + + testvector t2 = { + "Test 2", + "password", 8, "salt", 4, 2, 20, + {0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57} + }; + + tv = &t2; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + +/* + Input: + P = "password" (8 octets) + S = "salt" (4 octets) + c = 4096 + dkLen = 20 + + Output: + DK = 4b 00 79 01 b7 65 48 9a + be ad 49 d9 26 f7 21 d0 + 65 a4 29 c1 (20 octets) + + +*/ + testvector t3 = { + "Test 3", + "password", 8, "salt", 4, 4096, 20, + {0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1} + }; + + tv = &t3; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + +/* + Input: + P = "password" (8 octets) + S = "salt" (4 octets) + c = 16777216 + dkLen = 20 + + Output: + DK = ee fe 3d 61 cd 4d a4 e4 + e9 94 5b 3d 6b a2 15 8c + 26 34 e9 84 (20 octets) + +*/ + testvector t4 = { + "Test 4", + "password", 8, "salt", 4, 16777216, 20, + {0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, + 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, + 0x26, 0x34, 0xe9, 0x84} + }; + + tv = &t4; + // res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + +/* + Input: + P = "passwordPASSWORDpassword" (24 octets) + S = "saltSALTsaltSALTsaltSALTsaltSALTsalt" (36 octets) + c = 4096 + dkLen = 25 + + Output: + DK = 3d 2e ec 4f e4 1c 84 9b + 80 c8 d8 36 62 c0 e4 4a + 8b 29 1a 96 4c f2 f0 70 + 38 (25 octets) + +*/ + testvector t5 = { + "Test 5", + "passwordPASSWORDpassword", 24, + "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, 25, + {0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38} + }; + + tv = &t5; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + +/* + Input: + P = "pass\0word" (9 octets) + S = "sa\0lt" (5 octets) + c = 4096 + dkLen = 16 + + Output: + DK = 56 fa 6a a7 55 48 09 9d + cc 37 d7 f0 34 25 e0 c3 (16 octets) +*/ + testvector t6 = { + "Test 6", + "pass\0word", 9, "sa\0lt", 5, 4096, 16, + {0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3, + } + }; + + tv = &t6; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + + printf("All tests successful\n"); + return 0; +} + +#endif +/* +int main() +{ +}*/ diff --git a/lib/pbkdf2-sha1.h b/lib/pbkdf2-sha1.h new file mode 100644 index 0000000..be5b71c --- /dev/null +++ b/lib/pbkdf2-sha1.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include + +void sha1(const unsigned char *input, int ilen, unsigned char output[20]); + +void sha1_hmac(const unsigned char *key, int keylen, const unsigned char *input, int ilen, unsigned char output[20]); + +void PKCS5_PBKDF2_HMAC_SHA1(const unsigned char *password, size_t plen, + const unsigned char *salt, size_t slen, + const unsigned long iteration_count, const unsigned long key_length, + unsigned char *output); diff --git a/lib/pbkdf2-sha256.c b/lib/pbkdf2-sha256.c new file mode 100644 index 0000000..85cb3dc --- /dev/null +++ b/lib/pbkdf2-sha256.c @@ -0,0 +1,871 @@ +/* + this file is from https://github.com/kholia/PKCS5_PBKDF2 + + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include +#include +#include + +#if defined(TEST) ||defined(DEBUG) +#undef TEST +#undef DEBUG +#warning "undefined TEST/DEBUG" +#endif + +typedef struct { + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ +} sha2_context; + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-256 context setup + */ +void sha2_starts( sha2_context *ctx, int is224 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; +} + +static void sha2_process( sha2_context *ctx, const unsigned char data[64] ) +{ + unsigned long temp1, temp2, W[64]; + unsigned long A, B, C, D, E, F, G, H; + + GET_ULONG_BE( W[ 0], data, 0 ); + GET_ULONG_BE( W[ 1], data, 4 ); + GET_ULONG_BE( W[ 2], data, 8 ); + GET_ULONG_BE( W[ 3], data, 12 ); + GET_ULONG_BE( W[ 4], data, 16 ); + GET_ULONG_BE( W[ 5], data, 20 ); + GET_ULONG_BE( W[ 6], data, 24 ); + GET_ULONG_BE( W[ 7], data, 28 ); + GET_ULONG_BE( W[ 8], data, 32 ); + GET_ULONG_BE( W[ 9], data, 36 ); + GET_ULONG_BE( W[10], data, 40 ); + GET_ULONG_BE( W[11], data, 44 ); + GET_ULONG_BE( W[12], data, 48 ); + GET_ULONG_BE( W[13], data, 52 ); + GET_ULONG_BE( W[14], data, 56 ); + GET_ULONG_BE( W[15], data, 60 ); + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + + P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 ); + P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 ); + P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF ); + P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 ); + P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B ); + P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 ); + P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 ); + P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 ); + P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 ); + P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 ); + P( G, H, A, B, C, D, E, F, W[10], 0x243185BE ); + P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 ); + P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 ); + P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE ); + P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 ); + P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 ); + P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 ); + P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 ); + P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 ); + P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC ); + P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F ); + P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA ); + P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC ); + P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA ); + P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 ); + P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D ); + P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 ); + P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 ); + P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 ); + P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 ); + P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 ); + P( B, C, D, E, F, G, H, A, R(31), 0x14292967 ); + P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 ); + P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 ); + P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC ); + P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 ); + P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 ); + P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB ); + P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E ); + P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 ); + P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 ); + P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B ); + P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 ); + P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 ); + P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 ); + P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 ); + P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 ); + P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 ); + P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 ); + P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 ); + P( G, H, A, B, C, D, E, F, R(50), 0x2748774C ); + P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 ); + P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 ); + P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A ); + P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F ); + P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 ); + P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE ); + P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F ); + P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 ); + P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 ); + P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA ); + P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB ); + P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 ); + P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +/* + * SHA-256 process buffer + */ +void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (unsigned long) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + sha2_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha2_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } +} + +static const unsigned char sha2_padding[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 +}; + +/* + * SHA-256 final digest + */ +void sha2_finish( sha2_context *ctx, unsigned char output[32] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_BE( high, msglen, 0 ); + PUT_ULONG_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha2_update( ctx, (unsigned char *) sha2_padding, padn ); + sha2_update( ctx, msglen, 8 ); + + PUT_ULONG_BE( ctx->state[0], output, 0 ); + PUT_ULONG_BE( ctx->state[1], output, 4 ); + PUT_ULONG_BE( ctx->state[2], output, 8 ); + PUT_ULONG_BE( ctx->state[3], output, 12 ); + PUT_ULONG_BE( ctx->state[4], output, 16 ); + PUT_ULONG_BE( ctx->state[5], output, 20 ); + PUT_ULONG_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_ULONG_BE( ctx->state[7], output, 28 ); +} + +/* + * output = SHA-256( input buffer ) + */ +void sha2( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + sha2_context ctx; + + sha2_starts( &ctx, is224 ); + sha2_update( &ctx, input, ilen ); + sha2_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha2_context ) ); +} + +/* + * SHA-256 HMAC context setup + */ +void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen, + int is224 ) +{ + size_t i; + unsigned char sum[32]; + + if( keylen > 64 ) + { + sha2( key, keylen, sum, is224 ); + keylen = ( is224 ) ? 28 : 32; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha2_starts( ctx, is224 ); + sha2_update( ctx, ctx->ipad, 64 ); + + memset( sum, 0, sizeof( sum ) ); +} + +/* + * SHA-256 HMAC process buffer + */ +void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) +{ + sha2_update( ctx, input, ilen ); +} + +/* + * SHA-256 HMAC final digest + */ +void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] ) +{ + int is224, hlen; + unsigned char tmpbuf[32]; + + is224 = ctx->is224; + hlen = ( is224 == 0 ) ? 32 : 28; + + sha2_finish( ctx, tmpbuf ); + sha2_starts( ctx, is224 ); + sha2_update( ctx, ctx->opad, 64 ); + sha2_update( ctx, tmpbuf, hlen ); + sha2_finish( ctx, output ); + + memset( tmpbuf, 0, sizeof( tmpbuf ) ); +} + +/* + * SHA-256 HMAC context reset + */ +void sha2_hmac_reset( sha2_context *ctx ) +{ + sha2_starts( ctx, ctx->is224 ); + sha2_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-SHA-256( hmac key, input buffer ) + */ +void sha2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + sha2_context ctx; + + sha2_hmac_starts( &ctx, key, keylen, is224 ); + sha2_hmac_update( &ctx, input, ilen ); + sha2_hmac_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha2_context ) ); +} + + + + + +#ifndef min +#define min( a, b ) ( ((a) < (b)) ? (a) : (b) ) +#endif + +void PKCS5_PBKDF2_HMAC_SHA256(unsigned char *password, size_t plen, + unsigned char *salt, size_t slen, + const unsigned long iteration_count, const unsigned long key_length, + unsigned char *output) +{ + sha2_context ctx; + sha2_starts(&ctx, 0); + + // Size of the generated digest + unsigned char md_size = 32; + unsigned char md1[32]; + unsigned char work[32]; + + unsigned long counter = 1; + unsigned long generated_key_length = 0; + while (generated_key_length < key_length) { + // U1 ends up in md1 and work + unsigned char c[4]; + c[0] = (counter >> 24) & 0xff; + c[1] = (counter >> 16) & 0xff; + c[2] = (counter >> 8) & 0xff; + c[3] = (counter >> 0) & 0xff; + + sha2_hmac_starts(&ctx, password, plen, 0); + sha2_hmac_update(&ctx, salt, slen); + sha2_hmac_update(&ctx, c, 4); + sha2_hmac_finish(&ctx, md1); + memcpy(work, md1, md_size); + + unsigned long ic = 1; + for (ic = 1; ic < iteration_count; ic++) { + // U2 ends up in md1 + sha2_hmac_starts(&ctx, password, plen, 0); + sha2_hmac_update(&ctx, md1, md_size); + sha2_hmac_finish(&ctx, md1); + // U1 xor U2 + unsigned long i = 0; + for (i = 0; i < md_size; i++) { + work[i] ^= md1[i]; + } + // and so on until iteration_count + } + + // Copy the generated bytes to the key + unsigned long bytes_to_write = + min((key_length - generated_key_length), md_size); + memcpy(output + generated_key_length, work, bytes_to_write); + generated_key_length += bytes_to_write; + ++counter; + } +} + + + + + + + + + +#ifdef TEST +/* + * FIPS-180-2 test vectors + */ +static unsigned char sha2_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha2_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha2_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * RFC 4231 test vectors + */ +static unsigned char sha2_hmac_test_key[7][26] = { + {"\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B"}, + {"Jefe"}, + {"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA"}, + {"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19"}, + {"\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C"}, + {""}, /* 0xAA 131 times */ + {""} +}; + +static const int sha2_hmac_test_keylen[7] = { + 20, 4, 20, 25, 20, 131, 131 +}; + +static unsigned char sha2_hmac_test_buf[7][153] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "This is a test using a larger than block-size key " + "and a larger than block-size data. The key needs to " + "be hashed before being used by the HMAC algorithm." } +}; + +static const int sha2_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 152 +}; + +static const unsigned char sha2_hmac_test_sum[14][32] = +{ + /* + * HMAC-SHA-224 test vectors + */ + { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19, + 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F, + 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F, + 0x53, 0x68, 0x4B, 0x22 }, + { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF, + 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F, + 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00, + 0x8F, 0xD0, 0x5E, 0x44 }, + { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6, + 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64, + 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1, + 0xEC, 0x83, 0x33, 0xEA }, + { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC, + 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C, + 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D, + 0xE7, 0xAF, 0xEC, 0x5A }, + { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37, + 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 }, + { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD, + 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2, + 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27, + 0x3F, 0xA6, 0x87, 0x0E }, + { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02, + 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD, + 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9, + 0xF6, 0xF5, 0x65, 0xD1 }, + + /* + * HMAC-SHA-256 test vectors + */ + { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53, + 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B, + 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7, + 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 }, + { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E, + 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7, + 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83, + 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 }, + { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46, + 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7, + 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22, + 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE }, + { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E, + 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A, + 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07, + 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B }, + { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0, + 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B }, + { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F, + 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F, + 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14, + 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 }, + { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB, + 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44, + 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93, + 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 } +}; +typedef struct { + char *t; + char *p; + int plen; + char *s; + int slen; + int c; + int dkLen; + char dk[1024]; // Remember to set this to max dkLen +} testvector; + +int do_test(testvector * tv) +{ + printf("Started %s\n", tv->t); + fflush(stdout); + char *key = malloc(tv->dkLen); + if (key == 0) { + return -1; + } + + PKCS5_PBKDF2_HMAC((unsigned char*)tv->p, tv->plen, + (unsigned char*)tv->s, tv->slen, tv->c, + tv->dkLen, (unsigned char*)key); + + if (memcmp(tv->dk, key, tv->dkLen) != 0) { + // Failed + return -1; + } + + return 0; +} + +/* + * Checkup routine + */ +int main() +{ + int verbose = 1; + int i, j, k, buflen; + unsigned char buf[1024]; + unsigned char sha2sum[32]; + sha2_context ctx; + + for (i = 0; i < 6; i++) { + j = i % 3; + k = i < 3; + + if (verbose != 0) + printf(" SHA-%d test #%d: ", 256 - k * 32, j + 1); + + sha2_starts(&ctx, k); + + if (j == 2) { + memset(buf, 'a', buflen = 1000); + + for (j = 0; j < 1000; j++) + sha2_update(&ctx, buf, buflen); + } else + sha2_update(&ctx, sha2_test_buf[j], + sha2_test_buflen[j]); + + sha2_finish(&ctx, sha2sum); + + if (memcmp(sha2sum, sha2_test_sum[i], 32 - k * 4) != 0) { + if (verbose != 0) + printf("failed\n"); + + return (1); + } + + if (verbose != 0) + printf("passed\n"); + } + + if (verbose != 0) + printf("\n"); + + for (i = 0; i < 14; i++) { + j = i % 7; + k = i < 7; + + if (verbose != 0) + printf(" HMAC-SHA-%d test #%d: ", 256 - k * 32, + j + 1); + + if (j == 5 || j == 6) { + memset(buf, '\xAA', buflen = 131); + sha2_hmac_starts(&ctx, buf, buflen, k); + } else + sha2_hmac_starts(&ctx, sha2_hmac_test_key[j], + sha2_hmac_test_keylen[j], k); + + sha2_hmac_update(&ctx, sha2_hmac_test_buf[j], + sha2_hmac_test_buflen[j]); + + sha2_hmac_finish(&ctx, sha2sum); + + buflen = (j == 4) ? 16 : 32 - k * 4; + + if (memcmp(sha2sum, sha2_hmac_test_sum[i], buflen) != 0) { + if (verbose != 0) + printf("failed\n"); + + return (1); + } + + if (verbose != 0) + printf("passed\n"); + } + + if (verbose != 0) + printf("\n"); + + testvector *tv = 0; + int res = 0; + + testvector t1 = { + "Test 1", + "password", 8, "salt", 4, 1, 32, + .dk = { 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, + 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, + 0xa8, 0x65, 0x48, 0xc9, 0x2c, 0xcc, 0x35, 0x48, + 0x08, 0x05, 0x98, 0x7c, 0xb7, 0x0b, 0xe1, 0x7b } + }; + + tv = &t1; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + + testvector t2 = { + "Test 2", + "password", 8, "salt", 4, 2, 32, { + 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, + 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, + 0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf, + 0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43 } + }; + + tv = &t2; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + + testvector t3 = { + "Test 3", + "password", 8, "salt", 4, 4096, 32, { + 0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, + 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, + 0x96, 0x28, 0x93, 0xa0, 0x01, 0xce, 0x4e, 0x11, + 0xa4, 0x96, 0x38, 0x73, 0xaa, 0x98, 0x13, 0x4a } + }; + + tv = &t3; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + + testvector t4 = { + "Test 4", + "password", 8, "salt", 4, 16777216, 32, { + 0xcf, 0x81, 0xc6, 0x6f, 0xe8, 0xcf, 0xc0, 0x4d, + 0x1f, 0x31, 0xec, 0xb6, 0x5d, 0xab, 0x40, 0x89, + 0xf7, 0xf1, 0x79, 0xe8, 0x9b, 0x3b, 0x0b, 0xcb, + 0x17, 0xad, 0x10, 0xe3, 0xac, 0x6e, 0xba, 0x46 } + }; + + tv = &t4; + // res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + + testvector t5 = { + "Test 5", + "passwordPASSWORDpassword", 24, + "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, 40, { + 0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f, + 0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf, + 0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18, + 0x1c, 0x4e, 0x2a, 0x1f, 0xb8, 0xdd, 0x53, 0xe1, + 0xc6, 0x35, 0x51, 0x8c, 0x7d, 0xac, 0x47, 0xe9 } + }; + + tv = &t5; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + + testvector t6 = { + "Test 6", + "pass\0word", 9, "sa\0lt", 5, 4096, 16, { + 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89, + 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87 } + }; + + tv = &t6; + res = do_test(tv); + if (res != 0) { + printf("%s failed\n", tv->t); + return res; + } + + return (0); +} + +#endif diff --git a/lib/pbkdf2-sha256.h b/lib/pbkdf2-sha256.h new file mode 100644 index 0000000..e647de7 --- /dev/null +++ b/lib/pbkdf2-sha256.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include + +void PKCS5_PBKDF2_HMAC_SHA256(unsigned char *password, size_t plen, + unsigned char *salt, size_t slen, + const unsigned long iteration_count, const unsigned long key_length, + unsigned char *output); + +void sha2( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 );