@@ -561,7 +561,7 @@ config CRYPTO_ANUBIS
config CRYPTO_ARC4
tristate "ARC4 cipher algorithm"
- select CRYPTO_ALGAPI
+ select CRYPTO_BLKCIPHER
help
ARC4 cipher algorithm.
@@ -1,4 +1,4 @@
-/*
+/*
* Cryptographic API
*
* ARC4 Cipher Algorithm
@@ -13,76 +13,122 @@
*/
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/arc4.h>
#define ARC4_MIN_KEY_SIZE 1
#define ARC4_MAX_KEY_SIZE 256
#define ARC4_BLOCK_SIZE 1
-struct arc4_ctx {
- u8 S[256];
- u8 x, y;
-};
-
static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
unsigned int key_len)
{
- struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
+ /*
+ * ARC4 is special: The user should supply an IV as struct arc4_iv and
+ * fill either the key or the iv.
+ */
+ return -EOPNOTSUPP;
+}
+
+static void arc4_key_to_iv(const u8 *in_key, u32 key_len, struct arc4_iv *iv)
+{
int i, j = 0, k = 0;
- ctx->x = 1;
- ctx->y = 0;
+ iv->iv.x = 1;
+ iv->iv.y = 0;
- for(i = 0; i < 256; i++)
- ctx->S[i] = i;
+ for (i = 0; i < 256; i++)
+ iv->iv.S[i] = i;
- for(i = 0; i < 256; i++)
+ for (i = 0; i < 256; i++)
{
- u8 a = ctx->S[i];
+ u8 a = iv->iv.S[i];
j = (j + in_key[k] + a) & 0xff;
- ctx->S[i] = ctx->S[j];
- ctx->S[j] = a;
- if(++k >= key_len)
+ iv->iv.S[i] = iv->iv.S[j];
+ iv->iv.S[j] = a;
+ if (++k >= key_len)
k = 0;
}
-
- return 0;
}
-static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+static void arc4_ivsetup(struct arc4_iv *iv)
{
- struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct arc4_iv tmp_iv;
- u8 *const S = ctx->S;
- u8 x = ctx->x;
- u8 y = ctx->y;
- u8 a, b;
+ if (iv->type == ARC4_TYPE_IV)
+ return;
- a = S[x];
- y = (y + a) & 0xff;
- b = S[y];
- S[x] = b;
- S[y] = a;
- x = (x + 1) & 0xff;
- *out++ = *in ^ S[(a + b) & 0xff];
+ memcpy(&tmp_iv, iv, sizeof(tmp_iv));
+ arc4_key_to_iv(tmp_iv.key.key, tmp_iv.key.key_len, iv);
+ iv->type = ARC4_TYPE_IV;
+}
+
+static int arc4_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ struct arc4_iv *aiv;
+ u8 *S;
+ u8 x;
+ u8 y;
+ u8 a, b;
+ int ret;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ ret = blkcipher_walk_virt(desc, &walk);
+ if (ret)
+ return ret;
+
+ aiv = (struct arc4_iv *)walk.iv;
+ arc4_ivsetup(aiv);
+
+ S = aiv->iv.S;
+ x = aiv->iv.x;
+ y = aiv->iv.y;
+
+ while (walk.nbytes) {
+ u8 *in = walk.src.virt.addr;
+ u8 *out = walk.dst.virt.addr;
+ u32 i;
+
+ for (i = 0; i < walk.nbytes; i++) {
+ a = S[x];
+ y = (y + a) & 0xff;
+ b = S[y];
+ S[x] = b;
+ S[y] = a;
+ x = (x + 1) & 0xff;
+ *out = *in ^ S[(a + b) & 0xff];
+
+ in++;
+ out++;
+ }
+ ret = blkcipher_walk_done(desc, &walk, 0);
+ WARN_ON(ret < 0);
+ }
- ctx->x = x;
- ctx->y = y;
+ aiv->iv.x = x;
+ aiv->iv.y = y;
+ return ret;
}
static struct crypto_alg arc4_alg = {
.cra_name = "arc4",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
.cra_blocksize = ARC4_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct arc4_ctx),
+ .cra_ctxsize = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(arc4_alg.cra_list),
- .cra_u = { .cipher = {
- .cia_min_keysize = ARC4_MIN_KEY_SIZE,
- .cia_max_keysize = ARC4_MAX_KEY_SIZE,
- .cia_setkey = arc4_set_key,
- .cia_encrypt = arc4_crypt,
- .cia_decrypt = arc4_crypt } }
+ .cra_u = { .blkcipher = {
+ .min_keysize = ARC4_MIN_KEY_SIZE,
+ .max_keysize = ARC4_MAX_KEY_SIZE,
+ .ivsize = sizeof(struct arc4_iv),
+ .setkey = arc4_set_key,
+ .encrypt = arc4_crypt,
+ .decrypt = arc4_crypt } }
};
static int __init arc4_init(void)
@@ -90,7 +136,6 @@ static int __init arc4_init(void)
return crypto_register_alg(&arc4_alg);
}
-
static void __exit arc4_exit(void)
{
crypto_unregister_alg(&arc4_alg);
@@ -24,7 +24,8 @@
#define MAX_TAP 8
#define MAX_KEYLEN 56
-#define MAX_IVLEN 32
+/* sizeof arc4_iv */
+#define MAX_IVLEN 260
struct hash_testvec {
/* only used with keyed hash algorithms */
@@ -3076,7 +3076,6 @@ config PPP_MPPE
select CRYPTO
select CRYPTO_SHA1
select CRYPTO_ARC4
- select CRYPTO_ECB
---help---
Support for the MPPE Encryption protocol, as employed by the
Microsoft Point-to-Point Tunneling Protocol.
@@ -5,10 +5,8 @@ config HOSTAP
select WEXT_PRIV
select CRYPTO
select CRYPTO_ARC4
- select CRYPTO_ECB
select CRYPTO_AES
select CRYPTO_MICHAEL_MIC
- select CRYPTO_ECB
select CRC32
select LIB80211
select LIB80211_CRYPT_WEP
@@ -159,10 +159,8 @@ config LIBIPW
select WEXT_SPY
select CRYPTO
select CRYPTO_ARC4
- select CRYPTO_ECB
select CRYPTO_AES
select CRYPTO_MICHAEL_MIC
- select CRYPTO_ECB
select CRC32
select LIB80211
select LIB80211_CRYPT_WEP
new file mode 100644
@@ -0,0 +1,26 @@
+#ifndef __CRYPTO_ARC4_H__
+#define __CRYPTO_ARC4_H__
+
+struct arc4_iv {
+ union {
+ struct arc4_key {
+ u8 key[256];
+ u16 key_len;
+ } key;
+ struct arc4_riv {
+ u8 S[256];
+ u8 x, y;
+ } iv;
+ };
+#define ARC4_TYPE_KEY 0
+#define ARC4_TYPE_IV 1
+ u8 type;
+};
+
+static inline void arc4_setup_iv(struct arc4_iv *iv, const u8 *key, u32 len)
+{
+ memcpy(iv->key.key, key, len);
+ iv->key.key_len = len;
+ iv->type = ARC4_TYPE_KEY;
+}
+#endif
@@ -2,7 +2,6 @@ config MAC80211
tristate "Generic IEEE 802.11 Networking Stack (mac80211)"
depends on CFG80211
select CRYPTO
- select CRYPTO_ECB
select CRYPTO_ARC4
select CRYPTO_AES
select CRC32
@@ -94,7 +94,7 @@ static void *lib80211_tkip_init(int key_idx)
priv->key_idx = key_idx;
- priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
+ priv->tx_tfm_arc4 = crypto_alloc_blkcipher("arc4", 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tx_tfm_arc4)) {
printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
@@ -112,7 +112,7 @@ static void *lib80211_tkip_init(int key_idx)
goto fail;
}
- priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
+ priv->rx_tfm_arc4 = crypto_alloc_blkcipher("arc4", 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->rx_tfm_arc4)) {
printk(KERN_DEBUG "lib80211_crypt_tkip: could not allocate "
@@ -360,6 +360,7 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct lib80211_tkip_data *tkey = priv;
struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 };
+ struct arc4_iv *iv = crypto_blkcipher_crt(tkey->tx_tfm_arc4)->iv;
int len;
u8 rc4key[16], *pos, *icv;
u32 crc;
@@ -392,7 +393,7 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
icv[2] = crc >> 16;
icv[3] = crc >> 24;
- crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
+ arc4_setup_iv(iv, rc4key, 16);
sg_init_one(&sg, pos, len + 4);
return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
}
@@ -414,6 +415,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct lib80211_tkip_data *tkey = priv;
struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
+ struct arc4_iv *iv = crypto_blkcipher_crt(tkey->rx_tfm_arc4)->iv;
u8 rc4key[16];
u8 keyidx, *pos;
u32 iv32;
@@ -485,7 +487,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
plen = skb->len - hdr_len - 12;
- crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
+ arc4_setup_iv(iv, rc4key, 16);
sg_init_one(&sg, pos, plen + 4);
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
if (net_ratelimit()) {