diff options
Diffstat (limited to 'sys/net80211/ieee80211_crypto.c')
-rw-r--r-- | sys/net80211/ieee80211_crypto.c | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c index a89b4c68393..748be9599ba 100644 --- a/sys/net80211/ieee80211_crypto.c +++ b/sys/net80211/ieee80211_crypto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_crypto.c,v 1.17 2007/07/18 18:10:31 damien Exp $ */ +/* $OpenBSD: ieee80211_crypto.c,v 1.18 2007/07/18 18:16:33 damien Exp $ */ /* $NetBSD: ieee80211_crypto.c,v 1.5 2003/12/14 09:56:53 dyoung Exp $ */ /*- @@ -65,6 +65,7 @@ #include <crypto/arc4.h> #include <crypto/md5.h> #include <crypto/sha1.h> +#include <crypto/rijndael.h> #define arc4_ctxlen() sizeof (struct rc4_ctx) #define arc4_setkey(_c,_k,_l) rc4_keysetup(_c,_k,_l) #define arc4_encrypt(_c,_d,_s,_l) rc4_crypt(_c,_s,_d,_l) @@ -76,6 +77,10 @@ struct vector { void ieee80211_crc_init(void); u_int32_t ieee80211_crc_update(u_int32_t, const u_int8_t *, int); +void ieee80211_aes_key_wrap(const u_int8_t *, size_t, const u_int8_t *, + size_t, u_int8_t *); +int ieee80211_aes_key_unwrap(const u_int8_t *, size_t, const u_int8_t *, + u_int8_t *, size_t); void ieee80211_hmac_md5_v(const struct vector *, int, const u_int8_t *, size_t, u_int8_t digest[]); void ieee80211_hmac_md5(const u_int8_t *, size_t, const u_int8_t *, size_t, @@ -362,6 +367,75 @@ ieee80211_crc_update(u_int32_t crc, const u_int8_t *buf, int len) return crc; } +/* + * AES Key Wrap Algorithm (see RFC 3394). + */ +static const u_int8_t aes_key_wrap_iv[8] = + { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 }; + +void +ieee80211_aes_key_wrap(const u_int8_t *kek, size_t kek_len, const u_int8_t *pt, + size_t len, u_int8_t *ct) +{ + rijndael_ctx ctx; + u_int8_t *a, *r, ar[16]; + u_int64_t t, b[2]; + size_t i; + int j; + + a = ct; + memcpy(a, aes_key_wrap_iv, 8); /* default IV */ + memcpy(ct + 8, pt, len * 8); + + rijndael_set_key_enc_only(&ctx, (u_int8_t *)kek, kek_len * 8); + + for (j = 0, t = 1; j < 6; j++) { + r = ct + 8; + for (i = 0; i < len; i++, t++) { + memcpy(ar, a, 8); + memcpy(ar + 8, r, 8); + rijndael_encrypt(&ctx, ar, (u_int8_t *)b); + b[0] ^= htobe64(t); + memcpy(a, &b[0], 8); + memcpy(r, &b[1], 8); + + r += 8; + } + } +} + +int +ieee80211_aes_key_unwrap(const u_int8_t *kek, size_t kek_len, + const u_int8_t *ct, u_int8_t *pt, size_t len) +{ + rijndael_ctx ctx; + u_int8_t a[8], *r, b[16]; + u_int64_t t, ar[2]; + size_t i; + int j; + + memcpy(a, ct, 8); + /* allow ciphertext and plaintext to overlap (ct == pt) */ + ovbcopy(ct + 8, pt, len * 8); + + rijndael_set_key(&ctx, (u_int8_t *)kek, kek_len * 8); + + for (j = 0, t = 6 * len; j < 6; j++) { + r = pt + (len - 1) * 8; + for (i = 0; i < len; i++, t--) { + memcpy(&ar[0], a, 8); + ar[0] ^= htobe64(t); + memcpy(&ar[1], r, 8); + rijndael_decrypt(&ctx, (u_int8_t *)ar, b); + memcpy(a, b, 8); + memcpy(r, b + 8, 8); + + r -= 8; + } + } + return memcmp(a, aes_key_wrap_iv, 8) != 0; +} + void ieee80211_hmac_md5_v(const struct vector *vec, int vcnt, const u_int8_t *key, size_t key_len, u_int8_t digest[MD5_DIGEST_LENGTH]) |