LCOV - code coverage report
Current view: top level - net80211 - ieee80211_crypto_bip.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 86 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ieee80211_crypto_bip.c,v 1.9 2017/05/02 17:07:06 mikeb Exp $  */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /*
      20             :  * This code implements the Broadcast/Multicast Integrity Protocol (BIP)
      21             :  * defined in IEEE P802.11w/D7.0 section 8.3.4.
      22             :  */
      23             : 
      24             : #include <sys/param.h>
      25             : #include <sys/systm.h>
      26             : #include <sys/mbuf.h>
      27             : #include <sys/malloc.h>
      28             : #include <sys/kernel.h>
      29             : #include <sys/socket.h>
      30             : #include <sys/endian.h>
      31             : 
      32             : #include <net/if.h>
      33             : #include <net/if_dl.h>
      34             : #include <net/if_media.h>
      35             : 
      36             : #include <netinet/in.h>
      37             : #include <netinet/if_ether.h>
      38             : 
      39             : #include <net80211/ieee80211_var.h>
      40             : #include <net80211/ieee80211_crypto.h>
      41             : #include <net80211/ieee80211_priv.h>
      42             : 
      43             : #include <crypto/aes.h>
      44             : #include <crypto/cmac.h>
      45             : 
      46             : /* BIP software crypto context */
      47             : struct ieee80211_bip_ctx {
      48             :         AES_CMAC_CTX    cmac;
      49             : };
      50             : 
      51             : /*
      52             :  * Initialize software crypto context.  This function can be overridden
      53             :  * by drivers doing hardware crypto.
      54             :  */
      55             : int
      56           0 : ieee80211_bip_set_key(struct ieee80211com *ic, struct ieee80211_key *k)
      57             : {
      58             :         struct ieee80211_bip_ctx *ctx;
      59             : 
      60           0 :         ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
      61           0 :         if (ctx == NULL)
      62           0 :                 return ENOMEM;
      63           0 :         AES_CMAC_SetKey(&ctx->cmac, k->k_key);
      64           0 :         k->k_priv = ctx;
      65           0 :         return 0;
      66           0 : }
      67             : 
      68             : void
      69           0 : ieee80211_bip_delete_key(struct ieee80211com *ic, struct ieee80211_key *k)
      70             : {
      71           0 :         if (k->k_priv != NULL) {
      72           0 :                 explicit_bzero(k->k_priv, sizeof(struct ieee80211_bip_ctx));
      73           0 :                 free(k->k_priv, M_DEVBUF, sizeof(struct ieee80211_bip_ctx));
      74           0 :         }
      75           0 :         k->k_priv = NULL;
      76           0 : }
      77             : 
      78             : /* pseudo-header used for BIP MIC computation */
      79             : struct ieee80211_bip_frame {
      80             :         u_int8_t        i_fc[2];
      81             :         u_int8_t        i_addr1[IEEE80211_ADDR_LEN];
      82             :         u_int8_t        i_addr2[IEEE80211_ADDR_LEN];
      83             :         u_int8_t        i_addr3[IEEE80211_ADDR_LEN];
      84             : } __packed;
      85             : 
      86             : struct mbuf *
      87           0 : ieee80211_bip_encap(struct ieee80211com *ic, struct mbuf *m0,
      88             :     struct ieee80211_key *k)
      89             : {
      90           0 :         struct ieee80211_bip_ctx *ctx = k->k_priv;
      91           0 :         struct ieee80211_bip_frame aad;
      92             :         struct ieee80211_frame *wh;
      93           0 :         u_int8_t *mmie, mic[AES_CMAC_DIGEST_LENGTH];
      94             :         struct mbuf *m;
      95             : 
      96           0 :         wh = mtod(m0, struct ieee80211_frame *);
      97           0 :         KASSERT((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
      98             :             IEEE80211_FC0_TYPE_MGT);
      99             :         /* clear Protected bit from group management frames */
     100           0 :         wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
     101             : 
     102             :         /* construct AAD (additional authenticated data) */
     103           0 :         aad.i_fc[0] = wh->i_fc[0];
     104           0 :         aad.i_fc[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY |
     105             :             IEEE80211_FC1_PWR_MGT | IEEE80211_FC1_MORE_DATA);
     106             :         /* XXX 11n may require clearing the Order bit too */
     107           0 :         IEEE80211_ADDR_COPY(aad.i_addr1, wh->i_addr1);
     108           0 :         IEEE80211_ADDR_COPY(aad.i_addr2, wh->i_addr2);
     109           0 :         IEEE80211_ADDR_COPY(aad.i_addr3, wh->i_addr3);
     110             : 
     111           0 :         AES_CMAC_Init(&ctx->cmac);
     112           0 :         AES_CMAC_Update(&ctx->cmac, (u_int8_t *)&aad, sizeof aad);
     113           0 :         AES_CMAC_Update(&ctx->cmac, (u_int8_t *)&wh[1],
     114           0 :             m0->m_len - sizeof(*wh));
     115             : 
     116             :         m = m0;
     117             :         /* reserve trailing space for MMIE */
     118           0 :         if (M_TRAILINGSPACE(m) < IEEE80211_MMIE_LEN) {
     119           0 :                 MGET(m->m_next, M_DONTWAIT, m->m_type);
     120           0 :                 if (m->m_next == NULL)
     121             :                         goto nospace;
     122             :                 m = m->m_next;
     123           0 :                 m->m_len = 0;
     124           0 :         }
     125             : 
     126             :         /* construct Management MIC IE */
     127           0 :         mmie = mtod(m, u_int8_t *) + m->m_len;
     128           0 :         mmie[0] = IEEE80211_ELEMID_MMIE;
     129           0 :         mmie[1] = 16;
     130           0 :         LE_WRITE_2(&mmie[2], k->k_id);
     131           0 :         LE_WRITE_6(&mmie[4], k->k_tsc);
     132           0 :         memset(&mmie[10], 0, 8);    /* MMIE MIC field set to 0 */
     133             : 
     134           0 :         AES_CMAC_Update(&ctx->cmac, mmie, IEEE80211_MMIE_LEN);
     135           0 :         AES_CMAC_Final(mic, &ctx->cmac);
     136             :         /* truncate AES-128-CMAC to 64-bit */
     137           0 :         memcpy(&mmie[10], mic, 8);
     138             : 
     139           0 :         m->m_len += IEEE80211_MMIE_LEN;
     140           0 :         m0->m_pkthdr.len += IEEE80211_MMIE_LEN;
     141             : 
     142           0 :         k->k_tsc++;
     143             : 
     144           0 :         return m0;
     145             :  nospace:
     146           0 :         ic->ic_stats.is_tx_nombuf++;
     147           0 :         m_freem(m0);
     148           0 :         return NULL;
     149           0 : }
     150             : 
     151             : struct mbuf *
     152           0 : ieee80211_bip_decap(struct ieee80211com *ic, struct mbuf *m0,
     153             :     struct ieee80211_key *k)
     154             : {
     155           0 :         struct ieee80211_bip_ctx *ctx = k->k_priv;
     156             :         struct ieee80211_frame *wh;
     157           0 :         struct ieee80211_bip_frame aad;
     158           0 :         u_int8_t *mmie, mic0[8], mic[AES_CMAC_DIGEST_LENGTH];
     159             :         u_int64_t ipn;
     160             : 
     161           0 :         wh = mtod(m0, struct ieee80211_frame *);
     162           0 :         KASSERT((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
     163             :             IEEE80211_FC0_TYPE_MGT);
     164             : 
     165             :         /*
     166             :          * It is assumed that management frames are contiguous and that
     167             :          * the mbuf length has already been checked to contain at least
     168             :          * a header and a MMIE (checked in ieee80211_decrypt()).
     169             :          */
     170           0 :         KASSERT(m0->m_len >= sizeof(*wh) + IEEE80211_MMIE_LEN);
     171           0 :         mmie = mtod(m0, u_int8_t *) + m0->m_len - IEEE80211_MMIE_LEN;
     172             : 
     173           0 :         ipn = LE_READ_6(&mmie[4]);
     174           0 :         if (ipn <= k->k_mgmt_rsc) {
     175             :                 /* replayed frame, discard */
     176           0 :                 ic->ic_stats.is_cmac_replays++;
     177           0 :                 m_freem(m0);
     178           0 :                 return NULL;
     179             :         }
     180             : 
     181             :         /* save and mask MMIE MIC field to 0 */
     182           0 :         memcpy(mic0, &mmie[10], 8);
     183           0 :         memset(&mmie[10], 0, 8);
     184             : 
     185             :         /* construct AAD (additional authenticated data) */
     186           0 :         aad.i_fc[0] = wh->i_fc[0];
     187           0 :         aad.i_fc[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY |
     188             :             IEEE80211_FC1_PWR_MGT | IEEE80211_FC1_MORE_DATA);
     189             :         /* XXX 11n may require clearing the Order bit too */
     190           0 :         IEEE80211_ADDR_COPY(aad.i_addr1, wh->i_addr1);
     191           0 :         IEEE80211_ADDR_COPY(aad.i_addr2, wh->i_addr2);
     192           0 :         IEEE80211_ADDR_COPY(aad.i_addr3, wh->i_addr3);
     193             : 
     194             :         /* compute MIC */
     195           0 :         AES_CMAC_Init(&ctx->cmac);
     196           0 :         AES_CMAC_Update(&ctx->cmac, (u_int8_t *)&aad, sizeof aad);
     197           0 :         AES_CMAC_Update(&ctx->cmac, (u_int8_t *)&wh[1],
     198           0 :             m0->m_len - sizeof(*wh));
     199           0 :         AES_CMAC_Final(mic, &ctx->cmac);
     200             : 
     201             :         /* check that MIC matches the one in MMIE */
     202           0 :         if (timingsafe_bcmp(mic, mic0, 8) != 0) {
     203           0 :                 ic->ic_stats.is_cmac_icv_errs++;
     204           0 :                 m_freem(m0);
     205           0 :                 return NULL;
     206             :         }
     207             :         /*
     208             :          * There is no need to trim the MMIE from the mbuf since it is
     209             :          * an information element and will be ignored by upper layers.
     210             :          * We do it anyway as it is cheap to do it here and because it
     211             :          * may be confused with fixed fields by upper layers.
     212             :          */
     213           0 :         m_adj(m0, -IEEE80211_MMIE_LEN);
     214             : 
     215             :         /* update last seen packet number (MIC is validated) */
     216           0 :         k->k_mgmt_rsc = ipn;
     217             : 
     218           0 :         return m0;
     219           0 : }

Generated by: LCOV version 1.13