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

          Line data    Source code
       1             : /*      $OpenBSD: ieee80211_crypto_ccmp.c,v 1.20 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 CTR with CBC-MAC protocol (CCMP) defined in
      21             :  * IEEE Std 802.11-2007 section 8.3.3.
      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             : 
      42             : #include <crypto/aes.h>
      43             : 
      44             : /* CCMP software crypto context */
      45             : struct ieee80211_ccmp_ctx {
      46             :         AES_CTX         aesctx;
      47             : };
      48             : 
      49             : /*
      50             :  * Initialize software crypto context.  This function can be overridden
      51             :  * by drivers doing hardware crypto.
      52             :  */
      53             : int
      54           0 : ieee80211_ccmp_set_key(struct ieee80211com *ic, struct ieee80211_key *k)
      55             : {
      56             :         struct ieee80211_ccmp_ctx *ctx;
      57             : 
      58           0 :         ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
      59           0 :         if (ctx == NULL)
      60           0 :                 return ENOMEM;
      61           0 :         AES_Setkey(&ctx->aesctx, k->k_key, 16);
      62           0 :         k->k_priv = ctx;
      63           0 :         return 0;
      64           0 : }
      65             : 
      66             : void
      67           0 : ieee80211_ccmp_delete_key(struct ieee80211com *ic, struct ieee80211_key *k)
      68             : {
      69           0 :         if (k->k_priv != NULL) {
      70           0 :                 explicit_bzero(k->k_priv, sizeof(struct ieee80211_ccmp_ctx));
      71           0 :                 free(k->k_priv, M_DEVBUF, sizeof(struct ieee80211_ccmp_ctx));
      72           0 :         }
      73           0 :         k->k_priv = NULL;
      74           0 : }
      75             : 
      76             : /*-
      77             :  * Counter with CBC-MAC (CCM) - see RFC3610.
      78             :  * CCMP uses the following CCM parameters: M = 8, L = 2
      79             :  */
      80             : static void
      81           0 : ieee80211_ccmp_phase1(AES_CTX *ctx, const struct ieee80211_frame *wh,
      82             :     u_int64_t pn, int lm, u_int8_t b[16], u_int8_t a[16], u_int8_t s0[16])
      83             : {
      84           0 :         u_int8_t auth[32], nonce[13];
      85             :         u_int8_t *aad;
      86             :         u_int8_t tid = 0;
      87             :         int la, i;
      88             : 
      89             :         /* construct AAD (additional authenticated data) */
      90           0 :         aad = &auth[2];     /* skip l(a), will be filled later */
      91           0 :         *aad = wh->i_fc[0];
      92             :         /* 11w: conditionally mask subtype field */
      93           0 :         if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
      94             :             IEEE80211_FC0_TYPE_DATA)
      95           0 :                 *aad &= ~IEEE80211_FC0_SUBTYPE_MASK |
      96             :                    IEEE80211_FC0_SUBTYPE_QOS;
      97           0 :         aad++;
      98             :         /* protected bit is already set in wh */
      99           0 :         *aad = wh->i_fc[1];
     100           0 :         *aad &= ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
     101             :             IEEE80211_FC1_MORE_DATA);
     102             :         /* 11n: conditionally mask order bit */
     103           0 :         if (ieee80211_has_qos(wh))
     104           0 :                 *aad &= ~IEEE80211_FC1_ORDER;
     105           0 :         aad++;
     106           0 :         IEEE80211_ADDR_COPY(aad, wh->i_addr1); aad += IEEE80211_ADDR_LEN;
     107           0 :         IEEE80211_ADDR_COPY(aad, wh->i_addr2); aad += IEEE80211_ADDR_LEN;
     108           0 :         IEEE80211_ADDR_COPY(aad, wh->i_addr3); aad += IEEE80211_ADDR_LEN;
     109           0 :         *aad++ = wh->i_seq[0] & ~0xf0;
     110           0 :         *aad++ = 0;
     111           0 :         if (ieee80211_has_addr4(wh)) {
     112           0 :                 IEEE80211_ADDR_COPY(aad,
     113             :                     ((const struct ieee80211_frame_addr4 *)wh)->i_addr4);
     114           0 :                 aad += IEEE80211_ADDR_LEN;
     115           0 :         }
     116           0 :         if (ieee80211_has_qos(wh)) {
     117             :                 /* 
     118             :                  * XXX 802.11-2012 11.4.3.3.3 g says the A-MSDU present bit
     119             :                  * must be set here if both STAs are SPP A-MSDU capable.
     120             :                  */
     121           0 :                 *aad++ = tid = ieee80211_get_qos(wh) & IEEE80211_QOS_TID;
     122           0 :                 *aad++ = 0;
     123           0 :         }
     124             : 
     125             :         /* construct CCM nonce */
     126             :         nonce[ 0] = tid;
     127           0 :         if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
     128             :             IEEE80211_FC0_TYPE_MGT)
     129           0 :                 nonce[0] |= 1 << 4;       /* 11w: set management bit */
     130           0 :         IEEE80211_ADDR_COPY(&nonce[1], wh->i_addr2);
     131           0 :         nonce[ 7] = pn >> 40;     /* PN5 */
     132           0 :         nonce[ 8] = pn >> 32;     /* PN4 */
     133           0 :         nonce[ 9] = pn >> 24;     /* PN3 */
     134           0 :         nonce[10] = pn >> 16;     /* PN2 */
     135           0 :         nonce[11] = pn >> 8;      /* PN1 */
     136           0 :         nonce[12] = pn;         /* PN0 */
     137             : 
     138             :         /* add 2 authentication blocks (including l(a) and padded AAD) */
     139           0 :         la = aad - &auth[2];                /* fill l(a) */
     140           0 :         auth[0] = la >> 8;
     141           0 :         auth[1] = la & 0xff;
     142           0 :         memset(aad, 0, 30 - la);        /* pad AAD with zeros */
     143             : 
     144             :         /* construct first block B_0 */
     145           0 :         b[ 0] = 89;     /* Flags = 64*Adata + 8*((M-2)/2) + (L-1) */
     146           0 :         memcpy(&b[1], nonce, 13);
     147           0 :         b[14] = lm >> 8;
     148           0 :         b[15] = lm & 0xff;
     149           0 :         AES_Encrypt(ctx, b, b);
     150             : 
     151           0 :         for (i = 0; i < 16; i++)
     152           0 :                 b[i] ^= auth[i];
     153           0 :         AES_Encrypt(ctx, b, b);
     154           0 :         for (i = 0; i < 16; i++)
     155           0 :                 b[i] ^= auth[16 + i];
     156           0 :         AES_Encrypt(ctx, b, b);
     157             : 
     158             :         /* construct S_0 */
     159           0 :         a[ 0] = 1;      /* Flags = L' = (L-1) */
     160           0 :         memcpy(&a[1], nonce, 13);
     161           0 :         a[14] = a[15] = 0;
     162           0 :         AES_Encrypt(ctx, a, s0);
     163           0 : }
     164             : 
     165             : struct mbuf *
     166           0 : ieee80211_ccmp_encrypt(struct ieee80211com *ic, struct mbuf *m0,
     167             :     struct ieee80211_key *k)
     168             : {
     169           0 :         struct ieee80211_ccmp_ctx *ctx = k->k_priv;
     170             :         const struct ieee80211_frame *wh;
     171             :         const u_int8_t *src;
     172             :         u_int8_t *ivp, *mic, *dst;
     173           0 :         u_int8_t a[16], b[16], s0[16], s[16];
     174             :         struct mbuf *n0, *m, *n;
     175             :         int hdrlen, left, moff, noff, len;
     176             :         u_int16_t ctr;
     177             :         int i, j;
     178             : 
     179           0 :         MGET(n0, M_DONTWAIT, m0->m_type);
     180           0 :         if (n0 == NULL)
     181             :                 goto nospace;
     182           0 :         if (m_dup_pkthdr(n0, m0, M_DONTWAIT))
     183             :                 goto nospace;
     184           0 :         n0->m_pkthdr.len += IEEE80211_CCMP_HDRLEN;
     185           0 :         n0->m_len = MHLEN;
     186           0 :         if (n0->m_pkthdr.len >= MINCLSIZE - IEEE80211_CCMP_MICLEN) {
     187           0 :                 MCLGET(n0, M_DONTWAIT);
     188           0 :                 if (n0->m_flags & M_EXT)
     189           0 :                         n0->m_len = n0->m_ext.ext_size;
     190             :         }
     191           0 :         if (n0->m_len > n0->m_pkthdr.len)
     192           0 :                 n0->m_len = n0->m_pkthdr.len;
     193             : 
     194             :         /* copy 802.11 header */
     195           0 :         wh = mtod(m0, struct ieee80211_frame *);
     196           0 :         hdrlen = ieee80211_get_hdrlen(wh);
     197           0 :         memcpy(mtod(n0, caddr_t), wh, hdrlen);
     198             : 
     199           0 :         k->k_tsc++;  /* increment the 48-bit PN */
     200             : 
     201             :         /* construct CCMP header */
     202           0 :         ivp = mtod(n0, u_int8_t *) + hdrlen;
     203           0 :         ivp[0] = k->k_tsc;           /* PN0 */
     204           0 :         ivp[1] = k->k_tsc >> 8;                /* PN1 */
     205           0 :         ivp[2] = 0;                     /* Rsvd */
     206           0 :         ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV;   /* KeyID | ExtIV */
     207           0 :         ivp[4] = k->k_tsc >> 16;       /* PN2 */
     208           0 :         ivp[5] = k->k_tsc >> 24;       /* PN3 */
     209           0 :         ivp[6] = k->k_tsc >> 32;       /* PN4 */
     210           0 :         ivp[7] = k->k_tsc >> 40;       /* PN5 */
     211             : 
     212             :         /* construct initial B, A and S_0 blocks */
     213           0 :         ieee80211_ccmp_phase1(&ctx->aesctx, wh, k->k_tsc,
     214           0 :             m0->m_pkthdr.len - hdrlen, b, a, s0);
     215             : 
     216             :         /* construct S_1 */
     217             :         ctr = 1;
     218           0 :         a[14] = ctr >> 8;
     219           0 :         a[15] = ctr & 0xff;
     220           0 :         AES_Encrypt(&ctx->aesctx, a, s);
     221             : 
     222             :         /* encrypt frame body and compute MIC */
     223             :         j = 0;
     224             :         m = m0;
     225             :         n = n0;
     226             :         moff = hdrlen;
     227           0 :         noff = hdrlen + IEEE80211_CCMP_HDRLEN;
     228           0 :         left = m0->m_pkthdr.len - moff;
     229           0 :         while (left > 0) {
     230           0 :                 if (moff == m->m_len) {
     231             :                         /* nothing left to copy from m */
     232           0 :                         m = m->m_next;
     233             :                         moff = 0;
     234           0 :                 }
     235           0 :                 if (noff == n->m_len) {
     236             :                         /* n is full and there's more data to copy */
     237           0 :                         MGET(n->m_next, M_DONTWAIT, n->m_type);
     238           0 :                         if (n->m_next == NULL)
     239             :                                 goto nospace;
     240             :                         n = n->m_next;
     241           0 :                         n->m_len = MLEN;
     242           0 :                         if (left >= MINCLSIZE - IEEE80211_CCMP_MICLEN) {
     243           0 :                                 MCLGET(n, M_DONTWAIT);
     244           0 :                                 if (n->m_flags & M_EXT)
     245           0 :                                         n->m_len = n->m_ext.ext_size;
     246             :                         }
     247           0 :                         if (n->m_len > left)
     248           0 :                                 n->m_len = left;
     249             :                         noff = 0;
     250           0 :                 }
     251           0 :                 len = min(m->m_len - moff, n->m_len - noff);
     252             : 
     253           0 :                 src = mtod(m, u_int8_t *) + moff;
     254           0 :                 dst = mtod(n, u_int8_t *) + noff;
     255           0 :                 for (i = 0; i < len; i++) {
     256             :                         /* update MIC with clear text */
     257           0 :                         b[j] ^= src[i];
     258             :                         /* encrypt message */
     259           0 :                         dst[i] = src[i] ^ s[j];
     260           0 :                         if (++j < 16)
     261             :                                 continue;
     262             :                         /* we have a full block, encrypt MIC */
     263           0 :                         AES_Encrypt(&ctx->aesctx, b, b);
     264             :                         /* construct a new S_ctr block */
     265           0 :                         ctr++;
     266           0 :                         a[14] = ctr >> 8;
     267           0 :                         a[15] = ctr & 0xff;
     268           0 :                         AES_Encrypt(&ctx->aesctx, a, s);
     269             :                         j = 0;
     270           0 :                 }
     271             : 
     272           0 :                 moff += len;
     273           0 :                 noff += len;
     274           0 :                 left -= len;
     275             :         }
     276           0 :         if (j != 0)     /* partial block, encrypt MIC */
     277           0 :                 AES_Encrypt(&ctx->aesctx, b, b);
     278             : 
     279             :         /* reserve trailing space for MIC */
     280           0 :         if (M_TRAILINGSPACE(n) < IEEE80211_CCMP_MICLEN) {
     281           0 :                 MGET(n->m_next, M_DONTWAIT, n->m_type);
     282           0 :                 if (n->m_next == NULL)
     283             :                         goto nospace;
     284             :                 n = n->m_next;
     285           0 :                 n->m_len = 0;
     286           0 :         }
     287             :         /* finalize MIC, U := T XOR first-M-bytes( S_0 ) */
     288           0 :         mic = mtod(n, u_int8_t *) + n->m_len;
     289           0 :         for (i = 0; i < IEEE80211_CCMP_MICLEN; i++)
     290           0 :                 mic[i] = b[i] ^ s0[i];
     291           0 :         n->m_len += IEEE80211_CCMP_MICLEN;
     292           0 :         n0->m_pkthdr.len += IEEE80211_CCMP_MICLEN;
     293             : 
     294           0 :         m_freem(m0);
     295           0 :         return n0;
     296             :  nospace:
     297           0 :         ic->ic_stats.is_tx_nombuf++;
     298           0 :         m_freem(m0);
     299           0 :         m_freem(n0);
     300           0 :         return NULL;
     301           0 : }
     302             : 
     303             : struct mbuf *
     304           0 : ieee80211_ccmp_decrypt(struct ieee80211com *ic, struct mbuf *m0,
     305             :     struct ieee80211_key *k)
     306             : {
     307           0 :         struct ieee80211_ccmp_ctx *ctx = k->k_priv;
     308             :         struct ieee80211_frame *wh;
     309             :         u_int64_t pn, *prsc;
     310             :         const u_int8_t *ivp, *src;
     311             :         u_int8_t *dst;
     312           0 :         u_int8_t mic0[IEEE80211_CCMP_MICLEN];
     313           0 :         u_int8_t a[16], b[16], s0[16], s[16];
     314             :         struct mbuf *n0, *m, *n;
     315             :         int hdrlen, left, moff, noff, len;
     316             :         u_int16_t ctr;
     317             :         int i, j;
     318             : 
     319           0 :         wh = mtod(m0, struct ieee80211_frame *);
     320           0 :         hdrlen = ieee80211_get_hdrlen(wh);
     321           0 :         ivp = (u_int8_t *)wh + hdrlen;
     322             : 
     323           0 :         if (m0->m_pkthdr.len < hdrlen + IEEE80211_CCMP_HDRLEN +
     324             :             IEEE80211_CCMP_MICLEN) {
     325           0 :                 m_freem(m0);
     326           0 :                 return NULL;
     327             :         }
     328             :         /* check that ExtIV bit is set */
     329           0 :         if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
     330           0 :                 m_freem(m0);
     331           0 :                 return NULL;
     332             :         }
     333             : 
     334             :         /* retrieve last seen packet number for this frame type/priority */
     335           0 :         if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
     336             :             IEEE80211_FC0_TYPE_DATA) {
     337           0 :                 u_int8_t tid = ieee80211_has_qos(wh) ?
     338           0 :                     ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
     339           0 :                 prsc = &k->k_rsc[tid];
     340           0 :         } else  /* 11w: management frames have their own counters */
     341           0 :                 prsc = &k->k_mgmt_rsc;
     342             : 
     343             :         /* extract the 48-bit PN from the CCMP header */
     344           0 :         pn = (u_int64_t)ivp[0]       |
     345           0 :              (u_int64_t)ivp[1] <<  8 |
     346           0 :              (u_int64_t)ivp[4] << 16 |
     347           0 :              (u_int64_t)ivp[5] << 24 |
     348           0 :              (u_int64_t)ivp[6] << 32 |
     349           0 :              (u_int64_t)ivp[7] << 40;
     350           0 :         if (pn <= *prsc) {
     351             :                 /* replayed frame, discard */
     352           0 :                 ic->ic_stats.is_ccmp_replays++;
     353           0 :                 m_freem(m0);
     354           0 :                 return NULL;
     355             :         }
     356             : 
     357           0 :         MGET(n0, M_DONTWAIT, m0->m_type);
     358           0 :         if (n0 == NULL)
     359             :                 goto nospace;
     360           0 :         if (m_dup_pkthdr(n0, m0, M_DONTWAIT))
     361             :                 goto nospace;
     362           0 :         n0->m_pkthdr.len -= IEEE80211_CCMP_HDRLEN + IEEE80211_CCMP_MICLEN;
     363           0 :         n0->m_len = MHLEN;
     364           0 :         if (n0->m_pkthdr.len >= MINCLSIZE) {
     365           0 :                 MCLGET(n0, M_DONTWAIT);
     366           0 :                 if (n0->m_flags & M_EXT)
     367           0 :                         n0->m_len = n0->m_ext.ext_size;
     368             :         }
     369           0 :         if (n0->m_len > n0->m_pkthdr.len)
     370           0 :                 n0->m_len = n0->m_pkthdr.len;
     371             : 
     372             :         /* construct initial B, A and S_0 blocks */
     373           0 :         ieee80211_ccmp_phase1(&ctx->aesctx, wh, pn,
     374           0 :             n0->m_pkthdr.len - hdrlen, b, a, s0);
     375             : 
     376             :         /* copy 802.11 header and clear protected bit */
     377           0 :         memcpy(mtod(n0, caddr_t), wh, hdrlen);
     378           0 :         wh = mtod(n0, struct ieee80211_frame *);
     379           0 :         wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
     380             : 
     381             :         /* construct S_1 */
     382             :         ctr = 1;
     383           0 :         a[14] = ctr >> 8;
     384           0 :         a[15] = ctr & 0xff;
     385           0 :         AES_Encrypt(&ctx->aesctx, a, s);
     386             : 
     387             :         /* decrypt frame body and compute MIC */
     388             :         j = 0;
     389             :         m = m0;
     390             :         n = n0;
     391             :         moff = hdrlen + IEEE80211_CCMP_HDRLEN;
     392             :         noff = hdrlen;
     393           0 :         left = n0->m_pkthdr.len - noff;
     394           0 :         while (left > 0) {
     395           0 :                 if (moff == m->m_len) {
     396             :                         /* nothing left to copy from m */
     397           0 :                         m = m->m_next;
     398             :                         moff = 0;
     399           0 :                 }
     400           0 :                 if (noff == n->m_len) {
     401             :                         /* n is full and there's more data to copy */
     402           0 :                         MGET(n->m_next, M_DONTWAIT, n->m_type);
     403           0 :                         if (n->m_next == NULL)
     404             :                                 goto nospace;
     405             :                         n = n->m_next;
     406           0 :                         n->m_len = MLEN;
     407           0 :                         if (left >= MINCLSIZE) {
     408           0 :                                 MCLGET(n, M_DONTWAIT);
     409           0 :                                 if (n->m_flags & M_EXT)
     410           0 :                                         n->m_len = n->m_ext.ext_size;
     411             :                         }
     412           0 :                         if (n->m_len > left)
     413           0 :                                 n->m_len = left;
     414             :                         noff = 0;
     415           0 :                 }
     416           0 :                 len = min(m->m_len - moff, n->m_len - noff);
     417             : 
     418           0 :                 src = mtod(m, u_int8_t *) + moff;
     419           0 :                 dst = mtod(n, u_int8_t *) + noff;
     420           0 :                 for (i = 0; i < len; i++) {
     421             :                         /* decrypt message */
     422           0 :                         dst[i] = src[i] ^ s[j];
     423             :                         /* update MIC with clear text */
     424           0 :                         b[j] ^= dst[i];
     425           0 :                         if (++j < 16)
     426             :                                 continue;
     427             :                         /* we have a full block, encrypt MIC */
     428           0 :                         AES_Encrypt(&ctx->aesctx, b, b);
     429             :                         /* construct a new S_ctr block */
     430           0 :                         ctr++;
     431           0 :                         a[14] = ctr >> 8;
     432           0 :                         a[15] = ctr & 0xff;
     433           0 :                         AES_Encrypt(&ctx->aesctx, a, s);
     434             :                         j = 0;
     435           0 :                 }
     436             : 
     437           0 :                 moff += len;
     438           0 :                 noff += len;
     439           0 :                 left -= len;
     440             :         }
     441           0 :         if (j != 0)     /* partial block, encrypt MIC */
     442           0 :                 AES_Encrypt(&ctx->aesctx, b, b);
     443             : 
     444             :         /* finalize MIC, U := T XOR first-M-bytes( S_0 ) */
     445           0 :         for (i = 0; i < IEEE80211_CCMP_MICLEN; i++)
     446           0 :                 b[i] ^= s0[i];
     447             : 
     448             :         /* check that it matches the MIC in received frame */
     449           0 :         m_copydata(m, moff, IEEE80211_CCMP_MICLEN, mic0);
     450           0 :         if (timingsafe_bcmp(mic0, b, IEEE80211_CCMP_MICLEN) != 0) {
     451           0 :                 ic->ic_stats.is_ccmp_dec_errs++;
     452           0 :                 m_freem(m0);
     453           0 :                 m_freem(n0);
     454           0 :                 return NULL;
     455             :         }
     456             : 
     457             :         /* update last seen packet number (MIC is validated) */
     458           0 :         *prsc = pn;
     459             : 
     460           0 :         m_freem(m0);
     461           0 :         return n0;
     462             :  nospace:
     463           0 :         ic->ic_stats.is_rx_nombuf++;
     464           0 :         m_freem(m0);
     465           0 :         m_freem(n0);
     466           0 :         return NULL;
     467           0 : }

Generated by: LCOV version 1.13