aboutsummaryrefslogtreecommitdiffstats
path: root/src/crypto
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-08-16 15:56:48 (GMT)
committerJouni Malinen <j@w1.fi>2009-08-16 15:56:48 (GMT)
commitff916b9df7ec5f691c7adca5cae059158a09d06f (patch)
treec6a70161e98f0cfe92eae008abe56a9f518079ff /src/crypto
parentbe299ca4ce9423cfc4fd30182bd1f9f6742bb200 (diff)
downloadhostap-ff916b9df7ec5f691c7adca5cae059158a09d06f.zip
hostap-ff916b9df7ec5f691c7adca5cae059158a09d06f.tar.gz
hostap-ff916b9df7ec5f691c7adca5cae059158a09d06f.tar.bz2
Allow non-FIPS MD5 to be used with TLS PRF even in FIPS mode
This is allowed per FIPS1402IG.pdf since the TLS PRF depends fully on both MD5 and SHA-1.
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/crypto.h16
-rw-r--r--src/crypto/crypto_openssl.c22
-rw-r--r--src/crypto/md5-non-fips.c113
-rw-r--r--src/crypto/md5.h10
-rw-r--r--src/crypto/sha1-tlsprf.c9
5 files changed, 162 insertions, 8 deletions
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index e2d2112..be3609e 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -47,6 +47,22 @@ int md4_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);
+#ifdef CONFIG_FIPS
+/**
+ * md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed)
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
+ const size_t *len, u8 *mac);
+#else /* CONFIG_FIPS */
+#define md5_vector_non_fips_allow md5_vector
+#endif /* CONFIG_FIPS */
+
+
/**
* sha1_vector - SHA-1 hash for data vector
* @num_elem: Number of elements in the data vector
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index fceefb1..4287e3e 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -32,7 +32,7 @@
#endif /* openssl < 0.9.7 */
-int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
+int openssl_digest_vector(const EVP_MD *type, int non_fips, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
EVP_MD_CTX ctx;
@@ -40,6 +40,8 @@ int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
unsigned int mac_len;
EVP_MD_CTX_init(&ctx);
+ if (non_fips)
+ EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
if (!EVP_DigestInit_ex(&ctx, type, NULL)) {
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
ERR_error_string(ERR_get_error(), NULL));
@@ -65,7 +67,7 @@ int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{
- return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac);
+ return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac);
}
@@ -92,20 +94,30 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{
- return openssl_digest_vector(EVP_md5(), num_elem, addr, len, mac);
+ return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac);
}
+#ifdef CONFIG_FIPS
+int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
+ const size_t *len, u8 *mac)
+{
+ return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac);
+}
+#endif /* CONFIG_FIPS */
+
+
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{
- return openssl_digest_vector(EVP_sha1(), num_elem, addr, len, mac);
+ return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac);
}
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac)
{
- return openssl_digest_vector(EVP_sha256(), num_elem, addr, len, mac);
+ return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len,
+ mac);
}
diff --git a/src/crypto/md5-non-fips.c b/src/crypto/md5-non-fips.c
new file mode 100644
index 0000000..6f29201
--- /dev/null
+++ b/src/crypto/md5-non-fips.c
@@ -0,0 +1,113 @@
+/*
+ * MD5 hash implementation and interface functions (non-FIPS allowed cases)
+ * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "md5.h"
+#include "crypto.h"
+
+
+/**
+ * hmac_md5_vector_non_fips_allow - HMAC-MD5 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len,
+ size_t num_elem, const u8 *addr[],
+ const size_t *len, u8 *mac)
+{
+ u8 k_pad[64]; /* padding - key XORd with ipad/opad */
+ u8 tk[16];
+ const u8 *_addr[6];
+ size_t i, _len[6];
+
+ if (num_elem > 5) {
+ /*
+ * Fixed limit on the number of fragments to avoid having to
+ * allocate memory (which could fail).
+ */
+ return -1;
+ }
+
+ /* if key is longer than 64 bytes reset it to key = MD5(key) */
+ if (key_len > 64) {
+ if (md5_vector_non_fips_allow(1, &key, &key_len, tk))
+ return -1;
+ key = tk;
+ key_len = 16;
+ }
+
+ /* the HMAC_MD5 transform looks like:
+ *
+ * MD5(K XOR opad, MD5(K XOR ipad, text))
+ *
+ * where K is an n byte key
+ * ipad is the byte 0x36 repeated 64 times
+ * opad is the byte 0x5c repeated 64 times
+ * and text is the data being protected */
+
+ /* start out by storing key in ipad */
+ os_memset(k_pad, 0, sizeof(k_pad));
+ os_memcpy(k_pad, key, key_len);
+
+ /* XOR key with ipad values */
+ for (i = 0; i < 64; i++)
+ k_pad[i] ^= 0x36;
+
+ /* perform inner MD5 */
+ _addr[0] = k_pad;
+ _len[0] = 64;
+ for (i = 0; i < num_elem; i++) {
+ _addr[i + 1] = addr[i];
+ _len[i + 1] = len[i];
+ }
+ if (md5_vector_non_fips_allow(1 + num_elem, _addr, _len, mac))
+ return -1;
+
+ os_memset(k_pad, 0, sizeof(k_pad));
+ os_memcpy(k_pad, key, key_len);
+ /* XOR key with opad values */
+ for (i = 0; i < 64; i++)
+ k_pad[i] ^= 0x5c;
+
+ /* perform outer MD5 */
+ _addr[0] = k_pad;
+ _len[0] = 64;
+ _addr[1] = mac;
+ _len[1] = MD5_MAC_LEN;
+ return md5_vector_non_fips_allow(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_md5_non_fips_allow - HMAC-MD5 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *mac)
+{
+ return hmac_md5_vector_non_fips_allow(key, key_len, 1, &data,
+ &data_len, mac);
+}
diff --git a/src/crypto/md5.h b/src/crypto/md5.h
index 40ab630..8952590 100644
--- a/src/crypto/md5.h
+++ b/src/crypto/md5.h
@@ -21,5 +21,15 @@ int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac);
int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac);
+#ifdef CONFIG_FIPS
+int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len,
+ size_t num_elem, const u8 *addr[],
+ const size_t *len, u8 *mac);
+int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *mac);
+#else /* CONFIG_FIPS */
+#define hmac_md5_vector_non_fips_allow hmac_md5_vector
+#define hmac_md5_non_fips_allow hmac_md5
+#endif /* CONFIG_FIPS */
#endif /* MD5_H */
diff --git a/src/crypto/sha1-tlsprf.c b/src/crypto/sha1-tlsprf.c
index 3e2ae49..2c8c029 100644
--- a/src/crypto/sha1-tlsprf.c
+++ b/src/crypto/sha1-tlsprf.c
@@ -78,16 +78,19 @@ int tls_prf(const u8 *secret, size_t secret_len, const char *label,
S2--;
}
- hmac_md5_vector(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5);
+ hmac_md5_vector_non_fips_allow(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1],
+ A_MD5);
hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1);
MD5_pos = MD5_MAC_LEN;
SHA1_pos = SHA1_MAC_LEN;
for (i = 0; i < outlen; i++) {
if (MD5_pos == MD5_MAC_LEN) {
- hmac_md5_vector(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5);
+ hmac_md5_vector_non_fips_allow(S1, L_S1, 3, MD5_addr,
+ MD5_len, P_MD5);
MD5_pos = 0;
- hmac_md5(S1, L_S1, A_MD5, MD5_MAC_LEN, A_MD5);
+ hmac_md5_non_fips_allow(S1, L_S1, A_MD5, MD5_MAC_LEN,
+ A_MD5);
}
if (SHA1_pos == SHA1_MAC_LEN) {
hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len,