aboutsummaryrefslogtreecommitdiffstats
path: root/src/crypto
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2013-01-01 12:00:40 (GMT)
committerJouni Malinen <j@w1.fi>2013-01-12 15:51:53 (GMT)
commitcd9c2714e795a0eb2d9cdad3edb9146b27ff261c (patch)
tree05fb522959eda3bb75ffeff26485d8da9234d07d /src/crypto
parentbf14657b9ffd8f46a46879708619b91a160f9967 (diff)
downloadhostap-cd9c2714e795a0eb2d9cdad3edb9146b27ff261c.zip
hostap-cd9c2714e795a0eb2d9cdad3edb9146b27ff261c.tar.gz
hostap-cd9c2714e795a0eb2d9cdad3edb9146b27ff261c.tar.bz2
SAE: Add support for ECC group 21 (521-bit random ECP group)
In addition to the trivial change in adding the new group ientifier, this required changes to KDF and random number generation to support cases where the length of the prime in bits is not a multiple of eight. The binary presentation of the value needs to be shifted so that the unused most significant bits are the zero padding rather than the extra bits in the end of the array. Signed-hostap: Jouni Malinen <j@w1.fi>
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/crypto.h7
-rw-r--r--src/crypto/crypto_openssl.c9
-rw-r--r--src/crypto/sha256-prf.c38
-rw-r--r--src/crypto/sha256.h5
4 files changed, 56 insertions, 3 deletions
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index d33ccb1..950cd9e 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -550,6 +550,13 @@ void crypto_ec_deinit(struct crypto_ec *e);
size_t crypto_ec_prime_len(struct crypto_ec *e);
/**
+ * crypto_ec_prime_len_bits - Get length of the prime in bits
+ * @e: EC context from crypto_ec_init()
+ * Returns: Length of the prime defining the group in bits
+ */
+size_t crypto_ec_prime_len_bits(struct crypto_ec *e);
+
+/**
* crypto_ec_get_prime - Get prime defining an EC group
* @e: EC context from crypto_ec_init()
* Returns: Prime (bignum) defining the group
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index a2b5c5f..593cf6f 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -917,6 +917,9 @@ struct crypto_ec * crypto_ec_init(int group)
case 20:
nid = NID_secp384r1;
break;
+ case 21:
+ nid = NID_secp521r1;
+ break;
case 25:
nid = NID_X9_62_prime192v1;
break;
@@ -972,6 +975,12 @@ size_t crypto_ec_prime_len(struct crypto_ec *e)
}
+size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
+{
+ return BN_num_bits(e->prime);
+}
+
+
const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
{
return (const struct crypto_bignum *) e->prime;
diff --git a/src/crypto/sha256-prf.c b/src/crypto/sha256-prf.c
index 0da6d13..9a11208 100644
--- a/src/crypto/sha256-prf.c
+++ b/src/crypto/sha256-prf.c
@@ -1,6 +1,6 @@
/*
* SHA256-based PRF (IEEE 802.11r)
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -29,12 +29,36 @@
void sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
{
+ sha256_prf_bits(key, key_len, label, data, data_len, buf, buf_len * 8);
+}
+
+
+/**
+ * sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function
+ * @key: Key for KDF
+ * @key_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @data: Extra data to bind into the key
+ * @data_len: Length of the data
+ * @buf: Buffer for the generated pseudo-random key
+ * @buf_len: Number of bits of key to generate
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key. If the requested buf_len is not divisible by eight, the least
+ * significant 1-7 bits of the last octet in the output are not part of the
+ * requested output.
+ */
+void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf,
+ size_t buf_len_bits)
+{
u16 counter = 1;
size_t pos, plen;
u8 hash[SHA256_MAC_LEN];
const u8 *addr[4];
size_t len[4];
u8 counter_le[2], length_le[2];
+ size_t buf_len = (buf_len_bits + 7) / 8;
addr[0] = counter_le;
len[0] = 2;
@@ -45,7 +69,7 @@ void sha256_prf(const u8 *key, size_t key_len, const char *label,
addr[3] = length_le;
len[3] = sizeof(length_le);
- WPA_PUT_LE16(length_le, buf_len * 8);
+ WPA_PUT_LE16(length_le, buf_len_bits);
pos = 0;
while (pos < buf_len) {
plen = buf_len - pos;
@@ -57,8 +81,18 @@ void sha256_prf(const u8 *key, size_t key_len, const char *label,
} else {
hmac_sha256_vector(key, key_len, 4, addr, len, hash);
os_memcpy(&buf[pos], hash, plen);
+ pos += plen;
break;
}
counter++;
}
+
+ /*
+ * Mask out unused bits in the last octet if it does not use all the
+ * bits.
+ */
+ if (buf_len_bits % 8) {
+ u8 mask = 0xff << (8 - buf_len_bits % 8);
+ buf[pos - 1] &= mask;
+ }
}
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index fcac800..7596a52 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -1,6 +1,6 @@
/*
* SHA256 hash implementation and interface functions
- * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -17,6 +17,9 @@ int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac);
void sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf,
+ size_t buf_len_bits);
void tls_prf_sha256(const u8 *secret, size_t secret_len,
const char *label, const u8 *seed, size_t seed_len,
u8 *out, size_t outlen);