1214501Srpaulo/* 2214501Srpaulo * FIPS 186-2 PRF for libcrypto 3214501Srpaulo * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "includes.h" 10214501Srpaulo#include <openssl/sha.h> 11214501Srpaulo 12214501Srpaulo#include "common.h" 13214501Srpaulo#include "crypto.h" 14214501Srpaulo 15214501Srpaulo 16289549Srpaulostatic void sha1_transform(u32 *state, const u8 data[64]) 17214501Srpaulo{ 18214501Srpaulo SHA_CTX context; 19214501Srpaulo os_memset(&context, 0, sizeof(context)); 20337817Scy#if defined(OPENSSL_IS_BORINGSSL) && !defined(ANDROID) 21337817Scy context.h[0] = state[0]; 22337817Scy context.h[1] = state[1]; 23337817Scy context.h[2] = state[2]; 24337817Scy context.h[3] = state[3]; 25337817Scy context.h[4] = state[4]; 26337817Scy SHA1_Transform(&context, data); 27337817Scy state[0] = context.h[0]; 28337817Scy state[1] = context.h[1]; 29337817Scy state[2] = context.h[2]; 30337817Scy state[3] = context.h[3]; 31337817Scy state[4] = context.h[4]; 32337817Scy#else 33289549Srpaulo context.h0 = state[0]; 34289549Srpaulo context.h1 = state[1]; 35289549Srpaulo context.h2 = state[2]; 36289549Srpaulo context.h3 = state[3]; 37289549Srpaulo context.h4 = state[4]; 38214501Srpaulo SHA1_Transform(&context, data); 39289549Srpaulo state[0] = context.h0; 40289549Srpaulo state[1] = context.h1; 41289549Srpaulo state[2] = context.h2; 42289549Srpaulo state[3] = context.h3; 43289549Srpaulo state[4] = context.h4; 44337817Scy#endif 45214501Srpaulo} 46214501Srpaulo 47214501Srpaulo 48214501Srpauloint fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) 49214501Srpaulo{ 50214501Srpaulo u8 xkey[64]; 51214501Srpaulo u32 t[5], _t[5]; 52214501Srpaulo int i, j, m, k; 53214501Srpaulo u8 *xpos = x; 54214501Srpaulo u32 carry; 55214501Srpaulo 56252726Srpaulo if (seed_len < sizeof(xkey)) 57252726Srpaulo os_memset(xkey + seed_len, 0, sizeof(xkey) - seed_len); 58252726Srpaulo else 59214501Srpaulo seed_len = sizeof(xkey); 60214501Srpaulo 61214501Srpaulo /* FIPS 186-2 + change notice 1 */ 62214501Srpaulo 63214501Srpaulo os_memcpy(xkey, seed, seed_len); 64214501Srpaulo t[0] = 0x67452301; 65214501Srpaulo t[1] = 0xEFCDAB89; 66214501Srpaulo t[2] = 0x98BADCFE; 67214501Srpaulo t[3] = 0x10325476; 68214501Srpaulo t[4] = 0xC3D2E1F0; 69214501Srpaulo 70214501Srpaulo m = xlen / 40; 71214501Srpaulo for (j = 0; j < m; j++) { 72214501Srpaulo /* XSEED_j = 0 */ 73214501Srpaulo for (i = 0; i < 2; i++) { 74214501Srpaulo /* XVAL = (XKEY + XSEED_j) mod 2^b */ 75214501Srpaulo 76214501Srpaulo /* w_i = G(t, XVAL) */ 77214501Srpaulo os_memcpy(_t, t, 20); 78289549Srpaulo sha1_transform(_t, xkey); 79337817Scy WPA_PUT_BE32(xpos, _t[0]); 80337817Scy WPA_PUT_BE32(xpos + 4, _t[1]); 81337817Scy WPA_PUT_BE32(xpos + 8, _t[2]); 82337817Scy WPA_PUT_BE32(xpos + 12, _t[3]); 83337817Scy WPA_PUT_BE32(xpos + 16, _t[4]); 84214501Srpaulo 85214501Srpaulo /* XKEY = (1 + XKEY + w_i) mod 2^b */ 86214501Srpaulo carry = 1; 87214501Srpaulo for (k = 19; k >= 0; k--) { 88214501Srpaulo carry += xkey[k] + xpos[k]; 89214501Srpaulo xkey[k] = carry & 0xff; 90214501Srpaulo carry >>= 8; 91214501Srpaulo } 92214501Srpaulo 93214501Srpaulo xpos += 20; 94214501Srpaulo } 95214501Srpaulo /* x_j = w_0|w_1 */ 96214501Srpaulo } 97214501Srpaulo 98214501Srpaulo return 0; 99214501Srpaulo} 100