Make hash functions return error value

Some crypto libraries can return in these functions (e.g., if a specific
hash function is disabled), so we better provide the caller a chance to
check whether the call failed. The return values are not yet used
anywhere, but they will be needed for future changes.
This commit is contained in:
Jouni Malinen 2009-08-16 14:06:00 +03:00
parent e1ffdfc18b
commit 0a5d68aba5
16 changed files with 153 additions and 94 deletions

View file

@ -1,6 +1,6 @@
/* /*
* WPA Supplicant / wrapper functions for crypto libraries * WPA Supplicant / wrapper functions for crypto libraries
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@ -33,8 +33,9 @@
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash * @mac: Buffer for the hash
* Returns: 0 on success, -1 on failure
*/ */
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
/** /**
* md5_vector - MD5 hash for data vector * md5_vector - MD5 hash for data vector
@ -42,8 +43,9 @@ void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash * @mac: Buffer for the hash
* Returns: 0 on success, -1 on failure
*/ */
void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
/** /**
* sha1_vector - SHA-1 hash for data vector * sha1_vector - SHA-1 hash for data vector
@ -51,9 +53,10 @@ void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash * @mac: Buffer for the hash
* Returns: 0 on success, -1 on failure
*/ */
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac); u8 *mac);
/** /**
* fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF
@ -76,9 +79,10 @@ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x,
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash * @mac: Buffer for the hash
* Returns: 0 on success, -1 on failure
*/ */
void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac); u8 *mac);
/** /**
* des_encrypt - Encrypt one block with DES * des_encrypt - Encrypt one block with DES

View file

@ -167,9 +167,9 @@ int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
} }
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac);
} }
@ -239,15 +239,15 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
#ifdef EAP_TLS_FUNCS #ifdef EAP_TLS_FUNCS
void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
} }
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac);
} }

View file

@ -18,20 +18,21 @@
#include "common.h" #include "common.h"
#include "crypto.h" #include "crypto.h"
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
gcry_md_hd_t hd; gcry_md_hd_t hd;
unsigned char *p; unsigned char *p;
size_t i; size_t i;
if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR)
return; return -1;
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
gcry_md_write(hd, addr[i], len[i]); gcry_md_write(hd, addr[i], len[i]);
p = gcry_md_read(hd, GCRY_MD_MD4); p = gcry_md_read(hd, GCRY_MD_MD4);
if (p) if (p)
memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4));
gcry_md_close(hd); gcry_md_close(hd);
return 0;
} }
@ -57,37 +58,39 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
} }
void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
gcry_md_hd_t hd; gcry_md_hd_t hd;
unsigned char *p; unsigned char *p;
size_t i; size_t i;
if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR)
return; return -1;
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
gcry_md_write(hd, addr[i], len[i]); gcry_md_write(hd, addr[i], len[i]);
p = gcry_md_read(hd, GCRY_MD_MD5); p = gcry_md_read(hd, GCRY_MD_MD5);
if (p) if (p)
memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5));
gcry_md_close(hd); gcry_md_close(hd);
return 0;
} }
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
gcry_md_hd_t hd; gcry_md_hd_t hd;
unsigned char *p; unsigned char *p;
size_t i; size_t i;
if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR)
return; return -1;
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
gcry_md_write(hd, addr[i], len[i]); gcry_md_write(hd, addr[i], len[i]);
p = gcry_md_read(hd, GCRY_MD_SHA1); p = gcry_md_read(hd, GCRY_MD_SHA1);
if (p) if (p)
memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1));
gcry_md_close(hd); gcry_md_close(hd);
return 0;
} }

View file

@ -29,7 +29,7 @@
#endif #endif
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
hash_state md; hash_state md;
size_t i; size_t i;
@ -38,6 +38,7 @@ void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
md4_process(&md, addr[i], len[i]); md4_process(&md, addr[i], len[i]);
md4_done(&md, mac); md4_done(&md, mac);
return 0;
} }
@ -63,7 +64,7 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
#ifdef EAP_TLS_FUNCS #ifdef EAP_TLS_FUNCS
void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
hash_state md; hash_state md;
size_t i; size_t i;
@ -72,10 +73,11 @@ void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
md5_process(&md, addr[i], len[i]); md5_process(&md, addr[i], len[i]);
md5_done(&md, mac); md5_done(&md, mac);
return 0;
} }
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
hash_state md; hash_state md;
size_t i; size_t i;
@ -84,6 +86,7 @@ void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
sha1_process(&md, addr[i], len[i]); sha1_process(&md, addr[i], len[i]);
sha1_done(&md, mac); sha1_done(&md, mac);
return 0;
} }

View file

@ -18,8 +18,9 @@
#include "crypto.h" #include "crypto.h"
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
return 0;
} }

View file

@ -1,6 +1,6 @@
/* /*
* WPA Supplicant / wrapper functions for libcrypto * WPA Supplicant / wrapper functions for libcrypto
* Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@ -34,15 +34,19 @@
#endif /* openssl < 0.9.7 */ #endif /* openssl < 0.9.7 */
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
MD4_CTX ctx; MD4_CTX ctx;
size_t i; size_t i;
MD4_Init(&ctx); if (!MD4_Init(&ctx))
return -1;
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
MD4_Update(&ctx, addr[i], len[i]); if (!MD4_Update(&ctx, addr[i], len[i]))
MD4_Final(mac, &ctx); return -1;
if (!MD4_Final(mac, &ctx))
return -1;
return 0;
} }
@ -67,29 +71,38 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
} }
void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
MD5_CTX ctx; MD5_CTX ctx;
size_t i; size_t i;
MD5_Init(&ctx); if (!MD5_Init(&ctx))
return -1;
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
MD5_Update(&ctx, addr[i], len[i]); if (!MD5_Update(&ctx, addr[i], len[i]))
MD5_Final(mac, &ctx); return -1;
if (!MD5_Final(mac, &ctx))
return -1;
return 0;
} }
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
SHA_CTX ctx; SHA_CTX ctx;
size_t i; size_t i;
SHA1_Init(&ctx); if (!SHA1_Init(&ctx))
return -1;
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
SHA1_Update(&ctx, addr[i], len[i]); if (!SHA1_Update(&ctx, addr[i], len[i]))
SHA1_Final(mac, &ctx); return -1;
if (!SHA1_Final(mac, &ctx))
return -1;
return 0;
} }
void * aes_encrypt_init(const u8 *key, size_t len) void * aes_encrypt_init(const u8 *key, size_t len)
{ {
AES_KEY *ak; AES_KEY *ak;

View file

@ -32,7 +32,7 @@ static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len);
static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx); static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx);
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
MD4_CTX ctx; MD4_CTX ctx;
size_t i; size_t i;
@ -41,6 +41,7 @@ void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
MD4Update(&ctx, addr[i], len[i]); MD4Update(&ctx, addr[i], len[i]);
MD4Final(mac, &ctx); MD4Final(mac, &ctx);
return 0;
} }

View file

@ -37,8 +37,9 @@ typedef struct MD5Context MD5_CTX;
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash * @mac: Buffer for the hash
* Returns: 0 on success, -1 of failure
*/ */
void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{ {
MD5_CTX ctx; MD5_CTX ctx;
size_t i; size_t i;
@ -47,6 +48,7 @@ void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
MD5Update(&ctx, addr[i], len[i]); MD5Update(&ctx, addr[i], len[i]);
MD5Final(mac, &ctx); MD5Final(mac, &ctx);
return 0;
} }

View file

@ -27,9 +27,10 @@
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash (16 bytes) * @mac: Buffer for the hash (16 bytes)
* Returns: 0 on success, -1 on failure
*/ */
void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac) const u8 *addr[], const size_t *len, u8 *mac)
{ {
u8 k_pad[64]; /* padding - key XORd with ipad/opad */ u8 k_pad[64]; /* padding - key XORd with ipad/opad */
u8 tk[16]; u8 tk[16];
@ -41,12 +42,13 @@ void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
* Fixed limit on the number of fragments to avoid having to * Fixed limit on the number of fragments to avoid having to
* allocate memory (which could fail). * allocate memory (which could fail).
*/ */
return; return -1;
} }
/* if key is longer than 64 bytes reset it to key = MD5(key) */ /* if key is longer than 64 bytes reset it to key = MD5(key) */
if (key_len > 64) { if (key_len > 64) {
md5_vector(1, &key, &key_len, tk); if (md5_vector(1, &key, &key_len, tk))
return -1;
key = tk; key = tk;
key_len = 16; key_len = 16;
} }
@ -75,7 +77,8 @@ void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
_addr[i + 1] = addr[i]; _addr[i + 1] = addr[i];
_len[i + 1] = len[i]; _len[i + 1] = len[i];
} }
md5_vector(1 + num_elem, _addr, _len, mac); if (md5_vector(1 + num_elem, _addr, _len, mac))
return -1;
os_memset(k_pad, 0, sizeof(k_pad)); os_memset(k_pad, 0, sizeof(k_pad));
os_memcpy(k_pad, key, key_len); os_memcpy(k_pad, key, key_len);
@ -88,7 +91,7 @@ void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
_len[0] = 64; _len[0] = 64;
_addr[1] = mac; _addr[1] = mac;
_len[1] = MD5_MAC_LEN; _len[1] = MD5_MAC_LEN;
md5_vector(2, _addr, _len, mac); return md5_vector(2, _addr, _len, mac);
} }
@ -99,9 +102,10 @@ void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
* @data: Pointers to the data area * @data: Pointers to the data area
* @data_len: Length of the data area * @data_len: Length of the data area
* @mac: Buffer for the hash (16 bytes) * @mac: Buffer for the hash (16 bytes)
* Returns: 0 on success, -1 on failure
*/ */
void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac) u8 *mac)
{ {
hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
} }

View file

@ -1,6 +1,6 @@
/* /*
* MD5 hash implementation and interface functions * MD5 hash implementation and interface functions
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@ -17,8 +17,9 @@
#define MD5_MAC_LEN 16 #define MD5_MAC_LEN 16
void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac); const u8 *addr[], const size_t *len, u8 *mac);
void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac); u8 *mac);
#endif /* MD5_H */ #endif /* MD5_H */

View file

@ -37,9 +37,9 @@ void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash * @mac: Buffer for the hash
* Returns: 0 on success, -1 of failure
*/ */
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
u8 *mac)
{ {
SHA1_CTX ctx; SHA1_CTX ctx;
size_t i; size_t i;
@ -48,6 +48,7 @@ void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
SHA1Update(&ctx, addr[i], len[i]); SHA1Update(&ctx, addr[i], len[i]);
SHA1Final(mac, &ctx); SHA1Final(mac, &ctx);
return 0;
} }

View file

@ -19,9 +19,9 @@
#include "md5.h" #include "md5.h"
#include "crypto.h" #include "crypto.h"
static void pbkdf2_sha1_f(const char *passphrase, const char *ssid, static int pbkdf2_sha1_f(const char *passphrase, const char *ssid,
size_t ssid_len, int iterations, unsigned int count, size_t ssid_len, int iterations, unsigned int count,
u8 *digest) u8 *digest)
{ {
unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN]; unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
int i, j; int i, j;
@ -45,16 +45,21 @@ static void pbkdf2_sha1_f(const char *passphrase, const char *ssid,
count_buf[1] = (count >> 16) & 0xff; count_buf[1] = (count >> 16) & 0xff;
count_buf[2] = (count >> 8) & 0xff; count_buf[2] = (count >> 8) & 0xff;
count_buf[3] = count & 0xff; count_buf[3] = count & 0xff;
hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp); if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len,
tmp))
return -1;
os_memcpy(digest, tmp, SHA1_MAC_LEN); os_memcpy(digest, tmp, SHA1_MAC_LEN);
for (i = 1; i < iterations; i++) { for (i = 1; i < iterations; i++) {
hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN, if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp,
tmp2); SHA1_MAC_LEN, tmp2))
return -1;
os_memcpy(tmp, tmp2, SHA1_MAC_LEN); os_memcpy(tmp, tmp2, SHA1_MAC_LEN);
for (j = 0; j < SHA1_MAC_LEN; j++) for (j = 0; j < SHA1_MAC_LEN; j++)
digest[j] ^= tmp2[j]; digest[j] ^= tmp2[j];
} }
return 0;
} }
@ -66,13 +71,14 @@ static void pbkdf2_sha1_f(const char *passphrase, const char *ssid,
* @iterations: Number of iterations to run * @iterations: Number of iterations to run
* @buf: Buffer for the generated key * @buf: Buffer for the generated key
* @buflen: Length of the buffer in bytes * @buflen: Length of the buffer in bytes
* Returns: 0 on success, -1 of failure
* *
* This function is used to derive PSK for WPA-PSK. For this protocol, * This function is used to derive PSK for WPA-PSK. For this protocol,
* iterations is set to 4096 and buflen to 32. This function is described in * iterations is set to 4096 and buflen to 32. This function is described in
* IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.
*/ */
void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
int iterations, u8 *buf, size_t buflen) int iterations, u8 *buf, size_t buflen)
{ {
unsigned int count = 0; unsigned int count = 0;
unsigned char *pos = buf; unsigned char *pos = buf;
@ -81,11 +87,14 @@ void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
while (left > 0) { while (left > 0) {
count++; count++;
pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count, if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations,
digest); count, digest))
return -1;
plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
os_memcpy(pos, digest, plen); os_memcpy(pos, digest, plen);
pos += plen; pos += plen;
left -= plen; left -= plen;
} }
return 0;
} }

View file

@ -27,12 +27,13 @@
* @seed_len: Length of the seed * @seed_len: Length of the seed
* @buf: Buffer for the generated pseudo-random key * @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bytes of key to generate * @buf_len: Number of bytes of key to generate
* Returns: 0 on success, -1 of failure
* *
* This function is used to derive new, cryptographically separate keys from a * This function is used to derive new, cryptographically separate keys from a
* given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5. * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5.
*/ */
void sha1_t_prf(const u8 *key, size_t key_len, const char *label, int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len) const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
{ {
unsigned char counter = 0; unsigned char counter = 0;
size_t pos, plen; size_t pos, plen;
@ -59,7 +60,8 @@ void sha1_t_prf(const u8 *key, size_t key_len, const char *label,
while (pos < buf_len) { while (pos < buf_len) {
counter++; counter++;
plen = buf_len - pos; plen = buf_len - pos;
hmac_sha1_vector(key, key_len, 5, addr, len, hash); if (hmac_sha1_vector(key, key_len, 5, addr, len, hash))
return -1;
if (plen >= SHA1_MAC_LEN) { if (plen >= SHA1_MAC_LEN) {
os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
pos += SHA1_MAC_LEN; pos += SHA1_MAC_LEN;
@ -69,4 +71,6 @@ void sha1_t_prf(const u8 *key, size_t key_len, const char *label,
} }
len[0] = SHA1_MAC_LEN; len[0] = SHA1_MAC_LEN;
} }
return 0;
} }

View file

@ -27,9 +27,10 @@
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash (20 bytes) * @mac: Buffer for the hash (20 bytes)
* Returns: 0 on success, -1 on failure
*/ */
void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac) const u8 *addr[], const size_t *len, u8 *mac)
{ {
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
unsigned char tk[20]; unsigned char tk[20];
@ -41,12 +42,13 @@ void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
* Fixed limit on the number of fragments to avoid having to * Fixed limit on the number of fragments to avoid having to
* allocate memory (which could fail). * allocate memory (which could fail).
*/ */
return; return -1;
} }
/* if key is longer than 64 bytes reset it to key = SHA1(key) */ /* if key is longer than 64 bytes reset it to key = SHA1(key) */
if (key_len > 64) { if (key_len > 64) {
sha1_vector(1, &key, &key_len, tk); if (sha1_vector(1, &key, &key_len, tk))
return -1;
key = tk; key = tk;
key_len = 20; key_len = 20;
} }
@ -74,7 +76,8 @@ void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
_addr[i + 1] = addr[i]; _addr[i + 1] = addr[i];
_len[i + 1] = len[i]; _len[i + 1] = len[i];
} }
sha1_vector(1 + num_elem, _addr, _len, mac); if (sha1_vector(1 + num_elem, _addr, _len, mac))
return -1;
os_memset(k_pad, 0, sizeof(k_pad)); os_memset(k_pad, 0, sizeof(k_pad));
os_memcpy(k_pad, key, key_len); os_memcpy(k_pad, key, key_len);
@ -87,7 +90,7 @@ void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
_len[0] = 64; _len[0] = 64;
_addr[1] = mac; _addr[1] = mac;
_len[1] = SHA1_MAC_LEN; _len[1] = SHA1_MAC_LEN;
sha1_vector(2, _addr, _len, mac); return sha1_vector(2, _addr, _len, mac);
} }
@ -98,11 +101,12 @@ void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
* @data: Pointers to the data area * @data: Pointers to the data area
* @data_len: Length of the data area * @data_len: Length of the data area
* @mac: Buffer for the hash (20 bytes) * @mac: Buffer for the hash (20 bytes)
* Returns: 0 on success, -1 of failure
*/ */
void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac) u8 *mac)
{ {
hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
} }
@ -115,12 +119,13 @@ void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
* @data_len: Length of the data * @data_len: Length of the data
* @buf: Buffer for the generated pseudo-random key * @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bytes of key to generate * @buf_len: Number of bytes of key to generate
* Returns: 0 on success, -1 of failure
* *
* This function is used to derive new, cryptographically separate keys from a * This function is used to derive new, cryptographically separate keys from a
* given key (e.g., PMK in IEEE 802.11i). * given key (e.g., PMK in IEEE 802.11i).
*/ */
void sha1_prf(const u8 *key, size_t key_len, const char *label, int sha1_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len) const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
{ {
u8 counter = 0; u8 counter = 0;
size_t pos, plen; size_t pos, plen;
@ -140,15 +145,19 @@ void sha1_prf(const u8 *key, size_t key_len, const char *label,
while (pos < buf_len) { while (pos < buf_len) {
plen = buf_len - pos; plen = buf_len - pos;
if (plen >= SHA1_MAC_LEN) { if (plen >= SHA1_MAC_LEN) {
hmac_sha1_vector(key, key_len, 3, addr, len, if (hmac_sha1_vector(key, key_len, 3, addr, len,
&buf[pos]); &buf[pos]))
return -1;
pos += SHA1_MAC_LEN; pos += SHA1_MAC_LEN;
} else { } else {
hmac_sha1_vector(key, key_len, 3, addr, len, if (hmac_sha1_vector(key, key_len, 3, addr, len,
hash); hash))
return -1;
os_memcpy(&buf[pos], hash, plen); os_memcpy(&buf[pos], hash, plen);
break; break;
} }
counter++; counter++;
} }
return 0;
} }

View file

@ -1,6 +1,6 @@
/* /*
* SHA1 hash implementation and interface functions * SHA1 hash implementation and interface functions
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@ -17,17 +17,17 @@
#define SHA1_MAC_LEN 20 #define SHA1_MAC_LEN 20
void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac); const u8 *addr[], const size_t *len, u8 *mac);
void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac); u8 *mac);
void sha1_prf(const u8 *key, size_t key_len, const char *label, int sha1_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len); const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
void sha1_t_prf(const u8 *key, size_t key_len, const char *label, int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len);
int __must_check tls_prf(const u8 *secret, size_t secret_len, int __must_check tls_prf(const u8 *secret, size_t secret_len,
const char *label, const u8 *seed, size_t seed_len, const char *label, const u8 *seed, size_t seed_len,
u8 *out, size_t outlen); u8 *out, size_t outlen);
void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
int iterations, u8 *buf, size_t buflen); int iterations, u8 *buf, size_t buflen);
#endif /* SHA1_H */ #endif /* SHA1_H */

View file

@ -36,17 +36,21 @@ static int sha256_done(struct sha256_state *md, unsigned char *out);
* @addr: Pointers to the data areas * @addr: Pointers to the data areas
* @len: Lengths of the data blocks * @len: Lengths of the data blocks
* @mac: Buffer for the hash * @mac: Buffer for the hash
* Returns: 0 on success, -1 of failure
*/ */
void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac) u8 *mac)
{ {
struct sha256_state ctx; struct sha256_state ctx;
size_t i; size_t i;
sha256_init(&ctx); sha256_init(&ctx);
for (i = 0; i < num_elem; i++) for (i = 0; i < num_elem; i++)
sha256_process(&ctx, addr[i], len[i]); if (sha256_process(&ctx, addr[i], len[i]))
sha256_done(&ctx, mac); return -1;
if (sha256_done(&ctx, mac))
return -1;
return 0;
} }