summaryrefslogtreecommitdiff
path: root/sys/net80211/ieee80211_crypto.c
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2008-08-12 19:57:00 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2008-08-12 19:57:00 +0000
commita2407eb6ca89941166b13df3af2931416358e300 (patch)
tree5884321fc4e0d1d126ca88792653453ab6d466ed /sys/net80211/ieee80211_crypto.c
parentc62b4649d45dd791966395d51a81465d216be52f (diff)
add the code to encrypt/decrypt management frames, retrieve key id
from MMIE etc... this code can't be triggered as no drivers claim MFP capability yet.
Diffstat (limited to 'sys/net80211/ieee80211_crypto.c')
-rw-r--r--sys/net80211/ieee80211_crypto.c78
1 files changed, 61 insertions, 17 deletions
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 484660cc9bb..329af139ef4 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto.c,v 1.51 2008/08/12 19:34:54 damien Exp $ */
+/* $OpenBSD: ieee80211_crypto.c,v 1.52 2008/08/12 19:56:59 damien Exp $ */
/*-
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
@@ -188,11 +188,20 @@ struct ieee80211_key *
ieee80211_get_txkey(struct ieee80211com *ic, const struct ieee80211_frame *wh,
struct ieee80211_node *ni)
{
- if (!(ic->ic_flags & IEEE80211_F_RSNON) ||
- IEEE80211_IS_MULTICAST(wh->i_addr1) ||
- ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP)
- return &ic->ic_nw_keys[ic->ic_wep_txkey];
- return &ni->ni_pairwise_key;
+ int kid;
+
+ if ((ic->ic_flags & IEEE80211_F_RSNON) &&
+ !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
+ ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)
+ return &ni->ni_pairwise_key;
+
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1) ||
+ (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
+ IEEE80211_FC0_TYPE_MGT)
+ kid = ic->ic_def_txkey;
+ else
+ kid = ic->ic_igtk_kid;
+ return &ic->ic_nw_keys[kid];
}
struct mbuf *
@@ -210,6 +219,9 @@ ieee80211_encrypt(struct ieee80211com *ic, struct mbuf *m0,
case IEEE80211_CIPHER_CCMP:
m0 = ieee80211_ccmp_encrypt(ic, m0, k);
break;
+ case IEEE80211_CIPHER_AES128_CMAC:
+ m0 = ieee80211_bip_encap(ic, m0, k);
+ break;
default:
/* should not get there */
m_freem(m0);
@@ -224,21 +236,50 @@ ieee80211_decrypt(struct ieee80211com *ic, struct mbuf *m0,
{
struct ieee80211_frame *wh;
struct ieee80211_key *k;
+ u_int8_t *ivp, *mmie;
+ u_int16_t kid;
+ int hdrlen;
- /* select the key for decryption */
+ /* find key for decryption */
wh = mtod(m0, struct ieee80211_frame *);
- if (!(ic->ic_flags & IEEE80211_F_RSNON) ||
- IEEE80211_IS_MULTICAST(wh->i_addr1) ||
- ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP) {
- /* XXX check length! */
- int hdrlen = ieee80211_get_hdrlen(wh);
- const u_int8_t *ivp = (u_int8_t *)wh + hdrlen;
- /* key identifier is always located at the same index */
- int kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
- k = &ic->ic_nw_keys[kid];
- } else
+ if ((ic->ic_flags & IEEE80211_F_RSNON) &&
+ !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
+ ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) {
k = &ni->ni_pairwise_key;
+ } else if (!IEEE80211_IS_MULTICAST(wh->i_addr1) ||
+ (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
+ IEEE80211_FC0_TYPE_MGT) {
+ /* retrieve group data key id from IV field */
+ hdrlen = ieee80211_get_hdrlen(wh);
+ /* check that IV field is present */
+ if (m0->m_len < hdrlen + 4) {
+ m_freem(m0);
+ return NULL;
+ }
+ ivp = (u_int8_t *)wh + hdrlen;
+ kid = ivp[3] >> 6;
+ k = &ic->ic_nw_keys[kid];
+ } else {
+ /* retrieve integrity group key id from MMIE */
+ if (m0->m_len < sizeof(*wh) + IEEE80211_MMIE_LEN) {
+ m_freem(m0);
+ return NULL;
+ }
+ /* it is assumed management frames are contiguous */
+ mmie = (u_int8_t *)wh + m0->m_len - IEEE80211_MMIE_LEN;
+ /* check that MMIE is valid */
+ if (mmie[0] != IEEE80211_ELEMID_MMIE || mmie[1] != 16) {
+ m_freem(m0);
+ return NULL;
+ }
+ kid = LE_READ_2(&mmie[2]);
+ if (kid != 4 && kid != 5) {
+ m_freem(m0);
+ return NULL;
+ }
+ k = &ic->ic_nw_keys[kid];
+ }
switch (k->k_cipher) {
case IEEE80211_CIPHER_WEP40:
case IEEE80211_CIPHER_WEP104:
@@ -250,6 +291,9 @@ ieee80211_decrypt(struct ieee80211com *ic, struct mbuf *m0,
case IEEE80211_CIPHER_CCMP:
m0 = ieee80211_ccmp_decrypt(ic, m0, k);
break;
+ case IEEE80211_CIPHER_AES128_CMAC:
+ m0 = ieee80211_bip_decap(ic, m0, k);
+ break;
default:
/* key not defined */
m_freem(m0);