Home | History | Annotate | Download | only in 80211
      1 /*
      2  * Copyright (c) 2009 Joshua Oreman <oremanj (at) rwcr.net>.
      3  *
      4  * This program is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU General Public License as
      6  * published by the Free Software Foundation; either version 2 of the
      7  * License, or any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write to the Free Software
     16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 #include <gpxe/net80211.h>
     22 #include <gpxe/crypto.h>
     23 #include <gpxe/hmac.h>
     24 #include <gpxe/sha1.h>
     25 #include <gpxe/aes.h>
     26 #include <gpxe/wpa.h>
     27 #include <byteswap.h>
     28 #include <errno.h>
     29 
     30 /** @file
     31  *
     32  * Backend for WPA using the CCMP encryption method
     33  */
     34 
     35 /** Context for CCMP encryption and decryption */
     36 struct ccmp_ctx
     37 {
     38 	/** AES context - only ever used for encryption */
     39 	u8 aes_ctx[AES_CTX_SIZE];
     40 
     41 	/** Most recently sent packet number */
     42 	u64 tx_seq;
     43 
     44 	/** Most recently received packet number */
     45 	u64 rx_seq;
     46 };
     47 
     48 /** Header structure at the beginning of CCMP frame data */
     49 struct ccmp_head
     50 {
     51 	u8 pn_lo[2];		/**< Bytes 0 and 1 of packet number */
     52 	u8 _rsvd;		/**< Reserved byte */
     53 	u8 kid;			/**< Key ID and ExtIV byte */
     54 	u8 pn_hi[4];		/**< Bytes 2-5 (2 first) of packet number */
     55 } __attribute__ (( packed ));
     56 
     57 
     58 /** CCMP header overhead */
     59 #define CCMP_HEAD_LEN	8
     60 
     61 /** CCMP MIC trailer overhead */
     62 #define CCMP_MIC_LEN	8
     63 
     64 /** CCMP nonce length */
     65 #define CCMP_NONCE_LEN	13
     66 
     67 /** CCMP nonce structure */
     68 struct ccmp_nonce
     69 {
     70 	u8 prio;		/**< Packet priority, 0 for non-QoS */
     71 	u8 a2[ETH_ALEN];	/**< Address 2 from packet header (sender) */
     72 	u8 pn[6];		/**< Packet number */
     73 } __attribute__ (( packed ));
     74 
     75 /** CCMP additional authentication data length (for non-QoS, non-WDS frames) */
     76 #define CCMP_AAD_LEN	22
     77 
     78 /** CCMP additional authentication data structure */
     79 struct ccmp_aad
     80 {
     81 	u16 fc;			/**< Frame Control field */
     82 	u8 a1[6];		/**< Address 1 */
     83 	u8 a2[6];		/**< Address 2 */
     84 	u8 a3[6];		/**< Address 3 */
     85 	u16 seq;		/**< Sequence Control field */
     86 	/* Address 4 and QoS Control are included if present */
     87 } __attribute__ (( packed ));
     88 
     89 /** Mask for Frame Control field in AAD */
     90 #define CCMP_AAD_FC_MASK	0xC38F
     91 
     92 /** Mask for Sequence Control field in AAD */
     93 #define CCMP_AAD_SEQ_MASK	0x000F
     94 
     95 
     96 /**
     97  * Convert 6-byte LSB packet number to 64-bit integer
     98  *
     99  * @v pn	Pointer to 6-byte packet number
    100  * @ret v	64-bit integer value of @a pn
    101  */
    102 static u64 pn_to_u64 ( const u8 *pn )
    103 {
    104 	int i;
    105 	u64 ret = 0;
    106 
    107 	for ( i = 5; i >= 0; i-- ) {
    108 		ret <<= 8;
    109 		ret |= pn[i];
    110 	}
    111 
    112 	return ret;
    113 }
    114 
    115 /**
    116  * Convert 64-bit integer to 6-byte packet number
    117  *
    118  * @v v		64-bit integer
    119  * @v msb	If TRUE, reverse the output PN to be in MSB order
    120  * @ret pn	6-byte packet number
    121  *
    122  * The PN is stored in LSB order in the packet header and in MSB order
    123  * in the nonce. WHYYYYY?
    124  */
    125 static void u64_to_pn ( u64 v, u8 *pn, int msb )
    126 {
    127 	int i;
    128 	u8 *pnp = pn + ( msb ? 5 : 0 );
    129 	int delta = ( msb ? -1 : +1 );
    130 
    131 	for ( i = 0; i < 6; i++ ) {
    132 		*pnp = v & 0xFF;
    133 		pnp += delta;
    134 		v >>= 8;
    135 	}
    136 }
    137 
    138 /** Value for @a msb argument of u64_to_pn() for MSB output */
    139 #define PN_MSB	1
    140 
    141 /** Value for @a msb argument of u64_to_pn() for LSB output */
    142 #define PN_LSB	0
    143 
    144 
    145 
    146 /**
    147  * Initialise CCMP state and install key
    148  *
    149  * @v crypto	CCMP cryptosystem structure
    150  * @v key	Pointer to 16-byte temporal key to install
    151  * @v keylen	Length of key (16 bytes)
    152  * @v rsc	Initial receive sequence counter
    153  */
    154 static int ccmp_init ( struct net80211_crypto *crypto, const void *key,
    155 		       int keylen, const void *rsc )
    156 {
    157 	struct ccmp_ctx *ctx = crypto->priv;
    158 
    159 	if ( keylen != 16 )
    160 		return -EINVAL;
    161 
    162 	if ( rsc )
    163 		ctx->rx_seq = pn_to_u64 ( rsc );
    164 
    165 	cipher_setkey ( &aes_algorithm, ctx->aes_ctx, key, keylen );
    166 
    167 	return 0;
    168 }
    169 
    170 
    171 /**
    172  * Encrypt or decrypt data stream using AES in Counter mode
    173  *
    174  * @v ctx	CCMP cryptosystem context
    175  * @v nonce	Nonce value, 13 bytes
    176  * @v srcv	Data to encrypt or decrypt
    177  * @v len	Number of bytes pointed to by @a src
    178  * @v msrcv	MIC value to encrypt or decrypt (may be NULL)
    179  * @ret destv	Encrypted or decrypted data
    180  * @ret mdestv	Encrypted or decrypted MIC value
    181  *
    182  * This assumes CCMP parameters of L=2 and M=8. The algorithm is
    183  * defined in RFC 3610.
    184  */
    185 static void ccmp_ctr_xor ( struct ccmp_ctx *ctx, const void *nonce,
    186 			   const void *srcv, void *destv, int len,
    187 			   const void *msrcv, void *mdestv )
    188 {
    189 	u8 A[16], S[16];
    190 	u16 ctr;
    191 	int i;
    192 	const u8 *src = srcv, *msrc = msrcv;
    193 	u8 *dest = destv, *mdest = mdestv;
    194 
    195 	A[0] = 0x01;		/* flags, L' = L - 1 = 1, other bits rsvd */
    196 	memcpy ( A + 1, nonce, CCMP_NONCE_LEN );
    197 
    198 	if ( msrcv ) {
    199 		A[14] = A[15] = 0;
    200 
    201 		cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, A, S, 16 );
    202 
    203 		for ( i = 0; i < 8; i++ ) {
    204 			*mdest++ = *msrc++ ^ S[i];
    205 		}
    206 	}
    207 
    208 	for ( ctr = 1 ;; ctr++ ) {
    209 		A[14] = ctr >> 8;
    210 		A[15] = ctr & 0xFF;
    211 
    212 		cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, A, S, 16 );
    213 
    214 		for ( i = 0; i < len && i < 16; i++ )
    215 			*dest++ = *src++ ^ S[i];
    216 
    217 		if ( len <= 16 )
    218 			break;	/* we're done */
    219 
    220 		len -= 16;
    221 	}
    222 }
    223 
    224 
    225 /**
    226  * Advance one block in CBC-MAC calculation
    227  *
    228  * @v aes_ctx	AES encryption context with key set
    229  * @v B		Cleartext block to incorporate (16 bytes)
    230  * @v X		Previous ciphertext block (16 bytes)
    231  * @ret B	Clobbered
    232  * @ret X	New ciphertext block (16 bytes)
    233  *
    234  * This function does X := E[key] ( X ^ B ).
    235  */
    236 static void ccmp_feed_cbc_mac ( void *aes_ctx, u8 *B, u8 *X )
    237 {
    238 	int i;
    239 	for ( i = 0; i < 16; i++ )
    240 		B[i] ^= X[i];
    241 	cipher_encrypt ( &aes_algorithm, aes_ctx, B, X, 16 );
    242 }
    243 
    244 
    245 /**
    246  * Calculate MIC on plaintext data using CBC-MAC
    247  *
    248  * @v ctx	CCMP cryptosystem context
    249  * @v nonce	Nonce value, 13 bytes
    250  * @v data	Data to calculate MIC over
    251  * @v datalen	Length of @a data
    252  * @v aad	Additional authentication data, for MIC but not encryption
    253  * @ret mic	MIC value (unencrypted), 8 bytes
    254  *
    255  * @a aadlen is assumed to be 22 bytes long, as it always is for
    256  * 802.11 use when transmitting non-QoS, not-between-APs frames (the
    257  * only type we deal with).
    258  */
    259 static void ccmp_cbc_mac ( struct ccmp_ctx *ctx, const void *nonce,
    260 			   const void *data, u16 datalen,
    261 			   const void *aad, void *mic )
    262 {
    263 	u8 X[16], B[16];
    264 
    265 	/* Zeroth block: flags, nonce, length */
    266 
    267 	/* Rsv AAD - M'-  - L'-
    268 	 *  0   1  0 1 1  0 0 1   for an 8-byte MAC and 2-byte message length
    269 	 */
    270 	B[0] = 0x59;
    271 	memcpy ( B + 1, nonce, CCMP_NONCE_LEN );
    272 	B[14] = datalen >> 8;
    273 	B[15] = datalen & 0xFF;
    274 
    275 	cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, B, X, 16 );
    276 
    277 	/* First block: AAD length field and 14 bytes of AAD */
    278 	B[0] = 0;
    279 	B[1] = CCMP_AAD_LEN;
    280 	memcpy ( B + 2, aad, 14 );
    281 
    282 	ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
    283 
    284 	/* Second block: Remaining 8 bytes of AAD, 8 bytes zero pad */
    285 	memcpy ( B, aad + 14, 8 );
    286 	memset ( B + 8, 0, 8 );
    287 
    288 	ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
    289 
    290 	/* Message blocks */
    291 	while ( datalen ) {
    292 		if ( datalen >= 16 ) {
    293 			memcpy ( B, data, 16 );
    294 			datalen -= 16;
    295 		} else {
    296 			memcpy ( B, data, datalen );
    297 			memset ( B + datalen, 0, 16 - datalen );
    298 			datalen = 0;
    299 		}
    300 
    301 		ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
    302 
    303 		data += 16;
    304 	}
    305 
    306 	/* Get MIC from final value of X */
    307 	memcpy ( mic, X, 8 );
    308 }
    309 
    310 
    311 /**
    312  * Encapsulate and encrypt a packet using CCMP
    313  *
    314  * @v crypto	CCMP cryptosystem
    315  * @v iob	I/O buffer containing cleartext packet
    316  * @ret eiob	I/O buffer containing encrypted packet
    317  */
    318 struct io_buffer * ccmp_encrypt ( struct net80211_crypto *crypto,
    319 				  struct io_buffer *iob )
    320 {
    321 	struct ccmp_ctx *ctx = crypto->priv;
    322 	struct ieee80211_frame *hdr = iob->data;
    323 	struct io_buffer *eiob;
    324 	const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
    325 	int datalen = iob_len ( iob ) - hdrlen;
    326 	struct ccmp_head head;
    327 	struct ccmp_nonce nonce;
    328 	struct ccmp_aad aad;
    329 	u8 mic[8], tx_pn[6];
    330 	void *edata, *emic;
    331 
    332 	ctx->tx_seq++;
    333 	u64_to_pn ( ctx->tx_seq, tx_pn, PN_LSB );
    334 
    335 	/* Allocate memory */
    336 	eiob = alloc_iob ( iob_len ( iob ) + CCMP_HEAD_LEN + CCMP_MIC_LEN );
    337 	if ( ! eiob )
    338 		return NULL;
    339 
    340 	/* Copy frame header */
    341 	memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
    342 	hdr = eiob->data;
    343 	hdr->fc |= IEEE80211_FC_PROTECTED;
    344 
    345 	/* Fill in packet number and extended IV */
    346 	memcpy ( head.pn_lo, tx_pn, 2 );
    347 	memcpy ( head.pn_hi, tx_pn + 2, 4 );
    348 	head.kid = 0x20;	/* have Extended IV, key ID 0 */
    349 	head._rsvd = 0;
    350 	memcpy ( iob_put ( eiob, sizeof ( head ) ), &head, sizeof ( head ) );
    351 
    352 	/* Form nonce */
    353 	nonce.prio = 0;
    354 	memcpy ( nonce.a2, hdr->addr2, ETH_ALEN );
    355 	u64_to_pn ( ctx->tx_seq, nonce.pn, PN_MSB );
    356 
    357 	/* Form additional authentication data */
    358 	aad.fc = hdr->fc & CCMP_AAD_FC_MASK;
    359 	memcpy ( aad.a1, hdr->addr1, 3 * ETH_ALEN ); /* all 3 at once */
    360 	aad.seq = hdr->seq & CCMP_AAD_SEQ_MASK;
    361 
    362 	/* Calculate MIC over the data */
    363 	ccmp_cbc_mac ( ctx, &nonce, iob->data + hdrlen, datalen, &aad, mic );
    364 
    365 	/* Copy and encrypt data and MIC */
    366 	edata = iob_put ( eiob, datalen );
    367 	emic = iob_put ( eiob, CCMP_MIC_LEN );
    368 	ccmp_ctr_xor ( ctx, &nonce,
    369 		       iob->data + hdrlen, edata, datalen,
    370 		       mic, emic );
    371 
    372 	/* Done! */
    373 	DBGC2 ( ctx, "WPA-CCMP %p: encrypted packet %p -> %p\n", ctx,
    374 		iob, eiob );
    375 
    376 	return eiob;
    377 }
    378 
    379 /**
    380  * Decrypt a packet using CCMP
    381  *
    382  * @v crypto	CCMP cryptosystem
    383  * @v eiob	I/O buffer containing encrypted packet
    384  * @ret iob	I/O buffer containing cleartext packet
    385  */
    386 static struct io_buffer * ccmp_decrypt ( struct net80211_crypto *crypto,
    387 					 struct io_buffer *eiob )
    388 {
    389 	struct ccmp_ctx *ctx = crypto->priv;
    390 	struct ieee80211_frame *hdr;
    391 	struct io_buffer *iob;
    392 	const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
    393 	int datalen = iob_len ( eiob ) - hdrlen - CCMP_HEAD_LEN - CCMP_MIC_LEN;
    394 	struct ccmp_head *head;
    395 	struct ccmp_nonce nonce;
    396 	struct ccmp_aad aad;
    397 	u8 rx_pn[6], their_mic[8], our_mic[8];
    398 
    399 	iob = alloc_iob ( hdrlen + datalen );
    400 	if ( ! iob )
    401 		return NULL;
    402 
    403 	/* Copy frame header */
    404 	memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
    405 	hdr = iob->data;
    406 	hdr->fc &= ~IEEE80211_FC_PROTECTED;
    407 
    408 	/* Check and update RX packet number */
    409 	head = eiob->data + hdrlen;
    410 	memcpy ( rx_pn, head->pn_lo, 2 );
    411 	memcpy ( rx_pn + 2, head->pn_hi, 4 );
    412 
    413 	if ( pn_to_u64 ( rx_pn ) <= ctx->rx_seq ) {
    414 		DBGC ( ctx, "WPA-CCMP %p: packet received out of order "
    415 		       "(%012llx <= %012llx)\n", ctx, pn_to_u64 ( rx_pn ),
    416 		       ctx->rx_seq );
    417 		free_iob ( iob );
    418 		return NULL;
    419 	}
    420 
    421 	ctx->rx_seq = pn_to_u64 ( rx_pn );
    422 	DBGC2 ( ctx, "WPA-CCMP %p: RX packet number %012llx\n", ctx, ctx->rx_seq );
    423 
    424 	/* Form nonce */
    425 	nonce.prio = 0;
    426 	memcpy ( nonce.a2, hdr->addr2, ETH_ALEN );
    427 	u64_to_pn ( ctx->rx_seq, nonce.pn, PN_MSB );
    428 
    429 	/* Form additional authentication data */
    430 	aad.fc = ( hdr->fc & CCMP_AAD_FC_MASK ) | IEEE80211_FC_PROTECTED;
    431 	memcpy ( aad.a1, hdr->addr1, 3 * ETH_ALEN ); /* all 3 at once */
    432 	aad.seq = hdr->seq & CCMP_AAD_SEQ_MASK;
    433 
    434 	/* Copy-decrypt data and MIC */
    435 	ccmp_ctr_xor ( ctx, &nonce, eiob->data + hdrlen + sizeof ( *head ),
    436 		       iob_put ( iob, datalen ), datalen,
    437 		       eiob->tail - CCMP_MIC_LEN, their_mic );
    438 
    439 	/* Check MIC */
    440 	ccmp_cbc_mac ( ctx, &nonce, iob->data + hdrlen, datalen, &aad,
    441 		       our_mic );
    442 
    443 	if ( memcmp ( their_mic, our_mic, CCMP_MIC_LEN ) != 0 ) {
    444 		DBGC2 ( ctx, "WPA-CCMP %p: MIC failure\n", ctx );
    445 		free_iob ( iob );
    446 		return NULL;
    447 	}
    448 
    449 	DBGC2 ( ctx, "WPA-CCMP %p: decrypted packet %p -> %p\n", ctx,
    450 		eiob, iob );
    451 
    452 	return iob;
    453 }
    454 
    455 
    456 /** CCMP cryptosystem */
    457 struct net80211_crypto ccmp_crypto __net80211_crypto = {
    458 	.algorithm = NET80211_CRYPT_CCMP,
    459 	.init = ccmp_init,
    460 	.encrypt = ccmp_encrypt,
    461 	.decrypt = ccmp_decrypt,
    462 	.priv_len = sizeof ( struct ccmp_ctx ),
    463 };
    464 
    465 
    466 
    467 
    468 /**
    469  * Calculate HMAC-SHA1 MIC for EAPOL-Key frame
    470  *
    471  * @v kck	Key Confirmation Key, 16 bytes
    472  * @v msg	Message to calculate MIC over
    473  * @v len	Number of bytes to calculate MIC over
    474  * @ret mic	Calculated MIC, 16 bytes long
    475  */
    476 static void ccmp_kie_mic ( const void *kck, const void *msg, size_t len,
    477 			   void *mic )
    478 {
    479 	u8 sha1_ctx[SHA1_CTX_SIZE];
    480 	u8 kckb[16];
    481 	u8 hash[SHA1_SIZE];
    482 	size_t kck_len = 16;
    483 
    484 	memcpy ( kckb, kck, kck_len );
    485 
    486 	hmac_init ( &sha1_algorithm, sha1_ctx, kckb, &kck_len );
    487 	hmac_update ( &sha1_algorithm, sha1_ctx, msg, len );
    488 	hmac_final ( &sha1_algorithm, sha1_ctx, kckb, &kck_len, hash );
    489 
    490 	memcpy ( mic, hash, 16 );
    491 }
    492 
    493 /**
    494  * Decrypt key data in EAPOL-Key frame
    495  *
    496  * @v kek	Key Encryption Key, 16 bytes
    497  * @v iv	Initialisation vector, 16 bytes (unused)
    498  * @v msg	Message to decrypt
    499  * @v len	Length of message
    500  * @ret msg	Decrypted message in place of original
    501  * @ret len	Adjusted downward for 8 bytes of overhead
    502  * @ret rc	Return status code
    503  *
    504  * The returned message may still contain padding of 0xDD followed by
    505  * zero or more 0x00 octets. It is impossible to remove the padding
    506  * without parsing the IEs in the packet (another design decision that
    507  * tends to make one question the 802.11i committee's intelligence...)
    508  */
    509 static int ccmp_kie_decrypt ( const void *kek, const void *iv __unused,
    510 			      void *msg, u16 *len )
    511 {
    512 	if ( *len % 8 != 0 )
    513 		return -EINVAL;
    514 
    515 	if ( aes_unwrap ( kek, msg, msg, *len / 8 - 1 ) != 0 )
    516 		return -EINVAL;
    517 
    518 	*len -= 8;
    519 
    520 	return 0;
    521 }
    522 
    523 /** CCMP-style key integrity and encryption handler */
    524 struct wpa_kie ccmp_kie __wpa_kie = {
    525 	.version = EAPOL_KEY_VERSION_WPA2,
    526 	.mic = ccmp_kie_mic,
    527 	.decrypt = ccmp_kie_decrypt,
    528 };
    529