hostap/src/crypto/fips_prf_openssl.c

87 lines
1.7 KiB
C
Raw Normal View History

/*
* FIPS 186-2 PRF for libcrypto
* Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include <openssl/sha.h>
#include "common.h"
#include "crypto.h"
Updates for stricter automatic memcpy bounds checking Both Android's libc and glibc support _FORTIFY_SOURCE, a compiler and libc feature which inserts automatic bounds checking into common C functions such as memcpy() and strcpy(). If a buffer overflow occurs when calling a hardened libc function, the automatic bounds checking will safely shutdown the program and prevent memory corruption. Android is experimenting with _FORTIFY_SOURCE=3, a new fortify level which enhances memcpy() to prevent overflowing an element of a struct. Under the enhancements, code such as struct foo { char empty[0]; char one[1]; char a[10]; char b[10]; }; int main() { foo myfoo; int n = atoi("11"); memcpy(myfoo.a, "01234567890123456789", n); return 0; } will cleanly crash when the memcpy() call is made. Fixup hostap code to support the new level. Specifically: * Fixup sha1_transform so it works with the enhanced bounds checking. The old memcpy() code was attempting to write to context.h0, but that structure element is too small and the write was extending (by design) into h1, h2, h3, and h4. Use explicit assignments instead of overflowing the struct element. * Modify most of the structures in ieee802_11_defs.h to use ISO C99 flexible array members (https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html) instead of a zero length array. Zero length arrays have zero length, and any attempt to call memcpy() on such elements will always overflow. Flexible array members have no such limitation. The only element not adjusted is probe_req, since doing so will generate a compile time error, and it's not obvious to me how to fix it. Signed-off-by: Nick Kralevich <nnk@google.com>
2015-04-12 22:20:26 +02:00
static void sha1_transform(u32 *state, const u8 data[64])
{
SHA_CTX context;
os_memset(&context, 0, sizeof(context));
Updates for stricter automatic memcpy bounds checking Both Android's libc and glibc support _FORTIFY_SOURCE, a compiler and libc feature which inserts automatic bounds checking into common C functions such as memcpy() and strcpy(). If a buffer overflow occurs when calling a hardened libc function, the automatic bounds checking will safely shutdown the program and prevent memory corruption. Android is experimenting with _FORTIFY_SOURCE=3, a new fortify level which enhances memcpy() to prevent overflowing an element of a struct. Under the enhancements, code such as struct foo { char empty[0]; char one[1]; char a[10]; char b[10]; }; int main() { foo myfoo; int n = atoi("11"); memcpy(myfoo.a, "01234567890123456789", n); return 0; } will cleanly crash when the memcpy() call is made. Fixup hostap code to support the new level. Specifically: * Fixup sha1_transform so it works with the enhanced bounds checking. The old memcpy() code was attempting to write to context.h0, but that structure element is too small and the write was extending (by design) into h1, h2, h3, and h4. Use explicit assignments instead of overflowing the struct element. * Modify most of the structures in ieee802_11_defs.h to use ISO C99 flexible array members (https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html) instead of a zero length array. Zero length arrays have zero length, and any attempt to call memcpy() on such elements will always overflow. Flexible array members have no such limitation. The only element not adjusted is probe_req, since doing so will generate a compile time error, and it's not obvious to me how to fix it. Signed-off-by: Nick Kralevich <nnk@google.com>
2015-04-12 22:20:26 +02:00
context.h0 = state[0];
context.h1 = state[1];
context.h2 = state[2];
context.h3 = state[3];
context.h4 = state[4];
SHA1_Transform(&context, data);
Updates for stricter automatic memcpy bounds checking Both Android's libc and glibc support _FORTIFY_SOURCE, a compiler and libc feature which inserts automatic bounds checking into common C functions such as memcpy() and strcpy(). If a buffer overflow occurs when calling a hardened libc function, the automatic bounds checking will safely shutdown the program and prevent memory corruption. Android is experimenting with _FORTIFY_SOURCE=3, a new fortify level which enhances memcpy() to prevent overflowing an element of a struct. Under the enhancements, code such as struct foo { char empty[0]; char one[1]; char a[10]; char b[10]; }; int main() { foo myfoo; int n = atoi("11"); memcpy(myfoo.a, "01234567890123456789", n); return 0; } will cleanly crash when the memcpy() call is made. Fixup hostap code to support the new level. Specifically: * Fixup sha1_transform so it works with the enhanced bounds checking. The old memcpy() code was attempting to write to context.h0, but that structure element is too small and the write was extending (by design) into h1, h2, h3, and h4. Use explicit assignments instead of overflowing the struct element. * Modify most of the structures in ieee802_11_defs.h to use ISO C99 flexible array members (https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html) instead of a zero length array. Zero length arrays have zero length, and any attempt to call memcpy() on such elements will always overflow. Flexible array members have no such limitation. The only element not adjusted is probe_req, since doing so will generate a compile time error, and it's not obvious to me how to fix it. Signed-off-by: Nick Kralevich <nnk@google.com>
2015-04-12 22:20:26 +02:00
state[0] = context.h0;
state[1] = context.h1;
state[2] = context.h2;
state[3] = context.h3;
state[4] = context.h4;
}
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
{
u8 xkey[64];
u32 t[5], _t[5];
int i, j, m, k;
u8 *xpos = x;
u32 carry;
if (seed_len < sizeof(xkey))
os_memset(xkey + seed_len, 0, sizeof(xkey) - seed_len);
else
seed_len = sizeof(xkey);
/* FIPS 186-2 + change notice 1 */
os_memcpy(xkey, seed, seed_len);
t[0] = 0x67452301;
t[1] = 0xEFCDAB89;
t[2] = 0x98BADCFE;
t[3] = 0x10325476;
t[4] = 0xC3D2E1F0;
m = xlen / 40;
for (j = 0; j < m; j++) {
/* XSEED_j = 0 */
for (i = 0; i < 2; i++) {
/* XVAL = (XKEY + XSEED_j) mod 2^b */
/* w_i = G(t, XVAL) */
os_memcpy(_t, t, 20);
Updates for stricter automatic memcpy bounds checking Both Android's libc and glibc support _FORTIFY_SOURCE, a compiler and libc feature which inserts automatic bounds checking into common C functions such as memcpy() and strcpy(). If a buffer overflow occurs when calling a hardened libc function, the automatic bounds checking will safely shutdown the program and prevent memory corruption. Android is experimenting with _FORTIFY_SOURCE=3, a new fortify level which enhances memcpy() to prevent overflowing an element of a struct. Under the enhancements, code such as struct foo { char empty[0]; char one[1]; char a[10]; char b[10]; }; int main() { foo myfoo; int n = atoi("11"); memcpy(myfoo.a, "01234567890123456789", n); return 0; } will cleanly crash when the memcpy() call is made. Fixup hostap code to support the new level. Specifically: * Fixup sha1_transform so it works with the enhanced bounds checking. The old memcpy() code was attempting to write to context.h0, but that structure element is too small and the write was extending (by design) into h1, h2, h3, and h4. Use explicit assignments instead of overflowing the struct element. * Modify most of the structures in ieee802_11_defs.h to use ISO C99 flexible array members (https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html) instead of a zero length array. Zero length arrays have zero length, and any attempt to call memcpy() on such elements will always overflow. Flexible array members have no such limitation. The only element not adjusted is probe_req, since doing so will generate a compile time error, and it's not obvious to me how to fix it. Signed-off-by: Nick Kralevich <nnk@google.com>
2015-04-12 22:20:26 +02:00
sha1_transform(_t, xkey);
_t[0] = host_to_be32(_t[0]);
_t[1] = host_to_be32(_t[1]);
_t[2] = host_to_be32(_t[2]);
_t[3] = host_to_be32(_t[3]);
_t[4] = host_to_be32(_t[4]);
os_memcpy(xpos, _t, 20);
/* XKEY = (1 + XKEY + w_i) mod 2^b */
carry = 1;
for (k = 19; k >= 0; k--) {
carry += xkey[k] + xpos[k];
xkey[k] = carry & 0xff;
carry >>= 8;
}
xpos += 20;
}
/* x_j = w_0|w_1 */
}
return 0;
}