aboutsummaryrefslogtreecommitdiffstats
path: root/src/eap_common
diff options
context:
space:
mode:
authorDan Harkins <dharkins@lounge.org>2011-11-19 16:43:49 +0200
committerJouni Malinen <j@w1.fi>2011-11-19 16:43:49 +0200
commit18f5f3de030da1c646585425e95de0f8a2a7432b (patch)
treec383f0e6a8b687f4be20759be623428997640305 /src/eap_common
parent43011639306d107971996d9d70afa74e6aca25f4 (diff)
downloadexternal_wpa_supplicant_8_ti-18f5f3de030da1c646585425e95de0f8a2a7432b.zip
external_wpa_supplicant_8_ti-18f5f3de030da1c646585425e95de0f8a2a7432b.tar.gz
external_wpa_supplicant_8_ti-18f5f3de030da1c646585425e95de0f8a2a7432b.tar.bz2
EAP-pwd: Fix KDF for group 21
The previous EAP-pwd KDF implemented has an issue with group 21, that is an elliptic curve group based on a 521 bit prime. 521 is not an even multiple of 8, and therein lies the problem. OpenSSL's BN library interprets a string of bits as in big-endian format so all the calls of BN_bin2bn() will take the binary blob of bits and turn it into a big number in big-endian format. In the EAP-pwd KDF, I am stretching the key to "primebitlen". When that is not an even multiple of 8 I have to mask off the excess. But I was masking off the excess bits in the 1st octet (big endian after all) but that isn't right. The KDF produces a string of endian-less bits. The 521st bit is the first bit in the last octet, not the 7th bit in the first octet. So that has been fixed and you can see in the attached diff what I'm doing.
Diffstat (limited to 'src/eap_common')
-rw-r--r--src/eap_common/eap_pwd_common.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index c24b146..5836cba 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -75,8 +75,8 @@ void eap_pwd_kdf(u8 *key, int keylen, u8 *label, int labellen,
/* since we're expanding to a bit length, mask off the excess */
if (resultbitlen % 8) {
- mask >>= ((resultbytelen * 8) - resultbitlen);
- result[0] &= mask;
+ mask <<= (8 - (resultbitlen % 8));
+ result[resultbytelen - 1] &= mask;
}
}
@@ -189,6 +189,18 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
prfbuf, primebitlen);
BN_bin2bn(prfbuf, primebytelen, x_candidate);
+
+ /*
+ * eap_pwd_kdf() returns a string of bits 0..primebitlen but
+ * BN_bin2bn will treat that string of bits as a big endian
+ * number. If the primebitlen is not an even multiple of 8
+ * then excessive bits-- those _after_ primebitlen-- so now
+ * we have to shift right the amount we masked off.
+ */
+ if (primebitlen % 8)
+ BN_rshift(x_candidate, x_candidate,
+ (8 - (primebitlen % 8)));
+
if (BN_ucmp(x_candidate, grp->prime) >= 0)
continue;