iPXE
Data Structures | Macros | Functions | Variables
wpa_ccmp.c File Reference

Backend for WPA using the CCMP encryption method. More...

#include <string.h>
#include <ipxe/net80211.h>
#include <ipxe/crypto.h>
#include <ipxe/hmac.h>
#include <ipxe/sha1.h>
#include <ipxe/aes.h>
#include <ipxe/wpa.h>
#include <byteswap.h>
#include <errno.h>

Go to the source code of this file.

Data Structures

struct  ccmp_ctx
 Context for CCMP encryption and decryption. More...
 
struct  ccmp_head
 Header structure at the beginning of CCMP frame data. More...
 
struct  ccmp_nonce
 CCMP nonce structure. More...
 
struct  ccmp_aad
 CCMP additional authentication data structure. More...
 

Macros

#define CCMP_HEAD_LEN   8
 CCMP header overhead. More...
 
#define CCMP_MIC_LEN   8
 CCMP MIC trailer overhead. More...
 
#define CCMP_NONCE_LEN   13
 CCMP nonce length. More...
 
#define CCMP_AAD_LEN   22
 CCMP additional authentication data length (for non-QoS, non-WDS frames) More...
 
#define CCMP_AAD_FC_MASK   0xC38F
 Mask for Frame Control field in AAD. More...
 
#define CCMP_AAD_SEQ_MASK   0x000F
 Mask for Sequence Control field in AAD. More...
 
#define PN_MSB   1
 Value for msb argument of u64_to_pn() for MSB output. More...
 
#define PN_LSB   0
 Value for msb argument of u64_to_pn() for LSB output. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 
static u64 pn_to_u64 (const u8 *pn)
 Convert 6-byte LSB packet number to 64-bit integer. More...
 
static void u64_to_pn (u64 v, u8 *pn, int msb)
 Convert 64-bit integer to 6-byte packet number. More...
 
static int ccmp_init (struct net80211_crypto *crypto, const void *key, int keylen, const void *rsc)
 Initialise CCMP state and install key. More...
 
static void ccmp_ctr_xor (struct ccmp_ctx *ctx, const void *nonce, const void *srcv, void *destv, int len, const void *msrcv, void *mdestv)
 Encrypt or decrypt data stream using AES in Counter mode. More...
 
static void ccmp_feed_cbc_mac (void *aes_ctx, u8 *B, u8 *X)
 Advance one block in CBC-MAC calculation. More...
 
static void ccmp_cbc_mac (struct ccmp_ctx *ctx, const void *nonce, const void *data, u16 datalen, const void *aad, void *mic)
 Calculate MIC on plaintext data using CBC-MAC. More...
 
struct io_bufferccmp_encrypt (struct net80211_crypto *crypto, struct io_buffer *iob)
 Encapsulate and encrypt a packet using CCMP. More...
 
static struct io_bufferccmp_decrypt (struct net80211_crypto *crypto, struct io_buffer *eiob)
 Decrypt a packet using CCMP. More...
 
static void ccmp_kie_mic (const void *kck, const void *msg, size_t len, void *mic)
 Calculate HMAC-SHA1 MIC for EAPOL-Key frame. More...
 
static int ccmp_kie_decrypt (const void *kek, const void *iv __unused, void *msg, u16 *len)
 Decrypt key data in EAPOL-Key frame. More...
 

Variables

struct net80211_crypto ccmp_crypto __net80211_crypto
 CCMP cryptosystem. More...
 
struct wpa_kie ccmp_kie __wpa_kie
 CCMP-style key integrity and encryption handler. More...
 

Detailed Description

Backend for WPA using the CCMP encryption method.

Definition in file wpa_ccmp.c.

Macro Definition Documentation

◆ CCMP_HEAD_LEN

#define CCMP_HEAD_LEN   8

CCMP header overhead.

Definition at line 61 of file wpa_ccmp.c.

◆ CCMP_MIC_LEN

#define CCMP_MIC_LEN   8

CCMP MIC trailer overhead.

Definition at line 64 of file wpa_ccmp.c.

◆ CCMP_NONCE_LEN

#define CCMP_NONCE_LEN   13

CCMP nonce length.

Definition at line 67 of file wpa_ccmp.c.

◆ CCMP_AAD_LEN

#define CCMP_AAD_LEN   22

CCMP additional authentication data length (for non-QoS, non-WDS frames)

Definition at line 78 of file wpa_ccmp.c.

◆ CCMP_AAD_FC_MASK

#define CCMP_AAD_FC_MASK   0xC38F

Mask for Frame Control field in AAD.

Definition at line 92 of file wpa_ccmp.c.

◆ CCMP_AAD_SEQ_MASK

#define CCMP_AAD_SEQ_MASK   0x000F

Mask for Sequence Control field in AAD.

Definition at line 95 of file wpa_ccmp.c.

◆ PN_MSB

#define PN_MSB   1

Value for msb argument of u64_to_pn() for MSB output.

Definition at line 141 of file wpa_ccmp.c.

◆ PN_LSB

#define PN_LSB   0

Value for msb argument of u64_to_pn() for LSB output.

Definition at line 144 of file wpa_ccmp.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER  )

◆ pn_to_u64()

static u64 pn_to_u64 ( const u8 pn)
static

Convert 6-byte LSB packet number to 64-bit integer.

Parameters
pnPointer to 6-byte packet number
Return values
v64-bit integer value of pn

Definition at line 104 of file wpa_ccmp.c.

105 {
106  int i;
107  u64 ret = 0;
108 
109  for ( i = 5; i >= 0; i-- ) {
110  ret <<= 8;
111  ret |= pn[i];
112  }
113 
114  return ret;
115 }
uint64_t u64
Definition: stdint.h:25

Referenced by ccmp_decrypt(), and ccmp_init().

◆ u64_to_pn()

static void u64_to_pn ( u64  v,
u8 pn,
int  msb 
)
static

Convert 64-bit integer to 6-byte packet number.

Parameters
v64-bit integer
msbIf TRUE, reverse the output PN to be in MSB order
Return values
pn6-byte packet number

The PN is stored in LSB order in the packet header and in MSB order in the nonce. WHYYYYY?

Definition at line 127 of file wpa_ccmp.c.

128 {
129  int i;
130  u8 *pnp = pn + ( msb ? 5 : 0 );
131  int delta = ( msb ? -1 : +1 );
132 
133  for ( i = 0; i < 6; i++ ) {
134  *pnp = v & 0xFF;
135  pnp += delta;
136  v >>= 8;
137  }
138 }
uint8_t u8
Definition: stdint.h:19

Referenced by ccmp_decrypt(), and ccmp_encrypt().

◆ ccmp_init()

static int ccmp_init ( struct net80211_crypto crypto,
const void *  key,
int  keylen,
const void *  rsc 
)
static

Initialise CCMP state and install key.

Parameters
cryptoCCMP cryptosystem structure
keyPointer to 16-byte temporal key to install
keylenLength of key (16 bytes)
rscInitial receive sequence counter

Definition at line 156 of file wpa_ccmp.c.

158 {
159  struct ccmp_ctx *ctx = crypto->priv;
160 
161  if ( keylen != 16 )
162  return -EINVAL;
163 
164  if ( rsc )
165  ctx->rx_seq = pn_to_u64 ( rsc );
166 
167  cipher_setkey ( &aes_algorithm, ctx->aes_ctx, key, keylen );
168 
169  return 0;
170 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
static u64 pn_to_u64(const u8 *pn)
Convert 6-byte LSB packet number to 64-bit integer.
Definition: wpa_ccmp.c:104
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
struct cipher_algorithm aes_algorithm
Basic AES algorithm.
Definition: aes.c:792
u8 rsc[8]
Receive sequence counter for GTK.
Definition: wpa.h:69
void * priv
Private data for the algorithm to store key and state info.
Definition: net80211.h:766
Context for CCMP encryption and decryption.
Definition: wpa_ccmp.c:38
union @375 key
Sense key.
Definition: scsi.h:18
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition: crypto.h:187

References aes_algorithm, cipher_setkey(), ctx, EINVAL, key, pn_to_u64(), net80211_crypto::priv, and rsc.

◆ ccmp_ctr_xor()

static void ccmp_ctr_xor ( struct ccmp_ctx ctx,
const void *  nonce,
const void *  srcv,
void *  destv,
int  len,
const void *  msrcv,
void *  mdestv 
)
static

Encrypt or decrypt data stream using AES in Counter mode.

Parameters
ctxCCMP cryptosystem context
nonceNonce value, 13 bytes
srcvData to encrypt or decrypt
lenNumber of bytes pointed to by src
msrcvMIC value to encrypt or decrypt (may be NULL)
Return values
destvEncrypted or decrypted data
mdestvEncrypted or decrypted MIC value

This assumes CCMP parameters of L=2 and M=8. The algorithm is defined in RFC 3610.

Definition at line 187 of file wpa_ccmp.c.

190 {
191  u8 A[16], S[16];
192  u16 ctr;
193  int i;
194  const u8 *src = srcv, *msrc = msrcv;
195  u8 *dest = destv, *mdest = mdestv;
196 
197  A[0] = 0x01; /* flags, L' = L - 1 = 1, other bits rsvd */
198  memcpy ( A + 1, nonce, CCMP_NONCE_LEN );
199 
200  if ( msrcv ) {
201  A[14] = A[15] = 0;
202 
203  cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, A, S, 16 );
204 
205  for ( i = 0; i < 8; i++ ) {
206  *mdest++ = *msrc++ ^ S[i];
207  }
208  }
209 
210  for ( ctr = 1 ;; ctr++ ) {
211  A[14] = ctr >> 8;
212  A[15] = ctr & 0xFF;
213 
214  cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, A, S, 16 );
215 
216  for ( i = 0; i < len && i < 16; i++ )
217  *dest++ = *src++ ^ S[i];
218 
219  if ( len <= 16 )
220  break; /* we're done */
221 
222  len -= 16;
223  }
224 }
uint16_t u16
Definition: stdint.h:21
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
struct cipher_algorithm aes_algorithm
Basic AES algorithm.
Definition: aes.c:792
static u16 S(u16 v)
Perform S-box mapping on a 16-bit value.
Definition: wpa_tkip.c:137
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:202
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static void * dest
Definition: strings.h:176
#define CCMP_NONCE_LEN
CCMP nonce length.
Definition: wpa_ccmp.c:67
static __always_inline void off_t userptr_t src
Definition: efi_uaccess.h:66
uint32_t len
Length.
Definition: ena.h:14
uint8_t u8
Definition: stdint.h:19
struct ntlm_nonce nonce
Server nonce.
Definition: ntlm.h:18

References aes_algorithm, CCMP_NONCE_LEN, cipher_encrypt, ctx, dest, len, memcpy(), nonce, S(), and src.

Referenced by ccmp_decrypt(), and ccmp_encrypt().

◆ ccmp_feed_cbc_mac()

static void ccmp_feed_cbc_mac ( void *  aes_ctx,
u8 B,
u8 X 
)
static

Advance one block in CBC-MAC calculation.

Parameters
aes_ctxAES encryption context with key set
BCleartext block to incorporate (16 bytes)
XPrevious ciphertext block (16 bytes)
Return values
BClobbered
XNew ciphertext block (16 bytes)

This function does X := E[key] ( X ^ B ).

Definition at line 238 of file wpa_ccmp.c.

239 {
240  int i;
241  for ( i = 0; i < 16; i++ )
242  B[i] ^= X[i];
243  cipher_encrypt ( &aes_algorithm, aes_ctx, B, X, 16 );
244 }
struct cipher_algorithm aes_algorithm
Basic AES algorithm.
Definition: aes.c:792
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:202
u8 aes_ctx[AES_CTX_SIZE]
AES context - only ever used for encryption.
Definition: wpa_ccmp.c:41

References aes_algorithm, ccmp_ctx::aes_ctx, and cipher_encrypt.

Referenced by ccmp_cbc_mac().

◆ ccmp_cbc_mac()

static void ccmp_cbc_mac ( struct ccmp_ctx ctx,
const void *  nonce,
const void *  data,
u16  datalen,
const void *  aad,
void *  mic 
)
static

Calculate MIC on plaintext data using CBC-MAC.

Parameters
ctxCCMP cryptosystem context
nonceNonce value, 13 bytes
dataData to calculate MIC over
datalenLength of data
aadAdditional authentication data, for MIC but not encryption
Return values
micMIC value (unencrypted), 8 bytes

aadlen is assumed to be 22 bytes long, as it always is for 802.11 use when transmitting non-QoS, not-between-APs frames (the only type we deal with).

Definition at line 261 of file wpa_ccmp.c.

264 {
265  u8 X[16], B[16];
266 
267  /* Zeroth block: flags, nonce, length */
268 
269  /* Rsv AAD - M'- - L'-
270  * 0 1 0 1 1 0 0 1 for an 8-byte MAC and 2-byte message length
271  */
272  B[0] = 0x59;
273  memcpy ( B + 1, nonce, CCMP_NONCE_LEN );
274  B[14] = datalen >> 8;
275  B[15] = datalen & 0xFF;
276 
277  cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, B, X, 16 );
278 
279  /* First block: AAD length field and 14 bytes of AAD */
280  B[0] = 0;
281  B[1] = CCMP_AAD_LEN;
282  memcpy ( B + 2, aad, 14 );
283 
284  ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
285 
286  /* Second block: Remaining 8 bytes of AAD, 8 bytes zero pad */
287  memcpy ( B, aad + 14, 8 );
288  memset ( B + 8, 0, 8 );
289 
290  ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
291 
292  /* Message blocks */
293  while ( datalen ) {
294  if ( datalen >= 16 ) {
295  memcpy ( B, data, 16 );
296  datalen -= 16;
297  } else {
298  memcpy ( B, data, datalen );
299  memset ( B + datalen, 0, 16 - datalen );
300  datalen = 0;
301  }
302 
303  ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
304 
305  data += 16;
306  }
307 
308  /* Get MIC from final value of X */
309  memcpy ( mic, X, 8 );
310 }
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
struct cipher_algorithm aes_algorithm
Basic AES algorithm.
Definition: aes.c:792
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:202
void * memcpy(void *dest, const void *src, size_t len) __nonnull
u16 datalen
Length of the data field in bytes, network byte order.
Definition: wpa.h:84
static void ccmp_feed_cbc_mac(void *aes_ctx, u8 *B, u8 *X)
Advance one block in CBC-MAC calculation.
Definition: wpa_ccmp.c:238
#define CCMP_NONCE_LEN
CCMP nonce length.
Definition: wpa_ccmp.c:67
#define CCMP_AAD_LEN
CCMP additional authentication data length (for non-QoS, non-WDS frames)
Definition: wpa_ccmp.c:78
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
u8 mic[16]
Message integrity code over the entire EAPOL frame.
Definition: wpa.h:81
uint8_t u8
Definition: stdint.h:19
struct ntlm_nonce nonce
Server nonce.
Definition: ntlm.h:18
void * memset(void *dest, int character, size_t len) __nonnull

References aes_algorithm, CCMP_AAD_LEN, ccmp_feed_cbc_mac(), CCMP_NONCE_LEN, cipher_encrypt, ctx, data, datalen, memcpy(), memset(), mic, and nonce.

Referenced by ccmp_decrypt(), and ccmp_encrypt().

◆ ccmp_encrypt()

struct io_buffer* ccmp_encrypt ( struct net80211_crypto crypto,
struct io_buffer iob 
)

Encapsulate and encrypt a packet using CCMP.

Parameters
cryptoCCMP cryptosystem
iobI/O buffer containing cleartext packet
Return values
eiobI/O buffer containing encrypted packet

Definition at line 320 of file wpa_ccmp.c.

322 {
323  struct ccmp_ctx *ctx = crypto->priv;
324  struct ieee80211_frame *hdr = iob->data;
325  struct io_buffer *eiob;
326  const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
327  int datalen = iob_len ( iob ) - hdrlen;
328  struct ccmp_head head;
329  struct ccmp_nonce nonce;
330  struct ccmp_aad aad;
331  u8 mic[8], tx_pn[6];
332  void *edata, *emic;
333 
334  ctx->tx_seq++;
335  u64_to_pn ( ctx->tx_seq, tx_pn, PN_LSB );
336 
337  /* Allocate memory */
338  eiob = alloc_iob ( iob_len ( iob ) + CCMP_HEAD_LEN + CCMP_MIC_LEN );
339  if ( ! eiob )
340  return NULL;
341 
342  /* Copy frame header */
343  memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
344  hdr = eiob->data;
346 
347  /* Fill in packet number and extended IV */
348  memcpy ( head.pn_lo, tx_pn, 2 );
349  memcpy ( head.pn_hi, tx_pn + 2, 4 );
350  head.kid = 0x20; /* have Extended IV, key ID 0 */
351  head._rsvd = 0;
352  memcpy ( iob_put ( eiob, sizeof ( head ) ), &head, sizeof ( head ) );
353 
354  /* Form nonce */
355  nonce.prio = 0;
356  memcpy ( nonce.a2, hdr->addr2, ETH_ALEN );
357  u64_to_pn ( ctx->tx_seq, nonce.pn, PN_MSB );
358 
359  /* Form additional authentication data */
360  aad.fc = hdr->fc & CCMP_AAD_FC_MASK;
361  memcpy ( aad.a1, hdr->addr1, 3 * ETH_ALEN ); /* all 3 at once */
362  aad.seq = hdr->seq & CCMP_AAD_SEQ_MASK;
363 
364  /* Calculate MIC over the data */
365  ccmp_cbc_mac ( ctx, &nonce, iob->data + hdrlen, datalen, &aad, mic );
366 
367  /* Copy and encrypt data and MIC */
368  edata = iob_put ( eiob, datalen );
369  emic = iob_put ( eiob, CCMP_MIC_LEN );
370  ccmp_ctr_xor ( ctx, &nonce,
371  iob->data + hdrlen, edata, datalen,
372  mic, emic );
373 
374  /* Done! */
375  DBGC2 ( ctx, "WPA-CCMP %p: encrypted packet %p -> %p\n", ctx,
376  iob, eiob );
377 
378  return eiob;
379 }
#define iob_put(iobuf, len)
Definition: iobuf.h:116
An 802.11 data or management frame without QoS or WDS header fields.
Definition: ieee80211.h:300
uint8_t head
Head number.
Definition: int13.h:34
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
static void u64_to_pn(u64 v, u8 *pn, int msb)
Convert 64-bit integer to 6-byte packet number.
Definition: wpa_ccmp.c:127
static void ccmp_cbc_mac(struct ccmp_ctx *ctx, const void *nonce, const void *data, u16 datalen, const void *aad, void *mic)
Calculate MIC on plaintext data using CBC-MAC.
Definition: wpa_ccmp.c:261
#define PN_MSB
Value for msb argument of u64_to_pn() for MSB output.
Definition: wpa_ccmp.c:141
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define IEEE80211_TYP_FRAME_HEADER_LEN
Frame header length for frames we might work with.
Definition: ieee80211.h:60
u16 datalen
Length of the data field in bytes, network byte order.
Definition: wpa.h:84
#define IEEE80211_FC_PROTECTED
802.11 Frame Control field: Protected flag
Definition: ieee80211.h:264
#define CCMP_AAD_SEQ_MASK
Mask for Sequence Control field in AAD.
Definition: wpa_ccmp.c:95
Header structure at the beginning of CCMP frame data.
Definition: wpa_ccmp.c:51
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
#define CCMP_MIC_LEN
CCMP MIC trailer overhead.
Definition: wpa_ccmp.c:64
static void ccmp_ctr_xor(struct ccmp_ctx *ctx, const void *nonce, const void *srcv, void *destv, int len, const void *msrcv, void *mdestv)
Encrypt or decrypt data stream using AES in Counter mode.
Definition: wpa_ccmp.c:187
#define ETH_ALEN
Definition: if_ether.h:8
void * priv
Private data for the algorithm to store key and state info.
Definition: net80211.h:766
uint32_t hdr
Message header.
Definition: intelvf.h:12
CCMP additional authentication data structure.
Definition: wpa_ccmp.c:81
#define DBGC2(...)
Definition: compiler.h:522
#define CCMP_HEAD_LEN
CCMP header overhead.
Definition: wpa_ccmp.c:61
Context for CCMP encryption and decryption.
Definition: wpa_ccmp.c:38
void * data
Start of data.
Definition: iobuf.h:44
CCMP nonce structure.
Definition: wpa_ccmp.c:70
#define CCMP_AAD_FC_MASK
Mask for Frame Control field in AAD.
Definition: wpa_ccmp.c:92
u8 mic[16]
Message integrity code over the entire EAPOL frame.
Definition: wpa.h:81
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
uint8_t u8
Definition: stdint.h:19
struct ntlm_nonce nonce
Server nonce.
Definition: ntlm.h:18
#define PN_LSB
Value for msb argument of u64_to_pn() for LSB output.
Definition: wpa_ccmp.c:144
A persistent I/O buffer.
Definition: iobuf.h:32

References ccmp_aad::a1, alloc_iob(), CCMP_AAD_FC_MASK, CCMP_AAD_SEQ_MASK, ccmp_cbc_mac(), ccmp_ctr_xor(), CCMP_HEAD_LEN, CCMP_MIC_LEN, ctx, io_buffer::data, datalen, DBGC2, ETH_ALEN, ccmp_aad::fc, hdr, head, IEEE80211_FC_PROTECTED, IEEE80211_TYP_FRAME_HEADER_LEN, iob_len(), iob_put, memcpy(), mic, nonce, NULL, PN_LSB, PN_MSB, net80211_crypto::priv, ccmp_aad::seq, and u64_to_pn().

◆ ccmp_decrypt()

static struct io_buffer* ccmp_decrypt ( struct net80211_crypto crypto,
struct io_buffer eiob 
)
static

Decrypt a packet using CCMP.

Parameters
cryptoCCMP cryptosystem
eiobI/O buffer containing encrypted packet
Return values
iobI/O buffer containing cleartext packet

Definition at line 388 of file wpa_ccmp.c.

390 {
391  struct ccmp_ctx *ctx = crypto->priv;
392  struct ieee80211_frame *hdr;
393  struct io_buffer *iob;
394  const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
395  int datalen = iob_len ( eiob ) - hdrlen - CCMP_HEAD_LEN - CCMP_MIC_LEN;
396  struct ccmp_head *head;
397  struct ccmp_nonce nonce;
398  struct ccmp_aad aad;
399  u8 rx_pn[6], their_mic[8], our_mic[8];
400 
401  iob = alloc_iob ( hdrlen + datalen );
402  if ( ! iob )
403  return NULL;
404 
405  /* Copy frame header */
406  memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
407  hdr = iob->data;
408  hdr->fc &= ~IEEE80211_FC_PROTECTED;
409 
410  /* Check and update RX packet number */
411  head = eiob->data + hdrlen;
412  memcpy ( rx_pn, head->pn_lo, 2 );
413  memcpy ( rx_pn + 2, head->pn_hi, 4 );
414 
415  if ( pn_to_u64 ( rx_pn ) <= ctx->rx_seq ) {
416  DBGC ( ctx, "WPA-CCMP %p: packet received out of order "
417  "(%012llx <= %012llx)\n", ctx, pn_to_u64 ( rx_pn ),
418  ctx->rx_seq );
419  free_iob ( iob );
420  return NULL;
421  }
422 
423  ctx->rx_seq = pn_to_u64 ( rx_pn );
424  DBGC2 ( ctx, "WPA-CCMP %p: RX packet number %012llx\n", ctx, ctx->rx_seq );
425 
426  /* Form nonce */
427  nonce.prio = 0;
428  memcpy ( nonce.a2, hdr->addr2, ETH_ALEN );
429  u64_to_pn ( ctx->rx_seq, nonce.pn, PN_MSB );
430 
431  /* Form additional authentication data */
432  aad.fc = ( hdr->fc & CCMP_AAD_FC_MASK ) | IEEE80211_FC_PROTECTED;
433  memcpy ( aad.a1, hdr->addr1, 3 * ETH_ALEN ); /* all 3 at once */
434  aad.seq = hdr->seq & CCMP_AAD_SEQ_MASK;
435 
436  /* Copy-decrypt data and MIC */
437  ccmp_ctr_xor ( ctx, &nonce, eiob->data + hdrlen + sizeof ( *head ),
438  iob_put ( iob, datalen ), datalen,
439  eiob->tail - CCMP_MIC_LEN, their_mic );
440 
441  /* Check MIC */
442  ccmp_cbc_mac ( ctx, &nonce, iob->data + hdrlen, datalen, &aad,
443  our_mic );
444 
445  if ( memcmp ( their_mic, our_mic, CCMP_MIC_LEN ) != 0 ) {
446  DBGC2 ( ctx, "WPA-CCMP %p: MIC failure\n", ctx );
447  free_iob ( iob );
448  return NULL;
449  }
450 
451  DBGC2 ( ctx, "WPA-CCMP %p: decrypted packet %p -> %p\n", ctx,
452  eiob, iob );
453 
454  return iob;
455 }
#define iob_put(iobuf, len)
Definition: iobuf.h:116
static u64 pn_to_u64(const u8 *pn)
Convert 6-byte LSB packet number to 64-bit integer.
Definition: wpa_ccmp.c:104
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
#define DBGC(...)
Definition: compiler.h:505
An 802.11 data or management frame without QoS or WDS header fields.
Definition: ieee80211.h:300
uint8_t head
Head number.
Definition: int13.h:34
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
static void u64_to_pn(u64 v, u8 *pn, int msb)
Convert 64-bit integer to 6-byte packet number.
Definition: wpa_ccmp.c:127
static void ccmp_cbc_mac(struct ccmp_ctx *ctx, const void *nonce, const void *data, u16 datalen, const void *aad, void *mic)
Calculate MIC on plaintext data using CBC-MAC.
Definition: wpa_ccmp.c:261
#define PN_MSB
Value for msb argument of u64_to_pn() for MSB output.
Definition: wpa_ccmp.c:141
void * tail
End of data.
Definition: iobuf.h:46
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define IEEE80211_TYP_FRAME_HEADER_LEN
Frame header length for frames we might work with.
Definition: ieee80211.h:60
u16 datalen
Length of the data field in bytes, network byte order.
Definition: wpa.h:84
#define IEEE80211_FC_PROTECTED
802.11 Frame Control field: Protected flag
Definition: ieee80211.h:264
#define CCMP_AAD_SEQ_MASK
Mask for Sequence Control field in AAD.
Definition: wpa_ccmp.c:95
Header structure at the beginning of CCMP frame data.
Definition: wpa_ccmp.c:51
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
#define CCMP_MIC_LEN
CCMP MIC trailer overhead.
Definition: wpa_ccmp.c:64
static void ccmp_ctr_xor(struct ccmp_ctx *ctx, const void *nonce, const void *srcv, void *destv, int len, const void *msrcv, void *mdestv)
Encrypt or decrypt data stream using AES in Counter mode.
Definition: wpa_ccmp.c:187
#define ETH_ALEN
Definition: if_ether.h:8
void * priv
Private data for the algorithm to store key and state info.
Definition: net80211.h:766
uint32_t hdr
Message header.
Definition: intelvf.h:12
CCMP additional authentication data structure.
Definition: wpa_ccmp.c:81
#define DBGC2(...)
Definition: compiler.h:522
#define CCMP_HEAD_LEN
CCMP header overhead.
Definition: wpa_ccmp.c:61
Context for CCMP encryption and decryption.
Definition: wpa_ccmp.c:38
void * data
Start of data.
Definition: iobuf.h:44
CCMP nonce structure.
Definition: wpa_ccmp.c:70
#define CCMP_AAD_FC_MASK
Mask for Frame Control field in AAD.
Definition: wpa_ccmp.c:92
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
uint8_t u8
Definition: stdint.h:19
struct ntlm_nonce nonce
Server nonce.
Definition: ntlm.h:18
A persistent I/O buffer.
Definition: iobuf.h:32

References ccmp_aad::a1, alloc_iob(), CCMP_AAD_FC_MASK, CCMP_AAD_SEQ_MASK, ccmp_cbc_mac(), ccmp_ctr_xor(), CCMP_HEAD_LEN, CCMP_MIC_LEN, ctx, io_buffer::data, datalen, DBGC, DBGC2, ETH_ALEN, ccmp_aad::fc, free_iob(), hdr, head, IEEE80211_FC_PROTECTED, IEEE80211_TYP_FRAME_HEADER_LEN, iob_len(), iob_put, memcmp(), memcpy(), nonce, NULL, PN_MSB, pn_to_u64(), net80211_crypto::priv, ccmp_aad::seq, io_buffer::tail, and u64_to_pn().

◆ ccmp_kie_mic()

static void ccmp_kie_mic ( const void *  kck,
const void *  msg,
size_t  len,
void *  mic 
)
static

Calculate HMAC-SHA1 MIC for EAPOL-Key frame.

Parameters
kckKey Confirmation Key, 16 bytes
msgMessage to calculate MIC over
lenNumber of bytes to calculate MIC over
Return values
micCalculated MIC, 16 bytes long

Definition at line 478 of file wpa_ccmp.c.

480 {
481  u8 sha1_ctx[SHA1_CTX_SIZE];
482  u8 kckb[16];
484  size_t kck_len = 16;
485 
486  memcpy ( kckb, kck, kck_len );
487 
488  hmac_init ( &sha1_algorithm, sha1_ctx, kckb, &kck_len );
489  hmac_update ( &sha1_algorithm, sha1_ctx, msg, len );
490  hmac_final ( &sha1_algorithm, sha1_ctx, kckb, &kck_len, hash );
491 
492  memcpy ( mic, hash, 16 );
493 }
void hmac_final(struct digest_algorithm *digest, void *digest_ctx, void *key, size_t *key_len, void *hmac)
Finalise HMAC.
Definition: hmac.c:115
u8 kck[WPA_KCK_LEN]
EAPOL-Key Key Confirmation Key (KCK)
Definition: wpa.h:28
void * memcpy(void *dest, const void *src, size_t len) __nonnull
pseudo_bit_t hash[0x00010]
Hash algorithm.
Definition: arbel.h:13
uint32_t len
Length.
Definition: ena.h:14
#define SHA1_DIGEST_SIZE
Definition: Tpm20.h:32
void hmac_init(struct digest_algorithm *digest, void *digest_ctx, void *key, size_t *key_len)
Initialise HMAC.
Definition: hmac.c:80
#define SHA1_CTX_SIZE
SHA-1 context size.
Definition: sha1.h:66
static void hmac_update(struct digest_algorithm *digest, void *digest_ctx, const void *data, size_t len)
Update HMAC.
Definition: hmac.h:21
u8 mic[16]
Message integrity code over the entire EAPOL frame.
Definition: wpa.h:81
uint8_t u8
Definition: stdint.h:19
struct digest_algorithm sha1_algorithm
SHA-1 algorithm.
Definition: sha1.c:258
static void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition: settings_ui.c:285

References hash, hmac_final(), hmac_init(), hmac_update(), kck, len, memcpy(), mic, msg(), sha1_algorithm, SHA1_CTX_SIZE, and SHA1_DIGEST_SIZE.

◆ ccmp_kie_decrypt()

static int ccmp_kie_decrypt ( const void *  kek,
const void *iv  __unused,
void *  msg,
u16 len 
)
static

Decrypt key data in EAPOL-Key frame.

Parameters
kekKey Encryption Key, 16 bytes
ivInitialisation vector, 16 bytes (unused)
msgMessage to decrypt
lenLength of message
Return values
msgDecrypted message in place of original
lenAdjusted downward for 8 bytes of overhead
rcReturn status code

The returned message may still contain padding of 0xDD followed by zero or more 0x00 octets. It is impossible to remove the padding without parsing the IEs in the packet (another design decision that tends to make one question the 802.11i committee's intelligence...)

Definition at line 511 of file wpa_ccmp.c.

513 {
514  if ( *len % 8 != 0 )
515  return -EINVAL;
516 
517  if ( aes_unwrap ( kek, msg, msg, *len / 8 - 1 ) != 0 )
518  return -EINVAL;
519 
520  *len -= 8;
521 
522  return 0;
523 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
u8 kek[WPA_KEK_LEN]
EAPOL-Key Key Encryption Key (KEK)
Definition: wpa.h:31
uint32_t len
Length.
Definition: ena.h:14
int aes_unwrap(const void *kek, const void *src, void *dest, int nblk)
Unwrap a key or other data using AES Key Wrap (RFC 3394)
Definition: aes_wrap.c:85
static void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition: settings_ui.c:285

References aes_unwrap(), EINVAL, kek, len, and msg().

Variable Documentation

◆ __net80211_crypto

struct net80211_crypto ccmp_crypto __net80211_crypto
Initial value:
= {
.algorithm = NET80211_CRYPT_CCMP,
.init = ccmp_init,
.encrypt = ccmp_encrypt,
.decrypt = ccmp_decrypt,
.priv_len = sizeof ( struct ccmp_ctx ),
}
Network protected with CCMP (AES-based system)
Definition: net80211.h:174
struct io_buffer * ccmp_encrypt(struct net80211_crypto *crypto, struct io_buffer *iob)
Encapsulate and encrypt a packet using CCMP.
Definition: wpa_ccmp.c:320
static int ccmp_init(struct net80211_crypto *crypto, const void *key, int keylen, const void *rsc)
Initialise CCMP state and install key.
Definition: wpa_ccmp.c:156
Context for CCMP encryption and decryption.
Definition: wpa_ccmp.c:38
static struct io_buffer * ccmp_decrypt(struct net80211_crypto *crypto, struct io_buffer *eiob)
Decrypt a packet using CCMP.
Definition: wpa_ccmp.c:388

CCMP cryptosystem.

Definition at line 459 of file wpa_ccmp.c.

◆ __wpa_kie

struct wpa_kie ccmp_kie __wpa_kie
Initial value:
= {
.mic = ccmp_kie_mic,
.decrypt = ccmp_kie_decrypt,
}
static void ccmp_kie_mic(const void *kck, const void *msg, size_t len, void *mic)
Calculate HMAC-SHA1 MIC for EAPOL-Key frame.
Definition: wpa_ccmp.c:478
#define EAPOL_KEY_VERSION_WPA2
Key descriptor version field value for WPA2 (CCMP)
Definition: wpa.h:81
static int ccmp_kie_decrypt(const void *kek, const void *iv __unused, void *msg, u16 *len)
Decrypt key data in EAPOL-Key frame.
Definition: wpa_ccmp.c:511

CCMP-style key integrity and encryption handler.

Definition at line 526 of file wpa_ccmp.c.