diff options
author | 2007-07-28 11:01:19 +0000 | |
---|---|---|
committer | 2007-07-28 11:01:19 +0000 | |
commit | 2b0e84b2e50f02d63d63cb34e9c6409b3bfcb07d (patch) | |
tree | 8591e5af35a2340a54bb8c04b1c97a7a07593407 | |
parent | WPA1 uses its own (non-standard) EAPOL-Key descriptor type. (diff) | |
download | wireguard-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.c | 55 | ||||
-rw-r--r-- | sys/net80211/ieee80211_crypto.h | 13 |
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_ */ |