00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <gpxe/net80211.h>
00022 #include <gpxe/crypto.h>
00023 #include <gpxe/hmac.h>
00024 #include <gpxe/sha1.h>
00025 #include <gpxe/aes.h>
00026 #include <gpxe/wpa.h>
00027 #include <byteswap.h>
00028 #include <errno.h>
00029
00030
00031
00032
00033
00034
00035
00036 struct ccmp_ctx
00037 {
00038
00039 u8 aes_ctx[AES_CTX_SIZE];
00040
00041
00042 u64 tx_seq;
00043
00044
00045 u64 rx_seq;
00046 };
00047
00048
00049 struct ccmp_head
00050 {
00051 u8 pn_lo[2];
00052 u8 _rsvd;
00053 u8 kid;
00054 u8 pn_hi[4];
00055 } __attribute__ (( packed ));
00056
00057
00058
00059 #define CCMP_HEAD_LEN 8
00060
00061
00062 #define CCMP_MIC_LEN 8
00063
00064
00065 #define CCMP_NONCE_LEN 13
00066
00067
00068 struct ccmp_nonce
00069 {
00070 u8 prio;
00071 u8 a2[ETH_ALEN];
00072 u8 pn[6];
00073 } __attribute__ (( packed ));
00074
00075
00076 #define CCMP_AAD_LEN 22
00077
00078
00079 struct ccmp_aad
00080 {
00081 u16 fc;
00082 u8 a1[6];
00083 u8 a2[6];
00084 u8 a3[6];
00085 u16 seq;
00086
00087 } __attribute__ (( packed ));
00088
00089
00090 #define CCMP_AAD_FC_MASK 0xC38F
00091
00092
00093 #define CCMP_AAD_SEQ_MASK 0x000F
00094
00095
00096
00097
00098
00099
00100
00101
00102 static u64 pn_to_u64 ( const u8 *pn )
00103 {
00104 int i;
00105 u64 ret = 0;
00106
00107 for ( i = 5; i >= 0; i-- ) {
00108 ret <<= 8;
00109 ret |= pn[i];
00110 }
00111
00112 return ret;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 static void u64_to_pn ( u64 v, u8 *pn, int msb )
00126 {
00127 int i;
00128 u8 *pnp = pn + ( msb ? 5 : 0 );
00129 int delta = ( msb ? -1 : +1 );
00130
00131 for ( i = 0; i < 6; i++ ) {
00132 *pnp = v & 0xFF;
00133 pnp += delta;
00134 v >>= 8;
00135 }
00136 }
00137
00138
00139 #define PN_MSB 1
00140
00141
00142 #define PN_LSB 0
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static int ccmp_init ( struct net80211_crypto *crypto, const void *key,
00155 int keylen, const void *rsc )
00156 {
00157 struct ccmp_ctx *ctx = crypto->priv;
00158
00159 if ( keylen != 16 )
00160 return -EINVAL;
00161
00162 if ( rsc )
00163 ctx->rx_seq = pn_to_u64 ( rsc );
00164
00165 cipher_setkey ( &aes_algorithm, ctx->aes_ctx, key, keylen );
00166
00167 return 0;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 static void ccmp_ctr_xor ( struct ccmp_ctx *ctx, const void *nonce,
00186 const void *srcv, void *destv, int len,
00187 const void *msrcv, void *mdestv )
00188 {
00189 u8 A[16], S[16];
00190 u16 ctr;
00191 int i;
00192 const u8 *src = srcv, *msrc = msrcv;
00193 u8 *dest = destv, *mdest = mdestv;
00194
00195 A[0] = 0x01;
00196 memcpy ( A + 1, nonce, CCMP_NONCE_LEN );
00197
00198 if ( msrcv ) {
00199 A[14] = A[15] = 0;
00200
00201 cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, A, S, 16 );
00202
00203 for ( i = 0; i < 8; i++ ) {
00204 *mdest++ = *msrc++ ^ S[i];
00205 }
00206 }
00207
00208 for ( ctr = 1 ;; ctr++ ) {
00209 A[14] = ctr >> 8;
00210 A[15] = ctr & 0xFF;
00211
00212 cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, A, S, 16 );
00213
00214 for ( i = 0; i < len && i < 16; i++ )
00215 *dest++ = *src++ ^ S[i];
00216
00217 if ( len <= 16 )
00218 break;
00219
00220 len -= 16;
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 static void ccmp_feed_cbc_mac ( void *aes_ctx, u8 *B, u8 *X )
00237 {
00238 int i;
00239 for ( i = 0; i < 16; i++ )
00240 B[i] ^= X[i];
00241 cipher_encrypt ( &aes_algorithm, aes_ctx, B, X, 16 );
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 static void ccmp_cbc_mac ( struct ccmp_ctx *ctx, const void *nonce,
00260 const void *data, u16 datalen,
00261 const void *aad, void *mic )
00262 {
00263 u8 X[16], B[16];
00264
00265
00266
00267
00268
00269
00270 B[0] = 0x59;
00271 memcpy ( B + 1, nonce, CCMP_NONCE_LEN );
00272 B[14] = datalen >> 8;
00273 B[15] = datalen & 0xFF;
00274
00275 cipher_encrypt ( &aes_algorithm, ctx->aes_ctx, B, X, 16 );
00276
00277
00278 B[0] = 0;
00279 B[1] = CCMP_AAD_LEN;
00280 memcpy ( B + 2, aad, 14 );
00281
00282 ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
00283
00284
00285 memcpy ( B, aad + 14, 8 );
00286 memset ( B + 8, 0, 8 );
00287
00288 ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
00289
00290
00291 while ( datalen ) {
00292 if ( datalen >= 16 ) {
00293 memcpy ( B, data, 16 );
00294 datalen -= 16;
00295 } else {
00296 memcpy ( B, data, datalen );
00297 memset ( B + datalen, 0, 16 - datalen );
00298 datalen = 0;
00299 }
00300
00301 ccmp_feed_cbc_mac ( ctx->aes_ctx, B, X );
00302
00303 data += 16;
00304 }
00305
00306
00307 memcpy ( mic, X, 8 );
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 struct io_buffer * ccmp_encrypt ( struct net80211_crypto *crypto,
00319 struct io_buffer *iob )
00320 {
00321 struct ccmp_ctx *ctx = crypto->priv;
00322 struct ieee80211_frame *hdr = iob->data;
00323 struct io_buffer *eiob;
00324 const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
00325 int datalen = iob_len ( iob ) - hdrlen;
00326 struct ccmp_head head;
00327 struct ccmp_nonce nonce;
00328 struct ccmp_aad aad;
00329 u8 mic[8], tx_pn[6];
00330 void *edata, *emic;
00331
00332 ctx->tx_seq++;
00333 u64_to_pn ( ctx->tx_seq, tx_pn, PN_LSB );
00334
00335
00336 eiob = alloc_iob ( iob_len ( iob ) + CCMP_HEAD_LEN + CCMP_MIC_LEN );
00337 if ( ! eiob )
00338 return NULL;
00339
00340
00341 memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
00342 hdr = eiob->data;
00343 hdr->fc |= IEEE80211_FC_PROTECTED;
00344
00345
00346 memcpy ( head.pn_lo, tx_pn, 2 );
00347 memcpy ( head.pn_hi, tx_pn + 2, 4 );
00348 head.kid = 0x20;
00349 head._rsvd = 0;
00350 memcpy ( iob_put ( eiob, sizeof ( head ) ), &head, sizeof ( head ) );
00351
00352
00353 nonce.prio = 0;
00354 memcpy ( nonce.a2, hdr->addr2, ETH_ALEN );
00355 u64_to_pn ( ctx->tx_seq, nonce.pn, PN_MSB );
00356
00357
00358 aad.fc = hdr->fc & CCMP_AAD_FC_MASK;
00359 memcpy ( aad.a1, hdr->addr1, 3 * ETH_ALEN );
00360 aad.seq = hdr->seq & CCMP_AAD_SEQ_MASK;
00361
00362
00363 ccmp_cbc_mac ( ctx, &nonce, iob->data + hdrlen, datalen, &aad, mic );
00364
00365
00366 edata = iob_put ( eiob, datalen );
00367 emic = iob_put ( eiob, CCMP_MIC_LEN );
00368 ccmp_ctr_xor ( ctx, &nonce,
00369 iob->data + hdrlen, edata, datalen,
00370 mic, emic );
00371
00372
00373 DBGC2 ( ctx, "WPA-CCMP %p: encrypted packet %p -> %p\n", ctx,
00374 iob, eiob );
00375
00376 return eiob;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386 static struct io_buffer * ccmp_decrypt ( struct net80211_crypto *crypto,
00387 struct io_buffer *eiob )
00388 {
00389 struct ccmp_ctx *ctx = crypto->priv;
00390 struct ieee80211_frame *hdr;
00391 struct io_buffer *iob;
00392 const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
00393 int datalen = iob_len ( eiob ) - hdrlen - CCMP_HEAD_LEN - CCMP_MIC_LEN;
00394 struct ccmp_head *head;
00395 struct ccmp_nonce nonce;
00396 struct ccmp_aad aad;
00397 u8 rx_pn[6], their_mic[8], our_mic[8];
00398
00399 iob = alloc_iob ( hdrlen + datalen );
00400 if ( ! iob )
00401 return NULL;
00402
00403
00404 memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
00405 hdr = iob->data;
00406 hdr->fc &= ~IEEE80211_FC_PROTECTED;
00407
00408
00409 head = eiob->data + hdrlen;
00410 memcpy ( rx_pn, head->pn_lo, 2 );
00411 memcpy ( rx_pn + 2, head->pn_hi, 4 );
00412
00413 if ( pn_to_u64 ( rx_pn ) <= ctx->rx_seq ) {
00414 DBGC ( ctx, "WPA-CCMP %p: packet received out of order "
00415 "(%012llx <= %012llx)\n", ctx, pn_to_u64 ( rx_pn ),
00416 ctx->rx_seq );
00417 free_iob ( iob );
00418 return NULL;
00419 }
00420
00421 ctx->rx_seq = pn_to_u64 ( rx_pn );
00422 DBGC2 ( ctx, "WPA-CCMP %p: RX packet number %012llx\n", ctx, ctx->rx_seq );
00423
00424
00425 nonce.prio = 0;
00426 memcpy ( nonce.a2, hdr->addr2, ETH_ALEN );
00427 u64_to_pn ( ctx->rx_seq, nonce.pn, PN_MSB );
00428
00429
00430 aad.fc = ( hdr->fc & CCMP_AAD_FC_MASK ) | IEEE80211_FC_PROTECTED;
00431 memcpy ( aad.a1, hdr->addr1, 3 * ETH_ALEN );
00432 aad.seq = hdr->seq & CCMP_AAD_SEQ_MASK;
00433
00434
00435 ccmp_ctr_xor ( ctx, &nonce, eiob->data + hdrlen + sizeof ( *head ),
00436 iob_put ( iob, datalen ), datalen,
00437 eiob->tail - CCMP_MIC_LEN, their_mic );
00438
00439
00440 ccmp_cbc_mac ( ctx, &nonce, iob->data + hdrlen, datalen, &aad,
00441 our_mic );
00442
00443 if ( memcmp ( their_mic, our_mic, CCMP_MIC_LEN ) != 0 ) {
00444 DBGC2 ( ctx, "WPA-CCMP %p: MIC failure\n", ctx );
00445 free_iob ( iob );
00446 return NULL;
00447 }
00448
00449 DBGC2 ( ctx, "WPA-CCMP %p: decrypted packet %p -> %p\n", ctx,
00450 eiob, iob );
00451
00452 return iob;
00453 }
00454
00455
00456
00457 struct net80211_crypto ccmp_crypto __net80211_crypto = {
00458 .algorithm = NET80211_CRYPT_CCMP,
00459 .init = ccmp_init,
00460 .encrypt = ccmp_encrypt,
00461 .decrypt = ccmp_decrypt,
00462 .priv_len = sizeof ( struct ccmp_ctx ),
00463 };
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 static void ccmp_kie_mic ( const void *kck, const void *msg, size_t len,
00477 void *mic )
00478 {
00479 u8 sha1_ctx[SHA1_CTX_SIZE];
00480 u8 kckb[16];
00481 u8 hash[SHA1_SIZE];
00482 size_t kck_len = 16;
00483
00484 memcpy ( kckb, kck, kck_len );
00485
00486 hmac_init ( &sha1_algorithm, sha1_ctx, kckb, &kck_len );
00487 hmac_update ( &sha1_algorithm, sha1_ctx, msg, len );
00488 hmac_final ( &sha1_algorithm, sha1_ctx, kckb, &kck_len, hash );
00489
00490 memcpy ( mic, hash, 16 );
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 static int ccmp_kie_decrypt ( const void *kek, const void *iv __unused,
00510 void *msg, u16 *len )
00511 {
00512 if ( *len % 8 != 0 )
00513 return -EINVAL;
00514
00515 if ( aes_unwrap ( kek, msg, msg, *len / 8 - 1 ) != 0 )
00516 return -EINVAL;
00517
00518 *len -= 8;
00519
00520 return 0;
00521 }
00522
00523
00524 struct wpa_kie ccmp_kie __wpa_kie = {
00525 .version = EAPOL_KEY_VERSION_WPA2,
00526 .mic = ccmp_kie_mic,
00527 .decrypt = ccmp_kie_decrypt,
00528 };