1341618Scy/* 2341618Scy * FIPS 186-2 PRF for libcrypto 3341618Scy * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> 4341618Scy * 5341618Scy * This software may be distributed under the terms of the BSD license. 6341618Scy * See README for more details. 7341618Scy */ 8341618Scy 9341618Scy#include "includes.h" 10341618Scy#include <wolfssl/options.h> 11341618Scy#include <wolfssl/wolfcrypt/sha.h> 12341618Scy 13341618Scy#include "common.h" 14341618Scy#include "crypto.h" 15341618Scy 16341618Scy 17341618Scystatic void sha1_transform(u32 *state, const u8 data[64]) 18341618Scy{ 19341618Scy wc_Sha sha; 20341618Scy 21341618Scy os_memset(&sha, 0, sizeof(sha)); 22341618Scy sha.digest[0] = state[0]; 23341618Scy sha.digest[1] = state[1]; 24341618Scy sha.digest[2] = state[2]; 25341618Scy sha.digest[3] = state[3]; 26341618Scy sha.digest[4] = state[4]; 27341618Scy wc_ShaUpdate(&sha, data, 64); 28341618Scy state[0] = sha.digest[0]; 29341618Scy state[1] = sha.digest[1]; 30341618Scy state[2] = sha.digest[2]; 31341618Scy state[3] = sha.digest[3]; 32341618Scy state[4] = sha.digest[4]; 33341618Scy} 34341618Scy 35341618Scy 36341618Scyint fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) 37341618Scy{ 38341618Scy u8 xkey[64]; 39341618Scy u32 t[5], _t[5]; 40341618Scy int i, j, m, k; 41341618Scy u8 *xpos = x; 42341618Scy u32 carry; 43341618Scy 44341618Scy if (seed_len < sizeof(xkey)) 45341618Scy os_memset(xkey + seed_len, 0, sizeof(xkey) - seed_len); 46341618Scy else 47341618Scy seed_len = sizeof(xkey); 48341618Scy 49341618Scy /* FIPS 186-2 + change notice 1 */ 50341618Scy 51341618Scy os_memcpy(xkey, seed, seed_len); 52341618Scy t[0] = 0x67452301; 53341618Scy t[1] = 0xEFCDAB89; 54341618Scy t[2] = 0x98BADCFE; 55341618Scy t[3] = 0x10325476; 56341618Scy t[4] = 0xC3D2E1F0; 57341618Scy 58341618Scy m = xlen / 40; 59341618Scy for (j = 0; j < m; j++) { 60341618Scy /* XSEED_j = 0 */ 61341618Scy for (i = 0; i < 2; i++) { 62341618Scy /* XVAL = (XKEY + XSEED_j) mod 2^b */ 63341618Scy 64341618Scy /* w_i = G(t, XVAL) */ 65341618Scy os_memcpy(_t, t, 20); 66341618Scy sha1_transform(_t, xkey); 67341618Scy WPA_PUT_BE32(xpos, _t[0]); 68341618Scy WPA_PUT_BE32(xpos + 4, _t[1]); 69341618Scy WPA_PUT_BE32(xpos + 8, _t[2]); 70341618Scy WPA_PUT_BE32(xpos + 12, _t[3]); 71341618Scy WPA_PUT_BE32(xpos + 16, _t[4]); 72341618Scy 73341618Scy /* XKEY = (1 + XKEY + w_i) mod 2^b */ 74341618Scy carry = 1; 75341618Scy for (k = 19; k >= 0; k--) { 76341618Scy carry += xkey[k] + xpos[k]; 77341618Scy xkey[k] = carry & 0xff; 78341618Scy carry >>= 8; 79341618Scy } 80341618Scy 81341618Scy xpos += 20; 82341618Scy } 83341618Scy /* x_j = w_0|w_1 */ 84341618Scy } 85341618Scy 86341618Scy return 0; 87341618Scy} 88