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