1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Host AP crypt: host-based WEP encryption implementation for Host AP driver 4 * 5 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi> 6 */ 7 8 #include <linux/fips.h> 9 #include <linux/module.h> 10 #include <linux/init.h> 11 #include <linux/slab.h> 12 #include <linux/random.h> 13 #include <linux/skbuff.h> 14 #include <linux/string.h> 15 16 #include "ieee80211.h" 17 18 #include <crypto/arc4.h> 19 #include <linux/crc32.h> 20 21 MODULE_AUTHOR("Jouni Malinen"); 22 MODULE_DESCRIPTION("Host AP crypt: WEP"); 23 MODULE_LICENSE("GPL"); 24 25 struct prism2_wep_data { 26 u32 iv; 27 #define WEP_KEY_LEN 13 28 u8 key[WEP_KEY_LEN + 1]; 29 u8 key_len; 30 u8 key_idx; 31 struct arc4_ctx rx_ctx_arc4; 32 struct arc4_ctx tx_ctx_arc4; 33 }; 34 35 36 static void *prism2_wep_init(int keyidx) 37 { 38 struct prism2_wep_data *priv; 39 40 if (fips_enabled) 41 return NULL; 42 43 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 44 if (!priv) 45 return NULL; 46 priv->key_idx = keyidx; 47 48 /* start WEP IV from a random value */ 49 get_random_bytes(&priv->iv, 4); 50 51 return priv; 52 } 53 54 55 static void prism2_wep_deinit(void *priv) 56 { 57 kfree_sensitive(priv); 58 } 59 60 /* Perform WEP encryption on given skb that has at least 4 bytes of headroom 61 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, 62 * so the payload length increases with 8 bytes. 63 * 64 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) 65 */ 66 static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 67 { 68 struct prism2_wep_data *wep = priv; 69 u32 klen, len; 70 u8 key[WEP_KEY_LEN + 3]; 71 u8 *pos; 72 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); 73 u32 crc; 74 u8 *icv; 75 76 if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || 77 skb->len < hdr_len) 78 return -1; 79 80 len = skb->len - hdr_len; 81 pos = skb_push(skb, 4); 82 memmove(pos, pos + 4, hdr_len); 83 pos += hdr_len; 84 85 klen = 3 + wep->key_len; 86 87 wep->iv++; 88 89 /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key 90 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) 91 * can be used to speedup attacks, so avoid using them. 92 */ 93 if ((wep->iv & 0xff00) == 0xff00) { 94 u8 B = (wep->iv >> 16) & 0xff; 95 96 if (B >= 3 && B < klen) 97 wep->iv += 0x0100; 98 } 99 100 /* Prepend 24-bit IV to RC4 key and TX frame */ 101 *pos++ = key[0] = (wep->iv >> 16) & 0xff; 102 *pos++ = key[1] = (wep->iv >> 8) & 0xff; 103 *pos++ = key[2] = wep->iv & 0xff; 104 *pos++ = wep->key_idx << 6; 105 106 /* Copy rest of the WEP key (the secret part) */ 107 memcpy(key + 3, wep->key, wep->key_len); 108 109 if (!tcb_desc->bHwSec) { 110 /* Append little-endian CRC32 and encrypt it to produce ICV */ 111 crc = ~crc32_le(~0, pos, len); 112 icv = skb_put(skb, 4); 113 icv[0] = crc; 114 icv[1] = crc >> 8; 115 icv[2] = crc >> 16; 116 icv[3] = crc >> 24; 117 118 arc4_setkey(&wep->tx_ctx_arc4, key, klen); 119 arc4_crypt(&wep->tx_ctx_arc4, pos, pos, len + 4); 120 } 121 122 return 0; 123 } 124 125 126 /* Perform WEP decryption on given buffer. Buffer includes whole WEP part of 127 * the frame: IV (4 bytes), encrypted payload (including SNAP header), 128 * ICV (4 bytes). len includes both IV and ICV. 129 * 130 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on 131 * failure. If frame is OK, IV and ICV will be removed. 132 */ 133 static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 134 { 135 struct prism2_wep_data *wep = priv; 136 u32 klen, plen; 137 u8 key[WEP_KEY_LEN + 3]; 138 u8 keyidx, *pos; 139 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); 140 u32 crc; 141 u8 icv[4]; 142 143 if (skb->len < hdr_len + 8) 144 return -1; 145 146 pos = skb->data + hdr_len; 147 key[0] = *pos++; 148 key[1] = *pos++; 149 key[2] = *pos++; 150 keyidx = *pos++ >> 6; 151 if (keyidx != wep->key_idx) 152 return -1; 153 154 klen = 3 + wep->key_len; 155 156 /* Copy rest of the WEP key (the secret part) */ 157 memcpy(key + 3, wep->key, wep->key_len); 158 159 /* Apply RC4 to data and compute CRC32 over decrypted data */ 160 plen = skb->len - hdr_len - 8; 161 162 if (!tcb_desc->bHwSec) { 163 arc4_setkey(&wep->rx_ctx_arc4, key, klen); 164 arc4_crypt(&wep->rx_ctx_arc4, pos, pos, plen + 4); 165 166 crc = ~crc32_le(~0, pos, plen); 167 icv[0] = crc; 168 icv[1] = crc >> 8; 169 icv[2] = crc >> 16; 170 icv[3] = crc >> 24; 171 if (memcmp(icv, pos + plen, 4) != 0) { 172 /* ICV mismatch - drop frame */ 173 return -2; 174 } 175 } 176 /* Remove IV and ICV */ 177 memmove(skb->data + 4, skb->data, hdr_len); 178 skb_pull(skb, 4); 179 skb_trim(skb, skb->len - 4); 180 181 return 0; 182 } 183 184 185 static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv) 186 { 187 struct prism2_wep_data *wep = priv; 188 189 if (len < 0 || len > WEP_KEY_LEN) 190 return -1; 191 192 memcpy(wep->key, key, len); 193 wep->key_len = len; 194 195 return 0; 196 } 197 198 199 static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv) 200 { 201 struct prism2_wep_data *wep = priv; 202 203 if (len < wep->key_len) 204 return -1; 205 206 memcpy(key, wep->key, wep->key_len); 207 208 return wep->key_len; 209 } 210 211 212 static char *prism2_wep_print_stats(char *p, void *priv) 213 { 214 struct prism2_wep_data *wep = priv; 215 216 p += sprintf(p, "key[%d] alg=WEP len=%d\n", 217 wep->key_idx, wep->key_len); 218 return p; 219 } 220 221 222 static struct ieee80211_crypto_ops ieee80211_crypt_wep = { 223 .name = "WEP", 224 .init = prism2_wep_init, 225 .deinit = prism2_wep_deinit, 226 .encrypt_mpdu = prism2_wep_encrypt, 227 .decrypt_mpdu = prism2_wep_decrypt, 228 .encrypt_msdu = NULL, 229 .decrypt_msdu = NULL, 230 .set_key = prism2_wep_set_key, 231 .get_key = prism2_wep_get_key, 232 .print_stats = prism2_wep_print_stats, 233 .extra_prefix_len = 4, /* IV */ 234 .extra_postfix_len = 4, /* ICV */ 235 .owner = THIS_MODULE, 236 }; 237 238 int __init ieee80211_crypto_wep_init(void) 239 { 240 return ieee80211_register_crypto_ops(&ieee80211_crypt_wep); 241 } 242 243 void __exit ieee80211_crypto_wep_exit(void) 244 { 245 ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep); 246 } 247 248