// SPDX-License-Identifier: GPL-2.0-only /* * Copyright 2002-2004, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. * Copyright (C) 2016 Intel Deutschland GmbH */ #include #include #include #include #include #include "driver-ops.h" #include "key.h" #include "tkip.h" #include "wep.h" #define PHASE1_LOOP_COUNT 8 /* * 2-byte by 2-byte subset of the full AES S-box table; second part of this * table is identical to first part but byte-swapped */ static u8 *write_tkip_iv(u8 *pos, u16 iv16) { *pos++ = iv16 >> 8; *pos++ = ((iv16 >> 8) | 0x20) & 0x7f; *pos++ = iv16 & 0xFF; return pos; } /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets * of the IV. Returns pointer to the octet following IVs (i.e., beginning of * the packet payload). */ u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key_conf *keyconf, u64 pn) { pos = write_tkip_iv(pos, TKIP_PN_TO_IV16(pn)); *pos++ = (keyconf->keyidx << 6) | (1 << 5) /* Ext IV */; put_unaligned_le32(TKIP_PN_TO_IV32(pn), pos); return pos + 4; } EXPORT_SYMBOL_GPL(ieee80211_tkip_add_iv); /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the * beginning of the buffer containing IEEE 802.11 header payload, i.e., * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the * length of payload, including IV, Ext. IV, MIC, ICV. */ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, u8 *ra, int only_iv, int queue, u32 *out_iv32, u16 *out_iv16) { u32 iv32; u32 iv16; u8 rc4key[16], keyid, *pos = payload; int res; const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; struct tkip_ctx_rx *rx_ctx = &key->u.tkip.rx[queue]; if (payload_len < 12) return -1; iv16 = (pos[0] << 8) | pos[2]; keyid = pos[3]; iv32 = get_unaligned_le32(pos + 4); pos += 8; if (!(keyid & (1 << 5))) return TKIP_DECRYPT_NO_EXT_IV; if ((keyid >> 6) != key->conf.keyidx) return TKIP_DECRYPT_INVALID_KEYIDX; if (rx_ctx->ctx.state != TKIP_STATE_NOT_INIT && (iv32 < rx_ctx->iv32 || (iv32 == rx_ctx->iv32 && iv16 <= rx_ctx->iv16))) return TKIP_DECRYPT_REPLAY; if (only_iv) { res = TKIP_DECRYPT_OK; rx_ctx->ctx.state = TKIP_STATE_PHASE1_HW_UPLOADED; goto done; } done: if (res == TKIP_DECRYPT_OK) { /* * Record previously received IV, will be copied into the * key information after MIC verification. It is possible * that we don't catch replays of fragments but that's ok * because the Michael MIC verication will then fail. */ *out_iv32 = iv32; *out_iv16 = iv16; } return res; }