summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordamien <damien@openbsd.org>2007-07-28 11:01:19 +0000
committerdamien <damien@openbsd.org>2007-07-28 11:01:19 +0000
commit2b0e84b2e50f02d63d63cb34e9c6409b3bfcb07d (patch)
tree8591e5af35a2340a54bb8c04b1c97a7a07593407
parentWPA1 uses its own (non-standard) EAPOL-Key descriptor type. (diff)
downloadwireguard-openbsd-2b0e84b2e50f02d63d63cb34e9c6409b3bfcb07d.tar.xz
wireguard-openbsd-2b0e84b2e50f02d63d63cb34e9c6409b3bfcb07d.zip
extend the ieee80211_key structure with a key identifier, a flags field
and a 64-bit receive sequence counter (for group keys). add a ieee80211_cipher_keylen() function to retrieve the key length in bytes used by a specific cipher. account for 802.1X header size when computing the Key MIC. some cleanup in comments and variable names while i'm here.
-rw-r--r--sys/net80211/ieee80211_crypto.c55
-rw-r--r--sys/net80211/ieee80211_crypto.h13
2 files changed, 48 insertions, 20 deletions
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 139658bed88..feb12d14e0a 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto.c,v 1.25 2007/07/24 20:34:16 damien Exp $ */
+/* $OpenBSD: ieee80211_crypto.c,v 1.26 2007/07/28 11:01:19 damien Exp $ */
/* $NetBSD: ieee80211_crypto.c,v 1.5 2003/12/14 09:56:53 dyoung Exp $ */
/*-
@@ -88,9 +88,6 @@ void ieee80211_hmac_sha1(const u_int8_t *, size_t, const u_int8_t *, size_t,
u_int8_t digest[]);
void ieee80211_prf(const u_int8_t *, size_t, struct vector *, int,
u_int8_t *, size_t);
-void ieee80211_derive_ptk(const u_int8_t *, size_t, const u_int8_t *,
- const u_int8_t *, const u_int8_t *, const u_int8_t *, u_int8_t *,
- size_t);
void ieee80211_derive_pmkid(const u_int8_t *, size_t, const u_int8_t *,
const u_int8_t *, u_int8_t *);
void ieee80211_derive_gtk(const u_int8_t *, size_t, const u_int8_t *,
@@ -656,22 +653,22 @@ ieee80211_eapol_key_mic(struct ieee80211_eapol_key *key, const u_int8_t *kck)
u_int8_t hash[SHA1_DIGEST_LENGTH];
u_int16_t len, info;
- len = BE_READ_2(key->len);
+ len = BE_READ_2(key->len) + 4;
info = BE_READ_2(key->info);
KASSERT(!(info & EAPOL_KEY_KEYMIC));
switch (info & EAPOL_KEY_VERSION_MASK) {
case EAPOL_KEY_DESC_V1:
- ieee80211_hmac_md5(kck, 16, (u_int8_t *)key, len, key->mic);
+ ieee80211_hmac_md5(kck, 16, &key->version, len, key->mic);
break;
case EAPOL_KEY_DESC_V2:
- ieee80211_hmac_sha1(kck, 16, (u_int8_t *)key, len, hash);
+ ieee80211_hmac_sha1(kck, 16, &key->version, len, hash);
/* truncate HMAC-SHA1 to its 128 MSBs */
memcpy(key->mic, hash, EAPOL_KEY_MIC_LEN);
break;
}
- /* set the Key MIC field */
+ /* set the Key MIC bit */
info |= EAPOL_KEY_KEYMIC;
BE_WRITE_2(key->info, info);
}
@@ -709,7 +706,7 @@ ieee80211_eapol_key_encrypt(struct ieee80211com *ic,
struct ieee80211_eapol_key *key, const u_int8_t *kek)
{
struct rc4_ctx ctx;
- u_int8_t buf[EAPOL_KEY_IV_LEN + 16];
+ u_int8_t keybuf[EAPOL_KEY_IV_LEN + 16];
u_int16_t len, info;
u_int8_t *data;
int n;
@@ -728,10 +725,10 @@ ieee80211_eapol_key_encrypt(struct ieee80211com *ic,
for (n = 31; n >= 0 && ++ic->ic_globalcnt[n] == 0; n--);
/* concatenate the EAPOL-Key IV field and the KEK */
- memcpy(buf, key->iv, EAPOL_KEY_IV_LEN);
- memcpy(buf + EAPOL_KEY_IV_LEN, kek, 16);
+ memcpy(keybuf, key->iv, EAPOL_KEY_IV_LEN);
+ memcpy(keybuf + EAPOL_KEY_IV_LEN, kek, 16);
- rc4_keysetup(&ctx, buf, sizeof buf);
+ rc4_keysetup(&ctx, keybuf, sizeof keybuf);
/* discard the first 256 octets of the ARC4 key stream */
rc4_skip(&ctx, RC4STATE);
rc4_crypt(&ctx, data, data, len);
@@ -751,7 +748,7 @@ ieee80211_eapol_key_encrypt(struct ieee80211com *ic,
break;
}
- /* set the Encrypted Key Data field */
+ /* set the Encrypted Key Data bit */
info |= EAPOL_KEY_ENCRYPTED;
BE_WRITE_2(key->info, info);
}
@@ -766,7 +763,7 @@ ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *key,
const u_int8_t *kek)
{
struct rc4_ctx ctx;
- u_int8_t buf[EAPOL_KEY_IV_LEN + 16];
+ u_int8_t keybuf[EAPOL_KEY_IV_LEN + 16];
u_int16_t len, info;
u_int8_t *data;
@@ -779,10 +776,10 @@ ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *key,
switch (info & EAPOL_KEY_VERSION_MASK) {
case EAPOL_KEY_DESC_V1:
/* concatenate the EAPOL-Key IV field and the KEK */
- memcpy(buf, key->iv, EAPOL_KEY_IV_LEN);
- memcpy(buf + EAPOL_KEY_IV_LEN, kek, 16);
+ memcpy(keybuf, key->iv, EAPOL_KEY_IV_LEN);
+ memcpy(keybuf + EAPOL_KEY_IV_LEN, kek, 16);
- rc4_keysetup(&ctx, buf, sizeof buf);
+ rc4_keysetup(&ctx, keybuf, sizeof keybuf);
/* discard the first 256 octets of the ARC4 key stream */
rc4_skip(&ctx, RC4STATE);
rc4_crypt(&ctx, data, data, len);
@@ -791,9 +788,29 @@ ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *key,
/* Key Data Length must be a multiple of 8 */
if (len < 16 + 8 || (len & 7) != 0)
return 1;
- len = (len / 8) - 1;
- return ieee80211_aes_key_unwrap(kek, 16, data, data, len);
+ len -= 8; /* AES Key Wrap adds 8 bytes */
+ return ieee80211_aes_key_unwrap(kek, 16, data, data, len / 8);
}
return 1; /* unknown Key Descriptor Version */
}
+
+/*
+ * Return the length in bytes of keys used by the specified cipher.
+ */
+int
+ieee80211_cipher_keylen(enum ieee80211_cipher cipher)
+{
+ switch (cipher) {
+ case IEEE80211_CIPHER_WEP40:
+ return 5;
+ case IEEE80211_CIPHER_TKIP:
+ return 32;
+ case IEEE80211_CIPHER_CCMP:
+ return 16;
+ case IEEE80211_CIPHER_WEP104:
+ return 13;
+ default: /* unknown cipher */
+ return 0;
+ }
+}
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
index 3f8f63a4865..8a54c0415ca 100644
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto.h,v 1.3 2007/07/18 18:10:31 damien Exp $ */
+/* $OpenBSD: ieee80211_crypto.h,v 1.4 2007/07/28 11:01:19 damien Exp $ */
/* $NetBSD: ieee80211_crypto.h,v 1.2 2003/09/14 01:14:55 dyoung Exp $ */
/*-
@@ -61,7 +61,13 @@ enum ieee80211_akm {
#define IEEE80211_KEYBUF_SIZE 16
struct ieee80211_key {
+ u_int8_t k_id; /* identifier (0-3) */
enum ieee80211_cipher k_cipher;
+ u_int k_flags;
+#define IEEE80211_KEY_GROUP 0x00000001 /* group key */
+#define IEEE80211_KEY_TX 0x00000002 /* Tx+Rx */
+
+ u_int64_t k_rsc; /* receive sequence counter */
int k_len;
u_int8_t k_key[IEEE80211_KEYBUF_SIZE];
};
@@ -69,4 +75,9 @@ struct ieee80211_key {
extern void ieee80211_crypto_attach(struct ifnet *);
extern void ieee80211_crypto_detach(struct ifnet *);
extern struct mbuf *ieee80211_wep_crypt(struct ifnet *, struct mbuf *, int);
+extern void ieee80211_derive_ptk(const u_int8_t *, size_t, const u_int8_t *,
+ const u_int8_t *, const u_int8_t *, const u_int8_t *, u_int8_t *,
+ size_t);
+extern int ieee80211_cipher_keylen(enum ieee80211_cipher);
+
#endif /* _NET80211_IEEE80211_CRYPTO_H_ */