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