Revision b3fc9c6c58c986f7a24fd8b0794d1e0794935a28 authored by Johannes Berg on 13 April 2008, 08:12:47 UTC, committed by John W. Linville on 15 April 2008, 19:04:36 UTC
Some people are getting this message a lot, and we have traced it to
broken access points that much too often send completely empty frames
(all bytes zeroed, which they shouldn't do at all.)

Since we cannot do anything about such frames in any case except the
special case where we're debugging an AP, just remove the message.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
1 parent 2dd0f69
Raw File
aes_generic.c
/* 
 * Cryptographic API.
 *
 * AES Cipher Algorithm.
 *
 * Based on Brian Gladman's code.
 *
 * Linux developers:
 *  Alexander Kjeldaas <astor@fast.no>
 *  Herbert Valerio Riedel <hvr@hvrlab.org>
 *  Kyle McMartin <kyle@debian.org>
 *  Adam J. Richter <adam@yggdrasil.com> (conversion to 2.5 API).
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * ---------------------------------------------------------------------------
 * Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
 * All rights reserved.
 *
 * LICENSE TERMS
 *
 * The free distribution and use of this software in both source and binary
 * form is allowed (with or without changes) provided that:
 *
 *   1. distributions of this source code include the above copyright
 *      notice, this list of conditions and the following disclaimer;
 *
 *   2. distributions in binary form include the above copyright
 *      notice, this list of conditions and the following disclaimer
 *      in the documentation and/or other associated materials;
 *
 *   3. the copyright holder's name is not used to endorse products
 *      built using this software without specific written permission.
 *
 * ALTERNATIVELY, provided that this notice is retained in full, this product
 * may be distributed under the terms of the GNU General Public License (GPL),
 * in which case the provisions of the GPL apply INSTEAD OF those given above.
 *
 * DISCLAIMER
 *
 * This software is provided 'as is' with no explicit or implied warranties
 * in respect of its properties, including, but not limited to, correctness
 * and/or fitness for purpose.
 * ---------------------------------------------------------------------------
 */

#include <crypto/aes.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/crypto.h>
#include <asm/byteorder.h>

static inline u8 byte(const u32 x, const unsigned n)
{
	return x >> (n << 3);
}

static u8 pow_tab[256] __initdata;
static u8 log_tab[256] __initdata;
static u8 sbx_tab[256] __initdata;
static u8 isb_tab[256] __initdata;
static u32 rco_tab[10];

u32 crypto_ft_tab[4][256];
u32 crypto_fl_tab[4][256];
u32 crypto_it_tab[4][256];
u32 crypto_il_tab[4][256];

EXPORT_SYMBOL_GPL(crypto_ft_tab);
EXPORT_SYMBOL_GPL(crypto_fl_tab);
EXPORT_SYMBOL_GPL(crypto_it_tab);
EXPORT_SYMBOL_GPL(crypto_il_tab);

static inline u8 __init f_mult(u8 a, u8 b)
{
	u8 aa = log_tab[a], cc = aa + log_tab[b];

	return pow_tab[cc + (cc < aa ? 1 : 0)];
}

#define ff_mult(a, b)	(a && b ? f_mult(a, b) : 0)

static void __init gen_tabs(void)
{
	u32 i, t;
	u8 p, q;

	/*
	 * log and power tables for GF(2**8) finite field with
	 * 0x011b as modular polynomial - the simplest primitive
	 * root is 0x03, used here to generate the tables
	 */

	for (i = 0, p = 1; i < 256; ++i) {
		pow_tab[i] = (u8) p;
		log_tab[p] = (u8) i;

		p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
	}

	log_tab[1] = 0;

	for (i = 0, p = 1; i < 10; ++i) {
		rco_tab[i] = p;

		p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
	}

	for (i = 0; i < 256; ++i) {
		p = (i ? pow_tab[255 - log_tab[i]] : 0);
		q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
		p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
		sbx_tab[i] = p;
		isb_tab[p] = (u8) i;
	}

	for (i = 0; i < 256; ++i) {
		p = sbx_tab[i];

		t = p;
		crypto_fl_tab[0][i] = t;
		crypto_fl_tab[1][i] = rol32(t, 8);
		crypto_fl_tab[2][i] = rol32(t, 16);
		crypto_fl_tab[3][i] = rol32(t, 24);

		t = ((u32) ff_mult(2, p)) |
		    ((u32) p << 8) |
		    ((u32) p << 16) | ((u32) ff_mult(3, p) << 24);

		crypto_ft_tab[0][i] = t;
		crypto_ft_tab[1][i] = rol32(t, 8);
		crypto_ft_tab[2][i] = rol32(t, 16);
		crypto_ft_tab[3][i] = rol32(t, 24);

		p = isb_tab[i];

		t = p;
		crypto_il_tab[0][i] = t;
		crypto_il_tab[1][i] = rol32(t, 8);
		crypto_il_tab[2][i] = rol32(t, 16);
		crypto_il_tab[3][i] = rol32(t, 24);

		t = ((u32) ff_mult(14, p)) |
		    ((u32) ff_mult(9, p) << 8) |
		    ((u32) ff_mult(13, p) << 16) |
		    ((u32) ff_mult(11, p) << 24);

		crypto_it_tab[0][i] = t;
		crypto_it_tab[1][i] = rol32(t, 8);
		crypto_it_tab[2][i] = rol32(t, 16);
		crypto_it_tab[3][i] = rol32(t, 24);
	}
}

/* initialise the key schedule from the user supplied key */

#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)

#define imix_col(y,x)	do {		\
	u	= star_x(x);		\
	v	= star_x(u);		\
	w	= star_x(v);		\
	t	= w ^ (x);		\
	(y)	= u ^ v ^ w;		\
	(y)	^= ror32(u ^ t, 8) ^	\
		ror32(v ^ t, 16) ^	\
		ror32(t, 24);		\
} while (0)

#define ls_box(x)		\
	crypto_fl_tab[0][byte(x, 0)] ^	\
	crypto_fl_tab[1][byte(x, 1)] ^	\
	crypto_fl_tab[2][byte(x, 2)] ^	\
	crypto_fl_tab[3][byte(x, 3)]

#define loop4(i)	do {		\
	t = ror32(t, 8);		\
	t = ls_box(t) ^ rco_tab[i];	\
	t ^= ctx->key_enc[4 * i];		\
	ctx->key_enc[4 * i + 4] = t;		\
	t ^= ctx->key_enc[4 * i + 1];		\
	ctx->key_enc[4 * i + 5] = t;		\
	t ^= ctx->key_enc[4 * i + 2];		\
	ctx->key_enc[4 * i + 6] = t;		\
	t ^= ctx->key_enc[4 * i + 3];		\
	ctx->key_enc[4 * i + 7] = t;		\
} while (0)

#define loop6(i)	do {		\
	t = ror32(t, 8);		\
	t = ls_box(t) ^ rco_tab[i];	\
	t ^= ctx->key_enc[6 * i];		\
	ctx->key_enc[6 * i + 6] = t;		\
	t ^= ctx->key_enc[6 * i + 1];		\
	ctx->key_enc[6 * i + 7] = t;		\
	t ^= ctx->key_enc[6 * i + 2];		\
	ctx->key_enc[6 * i + 8] = t;		\
	t ^= ctx->key_enc[6 * i + 3];		\
	ctx->key_enc[6 * i + 9] = t;		\
	t ^= ctx->key_enc[6 * i + 4];		\
	ctx->key_enc[6 * i + 10] = t;		\
	t ^= ctx->key_enc[6 * i + 5];		\
	ctx->key_enc[6 * i + 11] = t;		\
} while (0)

#define loop8(i)	do {			\
	t = ror32(t, 8);			\
	t = ls_box(t) ^ rco_tab[i];		\
	t ^= ctx->key_enc[8 * i];			\
	ctx->key_enc[8 * i + 8] = t;			\
	t ^= ctx->key_enc[8 * i + 1];			\
	ctx->key_enc[8 * i + 9] = t;			\
	t ^= ctx->key_enc[8 * i + 2];			\
	ctx->key_enc[8 * i + 10] = t;			\
	t ^= ctx->key_enc[8 * i + 3];			\
	ctx->key_enc[8 * i + 11] = t;			\
	t  = ctx->key_enc[8 * i + 4] ^ ls_box(t);	\
	ctx->key_enc[8 * i + 12] = t;			\
	t ^= ctx->key_enc[8 * i + 5];			\
	ctx->key_enc[8 * i + 13] = t;			\
	t ^= ctx->key_enc[8 * i + 6];			\
	ctx->key_enc[8 * i + 14] = t;			\
	t ^= ctx->key_enc[8 * i + 7];			\
	ctx->key_enc[8 * i + 15] = t;			\
} while (0)

int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
		unsigned int key_len)
{
	struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
	const __le32 *key = (const __le32 *)in_key;
	u32 *flags = &tfm->crt_flags;
	u32 i, t, u, v, w, j;

	if (key_len % 8) {
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
		return -EINVAL;
	}

	ctx->key_length = key_len;

	ctx->key_dec[key_len + 24] = ctx->key_enc[0] = le32_to_cpu(key[0]);
	ctx->key_dec[key_len + 25] = ctx->key_enc[1] = le32_to_cpu(key[1]);
	ctx->key_dec[key_len + 26] = ctx->key_enc[2] = le32_to_cpu(key[2]);
	ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]);

	switch (key_len) {
	case 16:
		t = ctx->key_enc[3];
		for (i = 0; i < 10; ++i)
			loop4(i);
		break;

	case 24:
		ctx->key_enc[4] = le32_to_cpu(key[4]);
		t = ctx->key_enc[5] = le32_to_cpu(key[5]);
		for (i = 0; i < 8; ++i)
			loop6(i);
		break;

	case 32:
		ctx->key_enc[4] = le32_to_cpu(key[4]);
		ctx->key_enc[5] = le32_to_cpu(key[5]);
		ctx->key_enc[6] = le32_to_cpu(key[6]);
		t = ctx->key_enc[7] = le32_to_cpu(key[7]);
		for (i = 0; i < 7; ++i)
			loop8(i);
		break;
	}

	ctx->key_dec[0] = ctx->key_enc[key_len + 24];
	ctx->key_dec[1] = ctx->key_enc[key_len + 25];
	ctx->key_dec[2] = ctx->key_enc[key_len + 26];
	ctx->key_dec[3] = ctx->key_enc[key_len + 27];

	for (i = 4; i < key_len + 24; ++i) {
		j = key_len + 24 - (i & ~3) + (i & 3);
		imix_col(ctx->key_dec[j], ctx->key_enc[i]);
	}
	return 0;
}
EXPORT_SYMBOL_GPL(crypto_aes_set_key);

/* encrypt a block of text */

#define f_rn(bo, bi, n, k)	do {				\
	bo[n] = crypto_ft_tab[0][byte(bi[n], 0)] ^			\
		crypto_ft_tab[1][byte(bi[(n + 1) & 3], 1)] ^		\
		crypto_ft_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
		crypto_ft_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n);	\
} while (0)

#define f_nround(bo, bi, k)	do {\
	f_rn(bo, bi, 0, k);	\
	f_rn(bo, bi, 1, k);	\
	f_rn(bo, bi, 2, k);	\
	f_rn(bo, bi, 3, k);	\
	k += 4;			\
} while (0)

#define f_rl(bo, bi, n, k)	do {				\
	bo[n] = crypto_fl_tab[0][byte(bi[n], 0)] ^			\
		crypto_fl_tab[1][byte(bi[(n + 1) & 3], 1)] ^		\
		crypto_fl_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
		crypto_fl_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n);	\
} while (0)

#define f_lround(bo, bi, k)	do {\
	f_rl(bo, bi, 0, k);	\
	f_rl(bo, bi, 1, k);	\
	f_rl(bo, bi, 2, k);	\
	f_rl(bo, bi, 3, k);	\
} while (0)

static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
	const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
	const __le32 *src = (const __le32 *)in;
	__le32 *dst = (__le32 *)out;
	u32 b0[4], b1[4];
	const u32 *kp = ctx->key_enc + 4;
	const int key_len = ctx->key_length;

	b0[0] = le32_to_cpu(src[0]) ^ ctx->key_enc[0];
	b0[1] = le32_to_cpu(src[1]) ^ ctx->key_enc[1];
	b0[2] = le32_to_cpu(src[2]) ^ ctx->key_enc[2];
	b0[3] = le32_to_cpu(src[3]) ^ ctx->key_enc[3];

	if (key_len > 24) {
		f_nround(b1, b0, kp);
		f_nround(b0, b1, kp);
	}

	if (key_len > 16) {
		f_nround(b1, b0, kp);
		f_nround(b0, b1, kp);
	}

	f_nround(b1, b0, kp);
	f_nround(b0, b1, kp);
	f_nround(b1, b0, kp);
	f_nround(b0, b1, kp);
	f_nround(b1, b0, kp);
	f_nround(b0, b1, kp);
	f_nround(b1, b0, kp);
	f_nround(b0, b1, kp);
	f_nround(b1, b0, kp);
	f_lround(b0, b1, kp);

	dst[0] = cpu_to_le32(b0[0]);
	dst[1] = cpu_to_le32(b0[1]);
	dst[2] = cpu_to_le32(b0[2]);
	dst[3] = cpu_to_le32(b0[3]);
}

/* decrypt a block of text */

#define i_rn(bo, bi, n, k)	do {				\
	bo[n] = crypto_it_tab[0][byte(bi[n], 0)] ^			\
		crypto_it_tab[1][byte(bi[(n + 3) & 3], 1)] ^		\
		crypto_it_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
		crypto_it_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n);	\
} while (0)

#define i_nround(bo, bi, k)	do {\
	i_rn(bo, bi, 0, k);	\
	i_rn(bo, bi, 1, k);	\
	i_rn(bo, bi, 2, k);	\
	i_rn(bo, bi, 3, k);	\
	k += 4;			\
} while (0)

#define i_rl(bo, bi, n, k)	do {			\
	bo[n] = crypto_il_tab[0][byte(bi[n], 0)] ^		\
	crypto_il_tab[1][byte(bi[(n + 3) & 3], 1)] ^		\
	crypto_il_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
	crypto_il_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n);	\
} while (0)

#define i_lround(bo, bi, k)	do {\
	i_rl(bo, bi, 0, k);	\
	i_rl(bo, bi, 1, k);	\
	i_rl(bo, bi, 2, k);	\
	i_rl(bo, bi, 3, k);	\
} while (0)

static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
	const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
	const __le32 *src = (const __le32 *)in;
	__le32 *dst = (__le32 *)out;
	u32 b0[4], b1[4];
	const int key_len = ctx->key_length;
	const u32 *kp = ctx->key_dec + 4;

	b0[0] = le32_to_cpu(src[0]) ^  ctx->key_dec[0];
	b0[1] = le32_to_cpu(src[1]) ^  ctx->key_dec[1];
	b0[2] = le32_to_cpu(src[2]) ^  ctx->key_dec[2];
	b0[3] = le32_to_cpu(src[3]) ^  ctx->key_dec[3];

	if (key_len > 24) {
		i_nround(b1, b0, kp);
		i_nround(b0, b1, kp);
	}

	if (key_len > 16) {
		i_nround(b1, b0, kp);
		i_nround(b0, b1, kp);
	}

	i_nround(b1, b0, kp);
	i_nround(b0, b1, kp);
	i_nround(b1, b0, kp);
	i_nround(b0, b1, kp);
	i_nround(b1, b0, kp);
	i_nround(b0, b1, kp);
	i_nround(b1, b0, kp);
	i_nround(b0, b1, kp);
	i_nround(b1, b0, kp);
	i_lround(b0, b1, kp);

	dst[0] = cpu_to_le32(b0[0]);
	dst[1] = cpu_to_le32(b0[1]);
	dst[2] = cpu_to_le32(b0[2]);
	dst[3] = cpu_to_le32(b0[3]);
}

static struct crypto_alg aes_alg = {
	.cra_name		=	"aes",
	.cra_driver_name	=	"aes-generic",
	.cra_priority		=	100,
	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
	.cra_blocksize		=	AES_BLOCK_SIZE,
	.cra_ctxsize		=	sizeof(struct crypto_aes_ctx),
	.cra_alignmask		=	3,
	.cra_module		=	THIS_MODULE,
	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
	.cra_u			=	{
		.cipher = {
			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
			.cia_setkey		=	crypto_aes_set_key,
			.cia_encrypt		=	aes_encrypt,
			.cia_decrypt		=	aes_decrypt
		}
	}
};

static int __init aes_init(void)
{
	gen_tabs();
	return crypto_register_alg(&aes_alg);
}

static void __exit aes_fini(void)
{
	crypto_unregister_alg(&aes_alg);
}

module_init(aes_init);
module_exit(aes_fini);

MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("aes");
back to top