From: damien Date: Tue, 12 Aug 2008 18:48:35 +0000 (+0000) Subject: add support for EAPOL-Key v3 descriptors (similar to v2 except that the X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=9cba77ff7de07c937763b496c5ff9e7f78276f05;p=openbsd add support for EAPOL-Key v3 descriptors (similar to v2 except that the MIC is computed using AES-128-CMAC instead of HMAC-SHA1). add a SHA-256 based key derivation function (not used yet). --- diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index ff849f4f240..10afb2914e2 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211.h,v 1.41 2008/08/12 18:30:02 damien Exp $ */ +/* $OpenBSD: ieee80211.h,v 1.42 2008/08/12 18:48:35 damien Exp $ */ /* $NetBSD: ieee80211.h,v 1.6 2004/04/30 23:51:53 dyoung Exp $ */ /*- @@ -548,6 +548,7 @@ struct ieee80211_eapol_key { #define EAPOL_KEY_VERSION_MASK 0x7 #define EAPOL_KEY_DESC_V1 1 #define EAPOL_KEY_DESC_V2 2 +#define EAPOL_KEY_DESC_V3 3 /* 11r */ #define EAPOL_KEY_PAIRWISE (1 << 3) #define EAPOL_KEY_INSTALL (1 << 6) /* I */ #define EAPOL_KEY_KEYACK (1 << 7) /* A */ diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c index 743d16cde8f..11668e3a10a 100644 --- a/sys/net80211/ieee80211_crypto.c +++ b/sys/net80211/ieee80211_crypto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_crypto.c,v 1.48 2008/08/12 18:41:18 damien Exp $ */ +/* $OpenBSD: ieee80211_crypto.c,v 1.49 2008/08/12 18:48:35 damien Exp $ */ /*- * Copyright (c) 2008 Damien Bergamini @@ -49,10 +49,13 @@ #include #include #include +#include #include void ieee80211_prf(const u_int8_t *, size_t, const u_int8_t *, size_t, const u_int8_t *, size_t, u_int8_t *, size_t); +void ieee80211_kdf(const u_int8_t *, size_t, const u_int8_t *, size_t, + const u_int8_t *, size_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 *); @@ -128,6 +131,9 @@ ieee80211_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, case IEEE80211_CIPHER_CCMP: error = ieee80211_ccmp_set_key(ic, k); break; + case IEEE80211_CIPHER_AES128_CMAC: + error = ieee80211_bip_set_key(ic, k); + break; default: /* should not get there */ error = EINVAL; @@ -150,11 +156,14 @@ ieee80211_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, case IEEE80211_CIPHER_CCMP: ieee80211_ccmp_delete_key(ic, k); break; + case IEEE80211_CIPHER_AES128_CMAC: + ieee80211_bip_delete_key(ic, k); + break; default: /* should not get there */ break; } - memset(k, 0, sizeof(*k)); /* XXX */ + memset(k, 0, sizeof(*k)); } /* @@ -277,6 +286,38 @@ ieee80211_prf(const u_int8_t *key, size_t key_len, const u_int8_t *label, } } +/* + * SHA256-based Key Derivation Function (see 8.5.1.5.2). + */ +void +ieee80211_kdf(const u_int8_t *key, size_t key_len, const u_int8_t *label, + size_t label_len, const u_int8_t *context, size_t context_len, + u_int8_t *output, size_t len) +{ + HMAC_SHA256_CTX ctx; + u_int8_t digest[SHA256_DIGEST_LENGTH]; + u_int16_t i, iter, length; + + length = htole16(len * NBBY); + for (i = 1; len != 0; i++) { + HMAC_SHA256_Init(&ctx, key, key_len); + iter = htole16(i); + HMAC_SHA256_Update(&ctx, (u_int8_t *)&iter, sizeof iter); + HMAC_SHA256_Update(&ctx, label, label_len); + HMAC_SHA256_Update(&ctx, context, context_len); + HMAC_SHA256_Update(&ctx, (u_int8_t *)&length, sizeof length); + if (len < SHA256_DIGEST_LENGTH) { + HMAC_SHA256_Final(digest, &ctx); + /* truncate HMAC-SHA-256 to len bytes */ + memcpy(output, digest, len); + break; + } + HMAC_SHA256_Final(output, &ctx); + output += SHA256_DIGEST_LENGTH; + len -= SHA256_DIGEST_LENGTH; + } +} + /* * Derive Pairwise Transient Key (PTK) (see 8.5.1.2). */ @@ -324,12 +365,13 @@ ieee80211_derive_pmkid(const u_int8_t *pmk, size_t pmk_len, const u_int8_t *aa, typedef union _ANY_CTX { HMAC_MD5_CTX md5; HMAC_SHA1_CTX sha1; + AES_CMAC_CTX cmac; } ANY_CTX; /* * Compute the Key MIC field of an EAPOL-Key frame using the specified Key - * Confirmation Key (KCK). The hash function can be either HMAC-MD5 or - * HMAC-SHA1 depending on the EAPOL-Key Key Descriptor Version. + * Confirmation Key (KCK). The hash function can be HMAC-MD5, HMAC-SHA1 + * or AES-128-CMAC depending on the EAPOL-Key Key Descriptor Version. */ void ieee80211_eapol_key_mic(struct ieee80211_eapol_key *key, const u_int8_t *kck) @@ -353,6 +395,12 @@ ieee80211_eapol_key_mic(struct ieee80211_eapol_key *key, const u_int8_t *kck) /* truncate HMAC-SHA1 to its 128 MSBs */ memcpy(key->mic, digest, EAPOL_KEY_MIC_LEN); break; + case EAPOL_KEY_DESC_V3: + AES_CMAC_Init(&ctx.cmac); + AES_CMAC_SetKey(&ctx.cmac, kck); + AES_CMAC_Update(&ctx.cmac, (u_int8_t *)key, len); + AES_CMAC_Final(key->mic, &ctx.cmac); + break; } } @@ -412,6 +460,7 @@ ieee80211_eapol_key_encrypt(struct ieee80211com *ic, rc4_crypt(&ctx.rc4, data, data, len); break; case EAPOL_KEY_DESC_V2: + case EAPOL_KEY_DESC_V3: if (len < 16 || (len & 7) != 0) { /* insert padding */ n = (len < 16) ? 16 - len : 8 - (len & 7); @@ -463,6 +512,7 @@ ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *key, rc4_crypt(&ctx.rc4, data, data, len); return 0; case EAPOL_KEY_DESC_V2: + case EAPOL_KEY_DESC_V3: /* Key Data Length must be a multiple of 8 */ if (len < 16 + 8 || (len & 7) != 0) return 1;