1e28a4053SRui Paulo /* 2e28a4053SRui Paulo * FIPS 186-2 PRF for libcrypto 3e28a4053SRui Paulo * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> 4e28a4053SRui Paulo * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 7e28a4053SRui Paulo */ 8e28a4053SRui Paulo 9e28a4053SRui Paulo #include "includes.h" 10e28a4053SRui Paulo #include <openssl/sha.h> 11e28a4053SRui Paulo 12e28a4053SRui Paulo #include "common.h" 13e28a4053SRui Paulo #include "crypto.h" 14e28a4053SRui Paulo 15e28a4053SRui Paulo 16*325151a3SRui Paulo static void sha1_transform(u32 *state, const u8 data[64]) 17e28a4053SRui Paulo { 18e28a4053SRui Paulo SHA_CTX context; 19e28a4053SRui Paulo os_memset(&context, 0, sizeof(context)); 20*325151a3SRui Paulo context.h0 = state[0]; 21*325151a3SRui Paulo context.h1 = state[1]; 22*325151a3SRui Paulo context.h2 = state[2]; 23*325151a3SRui Paulo context.h3 = state[3]; 24*325151a3SRui Paulo context.h4 = state[4]; 25e28a4053SRui Paulo SHA1_Transform(&context, data); 26*325151a3SRui Paulo state[0] = context.h0; 27*325151a3SRui Paulo state[1] = context.h1; 28*325151a3SRui Paulo state[2] = context.h2; 29*325151a3SRui Paulo state[3] = context.h3; 30*325151a3SRui Paulo state[4] = context.h4; 31e28a4053SRui Paulo } 32e28a4053SRui Paulo 33e28a4053SRui Paulo 34e28a4053SRui Paulo int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) 35e28a4053SRui Paulo { 36e28a4053SRui Paulo u8 xkey[64]; 37e28a4053SRui Paulo u32 t[5], _t[5]; 38e28a4053SRui Paulo int i, j, m, k; 39e28a4053SRui Paulo u8 *xpos = x; 40e28a4053SRui Paulo u32 carry; 41e28a4053SRui Paulo 42f05cddf9SRui Paulo if (seed_len < sizeof(xkey)) 43f05cddf9SRui Paulo os_memset(xkey + seed_len, 0, sizeof(xkey) - seed_len); 44f05cddf9SRui Paulo else 45e28a4053SRui Paulo seed_len = sizeof(xkey); 46e28a4053SRui Paulo 47e28a4053SRui Paulo /* FIPS 186-2 + change notice 1 */ 48e28a4053SRui Paulo 49e28a4053SRui Paulo os_memcpy(xkey, seed, seed_len); 50e28a4053SRui Paulo t[0] = 0x67452301; 51e28a4053SRui Paulo t[1] = 0xEFCDAB89; 52e28a4053SRui Paulo t[2] = 0x98BADCFE; 53e28a4053SRui Paulo t[3] = 0x10325476; 54e28a4053SRui Paulo t[4] = 0xC3D2E1F0; 55e28a4053SRui Paulo 56e28a4053SRui Paulo m = xlen / 40; 57e28a4053SRui Paulo for (j = 0; j < m; j++) { 58e28a4053SRui Paulo /* XSEED_j = 0 */ 59e28a4053SRui Paulo for (i = 0; i < 2; i++) { 60e28a4053SRui Paulo /* XVAL = (XKEY + XSEED_j) mod 2^b */ 61e28a4053SRui Paulo 62e28a4053SRui Paulo /* w_i = G(t, XVAL) */ 63e28a4053SRui Paulo os_memcpy(_t, t, 20); 64*325151a3SRui Paulo sha1_transform(_t, xkey); 65e28a4053SRui Paulo _t[0] = host_to_be32(_t[0]); 66e28a4053SRui Paulo _t[1] = host_to_be32(_t[1]); 67e28a4053SRui Paulo _t[2] = host_to_be32(_t[2]); 68e28a4053SRui Paulo _t[3] = host_to_be32(_t[3]); 69e28a4053SRui Paulo _t[4] = host_to_be32(_t[4]); 70e28a4053SRui Paulo os_memcpy(xpos, _t, 20); 71e28a4053SRui Paulo 72e28a4053SRui Paulo /* XKEY = (1 + XKEY + w_i) mod 2^b */ 73e28a4053SRui Paulo carry = 1; 74e28a4053SRui Paulo for (k = 19; k >= 0; k--) { 75e28a4053SRui Paulo carry += xkey[k] + xpos[k]; 76e28a4053SRui Paulo xkey[k] = carry & 0xff; 77e28a4053SRui Paulo carry >>= 8; 78e28a4053SRui Paulo } 79e28a4053SRui Paulo 80e28a4053SRui Paulo xpos += 20; 81e28a4053SRui Paulo } 82e28a4053SRui Paulo /* x_j = w_0|w_1 */ 83e28a4053SRui Paulo } 84e28a4053SRui Paulo 85e28a4053SRui Paulo return 0; 86e28a4053SRui Paulo } 87