aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tkip.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/tkip.c')
-rw-r--r--net/mac80211/tkip.c115
1 files changed, 66 insertions, 49 deletions
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
index 757e4eb2baf..f49d00a4c7f 100644
--- a/net/mac80211/tkip.c
+++ b/net/mac80211/tkip.c
@@ -101,6 +101,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx,
101 p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; 101 p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i;
102 } 102 }
103 ctx->state = TKIP_STATE_PHASE1_DONE; 103 ctx->state = TKIP_STATE_PHASE1_DONE;
104 ctx->p1k_iv32 = tsc_IV32;
104} 105}
105 106
106static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, 107static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
@@ -140,60 +141,80 @@ static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
140/* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets 141/* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
141 * of the IV. Returns pointer to the octet following IVs (i.e., beginning of 142 * of the IV. Returns pointer to the octet following IVs (i.e., beginning of
142 * the packet payload). */ 143 * the packet payload). */
143u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16) 144u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key)
144{ 145{
145 pos = write_tkip_iv(pos, iv16); 146 lockdep_assert_held(&key->u.tkip.txlock);
147
148 pos = write_tkip_iv(pos, key->u.tkip.tx.iv16);
146 *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; 149 *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */;
147 put_unaligned_le32(key->u.tkip.tx.iv32, pos); 150 put_unaligned_le32(key->u.tkip.tx.iv32, pos);
148 return pos + 4; 151 return pos + 4;
149} 152}
150 153
151void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, 154static void ieee80211_compute_tkip_p1k(struct ieee80211_key *key, u32 iv32)
152 struct sk_buff *skb, enum ieee80211_tkip_key_type type,
153 u8 *outkey)
154{ 155{
155 struct ieee80211_key *key = (struct ieee80211_key *) 156 struct ieee80211_sub_if_data *sdata = key->sdata;
156 container_of(keyconf, struct ieee80211_key, conf); 157 struct tkip_ctx *ctx = &key->u.tkip.tx;
157 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 158 const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
158 u8 *data;
159 const u8 *tk;
160 struct tkip_ctx *ctx;
161 u16 iv16;
162 u32 iv32;
163 159
164 data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control); 160 lockdep_assert_held(&key->u.tkip.txlock);
165 iv16 = data[2] | (data[0] << 8); 161
166 iv32 = get_unaligned_le32(&data[4]); 162 /*
163 * Update the P1K when the IV32 is different from the value it
164 * had when we last computed it (or when not initialised yet).
165 * This might flip-flop back and forth if packets are processed
166 * out-of-order due to the different ACs, but then we have to
167 * just compute the P1K more often.
168 */
169 if (ctx->p1k_iv32 != iv32 || ctx->state == TKIP_STATE_NOT_INIT)
170 tkip_mixing_phase1(tk, ctx, sdata->vif.addr, iv32);
171}
167 172
168 tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; 173void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
169 ctx = &key->u.tkip.tx; 174 u32 iv32, u16 *p1k)
175{
176 struct ieee80211_key *key = (struct ieee80211_key *)
177 container_of(keyconf, struct ieee80211_key, conf);
178 struct tkip_ctx *ctx = &key->u.tkip.tx;
179 unsigned long flags;
170 180
171#ifdef CONFIG_MAC80211_TKIP_DEBUG 181 spin_lock_irqsave(&key->u.tkip.txlock, flags);
172 printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", 182 ieee80211_compute_tkip_p1k(key, iv32);
173 iv16, iv32); 183 memcpy(p1k, ctx->p1k, sizeof(ctx->p1k));
174 184 spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
175 if (iv32 != ctx->iv32) { 185}
176 printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n", 186EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv);
177 iv32, ctx->iv32);
178 printk(KERN_DEBUG "Wrap around of iv16 in the middle of a "
179 "fragmented packet\n");
180 }
181#endif
182 187
183 /* Update the p1k only when the iv16 in the packet wraps around, this 188void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf,
184 * might occur after the wrap around of iv16 in the key in case of 189 const u8 *ta, u32 iv32, u16 *p1k)
185 * fragmented packets. */ 190{
186 if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) 191 const u8 *tk = &keyconf->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
187 tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); 192 struct tkip_ctx ctx;
188 193
189 if (type == IEEE80211_TKIP_P1_KEY) { 194 tkip_mixing_phase1(tk, &ctx, ta, iv32);
190 memcpy(outkey, ctx->p1k, sizeof(u16) * 5); 195 memcpy(p1k, ctx.p1k, sizeof(ctx.p1k));
191 return; 196}
192 } 197EXPORT_SYMBOL(ieee80211_get_tkip_rx_p1k);
193 198
194 tkip_mixing_phase2(tk, ctx, iv16, outkey); 199void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
200 struct sk_buff *skb, u8 *p2k)
201{
202 struct ieee80211_key *key = (struct ieee80211_key *)
203 container_of(keyconf, struct ieee80211_key, conf);
204 const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
205 struct tkip_ctx *ctx = &key->u.tkip.tx;
206 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
207 const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
208 u32 iv32 = get_unaligned_le32(&data[4]);
209 u16 iv16 = data[2] | (data[0] << 8);
210 unsigned long flags;
211
212 spin_lock_irqsave(&key->u.tkip.txlock, flags);
213 ieee80211_compute_tkip_p1k(key, iv32);
214 tkip_mixing_phase2(tk, ctx, iv16, p2k);
215 spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
195} 216}
196EXPORT_SYMBOL(ieee80211_get_tkip_key); 217EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
197 218
198/* 219/*
199 * Encrypt packet payload with TKIP using @key. @pos is a pointer to the 220 * Encrypt packet payload with TKIP using @key. @pos is a pointer to the
@@ -204,19 +225,15 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key);
204 */ 225 */
205int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, 226int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
206 struct ieee80211_key *key, 227 struct ieee80211_key *key,
207 u8 *pos, size_t payload_len, u8 *ta) 228 struct sk_buff *skb,
229 u8 *payload, size_t payload_len)
208{ 230{
209 u8 rc4key[16]; 231 u8 rc4key[16];
210 struct tkip_ctx *ctx = &key->u.tkip.tx;
211 const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
212
213 /* Calculate per-packet key */
214 if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
215 tkip_mixing_phase1(tk, ctx, ta, ctx->iv32);
216 232
217 tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); 233 ieee80211_get_tkip_p2k(&key->conf, skb, rc4key);
218 234
219 return ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); 235 return ieee80211_wep_encrypt_data(tfm, rc4key, 16,
236 payload, payload_len);
220} 237}
221 238
222/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the 239/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the