INT AirPDcapCcmpDecrypt( UINT8 *m, gint mac_header_len, INT len, UCHAR TK1[16]) { PAIRPDCAP_MAC_FRAME wh; UINT8 aad[2 * AES_BLOCK_LEN]; UINT8 b0[AES_BLOCK_LEN], b[AES_BLOCK_LEN], a[AES_BLOCK_LEN]; UINT8 mic[AES_BLOCK_LEN]; size_t data_len; UINT i; UINT8 *pos; UINT space; INT z = mac_header_len; rijndael_ctx key; UINT64 PN; UINT8 *ivp=m+z; PN = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); /* freebsd */ rijndael_set_key(&key, TK1, 128); wh = (PAIRPDCAP_MAC_FRAME )m; data_len = len - (z + AIRPDCAP_CCMP_HEADER+AIRPDCAP_CCMP_TRAILER); if (data_len < 1) return 0; ccmp_init_blocks(&key, wh, PN, data_len, b0, aad, a, b); memcpy(mic, m+len-AIRPDCAP_CCMP_TRAILER, AIRPDCAP_CCMP_TRAILER); XOR_BLOCK(mic, b, AIRPDCAP_CCMP_TRAILER); i = 1; pos = (UINT8 *)m + z + AIRPDCAP_CCMP_HEADER; space = len - (z + AIRPDCAP_CCMP_HEADER); if (space > data_len) space = (UINT)data_len; while (space >= AES_BLOCK_LEN) { CCMP_DECRYPT(i, b, b0, pos, a, AES_BLOCK_LEN); pos += AES_BLOCK_LEN, space -= AES_BLOCK_LEN; data_len -= AES_BLOCK_LEN; i++; } if (space != 0) /* short last block */ CCMP_DECRYPT(i, b, b0, pos, a, space); /* MIC Key ?= MIC */ if (memcmp(mic, a, AIRPDCAP_CCMP_TRAILER) == 0) { return 0; } /* TODO replay check (IEEE 802.11i-2004, pg. 62) */ /* TODO PN must be incremental (IEEE 802.11i-2004, pg. 62) */ return 1; }
/* sys/net80211/ieee80211_crypto_tkip.c, 936 */ INT AirPDcapTkipDecrypt( UCHAR *tkip_mpdu, size_t mpdu_len, UCHAR TA[AIRPDCAP_MAC_LEN], UCHAR TK[AIRPDCAP_TK_LEN]) { UINT64 TSC64; UINT32 TSC; UINT16 TSC16; UINT8 *IV; UINT16 TTAK[AIRPDCAP_TTAK_LEN]; UINT8 wep_seed[AIRPDCAP_WEP_128_KEY_LEN]; /* DEBUG_DUMP("TA", TA, 6); */ IV = tkip_mpdu; TSC64 = READ_6(IV[2], IV[0], IV[4], IV[5], IV[6], IV[7]); TSC16 = (UINT16)TSC64; /* The original code made no sense!! We were shifting a 16-bit number 16 bits to the right. */ /* We instead have to have READ_6() be returned to a UINT64 and shift *that* value. */ TSC = (UINT32)(TSC64 >> 16); AirPDcapTkipMixingPhase1(TTAK, TK, TA, TSC); AirPDcapTkipMixingPhase2(wep_seed, TK, TTAK, TSC16); return AirPDcapWepDecrypt( wep_seed, AIRPDCAP_WEP_128_KEY_LEN, tkip_mpdu + AIRPDCAP_TKIP_HEADER, mpdu_len-(AIRPDCAP_TKIP_HEADER+AIRPDCAP_WEP_ICV)); /* MPDU - TKIP_HEADER - MIC */ /* TODO check (IEEE 802.11i-2004, pg. 44) */ }
IOReturn IOSCSITape::ReadWrite(IOMemoryDescriptor *dataBuffer, int *realizedBytes) { SCSITaskIdentifier task = NULL; IOReturn status = kIOReturnNoResources; SCSITaskStatus taskStatus = kSCSITaskStatus_No_Status; bool cmdStatus = false; int transferSize = 0; require((dataBuffer != 0), ErrorExit); transferSize = dataBuffer->getLength(); if (IsFixedBlockSize()) { if (transferSize % blksize) { STATUS_LOG("must be multiple of block size"); return kIOReturnNotAligned; } transferSize /= blksize; } task = GetSCSITask(); require((task != 0), ErrorExit); if (dataBuffer->getDirection() == kIODirectionIn) { cmdStatus = READ_6( task, dataBuffer, blksize, 0x0, IsFixedBlockSize() ? 0x1 : 0x0, transferSize, 0x00); } else { cmdStatus = WRITE_6( task, dataBuffer, blksize, IsFixedBlockSize() ? 0x1 : 0x0, transferSize, 0x00); flags |= ST_WRITTEN_TOGGLE; } if (cmdStatus == true) taskStatus = DoSCSICommand(task, SCSI_MOTION_TIMEOUT); *realizedBytes = GetRealizedDataTransferCount(task); if (taskStatus == kSCSITaskStatus_GOOD) status = kIOReturnSuccess; ReleaseSCSITask(task); ErrorExit: return status; }
/* * Validate and strip privacy headers (and trailer) for a * received frame. The specified key should be correct but * is also verified. */ static int ccmp_decap(struct ieee80211_key *k, wbuf_t wbuf, int hdrlen, struct ieee80211_rx_status *rs) { struct ccmp_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->cc_vap; struct ieee80211_frame *wh; uint8_t *ivp, *origHdr; u_int64_t pn; u_int8_t tid; struct ieee80211_mac_stats *mac_stats; u_int32_t hwmfp; uint8_t update_keyrsc = 1; /* * Header should have extended IV and sequence number; * verify the former and validate the latter. */ origHdr = (u_int8_t *)wbuf_header(wbuf); wh = (struct ieee80211_frame *)origHdr; mac_stats = IEEE80211_IS_MULTICAST(wh->i_addr1) ? &vap->iv_multicast_stats : &vap->iv_unicast_stats; if (IEEE80211_IS_MFP_FRAME(wh)) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s MFP frame\n", __func__); } if (rs->rs_flags & IEEE80211_RX_DECRYPT_ERROR) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s decrypt error\n", __func__); if (IEEE80211_IS_MFP_FRAME(wh)) { /* It may not be real crypto error, but hardware didn't do correct * decryption. Try software decrypt later. */ rs->rs_flags &= ~IEEE80211_RX_DECRYPT_ERROR; rs->rs_flags |= IEEE80211_RX_MIC_ERROR; } else { /* The frame already failed decryption in hardware, * just update statistics and return. */ mac_stats->ims_rx_ccmpmic++; return 0; } } ivp = origHdr + hdrlen; if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) { /* * No extended IV; discard frame. */ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, "%s", "Missing ExtIV for AES-CCM cipher"); mac_stats->ims_rx_ccmpformat++; return 0; } tid = IEEE80211_NON_QOS_SEQ; if (IEEE80211_QOS_HAS_SEQ(wh)) { if ( (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS ) { tid = ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0] & IEEE80211_QOS_TID; } else { tid = ((struct ieee80211_qosframe *)wh)->i_qos[0] & IEEE80211_QOS_TID; } } /* NB: assume IEEEE80211_WEP_MINLEN covers the extended IV */ pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); if (pn <= k->wk_keyrsc[tid]) { /* * Replay violation. */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: CCMP Replay! Throw away. new pn=0x%x%x, " "current pn=0x%x%x. seq=0x%x,Rsvd=0x%x,keyID=0x%x,tid=%d\n", __func__, (u_int32_t)(pn>>32), (u_int32_t)pn, (u_int32_t)(k->wk_keyrsc[tid] >> 32), (u_int32_t)k->wk_keyrsc[tid], *(u_int16_t*)(wh->i_seq), ivp[2], ivp[3], tid ); ieee80211_notify_replay_failure(vap, wh, k, pn); mac_stats->ims_rx_ccmpreplay++; return 0; }