| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Software WEP encryption implementation |
|---|
| 3 | 4 | * Copyright 2002, Jouni Malinen <jkmaline@cc.hut.fi> |
|---|
| 4 | 5 | * Copyright 2003, Instant802 Networks, Inc. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 8 | | - * published by the Free Software Foundation. |
|---|
| 9 | 6 | */ |
|---|
| 10 | 7 | |
|---|
| 11 | 8 | #include <linux/netdevice.h> |
|---|
| .. | .. |
|---|
| 25 | 22 | #include "wep.h" |
|---|
| 26 | 23 | |
|---|
| 27 | 24 | |
|---|
| 28 | | -int ieee80211_wep_init(struct ieee80211_local *local) |
|---|
| 25 | +void ieee80211_wep_init(struct ieee80211_local *local) |
|---|
| 29 | 26 | { |
|---|
| 30 | 27 | /* start WEP IV from a random value */ |
|---|
| 31 | 28 | get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN); |
|---|
| 32 | | - |
|---|
| 33 | | - local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); |
|---|
| 34 | | - if (IS_ERR(local->wep_tx_tfm)) { |
|---|
| 35 | | - local->wep_rx_tfm = ERR_PTR(-EINVAL); |
|---|
| 36 | | - return PTR_ERR(local->wep_tx_tfm); |
|---|
| 37 | | - } |
|---|
| 38 | | - |
|---|
| 39 | | - local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); |
|---|
| 40 | | - if (IS_ERR(local->wep_rx_tfm)) { |
|---|
| 41 | | - crypto_free_cipher(local->wep_tx_tfm); |
|---|
| 42 | | - local->wep_tx_tfm = ERR_PTR(-EINVAL); |
|---|
| 43 | | - return PTR_ERR(local->wep_rx_tfm); |
|---|
| 44 | | - } |
|---|
| 45 | | - |
|---|
| 46 | | - return 0; |
|---|
| 47 | | -} |
|---|
| 48 | | - |
|---|
| 49 | | -void ieee80211_wep_free(struct ieee80211_local *local) |
|---|
| 50 | | -{ |
|---|
| 51 | | - if (!IS_ERR(local->wep_tx_tfm)) |
|---|
| 52 | | - crypto_free_cipher(local->wep_tx_tfm); |
|---|
| 53 | | - if (!IS_ERR(local->wep_rx_tfm)) |
|---|
| 54 | | - crypto_free_cipher(local->wep_rx_tfm); |
|---|
| 55 | 29 | } |
|---|
| 56 | 30 | |
|---|
| 57 | 31 | static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) |
|---|
| .. | .. |
|---|
| 131 | 105 | /* Perform WEP encryption using given key. data buffer must have tailroom |
|---|
| 132 | 106 | * for 4-byte ICV. data_len must not include this ICV. Note: this function |
|---|
| 133 | 107 | * does _not_ add IV. data = RC4(data | CRC32(data)) */ |
|---|
| 134 | | -int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, |
|---|
| 108 | +int ieee80211_wep_encrypt_data(struct arc4_ctx *ctx, u8 *rc4key, |
|---|
| 135 | 109 | size_t klen, u8 *data, size_t data_len) |
|---|
| 136 | 110 | { |
|---|
| 137 | 111 | __le32 icv; |
|---|
| 138 | | - int i; |
|---|
| 139 | | - |
|---|
| 140 | | - if (IS_ERR(tfm)) |
|---|
| 141 | | - return -1; |
|---|
| 142 | 112 | |
|---|
| 143 | 113 | icv = cpu_to_le32(~crc32_le(~0, data, data_len)); |
|---|
| 144 | 114 | put_unaligned(icv, (__le32 *)(data + data_len)); |
|---|
| 145 | 115 | |
|---|
| 146 | | - crypto_cipher_setkey(tfm, rc4key, klen); |
|---|
| 147 | | - for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++) |
|---|
| 148 | | - crypto_cipher_encrypt_one(tfm, data + i, data + i); |
|---|
| 116 | + arc4_setkey(ctx, rc4key, klen); |
|---|
| 117 | + arc4_crypt(ctx, data, data, data_len + IEEE80211_WEP_ICV_LEN); |
|---|
| 118 | + memzero_explicit(ctx, sizeof(*ctx)); |
|---|
| 149 | 119 | |
|---|
| 150 | 120 | return 0; |
|---|
| 151 | 121 | } |
|---|
| .. | .. |
|---|
| 184 | 154 | /* Add room for ICV */ |
|---|
| 185 | 155 | skb_put(skb, IEEE80211_WEP_ICV_LEN); |
|---|
| 186 | 156 | |
|---|
| 187 | | - return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3, |
|---|
| 157 | + return ieee80211_wep_encrypt_data(&local->wep_tx_ctx, rc4key, keylen + 3, |
|---|
| 188 | 158 | iv + IEEE80211_WEP_IV_LEN, len); |
|---|
| 189 | 159 | } |
|---|
| 190 | 160 | |
|---|
| .. | .. |
|---|
| 192 | 162 | /* Perform WEP decryption using given key. data buffer includes encrypted |
|---|
| 193 | 163 | * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. |
|---|
| 194 | 164 | * Return 0 on success and -1 on ICV mismatch. */ |
|---|
| 195 | | -int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, |
|---|
| 165 | +int ieee80211_wep_decrypt_data(struct arc4_ctx *ctx, u8 *rc4key, |
|---|
| 196 | 166 | size_t klen, u8 *data, size_t data_len) |
|---|
| 197 | 167 | { |
|---|
| 198 | 168 | __le32 crc; |
|---|
| 199 | | - int i; |
|---|
| 200 | 169 | |
|---|
| 201 | | - if (IS_ERR(tfm)) |
|---|
| 202 | | - return -1; |
|---|
| 203 | | - |
|---|
| 204 | | - crypto_cipher_setkey(tfm, rc4key, klen); |
|---|
| 205 | | - for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++) |
|---|
| 206 | | - crypto_cipher_decrypt_one(tfm, data + i, data + i); |
|---|
| 170 | + arc4_setkey(ctx, rc4key, klen); |
|---|
| 171 | + arc4_crypt(ctx, data, data, data_len + IEEE80211_WEP_ICV_LEN); |
|---|
| 172 | + memzero_explicit(ctx, sizeof(*ctx)); |
|---|
| 207 | 173 | |
|---|
| 208 | 174 | crc = cpu_to_le32(~crc32_le(~0, data, data_len)); |
|---|
| 209 | 175 | if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0) |
|---|
| .. | .. |
|---|
| 256 | 222 | /* Copy rest of the WEP key (the secret part) */ |
|---|
| 257 | 223 | memcpy(rc4key + 3, key->conf.key, key->conf.keylen); |
|---|
| 258 | 224 | |
|---|
| 259 | | - if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen, |
|---|
| 225 | + if (ieee80211_wep_decrypt_data(&local->wep_rx_ctx, rc4key, klen, |
|---|
| 260 | 226 | skb->data + hdrlen + |
|---|
| 261 | 227 | IEEE80211_WEP_IV_LEN, len)) |
|---|
| 262 | 228 | ret = -1; |
|---|