~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/mac80211/wpa.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /net/mac80211/wpa.c (Version linux-6.12-rc7) and /net/mac80211/wpa.c (Version linux-2.4.37.11)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 /*                                                
  3  * Copyright 2002-2004, Instant802 Networks, I    
  4  * Copyright 2008, Jouni Malinen <j@w1.fi>        
  5  * Copyright (C) 2016-2017 Intel Deutschland G    
  6  * Copyright (C) 2020-2023 Intel Corporation      
  7  */                                               
  8                                                   
  9 #include <linux/netdevice.h>                      
 10 #include <linux/types.h>                          
 11 #include <linux/skbuff.h>                         
 12 #include <linux/compiler.h>                       
 13 #include <linux/ieee80211.h>                      
 14 #include <linux/gfp.h>                            
 15 #include <linux/unaligned.h>                      
 16 #include <net/mac80211.h>                         
 17 #include <crypto/aes.h>                           
 18 #include <crypto/utils.h>                         
 19                                                   
 20 #include "ieee80211_i.h"                          
 21 #include "michael.h"                              
 22 #include "tkip.h"                                 
 23 #include "aes_ccm.h"                              
 24 #include "aes_cmac.h"                             
 25 #include "aes_gmac.h"                             
 26 #include "aes_gcm.h"                              
 27 #include "wpa.h"                                  
 28                                                   
 29 ieee80211_tx_result                               
 30 ieee80211_tx_h_michael_mic_add(struct ieee8021    
 31 {                                                 
 32         u8 *data, *key, *mic;                     
 33         size_t data_len;                          
 34         unsigned int hdrlen;                      
 35         struct ieee80211_hdr *hdr;                
 36         struct sk_buff *skb = tx->skb;            
 37         struct ieee80211_tx_info *info = IEEE8    
 38         int tail;                                 
 39                                                   
 40         hdr = (struct ieee80211_hdr *)skb->dat    
 41         if (!tx->key || tx->key->conf.cipher !    
 42             skb->len < 24 || !ieee80211_is_dat    
 43                 return TX_CONTINUE;               
 44                                                   
 45         hdrlen = ieee80211_hdrlen(hdr->frame_c    
 46         if (skb->len < hdrlen)                    
 47                 return TX_DROP;                   
 48                                                   
 49         data = skb->data + hdrlen;                
 50         data_len = skb->len - hdrlen;             
 51                                                   
 52         if (unlikely(info->flags & IEEE80211_T    
 53                 /* Need to use software crypto    
 54                 info->control.hw_key = NULL;      
 55         }                                         
 56                                                   
 57         if (info->control.hw_key &&               
 58             (info->flags & IEEE80211_TX_CTL_DO    
 59              ieee80211_hw_check(&tx->local->hw    
 60             !(tx->key->conf.flags & (IEEE80211    
 61                                      IEEE80211    
 62                 /* hwaccel - with no need for     
 63                 return TX_CONTINUE;               
 64         }                                         
 65                                                   
 66         tail = MICHAEL_MIC_LEN;                   
 67         if (!info->control.hw_key)                
 68                 tail += IEEE80211_TKIP_ICV_LEN    
 69                                                   
 70         if (WARN(skb_tailroom(skb) < tail ||      
 71                  skb_headroom(skb) < IEEE80211    
 72                  "mmic: not enough head/tail (    
 73                  skb_headroom(skb), IEEE80211_    
 74                  skb_tailroom(skb), tail))        
 75                 return TX_DROP;                   
 76                                                   
 77         mic = skb_put(skb, MICHAEL_MIC_LEN);      
 78                                                   
 79         if (tx->key->conf.flags & IEEE80211_KE    
 80                 /* Zeroed MIC can help with de    
 81                 memset(mic, 0, MICHAEL_MIC_LEN    
 82                 return TX_CONTINUE;               
 83         }                                         
 84                                                   
 85         key = &tx->key->conf.key[NL80211_TKIP_    
 86         michael_mic(key, hdr, data, data_len,     
 87         if (unlikely(info->flags & IEEE80211_T    
 88                 mic[0]++;                         
 89                                                   
 90         return TX_CONTINUE;                       
 91 }                                                 
 92                                                   
 93                                                   
 94 ieee80211_rx_result                               
 95 ieee80211_rx_h_michael_mic_verify(struct ieee8    
 96 {                                                 
 97         u8 *data, *key = NULL;                    
 98         size_t data_len;                          
 99         unsigned int hdrlen;                      
100         u8 mic[MICHAEL_MIC_LEN];                  
101         struct sk_buff *skb = rx->skb;            
102         struct ieee80211_rx_status *status = I    
103         struct ieee80211_hdr *hdr = (struct ie    
104                                                   
105         /*                                        
106          * it makes no sense to check for MIC     
107          * than data frames.                      
108          */                                       
109         if (!ieee80211_is_data_present(hdr->fr    
110                 return RX_CONTINUE;               
111                                                   
112         /*                                        
113          * No way to verify the MIC if the har    
114          * the IV with the key index. In this     
115          * on the driver to set RX_FLAG_MMIC_E    
116          * MIC failure report.                    
117          */                                       
118         if (status->flag & (RX_FLAG_MMIC_STRIP    
119                 if (status->flag & RX_FLAG_MMI    
120                         goto mic_fail_no_key;     
121                                                   
122                 if (!(status->flag & RX_FLAG_I    
123                     rx->key->conf.cipher == WL    
124                         goto update_iv;           
125                                                   
126                 return RX_CONTINUE;               
127         }                                         
128                                                   
129         /*                                        
130          * Some hardware seems to generate Mic    
131          * though, the frame was not encrypted    
132          * MIC. Ignore the flag them to avoid     
133          */                                       
134         if (!rx->key || rx->key->conf.cipher !    
135             !(status->flag & RX_FLAG_DECRYPTED    
136                 return RX_CONTINUE;               
137                                                   
138         if (rx->sdata->vif.type == NL80211_IFT    
139                 /*                                
140                  * APs with pairwise keys shou    
141                  * errors for non-zero keyidx     
142                  * group keys and only the AP     
143                  * frames in the BSS.             
144                  */                               
145                 return RX_DROP_U_AP_RX_GROUPCA    
146         }                                         
147                                                   
148         if (status->flag & RX_FLAG_MMIC_ERROR)    
149                 goto mic_fail;                    
150                                                   
151         hdrlen = ieee80211_hdrlen(hdr->frame_c    
152         if (skb->len < hdrlen + MICHAEL_MIC_LE    
153                 return RX_DROP_U_SHORT_MMIC;      
154                                                   
155         if (skb_linearize(rx->skb))               
156                 return RX_DROP_U_OOM;             
157         hdr = (void *)skb->data;                  
158                                                   
159         data = skb->data + hdrlen;                
160         data_len = skb->len - hdrlen - MICHAEL    
161         key = &rx->key->conf.key[NL80211_TKIP_    
162         michael_mic(key, hdr, data, data_len,     
163         if (crypto_memneq(mic, data + data_len    
164                 goto mic_fail;                    
165                                                   
166         /* remove Michael MIC from payload */     
167         skb_trim(skb, skb->len - MICHAEL_MIC_L    
168                                                   
169 update_iv:                                        
170         /* update IV in key information to be     
171         rx->key->u.tkip.rx[rx->security_idx].i    
172         rx->key->u.tkip.rx[rx->security_idx].i    
173                                                   
174         return RX_CONTINUE;                       
175                                                   
176 mic_fail:                                         
177         rx->key->u.tkip.mic_failures++;           
178                                                   
179 mic_fail_no_key:                                  
180         /*                                        
181          * In some cases the key can be unset     
182          * a driver that supports HW encryptio    
183          * the key is set.                        
184          */                                       
185         cfg80211_michael_mic_failure(rx->sdata    
186                                      is_multic    
187                                      NL80211_K    
188                                      NL80211_K    
189                                      rx->key ?    
190                                      NULL, GFP    
191         return RX_DROP_U_MMIC_FAIL;               
192 }                                                 
193                                                   
194 static int tkip_encrypt_skb(struct ieee80211_t    
195 {                                                 
196         struct ieee80211_hdr *hdr = (struct ie    
197         struct ieee80211_key *key = tx->key;      
198         struct ieee80211_tx_info *info = IEEE8    
199         unsigned int hdrlen;                      
200         int len, tail;                            
201         u64 pn;                                   
202         u8 *pos;                                  
203                                                   
204         if (info->control.hw_key &&               
205             !(info->control.hw_key->flags & IE    
206             !(info->control.hw_key->flags & IE    
207                 /* hwaccel - with no need for     
208                 return 0;                         
209         }                                         
210                                                   
211         hdrlen = ieee80211_hdrlen(hdr->frame_c    
212         len = skb->len - hdrlen;                  
213                                                   
214         if (info->control.hw_key)                 
215                 tail = 0;                         
216         else                                      
217                 tail = IEEE80211_TKIP_ICV_LEN;    
218                                                   
219         if (WARN_ON(skb_tailroom(skb) < tail |    
220                     skb_headroom(skb) < IEEE80    
221                 return -1;                        
222                                                   
223         pos = skb_push(skb, IEEE80211_TKIP_IV_    
224         memmove(pos, pos + IEEE80211_TKIP_IV_L    
225         pos += hdrlen;                            
226                                                   
227         /* the HW only needs room for the IV,     
228         if (info->control.hw_key &&               
229             (info->control.hw_key->flags & IEE    
230                 return 0;                         
231                                                   
232         /* Increase IV for the frame */           
233         pn = atomic64_inc_return(&key->conf.tx    
234         pos = ieee80211_tkip_add_iv(pos, &key-    
235                                                   
236         /* hwaccel - with software IV */          
237         if (info->control.hw_key)                 
238                 return 0;                         
239                                                   
240         /* Add room for ICV */                    
241         skb_put(skb, IEEE80211_TKIP_ICV_LEN);     
242                                                   
243         return ieee80211_tkip_encrypt_data(&tx    
244                                            key    
245 }                                                 
246                                                   
247                                                   
248 ieee80211_tx_result                               
249 ieee80211_crypto_tkip_encrypt(struct ieee80211    
250 {                                                 
251         struct sk_buff *skb;                      
252                                                   
253         ieee80211_tx_set_protected(tx);           
254                                                   
255         skb_queue_walk(&tx->skbs, skb) {          
256                 if (tkip_encrypt_skb(tx, skb)     
257                         return TX_DROP;           
258         }                                         
259                                                   
260         return TX_CONTINUE;                       
261 }                                                 
262                                                   
263                                                   
264 ieee80211_rx_result                               
265 ieee80211_crypto_tkip_decrypt(struct ieee80211    
266 {                                                 
267         struct ieee80211_hdr *hdr = (struct ie    
268         int hdrlen, res, hwaccel = 0;             
269         struct ieee80211_key *key = rx->key;      
270         struct sk_buff *skb = rx->skb;            
271         struct ieee80211_rx_status *status = I    
272                                                   
273         hdrlen = ieee80211_hdrlen(hdr->frame_c    
274                                                   
275         if (!ieee80211_is_data(hdr->frame_cont    
276                 return RX_CONTINUE;               
277                                                   
278         if (!rx->sta || skb->len - hdrlen < 12    
279                 return RX_DROP_U_SHORT_TKIP;      
280                                                   
281         /* it may be possible to optimize this    
282         if (skb_linearize(rx->skb))               
283                 return RX_DROP_U_OOM;             
284         hdr = (void *)skb->data;                  
285                                                   
286         /*                                        
287          * Let TKIP code verify IV, but skip d    
288          * In the case where hardware checks t    
289          * we don't even get here, see ieee802    
290          */                                       
291         if (status->flag & RX_FLAG_DECRYPTED)     
292                 hwaccel = 1;                      
293                                                   
294         res = ieee80211_tkip_decrypt_data(&rx-    
295                                           key,    
296                                           skb-    
297                                           hdr-    
298                                           &rx-    
299                                           &rx-    
300         if (res != TKIP_DECRYPT_OK)               
301                 return RX_DROP_U_TKIP_FAIL;       
302                                                   
303         /* Trim ICV */                            
304         if (!(status->flag & RX_FLAG_ICV_STRIP    
305                 skb_trim(skb, skb->len - IEEE8    
306                                                   
307         /* Remove IV */                           
308         memmove(skb->data + IEEE80211_TKIP_IV_    
309         skb_pull(skb, IEEE80211_TKIP_IV_LEN);     
310                                                   
311         return RX_CONTINUE;                       
312 }                                                 
313                                                   
314 /*                                                
315  * Calculate AAD for CCMP/GCMP, returning qos_    
316  * need that in CCMP also for b_0.                
317  */                                               
318 static u8 ccmp_gcmp_aad(struct sk_buff *skb, u    
319 {                                                 
320         struct ieee80211_hdr *hdr = (void *)sk    
321         __le16 mask_fc;                           
322         int a4_included, mgmt;                    
323         u8 qos_tid;                               
324         u16 len_a = 22;                           
325                                                   
326         /*                                        
327          * Mask FC: zero subtype b4 b5 b6 (if     
328          * Retry, PwrMgt, MoreData, Order (if     
329          */                                       
330         mgmt = ieee80211_is_mgmt(hdr->frame_co    
331         mask_fc = hdr->frame_control;             
332         mask_fc &= ~cpu_to_le16(IEEE80211_FCTL    
333                                 IEEE80211_FCTL    
334         if (!mgmt)                                
335                 mask_fc &= ~cpu_to_le16(0x0070    
336         mask_fc |= cpu_to_le16(IEEE80211_FCTL_    
337                                                   
338         a4_included = ieee80211_has_a4(hdr->fr    
339         if (a4_included)                          
340                 len_a += 6;                       
341                                                   
342         if (ieee80211_is_data_qos(hdr->frame_c    
343                 qos_tid = *ieee80211_get_qos_c    
344                                                   
345                 if (spp_amsdu)                    
346                         qos_tid &= IEEE80211_Q    
347                                    IEEE80211_Q    
348                 else                              
349                         qos_tid &= IEEE80211_Q    
350                                                   
351                 mask_fc &= ~cpu_to_le16(IEEE80    
352                 len_a += 2;                       
353         } else {                                  
354                 qos_tid = 0;                      
355         }                                         
356                                                   
357         /* AAD (extra authenticate-only data)     
358          * FC | A1 | A2 | A3 | SC | [A4] | [QC    
359         put_unaligned_be16(len_a, &aad[0]);       
360         put_unaligned(mask_fc, (__le16 *)&aad[    
361         memcpy(&aad[4], &hdr->addrs, 3 * ETH_A    
362                                                   
363         /* Mask Seq#, leave Frag# */              
364         aad[22] = *((u8 *) &hdr->seq_ctrl) & 0    
365         aad[23] = 0;                              
366                                                   
367         if (a4_included) {                        
368                 memcpy(&aad[24], hdr->addr4, E    
369                 aad[30] = qos_tid;                
370                 aad[31] = 0;                      
371         } else {                                  
372                 memset(&aad[24], 0, ETH_ALEN +    
373                 aad[24] = qos_tid;                
374         }                                         
375                                                   
376         return qos_tid;                           
377 }                                                 
378                                                   
379 static void ccmp_special_blocks(struct sk_buff    
380                                 bool spp_amsdu    
381 {                                                 
382         struct ieee80211_hdr *hdr = (struct ie    
383         u8 qos_tid = ccmp_gcmp_aad(skb, aad, s    
384                                                   
385         /* In CCM, the initial vectors (IV) us    
386          * mode authentication are not allowed    
387          * from this vector b_0. We only set L    
388          * data size can be represented in (L+    
389          * care of storing the data length in     
390          * and clearing the other bits as is r    
391          */                                       
392         b_0[0] = 0x1;                             
393                                                   
394         /* Nonce: Nonce Flags | A2 | PN           
395          * Nonce Flags: Priority (b0..b3) | Ma    
396          */                                       
397         b_0[1] = qos_tid | (ieee80211_is_mgmt(    
398         memcpy(&b_0[2], hdr->addr2, ETH_ALEN);    
399         memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_    
400 }                                                 
401                                                   
402 static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn    
403 {                                                 
404         hdr[0] = pn[5];                           
405         hdr[1] = pn[4];                           
406         hdr[2] = 0;                               
407         hdr[3] = 0x20 | (key_id << 6);            
408         hdr[4] = pn[3];                           
409         hdr[5] = pn[2];                           
410         hdr[6] = pn[1];                           
411         hdr[7] = pn[0];                           
412 }                                                 
413                                                   
414                                                   
415 static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr    
416 {                                                 
417         pn[0] = hdr[7];                           
418         pn[1] = hdr[6];                           
419         pn[2] = hdr[5];                           
420         pn[3] = hdr[4];                           
421         pn[4] = hdr[1];                           
422         pn[5] = hdr[0];                           
423 }                                                 
424                                                   
425                                                   
426 static int ccmp_encrypt_skb(struct ieee80211_t    
427                             unsigned int mic_l    
428 {                                                 
429         struct ieee80211_hdr *hdr = (struct ie    
430         struct ieee80211_key *key = tx->key;      
431         struct ieee80211_tx_info *info = IEEE8    
432         int hdrlen, len, tail;                    
433         u8 *pos;                                  
434         u8 pn[6];                                 
435         u64 pn64;                                 
436         u8 aad[CCM_AAD_LEN];                      
437         u8 b_0[AES_BLOCK_SIZE];                   
438                                                   
439         if (info->control.hw_key &&               
440             !(info->control.hw_key->flags & IE    
441             !(info->control.hw_key->flags & IE    
442             !((info->control.hw_key->flags &      
443                IEEE80211_KEY_FLAG_GENERATE_IV_    
444               ieee80211_is_mgmt(hdr->frame_con    
445                 /*                                
446                  * hwaccel has no need for pre    
447                  * header or MIC fields           
448                  */                               
449                 return 0;                         
450         }                                         
451                                                   
452         hdrlen = ieee80211_hdrlen(hdr->frame_c    
453         len = skb->len - hdrlen;                  
454                                                   
455         if (info->control.hw_key)                 
456                 tail = 0;                         
457         else                                      
458                 tail = mic_len;                   
459                                                   
460         if (WARN_ON(skb_tailroom(skb) < tail |    
461                     skb_headroom(skb) < IEEE80    
462                 return -1;                        
463                                                   
464         pos = skb_push(skb, IEEE80211_CCMP_HDR    
465         memmove(pos, pos + IEEE80211_CCMP_HDR_    
466                                                   
467         /* the HW only needs room for the IV,     
468         if (info->control.hw_key &&               
469             (info->control.hw_key->flags & IEE    
470                 return 0;                         
471                                                   
472         pos += hdrlen;                            
473                                                   
474         pn64 = atomic64_inc_return(&key->conf.    
475                                                   
476         pn[5] = pn64;                             
477         pn[4] = pn64 >> 8;                        
478         pn[3] = pn64 >> 16;                       
479         pn[2] = pn64 >> 24;                       
480         pn[1] = pn64 >> 32;                       
481         pn[0] = pn64 >> 40;                       
482                                                   
483         ccmp_pn2hdr(pos, pn, key->conf.keyidx)    
484                                                   
485         /* hwaccel - with software CCMP header    
486         if (info->control.hw_key)                 
487                 return 0;                         
488                                                   
489         pos += IEEE80211_CCMP_HDR_LEN;            
490         ccmp_special_blocks(skb, pn, b_0, aad,    
491                             key->conf.flags &     
492         return ieee80211_aes_ccm_encrypt(key->    
493                                          skb_p    
494 }                                                 
495                                                   
496                                                   
497 ieee80211_tx_result                               
498 ieee80211_crypto_ccmp_encrypt(struct ieee80211    
499                               unsigned int mic    
500 {                                                 
501         struct sk_buff *skb;                      
502                                                   
503         ieee80211_tx_set_protected(tx);           
504                                                   
505         skb_queue_walk(&tx->skbs, skb) {          
506                 if (ccmp_encrypt_skb(tx, skb,     
507                         return TX_DROP;           
508         }                                         
509                                                   
510         return TX_CONTINUE;                       
511 }                                                 
512                                                   
513                                                   
514 ieee80211_rx_result                               
515 ieee80211_crypto_ccmp_decrypt(struct ieee80211    
516                               unsigned int mic    
517 {                                                 
518         struct ieee80211_hdr *hdr = (struct ie    
519         int hdrlen;                               
520         struct ieee80211_key *key = rx->key;      
521         struct sk_buff *skb = rx->skb;            
522         struct ieee80211_rx_status *status = I    
523         u8 pn[IEEE80211_CCMP_PN_LEN];             
524         int data_len;                             
525         int queue;                                
526                                                   
527         hdrlen = ieee80211_hdrlen(hdr->frame_c    
528                                                   
529         if (!ieee80211_is_data(hdr->frame_cont    
530             !ieee80211_is_robust_mgmt_frame(sk    
531                 return RX_CONTINUE;               
532                                                   
533         if (status->flag & RX_FLAG_DECRYPTED)     
534                 if (!pskb_may_pull(rx->skb, hd    
535                         return RX_DROP_U_SHORT    
536                 if (status->flag & RX_FLAG_MIC    
537                         mic_len = 0;              
538         } else {                                  
539                 if (skb_linearize(rx->skb))       
540                         return RX_DROP_U_OOM;     
541         }                                         
542                                                   
543         /* reload hdr - skb might have been re    
544         hdr = (void *)rx->skb->data;              
545                                                   
546         data_len = skb->len - hdrlen - IEEE802    
547         if (!rx->sta || data_len < 0)             
548                 return RX_DROP_U_SHORT_CCMP;      
549                                                   
550         if (!(status->flag & RX_FLAG_PN_VALIDA    
551                 int res;                          
552                                                   
553                 ccmp_hdr2pn(pn, skb->data + hd    
554                                                   
555                 queue = rx->security_idx;         
556                                                   
557                 res = memcmp(pn, key->u.ccmp.r    
558                              IEEE80211_CCMP_PN    
559                 if (res < 0 ||                    
560                     (!res && !(status->flag &     
561                         key->u.ccmp.replays++;    
562                         return RX_DROP_U_REPLA    
563                 }                                 
564                                                   
565                 if (!(status->flag & RX_FLAG_D    
566                         u8 aad[2 * AES_BLOCK_S    
567                         u8 b_0[AES_BLOCK_SIZE]    
568                         /* hardware didn't dec    
569                         ccmp_special_blocks(sk    
570                                             ke    
571                                                   
572                         if (ieee80211_aes_ccm_    
573                                     key->u.ccm    
574                                     skb->data     
575                                     data_len,     
576                                     skb->data     
577                                 return RX_DROP    
578                 }                                 
579                                                   
580                 memcpy(key->u.ccmp.rx_pn[queue    
581                 if (unlikely(ieee80211_is_frag    
582                         memcpy(rx->ccm_gcm.pn,    
583         }                                         
584                                                   
585         /* Remove CCMP header and MIC */          
586         if (pskb_trim(skb, skb->len - mic_len)    
587                 return RX_DROP_U_SHORT_CCMP_MI    
588         memmove(skb->data + IEEE80211_CCMP_HDR    
589         skb_pull(skb, IEEE80211_CCMP_HDR_LEN);    
590                                                   
591         return RX_CONTINUE;                       
592 }                                                 
593                                                   
594 static void gcmp_special_blocks(struct sk_buff    
595                                 bool spp_amsdu    
596 {                                                 
597         struct ieee80211_hdr *hdr = (void *)sk    
598                                                   
599         memcpy(j_0, hdr->addr2, ETH_ALEN);        
600         memcpy(&j_0[ETH_ALEN], pn, IEEE80211_G    
601         j_0[13] = 0;                              
602         j_0[14] = 0;                              
603         j_0[AES_BLOCK_SIZE - 1] = 0x01;           
604                                                   
605         ccmp_gcmp_aad(skb, aad, spp_amsdu);       
606 }                                                 
607                                                   
608 static inline void gcmp_pn2hdr(u8 *hdr, const     
609 {                                                 
610         hdr[0] = pn[5];                           
611         hdr[1] = pn[4];                           
612         hdr[2] = 0;                               
613         hdr[3] = 0x20 | (key_id << 6);            
614         hdr[4] = pn[3];                           
615         hdr[5] = pn[2];                           
616         hdr[6] = pn[1];                           
617         hdr[7] = pn[0];                           
618 }                                                 
619                                                   
620 static inline void gcmp_hdr2pn(u8 *pn, const u    
621 {                                                 
622         pn[0] = hdr[7];                           
623         pn[1] = hdr[6];                           
624         pn[2] = hdr[5];                           
625         pn[3] = hdr[4];                           
626         pn[4] = hdr[1];                           
627         pn[5] = hdr[0];                           
628 }                                                 
629                                                   
630 static int gcmp_encrypt_skb(struct ieee80211_t    
631 {                                                 
632         struct ieee80211_hdr *hdr = (struct ie    
633         struct ieee80211_key *key = tx->key;      
634         struct ieee80211_tx_info *info = IEEE8    
635         int hdrlen, len, tail;                    
636         u8 *pos;                                  
637         u8 pn[6];                                 
638         u64 pn64;                                 
639         u8 aad[GCM_AAD_LEN];                      
640         u8 j_0[AES_BLOCK_SIZE];                   
641                                                   
642         if (info->control.hw_key &&               
643             !(info->control.hw_key->flags & IE    
644             !(info->control.hw_key->flags & IE    
645             !((info->control.hw_key->flags &      
646                IEEE80211_KEY_FLAG_GENERATE_IV_    
647               ieee80211_is_mgmt(hdr->frame_con    
648                 /* hwaccel has no need for pre    
649                  * header or MIC fields           
650                  */                               
651                 return 0;                         
652         }                                         
653                                                   
654         hdrlen = ieee80211_hdrlen(hdr->frame_c    
655         len = skb->len - hdrlen;                  
656                                                   
657         if (info->control.hw_key)                 
658                 tail = 0;                         
659         else                                      
660                 tail = IEEE80211_GCMP_MIC_LEN;    
661                                                   
662         if (WARN_ON(skb_tailroom(skb) < tail |    
663                     skb_headroom(skb) < IEEE80    
664                 return -1;                        
665                                                   
666         pos = skb_push(skb, IEEE80211_GCMP_HDR    
667         memmove(pos, pos + IEEE80211_GCMP_HDR_    
668         skb_set_network_header(skb, skb_networ    
669                                     IEEE80211_    
670                                                   
671         /* the HW only needs room for the IV,     
672         if (info->control.hw_key &&               
673             (info->control.hw_key->flags & IEE    
674                 return 0;                         
675                                                   
676         pos += hdrlen;                            
677                                                   
678         pn64 = atomic64_inc_return(&key->conf.    
679                                                   
680         pn[5] = pn64;                             
681         pn[4] = pn64 >> 8;                        
682         pn[3] = pn64 >> 16;                       
683         pn[2] = pn64 >> 24;                       
684         pn[1] = pn64 >> 32;                       
685         pn[0] = pn64 >> 40;                       
686                                                   
687         gcmp_pn2hdr(pos, pn, key->conf.keyidx)    
688                                                   
689         /* hwaccel - with software GCMP header    
690         if (info->control.hw_key)                 
691                 return 0;                         
692                                                   
693         pos += IEEE80211_GCMP_HDR_LEN;            
694         gcmp_special_blocks(skb, pn, j_0, aad,    
695                             key->conf.flags &     
696         return ieee80211_aes_gcm_encrypt(key->    
697                                          skb_p    
698 }                                                 
699                                                   
700 ieee80211_tx_result                               
701 ieee80211_crypto_gcmp_encrypt(struct ieee80211    
702 {                                                 
703         struct sk_buff *skb;                      
704                                                   
705         ieee80211_tx_set_protected(tx);           
706                                                   
707         skb_queue_walk(&tx->skbs, skb) {          
708                 if (gcmp_encrypt_skb(tx, skb)     
709                         return TX_DROP;           
710         }                                         
711                                                   
712         return TX_CONTINUE;                       
713 }                                                 
714                                                   
715 ieee80211_rx_result                               
716 ieee80211_crypto_gcmp_decrypt(struct ieee80211    
717 {                                                 
718         struct ieee80211_hdr *hdr = (struct ie    
719         int hdrlen;                               
720         struct ieee80211_key *key = rx->key;      
721         struct sk_buff *skb = rx->skb;            
722         struct ieee80211_rx_status *status = I    
723         u8 pn[IEEE80211_GCMP_PN_LEN];             
724         int data_len, queue, mic_len = IEEE802    
725                                                   
726         hdrlen = ieee80211_hdrlen(hdr->frame_c    
727                                                   
728         if (!ieee80211_is_data(hdr->frame_cont    
729             !ieee80211_is_robust_mgmt_frame(sk    
730                 return RX_CONTINUE;               
731                                                   
732         if (status->flag & RX_FLAG_DECRYPTED)     
733                 if (!pskb_may_pull(rx->skb, hd    
734                         return RX_DROP_U_SHORT    
735                 if (status->flag & RX_FLAG_MIC    
736                         mic_len = 0;              
737         } else {                                  
738                 if (skb_linearize(rx->skb))       
739                         return RX_DROP_U_OOM;     
740         }                                         
741                                                   
742         /* reload hdr - skb might have been re    
743         hdr = (void *)rx->skb->data;              
744                                                   
745         data_len = skb->len - hdrlen - IEEE802    
746         if (!rx->sta || data_len < 0)             
747                 return RX_DROP_U_SHORT_GCMP;      
748                                                   
749         if (!(status->flag & RX_FLAG_PN_VALIDA    
750                 int res;                          
751                                                   
752                 gcmp_hdr2pn(pn, skb->data + hd    
753                                                   
754                 queue = rx->security_idx;         
755                                                   
756                 res = memcmp(pn, key->u.gcmp.r    
757                              IEEE80211_GCMP_PN    
758                 if (res < 0 ||                    
759                     (!res && !(status->flag &     
760                         key->u.gcmp.replays++;    
761                         return RX_DROP_U_REPLA    
762                 }                                 
763                                                   
764                 if (!(status->flag & RX_FLAG_D    
765                         u8 aad[2 * AES_BLOCK_S    
766                         u8 j_0[AES_BLOCK_SIZE]    
767                         /* hardware didn't dec    
768                         gcmp_special_blocks(sk    
769                                             ke    
770                                                   
771                         if (ieee80211_aes_gcm_    
772                                     key->u.gcm    
773                                     skb->data     
774                                     data_len,     
775                                     skb->data     
776                                     IEEE80211_    
777                                 return RX_DROP    
778                 }                                 
779                                                   
780                 memcpy(key->u.gcmp.rx_pn[queue    
781                 if (unlikely(ieee80211_is_frag    
782                         memcpy(rx->ccm_gcm.pn,    
783         }                                         
784                                                   
785         /* Remove GCMP header and MIC */          
786         if (pskb_trim(skb, skb->len - mic_len)    
787                 return RX_DROP_U_SHORT_GCMP_MI    
788         memmove(skb->data + IEEE80211_GCMP_HDR    
789         skb_pull(skb, IEEE80211_GCMP_HDR_LEN);    
790                                                   
791         return RX_CONTINUE;                       
792 }                                                 
793                                                   
794 static void bip_aad(struct sk_buff *skb, u8 *a    
795 {                                                 
796         __le16 mask_fc;                           
797         struct ieee80211_hdr *hdr = (struct ie    
798                                                   
799         /* BIP AAD: FC(masked) || A1 || A2 ||     
800                                                   
801         /* FC type/subtype */                     
802         /* Mask FC Retry, PwrMgt, MoreData fla    
803         mask_fc = hdr->frame_control;             
804         mask_fc &= ~cpu_to_le16(IEEE80211_FCTL    
805                                 IEEE80211_FCTL    
806         put_unaligned(mask_fc, (__le16 *) &aad    
807         /* A1 || A2 || A3 */                      
808         memcpy(aad + 2, &hdr->addrs, 3 * ETH_A    
809 }                                                 
810                                                   
811                                                   
812 static inline void bip_ipn_set64(u8 *d, u64 pn    
813 {                                                 
814         *d++ = pn;                                
815         *d++ = pn >> 8;                           
816         *d++ = pn >> 16;                          
817         *d++ = pn >> 24;                          
818         *d++ = pn >> 32;                          
819         *d = pn >> 40;                            
820 }                                                 
821                                                   
822 static inline void bip_ipn_swap(u8 *d, const u    
823 {                                                 
824         *d++ = s[5];                              
825         *d++ = s[4];                              
826         *d++ = s[3];                              
827         *d++ = s[2];                              
828         *d++ = s[1];                              
829         *d = s[0];                                
830 }                                                 
831                                                   
832                                                   
833 ieee80211_tx_result                               
834 ieee80211_crypto_aes_cmac_encrypt(struct ieee8    
835 {                                                 
836         struct sk_buff *skb;                      
837         struct ieee80211_tx_info *info;           
838         struct ieee80211_key *key = tx->key;      
839         struct ieee80211_mmie *mmie;              
840         u8 aad[20];                               
841         u64 pn64;                                 
842                                                   
843         if (WARN_ON(skb_queue_len(&tx->skbs) !    
844                 return TX_DROP;                   
845                                                   
846         skb = skb_peek(&tx->skbs);                
847                                                   
848         info = IEEE80211_SKB_CB(skb);             
849                                                   
850         if (info->control.hw_key &&               
851             !(key->conf.flags & IEEE80211_KEY_    
852                 return TX_CONTINUE;               
853                                                   
854         if (WARN_ON(skb_tailroom(skb) < sizeof    
855                 return TX_DROP;                   
856                                                   
857         mmie = skb_put(skb, sizeof(*mmie));       
858         mmie->element_id = WLAN_EID_MMIE;         
859         mmie->length = sizeof(*mmie) - 2;         
860         mmie->key_id = cpu_to_le16(key->conf.k    
861                                                   
862         /* PN = PN + 1 */                         
863         pn64 = atomic64_inc_return(&key->conf.    
864                                                   
865         bip_ipn_set64(mmie->sequence_number, p    
866                                                   
867         if (info->control.hw_key)                 
868                 return TX_CONTINUE;               
869                                                   
870         bip_aad(skb, aad);                        
871                                                   
872         /*                                        
873          * MIC = AES-128-CMAC(IGTK, AAD || Man    
874          */                                       
875         ieee80211_aes_cmac(key->u.aes_cmac.tfm    
876                            skb->data + 24, skb    
877                                                   
878         return TX_CONTINUE;                       
879 }                                                 
880                                                   
881 ieee80211_tx_result                               
882 ieee80211_crypto_aes_cmac_256_encrypt(struct i    
883 {                                                 
884         struct sk_buff *skb;                      
885         struct ieee80211_tx_info *info;           
886         struct ieee80211_key *key = tx->key;      
887         struct ieee80211_mmie_16 *mmie;           
888         u8 aad[20];                               
889         u64 pn64;                                 
890                                                   
891         if (WARN_ON(skb_queue_len(&tx->skbs) !    
892                 return TX_DROP;                   
893                                                   
894         skb = skb_peek(&tx->skbs);                
895                                                   
896         info = IEEE80211_SKB_CB(skb);             
897                                                   
898         if (info->control.hw_key &&               
899             !(key->conf.flags & IEEE80211_KEY_    
900                 return TX_CONTINUE;               
901                                                   
902         if (WARN_ON(skb_tailroom(skb) < sizeof    
903                 return TX_DROP;                   
904                                                   
905         mmie = skb_put(skb, sizeof(*mmie));       
906         mmie->element_id = WLAN_EID_MMIE;         
907         mmie->length = sizeof(*mmie) - 2;         
908         mmie->key_id = cpu_to_le16(key->conf.k    
909                                                   
910         /* PN = PN + 1 */                         
911         pn64 = atomic64_inc_return(&key->conf.    
912                                                   
913         bip_ipn_set64(mmie->sequence_number, p    
914                                                   
915         if (info->control.hw_key)                 
916                 return TX_CONTINUE;               
917                                                   
918         bip_aad(skb, aad);                        
919                                                   
920         /* MIC = AES-256-CMAC(IGTK, AAD || Man    
921          */                                       
922         ieee80211_aes_cmac_256(key->u.aes_cmac    
923                                skb->data + 24,    
924                                                   
925         return TX_CONTINUE;                       
926 }                                                 
927                                                   
928 ieee80211_rx_result                               
929 ieee80211_crypto_aes_cmac_decrypt(struct ieee8    
930 {                                                 
931         struct sk_buff *skb = rx->skb;            
932         struct ieee80211_rx_status *status = I    
933         struct ieee80211_key *key = rx->key;      
934         struct ieee80211_mmie *mmie;              
935         u8 aad[20], mic[8], ipn[6];               
936         struct ieee80211_hdr *hdr = (struct ie    
937                                                   
938         if (!ieee80211_is_mgmt(hdr->frame_cont    
939                 return RX_CONTINUE;               
940                                                   
941         /* management frames are already linea    
942                                                   
943         if (skb->len < 24 + sizeof(*mmie))        
944                 return RX_DROP_U_SHORT_CMAC;      
945                                                   
946         mmie = (struct ieee80211_mmie *)          
947                 (skb->data + skb->len - sizeof    
948         if (mmie->element_id != WLAN_EID_MMIE     
949             mmie->length != sizeof(*mmie) - 2)    
950                 return RX_DROP_U_BAD_MMIE; /*     
951                                                   
952         bip_ipn_swap(ipn, mmie->sequence_numbe    
953                                                   
954         if (memcmp(ipn, key->u.aes_cmac.rx_pn,    
955                 key->u.aes_cmac.replays++;        
956                 return RX_DROP_U_REPLAY;          
957         }                                         
958                                                   
959         if (!(status->flag & RX_FLAG_DECRYPTED    
960                 /* hardware didn't decrypt/ver    
961                 bip_aad(skb, aad);                
962                 ieee80211_aes_cmac(key->u.aes_    
963                                    skb->data +    
964                 if (crypto_memneq(mic, mmie->m    
965                         key->u.aes_cmac.icverr    
966                         return RX_DROP_U_MIC_F    
967                 }                                 
968         }                                         
969                                                   
970         memcpy(key->u.aes_cmac.rx_pn, ipn, 6);    
971                                                   
972         /* Remove MMIE */                         
973         skb_trim(skb, skb->len - sizeof(*mmie)    
974                                                   
975         return RX_CONTINUE;                       
976 }                                                 
977                                                   
978 ieee80211_rx_result                               
979 ieee80211_crypto_aes_cmac_256_decrypt(struct i    
980 {                                                 
981         struct sk_buff *skb = rx->skb;            
982         struct ieee80211_rx_status *status = I    
983         struct ieee80211_key *key = rx->key;      
984         struct ieee80211_mmie_16 *mmie;           
985         u8 aad[20], mic[16], ipn[6];              
986         struct ieee80211_hdr *hdr = (struct ie    
987                                                   
988         if (!ieee80211_is_mgmt(hdr->frame_cont    
989                 return RX_CONTINUE;               
990                                                   
991         /* management frames are already linea    
992                                                   
993         if (skb->len < 24 + sizeof(*mmie))        
994                 return RX_DROP_U_SHORT_CMAC256    
995                                                   
996         mmie = (struct ieee80211_mmie_16 *)       
997                 (skb->data + skb->len - sizeof    
998         if (mmie->element_id != WLAN_EID_MMIE     
999             mmie->length != sizeof(*mmie) - 2)    
1000                 return RX_DROP_U_BAD_MMIE; /*    
1001                                                  
1002         bip_ipn_swap(ipn, mmie->sequence_numb    
1003                                                  
1004         if (memcmp(ipn, key->u.aes_cmac.rx_pn    
1005                 key->u.aes_cmac.replays++;       
1006                 return RX_DROP_U_REPLAY;         
1007         }                                        
1008                                                  
1009         if (!(status->flag & RX_FLAG_DECRYPTE    
1010                 /* hardware didn't decrypt/ve    
1011                 bip_aad(skb, aad);               
1012                 ieee80211_aes_cmac_256(key->u    
1013                                        skb->d    
1014                 if (crypto_memneq(mic, mmie->    
1015                         key->u.aes_cmac.icver    
1016                         return RX_DROP_U_MIC_    
1017                 }                                
1018         }                                        
1019                                                  
1020         memcpy(key->u.aes_cmac.rx_pn, ipn, 6)    
1021                                                  
1022         /* Remove MMIE */                        
1023         skb_trim(skb, skb->len - sizeof(*mmie    
1024                                                  
1025         return RX_CONTINUE;                      
1026 }                                                
1027                                                  
1028 ieee80211_tx_result                              
1029 ieee80211_crypto_aes_gmac_encrypt(struct ieee    
1030 {                                                
1031         struct sk_buff *skb;                     
1032         struct ieee80211_tx_info *info;          
1033         struct ieee80211_key *key = tx->key;     
1034         struct ieee80211_mmie_16 *mmie;          
1035         struct ieee80211_hdr *hdr;               
1036         u8 aad[GMAC_AAD_LEN];                    
1037         u64 pn64;                                
1038         u8 nonce[GMAC_NONCE_LEN];                
1039                                                  
1040         if (WARN_ON(skb_queue_len(&tx->skbs)     
1041                 return TX_DROP;                  
1042                                                  
1043         skb = skb_peek(&tx->skbs);               
1044                                                  
1045         info = IEEE80211_SKB_CB(skb);            
1046                                                  
1047         if (info->control.hw_key &&              
1048             !(key->conf.flags & IEEE80211_KEY    
1049                 return TX_CONTINUE;              
1050                                                  
1051         if (WARN_ON(skb_tailroom(skb) < sizeo    
1052                 return TX_DROP;                  
1053                                                  
1054         mmie = skb_put(skb, sizeof(*mmie));      
1055         mmie->element_id = WLAN_EID_MMIE;        
1056         mmie->length = sizeof(*mmie) - 2;        
1057         mmie->key_id = cpu_to_le16(key->conf.    
1058                                                  
1059         /* PN = PN + 1 */                        
1060         pn64 = atomic64_inc_return(&key->conf    
1061                                                  
1062         bip_ipn_set64(mmie->sequence_number,     
1063                                                  
1064         if (info->control.hw_key)                
1065                 return TX_CONTINUE;              
1066                                                  
1067         bip_aad(skb, aad);                       
1068                                                  
1069         hdr = (struct ieee80211_hdr *)skb->da    
1070         memcpy(nonce, hdr->addr2, ETH_ALEN);     
1071         bip_ipn_swap(nonce + ETH_ALEN, mmie->    
1072                                                  
1073         /* MIC = AES-GMAC(IGTK, AAD || Manage    
1074         if (ieee80211_aes_gmac(key->u.aes_gma    
1075                                skb->data + 24    
1076                 return TX_DROP;                  
1077                                                  
1078         return TX_CONTINUE;                      
1079 }                                                
1080                                                  
1081 ieee80211_rx_result                              
1082 ieee80211_crypto_aes_gmac_decrypt(struct ieee    
1083 {                                                
1084         struct sk_buff *skb = rx->skb;           
1085         struct ieee80211_rx_status *status =     
1086         struct ieee80211_key *key = rx->key;     
1087         struct ieee80211_mmie_16 *mmie;          
1088         u8 aad[GMAC_AAD_LEN], *mic, ipn[6], n    
1089         struct ieee80211_hdr *hdr = (struct i    
1090                                                  
1091         if (!ieee80211_is_mgmt(hdr->frame_con    
1092                 return RX_CONTINUE;              
1093                                                  
1094         /* management frames are already line    
1095                                                  
1096         if (skb->len < 24 + sizeof(*mmie))       
1097                 return RX_DROP_U_SHORT_GMAC;     
1098                                                  
1099         mmie = (struct ieee80211_mmie_16 *)      
1100                 (skb->data + skb->len - sizeo    
1101         if (mmie->element_id != WLAN_EID_MMIE    
1102             mmie->length != sizeof(*mmie) - 2    
1103                 return RX_DROP_U_BAD_MMIE; /*    
1104                                                  
1105         bip_ipn_swap(ipn, mmie->sequence_numb    
1106                                                  
1107         if (memcmp(ipn, key->u.aes_gmac.rx_pn    
1108                 key->u.aes_gmac.replays++;       
1109                 return RX_DROP_U_REPLAY;         
1110         }                                        
1111                                                  
1112         if (!(status->flag & RX_FLAG_DECRYPTE    
1113                 /* hardware didn't decrypt/ve    
1114                 bip_aad(skb, aad);               
1115                                                  
1116                 memcpy(nonce, hdr->addr2, ETH    
1117                 memcpy(nonce + ETH_ALEN, ipn,    
1118                                                  
1119                 mic = kmalloc(GMAC_MIC_LEN, G    
1120                 if (!mic)                        
1121                         return RX_DROP_U_OOM;    
1122                 if (ieee80211_aes_gmac(key->u    
1123                                        skb->d    
1124                                        mic) <    
1125                     crypto_memneq(mic, mmie->    
1126                         key->u.aes_gmac.icver    
1127                         kfree(mic);              
1128                         return RX_DROP_U_MIC_    
1129                 }                                
1130                 kfree(mic);                      
1131         }                                        
1132                                                  
1133         memcpy(key->u.aes_gmac.rx_pn, ipn, 6)    
1134                                                  
1135         /* Remove MMIE */                        
1136         skb_trim(skb, skb->len - sizeof(*mmie    
1137                                                  
1138         return RX_CONTINUE;                      
1139 }                                                
1140                                                  

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php