Commit 48565b09 authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5

into kernel.bkbits.net:/home/davem/net-2.5
parents 27d23d3f e74356b9
...@@ -186,6 +186,7 @@ Original developers of the crypto algorithms: ...@@ -186,6 +186,7 @@ Original developers of the crypto algorithms:
Kazunori Miyazawa / USAGI (HMAC) Kazunori Miyazawa / USAGI (HMAC)
Matthew Skala (Twofish) Matthew Skala (Twofish)
Dag Arne Osvik (Serpent) Dag Arne Osvik (Serpent)
Brian Gladman (AES)
DES algorithm contributors: DES algorithm contributors:
Raimar Falke Raimar Falke
...@@ -203,6 +204,10 @@ Twofish algorithm contributors: ...@@ -203,6 +204,10 @@ Twofish algorithm contributors:
SHA256 algorithm contributors: SHA256 algorithm contributors:
Andrew McDonald Andrew McDonald
AES algorithm contributors:
Alexander Kjeldaas
Adam J. Richter
Please send any credits updates or corrections to: Please send any credits updates or corrections to:
James Morris <jmorris@intercode.com.au> James Morris <jmorris@intercode.com.au>
...@@ -1462,10 +1462,14 @@ routing issues. ...@@ -1462,10 +1462,14 @@ routing issues.
error_burst and error_cost error_burst and error_cost
-------------------------- --------------------------
These parameters are used to limit the warning messages written to the kernel These parameters are used to limit how many ICMP destination unreachable to
log from the routing code. The higher the error_cost factor is, the fewer send from the host in question. ICMP destination unreachable messages are
messages will be written. Error_burst controls when messages will be dropped. sent when we can not reach the next hop, while trying to transmit a packet.
The default settings limit warning messages to one every five seconds. It will also print some error messages to kernel logs if someone is ignoring
our ICMP redirects. The higher the error_cost factor is, the fewer
destination unreachable and error messages will be let through. Error_burst
controls when destination unreachable messages and error messages will be
dropped. The default settings limit warning messages to five every second.
flush flush
----- -----
......
...@@ -94,6 +94,26 @@ config CRYPTO_SERPENT ...@@ -94,6 +94,26 @@ config CRYPTO_SERPENT
See also: See also:
http://www.cl.cam.ac.uk/~rja14/serpent.html http://www.cl.cam.ac.uk/~rja14/serpent.html
config CRYPTO_AES
tristate "AES cipher algorithms"
depends on CRYPTO
help
AES cipher algorithms (FIPS-197). AES uses the Rijndael
algorithm.
Rijndael appears to be consistently a very good performer in
both hardware and software across a wide range of computing
environments regardless of its use in feedback or non-feedback
modes. Its key setup time is excellent, and its key agility is
good. Rijndael's very low memory requirements make it very well
suited for restricted-space environments, in which it also
demonstrates excellent performance. Rijndael's operations are
among the easiest to defend against power and timing attacks.
The AES specifies three key sizes: 128, 192 and 256 bits
See http://csrc.nist.gov/encryption/aes/ for more information.
config CRYPTO_TEST config CRYPTO_TEST
tristate "Testing module" tristate "Testing module"
depends on CRYPTO depends on CRYPTO
......
...@@ -20,5 +20,6 @@ obj-$(CONFIG_CRYPTO_DES) += des.o ...@@ -20,5 +20,6 @@ obj-$(CONFIG_CRYPTO_DES) += des.o
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
obj-$(CONFIG_CRYPTO_AES) += aes.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
/*
* Cryptographic API.
*
* AES Cipher Algorithm.
*
* Based on Brian Gladman's code.
*
* Linux developers:
* Alexander Kjeldaas <astor@fast.no>
* 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.
* ---------------------------------------------------------------------------
*/
/* Some changes from the Gladman version:
s/RIJNDAEL(e_key)/E_KEY/g
s/RIJNDAEL(d_key)/D_KEY/g
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/crypto.h>
#include <asm/byteorder.h>
#define AES_MIN_KEY_SIZE 16
#define AES_MAX_KEY_SIZE 32
#define AES_BLOCK_SIZE 16
static inline
u32 generic_rotr32 (const u32 x, const unsigned bits)
{
const unsigned n = bits % 32;
return (x >> n) | (x << (32 - n));
}
static inline
u32 generic_rotl32 (const u32 x, const unsigned bits)
{
const unsigned n = bits % 32;
return (x << n) | (x >> (32 - n));
}
#define rotl generic_rotl32
#define rotr generic_rotr32
/*
* #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
*/
inline static u8
byte(const u32 x, const unsigned n)
{
return x >> (n << 3);
}
#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
struct aes_ctx {
int key_length;
u32 E[60];
u32 D[60];
};
#define E_KEY ctx->E
#define D_KEY ctx->D
static u8 pow_tab[256];
static u8 log_tab[256];
static u8 sbx_tab[256];
static u8 isb_tab[256];
static u32 rco_tab[10];
static u32 ft_tab[4][256];
static u32 it_tab[4][256];
static u32 fl_tab[4][256];
static u32 il_tab[4][256];
static inline u8
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)
#define f_rn(bo, bi, n, k) \
bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rn(bo, bi, n, k) \
bo[n] = it_tab[0][byte(bi[n],0)] ^ \
it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
#define ls_box(x) \
( fl_tab[0][byte(x, 0)] ^ \
fl_tab[1][byte(x, 1)] ^ \
fl_tab[2][byte(x, 2)] ^ \
fl_tab[3][byte(x, 3)] )
#define f_rl(bo, bi, n, k) \
bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rl(bo, bi, n, k) \
bo[n] = il_tab[0][byte(bi[n],0)] ^ \
il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
static void
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 prmitive
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;
fl_tab[0][i] = t;
fl_tab[1][i] = rotl (t, 8);
fl_tab[2][i] = rotl (t, 16);
fl_tab[3][i] = rotl (t, 24);
t = ((u32) ff_mult (2, p)) |
((u32) p << 8) |
((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
ft_tab[0][i] = t;
ft_tab[1][i] = rotl (t, 8);
ft_tab[2][i] = rotl (t, 16);
ft_tab[3][i] = rotl (t, 24);
p = isb_tab[i];
t = p;
il_tab[0][i] = t;
il_tab[1][i] = rotl (t, 8);
il_tab[2][i] = rotl (t, 16);
il_tab[3][i] = rotl (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);
it_tab[0][i] = t;
it_tab[1][i] = rotl (t, 8);
it_tab[2][i] = rotl (t, 16);
it_tab[3][i] = rotl (t, 24);
}
}
#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
#define imix_col(y,x) \
u = star_x(x); \
v = star_x(u); \
w = star_x(v); \
t = w ^ (x); \
(y) = u ^ v ^ w; \
(y) ^= rotr(u ^ t, 8) ^ \
rotr(v ^ t, 16) ^ \
rotr(t,24)
/* initialise the key schedule from the user supplied key */
#define loop4(i) \
{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \
t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \
t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \
t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \
}
#define loop6(i) \
{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \
t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \
t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \
t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \
t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \
t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \
}
#define loop8(i) \
{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \
t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \
t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \
t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \
t = E_KEY[8 * i + 4] ^ ls_box(t); \
E_KEY[8 * i + 12] = t; \
t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \
t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \
t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \
}
static int
aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
{
struct aes_ctx *ctx = ctx_arg;
u32 i, t, u, v, w;
if (key_len != 16 && key_len != 24 && key_len != 32) {
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
}
ctx->key_length = key_len;
E_KEY[0] = u32_in (in_key);
E_KEY[1] = u32_in (in_key + 4);
E_KEY[2] = u32_in (in_key + 8);
E_KEY[3] = u32_in (in_key + 12);
switch (key_len) {
case 16:
t = E_KEY[3];
for (i = 0; i < 10; ++i)
loop4 (i);
break;
case 24:
E_KEY[4] = u32_in (in_key + 16);
t = E_KEY[5] = u32_in (in_key + 20);
for (i = 0; i < 8; ++i)
loop6 (i);
break;
case 32:
E_KEY[4] = u32_in (in_key + 16);
E_KEY[5] = u32_in (in_key + 20);
E_KEY[6] = u32_in (in_key + 24);
t = E_KEY[7] = u32_in (in_key + 28);
for (i = 0; i < 7; ++i)
loop8 (i);
break;
}
D_KEY[0] = E_KEY[0];
D_KEY[1] = E_KEY[1];
D_KEY[2] = E_KEY[2];
D_KEY[3] = E_KEY[3];
for (i = 4; i < key_len + 24; ++i) {
imix_col (D_KEY[i], E_KEY[i]);
}
return 0;
}
/* encrypt a block of text */
#define f_nround(bo, bi, k) \
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
#define f_lround(bo, bi, k) \
f_rl(bo, bi, 0, k); \
f_rl(bo, bi, 1, k); \
f_rl(bo, bi, 2, k); \
f_rl(bo, bi, 3, k)
static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
{
const struct aes_ctx *ctx = ctx_arg;
u32 b0[4], b1[4];
const u32 *kp = E_KEY + 4;
b0[0] = u32_in (in) ^ E_KEY[0];
b0[1] = u32_in (in + 4) ^ E_KEY[1];
b0[2] = u32_in (in + 8) ^ E_KEY[2];
b0[3] = u32_in (in + 12) ^ E_KEY[3];
if (ctx->key_length > 24) {
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
}
if (ctx->key_length > 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);
u32_out (out, b0[0]);
u32_out (out + 4, b0[1]);
u32_out (out + 8, b0[2]);
u32_out (out + 12, b0[3]);
}
/* decrypt a block of text */
#define i_nround(bo, bi, k) \
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
#define i_lround(bo, bi, k) \
i_rl(bo, bi, 0, k); \
i_rl(bo, bi, 1, k); \
i_rl(bo, bi, 2, k); \
i_rl(bo, bi, 3, k)
static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
{
const struct aes_ctx *ctx = ctx_arg;
u32 b0[4], b1[4];
const int key_len = ctx->key_length;
const u32 *kp = D_KEY + key_len + 20;
b0[0] = u32_in (in) ^ E_KEY[key_len + 24];
b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25];
b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26];
b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27];
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);
u32_out (out, b0[0]);
u32_out (out + 4, b0[1]);
u32_out (out + 8, b0[2]);
u32_out (out + 12, b0[3]);
}
static struct crypto_alg aes_alg = {
.cra_name = "aes",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct aes_ctx),
.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_ivsize = AES_BLOCK_SIZE,
.cia_setkey = 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");
...@@ -1983,6 +1983,111 @@ test_serpent(void) ...@@ -1983,6 +1983,111 @@ test_serpent(void)
crypto_free_tfm(tfm); crypto_free_tfm(tfm);
} }
void
test_aes(void)
{
unsigned int ret, i;
unsigned int tsize;
char *p, *q;
struct crypto_tfm *tfm;
char *key;
struct aes_tv *aes_tv;
struct scatterlist sg[1];
printk("\ntesting aes encryption\n");
tsize = sizeof (aes_enc_tv_template);
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
return;
}
memcpy(tvmem, aes_enc_tv_template, tsize);
aes_tv = (void *) tvmem;
tfm = crypto_alloc_tfm("aes", 0);
if (tfm == NULL) {
printk("failed to load transform for aes (default ecb)\n");
return;
}
for (i = 0; i < AES_ENC_TEST_VECTORS; i++) {
printk("test %u (%d bit key):\n",
i + 1, aes_tv[i].keylen * 8);
key = aes_tv[i].key;
ret = crypto_cipher_setkey(tfm, key, aes_tv[i].keylen);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
if (!aes_tv[i].fail)
goto out;
}
p = aes_tv[i].plaintext;
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = aes_tv[i].plen;
ret = crypto_cipher_encrypt(tfm, sg, 1);
if (ret) {
printk("encrypt() failed flags=%x\n", tfm->crt_flags);
goto out;
}
q = kmap(sg[0].page) + sg[0].offset;
hexdump(q, aes_tv[i].rlen);
printk("%s\n", memcmp(q, aes_tv[i].result, aes_tv[i].rlen) ?
"fail" : "pass");
}
printk("\ntesting aes decryption\n");
tsize = sizeof (aes_dec_tv_template);
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
return;
}
memcpy(tvmem, aes_dec_tv_template, tsize);
aes_tv = (void *) tvmem;
for (i = 0; i < AES_DEC_TEST_VECTORS; i++) {
printk("test %u (%d bit key):\n",
i + 1, aes_tv[i].keylen * 8);
key = aes_tv[i].key;
ret = crypto_cipher_setkey(tfm, key, aes_tv[i].keylen);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
if (!aes_tv[i].fail)
goto out;
}
p = aes_tv[i].plaintext;
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = aes_tv[i].plen;
ret = crypto_cipher_decrypt(tfm, sg, 1);
if (ret) {
printk("decrypt() failed flags=%x\n", tfm->crt_flags);
goto out;
}
q = kmap(sg[0].page) + sg[0].offset;
hexdump(q, aes_tv[i].rlen);
printk("%s\n", memcmp(q, aes_tv[i].result, aes_tv[i].rlen) ?
"fail" : "pass");
}
out:
crypto_free_tfm(tfm);
}
static void static void
test_available(void) test_available(void)
{ {
...@@ -2011,6 +2116,7 @@ do_test(void) ...@@ -2011,6 +2116,7 @@ do_test(void)
test_blowfish(); test_blowfish();
test_twofish(); test_twofish();
test_serpent(); test_serpent();
test_aes();
#ifdef CONFIG_CRYPTO_HMAC #ifdef CONFIG_CRYPTO_HMAC
test_hmac_md5(); test_hmac_md5();
test_hmac_sha1(); test_hmac_sha1();
...@@ -2054,6 +2160,10 @@ do_test(void) ...@@ -2054,6 +2160,10 @@ do_test(void)
test_serpent(); test_serpent();
break; break;
case 10:
test_aes();
break;
#ifdef CONFIG_CRYPTO_HMAC #ifdef CONFIG_CRYPTO_HMAC
case 100: case 100:
test_hmac_md5(); test_hmac_md5();
......
...@@ -1480,4 +1480,97 @@ struct serpent_tv serpent_dec_tv_template[] = ...@@ -1480,4 +1480,97 @@ struct serpent_tv serpent_dec_tv_template[] =
} }
}; };
/*
* AES test vectors.
*/
#define AES_ENC_TEST_VECTORS 3
#define AES_DEC_TEST_VECTORS 3
struct aes_tv {
unsigned int keylen;
unsigned int plen;
unsigned int rlen;
int fail;
char key[32];
char iv[8];
char plaintext[16];
char result[16];
};
struct aes_tv aes_enc_tv_template[] = {
/* From FIPS-197 */
{
16, 16, 16, 0,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
{ 0 },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
{ 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
},
{
24, 16, 16, 0,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
{ 0 },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
{ 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
},
{
32, 16, 16, 0,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
{ 0 },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
{ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
},
};
struct aes_tv aes_dec_tv_template[] = {
/* From FIPS-197 */
{
16, 16, 16, 0,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
{ 0 },
{ 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
},
{
24, 16, 16, 0,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
{ 0 },
{ 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
},
{
32, 16, 16, 0,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
{ 0 },
{ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
},
};
#endif /* _CRYPTO_TCRYPT_H */ #endif /* _CRYPTO_TCRYPT_H */
...@@ -245,14 +245,22 @@ struct sadb_x_ipsecrequest { ...@@ -245,14 +245,22 @@ struct sadb_x_ipsecrequest {
#define SADB_AALG_NONE 0 #define SADB_AALG_NONE 0
#define SADB_AALG_MD5HMAC 2 #define SADB_AALG_MD5HMAC 2
#define SADB_AALG_SHA1HMAC 3 #define SADB_AALG_SHA1HMAC 3
#define SADB_AALG_MAX 3 #define SADB_X_AALG_SHA2_256HMAC 5
#define SADB_X_AALG_SHA2_384HMAC 6
#define SADB_X_AALG_SHA2_512HMAC 7
#define SADB_X_AALG_RIPEMD160HMAC 8
#define SADB_X_AALG_NULL 251 /* kame */
#define SADB_AALG_MAX 251
/* Encryption algorithms */ /* Encryption algorithms */
#define SADB_EALG_NONE 0 #define SADB_EALG_NONE 0
#define SADB_EALG_DESCBC 1 #define SADB_EALG_DESCBC 1
#define SADB_EALG_3DESCBC 2 #define SADB_EALG_3DESCBC 2
#define SADB_X_EALG_CASTCBC 6
#define SADB_X_EALG_BLOWFISHCBC 7
#define SADB_EALG_NULL 11 #define SADB_EALG_NULL 11
#define SADB_EALG_MAX 11 #define SADB_X_EALG_AESCBC 12
#define SADB_EALG_MAX 12
/* Extension Header values */ /* Extension Header values */
#define SADB_EXT_RESERVED 0 #define SADB_EXT_RESERVED 0
......
...@@ -637,8 +637,7 @@ DECLARE_SNMP_STAT(struct tcp_mib, tcp_statistics); ...@@ -637,8 +637,7 @@ DECLARE_SNMP_STAT(struct tcp_mib, tcp_statistics);
#define TCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(tcp_statistics, field) #define TCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(tcp_statistics, field)
#define TCP_DEC_STATS(field) SNMP_DEC_STATS(tcp_statistics, field) #define TCP_DEC_STATS(field) SNMP_DEC_STATS(tcp_statistics, field)
extern void tcp_put_port(struct sock *sk); extern __inline__ void tcp_put_port(struct sock *sk);
extern void __tcp_put_port(struct sock *sk);
extern void tcp_inherit_port(struct sock *sk, struct sock *child); extern void tcp_inherit_port(struct sock *sk, struct sock *child);
extern void tcp_v4_err(struct sk_buff *skb, u32); extern void tcp_v4_err(struct sk_buff *skb, u32);
......
#ifndef _NET_XFRM_H
#define _NET_XFRM_H
#include <linux/xfrm.h> #include <linux/xfrm.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/pfkeyv2.h>
#include <net/dst.h> #include <net/dst.h>
#include <net/route.h> #include <net/route.h>
#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
extern struct semaphore xfrm_cfg_sem; extern struct semaphore xfrm_cfg_sem;
/* Organization of SPD aka "XFRM rules" /* Organization of SPD aka "XFRM rules"
...@@ -347,6 +353,29 @@ static inline void xfrm_sk_free_policy(struct sock *sk) ...@@ -347,6 +353,29 @@ static inline void xfrm_sk_free_policy(struct sock *sk)
} }
} }
/*
* xfrm algorithm information
*/
struct xfrm_algo_auth_info {
u16 icv_truncbits;
u16 icv_fullbits;
};
struct xfrm_algo_encr_info {
u16 blockbits;
u16 defkeybits;
};
struct xfrm_algo_desc {
char *name;
u8 available:1;
union {
struct xfrm_algo_auth_info auth;
struct xfrm_algo_encr_info encr;
} uinfo;
struct sadb_alg desc;
};
extern void xfrm_state_init(void); extern void xfrm_state_init(void);
extern void xfrm_input_init(void); extern void xfrm_input_init(void);
extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *); extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
...@@ -385,3 +414,15 @@ extern wait_queue_head_t km_waitq; ...@@ -385,3 +414,15 @@ extern wait_queue_head_t km_waitq;
extern void km_warn_expired(struct xfrm_state *x); extern void km_warn_expired(struct xfrm_state *x);
extern void km_expired(struct xfrm_state *x); extern void km_expired(struct xfrm_state *x);
extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol); extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol);
extern void xfrm_probe_algs(void);
extern int xfrm_count_auth_supported(void);
extern int xfrm_count_enc_supported(void);
extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name);
extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name);
#endif /* _NET_XFRM_H */
...@@ -225,7 +225,7 @@ struct sk_buff *alloc_skb(unsigned int size, int gfp_mask) ...@@ -225,7 +225,7 @@ struct sk_buff *alloc_skb(unsigned int size, int gfp_mask)
/* /*
* Slab constructor for a skb head. * Slab constructor for a skb head.
*/ */
static inline void skb_headerinit(void *p, kmem_cache_t *cache, static void skb_headerinit(void *p, kmem_cache_t *cache,
unsigned long flags) unsigned long flags)
{ {
struct sk_buff *skb = p; struct sk_buff *skb = p;
......
...@@ -22,4 +22,4 @@ obj-$(CONFIG_IP_PNP) += ipconfig.o ...@@ -22,4 +22,4 @@ obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_XFRM_USER) += xfrm_user.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o
obj-y += xfrm_policy.o xfrm_state.o xfrm_input.o obj-y += xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o
...@@ -7,26 +7,31 @@ ...@@ -7,26 +7,31 @@
#include <net/icmp.h> #include <net/icmp.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
#define AH_HLEN_NOICV 12
typedef void (icv_update_fn_t)(struct crypto_tfm *,
struct scatterlist *, unsigned int);
struct ah_data struct ah_data
{ {
u8 *key; u8 *key;
int key_len; int key_len;
u8 *work_digest; u8 *work_icv;
int digest_len; int icv_full_len;
int icv_trunc_len;
void (*digest)(struct ah_data*, void (*icv)(struct ah_data*,
struct sk_buff *skb, struct sk_buff *skb, u8 *icv);
u8 *digest);
struct crypto_tfm *tfm; struct crypto_tfm *tfm;
}; };
/* Clear mutable options and find final destination to substitute /* Clear mutable options and find final destination to substitute
* into IP header for digest calculation. Options are already checked * into IP header for icv calculation. Options are already checked
* for validity, so paranoia is not required. */ * for validity, so paranoia is not required. */
int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr) static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr)
{ {
unsigned char * optptr = (unsigned char*)(iph+1); unsigned char * optptr = (unsigned char*)(iph+1);
int l = iph->ihl*4 - 20; int l = iph->ihl*4 - 20;
...@@ -66,7 +71,8 @@ int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr) ...@@ -66,7 +71,8 @@ int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr)
return 0; return 0;
} }
void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm) static void skb_ah_walk(const struct sk_buff *skb,
struct crypto_tfm *tfm, icv_update_fn_t icv_update)
{ {
int offset = 0; int offset = 0;
int len = skb->len; int len = skb->len;
...@@ -83,7 +89,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm) ...@@ -83,7 +89,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm)
sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
sg.length = copy; sg.length = copy;
crypto_hmac_update(tfm, &sg, 1); icv_update(tfm, &sg, 1);
if ((len -= copy) == 0) if ((len -= copy) == 0)
return; return;
...@@ -106,7 +112,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm) ...@@ -106,7 +112,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm)
sg.offset = frag->page_offset + offset-start; sg.offset = frag->page_offset + offset-start;
sg.length = copy; sg.length = copy;
crypto_hmac_update(tfm, &sg, 1); icv_update(tfm, &sg, 1);
if (!(len -= copy)) if (!(len -= copy))
return; return;
...@@ -127,7 +133,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm) ...@@ -127,7 +133,7 @@ void skb_ah_walk(const struct sk_buff *skb, struct crypto_tfm *tfm)
if ((copy = end - offset) > 0) { if ((copy = end - offset) > 0) {
if (copy > len) if (copy > len)
copy = len; copy = len;
skb_ah_walk(list, tfm); skb_ah_walk(list, tfm, icv_update);
if ((len -= copy) == 0) if ((len -= copy) == 0)
return; return;
offset += copy; offset += copy;
...@@ -144,14 +150,14 @@ ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) ...@@ -144,14 +150,14 @@ ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
{ {
struct crypto_tfm *tfm = ahp->tfm; struct crypto_tfm *tfm = ahp->tfm;
memset(auth_data, 0, ahp->digest_len); memset(auth_data, 0, ahp->icv_trunc_len);
crypto_hmac_init(tfm, ahp->key, &ahp->key_len); crypto_hmac_init(tfm, ahp->key, &ahp->key_len);
skb_ah_walk(skb, tfm); skb_ah_walk(skb, tfm, crypto_hmac_update);
crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_digest); crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv);
memcpy(auth_data, ahp->work_digest, ahp->digest_len); memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len);
} }
int ah_output(struct sk_buff *skb) static int ah_output(struct sk_buff *skb)
{ {
int err; int err;
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
...@@ -210,11 +216,13 @@ int ah_output(struct sk_buff *skb) ...@@ -210,11 +216,13 @@ int ah_output(struct sk_buff *skb)
ah->nexthdr = iph->protocol; ah->nexthdr = iph->protocol;
} }
ahp = x->data; ahp = x->data;
ah->hdrlen = (((ahp->digest_len + 12 + 7)&~7)>>2)-2; ah->hdrlen = (XFRM_ALIGN8(ahp->icv_trunc_len +
AH_HLEN_NOICV) >> 2) - 2;
ah->reserved = 0; ah->reserved = 0;
ah->spi = x->id.spi; ah->spi = x->id.spi;
ah->seq_no = htonl(++x->replay.oseq); ah->seq_no = htonl(++x->replay.oseq);
ahp->digest(ahp, skb, ah->auth_data); ahp->icv(ahp, skb, ah->auth_data);
top_iph->tos = iph->tos; top_iph->tos = iph->tos;
top_iph->ttl = iph->ttl; top_iph->ttl = iph->ttl;
if (x->props.mode) { if (x->props.mode) {
...@@ -246,6 +254,7 @@ int ah_output(struct sk_buff *skb) ...@@ -246,6 +254,7 @@ int ah_output(struct sk_buff *skb)
int ah_input(struct xfrm_state *x, struct sk_buff *skb) int ah_input(struct xfrm_state *x, struct sk_buff *skb)
{ {
int ah_hlen;
struct iphdr *iph; struct iphdr *iph;
struct ip_auth_hdr *ah; struct ip_auth_hdr *ah;
struct ah_data *ahp; struct ah_data *ahp;
...@@ -255,13 +264,14 @@ int ah_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -255,13 +264,14 @@ int ah_input(struct xfrm_state *x, struct sk_buff *skb)
goto out; goto out;
ah = (struct ip_auth_hdr*)skb->data; ah = (struct ip_auth_hdr*)skb->data;
ahp = x->data; ahp = x->data;
ah_hlen = (ah->hdrlen + 2) << 2;
if (((ah->hdrlen+2)<<2) != ((ahp->digest_len + 12 + 7)&~7)) if (ah_hlen != XFRM_ALIGN8(ahp->icv_full_len + AH_HLEN_NOICV) &&
ah_hlen != XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV))
goto out; goto out;
if (!pskb_may_pull(skb, (ah->hdrlen+2)<<2)) if (!pskb_may_pull(skb, ah_hlen))
goto out; goto out;
/* We are going to _remove_ AH header to keep sockets happy, /* We are going to _remove_ AH header to keep sockets happy,
...@@ -285,17 +295,18 @@ int ah_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -285,17 +295,18 @@ int ah_input(struct xfrm_state *x, struct sk_buff *skb)
goto out; goto out;
} }
{ {
u8 auth_data[ahp->digest_len]; u8 auth_data[ahp->icv_trunc_len];
memcpy(auth_data, ah->auth_data, ahp->digest_len);
memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
skb_push(skb, skb->data - skb->nh.raw); skb_push(skb, skb->data - skb->nh.raw);
ahp->digest(ahp, skb, ah->auth_data); ahp->icv(ahp, skb, ah->auth_data);
if (memcmp(ah->auth_data, auth_data, ahp->digest_len)) { if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
x->stats.integrity_failed++; x->stats.integrity_failed++;
goto out; goto out;
} }
} }
((struct iphdr*)work_buf)->protocol = ah->nexthdr; ((struct iphdr*)work_buf)->protocol = ah->nexthdr;
skb->nh.raw = skb_pull(skb, (ah->hdrlen+2)<<2); skb->nh.raw = skb_pull(skb, ah_hlen);
memcpy(skb->nh.raw, work_buf, iph->ihl*4); memcpy(skb->nh.raw, work_buf, iph->ihl*4);
skb->nh.iph->tot_len = htons(skb->len); skb->nh.iph->tot_len = htons(skb->len);
skb_pull(skb, skb->nh.iph->ihl*4); skb_pull(skb, skb->nh.iph->ihl*4);
...@@ -325,12 +336,13 @@ void ah4_err(struct sk_buff *skb, u32 info) ...@@ -325,12 +336,13 @@ void ah4_err(struct sk_buff *skb, u32 info)
xfrm_state_put(x); xfrm_state_put(x);
} }
int ah_init_state(struct xfrm_state *x, void *args) static int ah_init_state(struct xfrm_state *x, void *args)
{ {
struct ah_data *ahp = NULL; struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
if (x->aalg == NULL || x->aalg->alg_key_len == 0 || /* null auth can use a zero length key */
x->aalg->alg_key_len > 512) if (x->aalg->alg_key_len > 512)
goto error; goto error;
ahp = kmalloc(sizeof(*ahp), GFP_KERNEL); ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
...@@ -344,13 +356,33 @@ int ah_init_state(struct xfrm_state *x, void *args) ...@@ -344,13 +356,33 @@ int ah_init_state(struct xfrm_state *x, void *args)
ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
if (!ahp->tfm) if (!ahp->tfm)
goto error; goto error;
ahp->digest = ah_hmac_digest; ahp->icv = ah_hmac_digest;
ahp->digest_len = 12;
ahp->work_digest = kmalloc(crypto_tfm_alg_digestsize(ahp->tfm), /*
GFP_KERNEL); * Lookup the algorithm description maintained by pfkey,
if (!ahp->work_digest) * verify crypto transform properties, and store information
* we need for AH processing. This lookup cannot fail here
* after a successful crypto_alloc_tfm().
*/
aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
BUG_ON(!aalg_desc);
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
crypto_tfm_alg_digestsize(ahp->tfm)) {
printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm),
aalg_desc->uinfo.auth.icv_fullbits/8);
goto error; goto error;
x->props.header_len = (12 + ahp->digest_len + 7)&~7; }
ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
if (!ahp->work_icv)
goto error;
x->props.header_len = XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV);
if (x->props.mode) if (x->props.mode)
x->props.header_len += 20; x->props.header_len += 20;
x->data = ahp; x->data = ahp;
...@@ -359,8 +391,8 @@ int ah_init_state(struct xfrm_state *x, void *args) ...@@ -359,8 +391,8 @@ int ah_init_state(struct xfrm_state *x, void *args)
error: error:
if (ahp) { if (ahp) {
if (ahp->work_digest) if (ahp->work_icv)
kfree(ahp->work_digest); kfree(ahp->work_icv);
if (ahp->tfm) if (ahp->tfm)
crypto_free_tfm(ahp->tfm); crypto_free_tfm(ahp->tfm);
kfree(ahp); kfree(ahp);
...@@ -368,13 +400,13 @@ int ah_init_state(struct xfrm_state *x, void *args) ...@@ -368,13 +400,13 @@ int ah_init_state(struct xfrm_state *x, void *args)
return -EINVAL; return -EINVAL;
} }
void ah_destroy(struct xfrm_state *x) static void ah_destroy(struct xfrm_state *x)
{ {
struct ah_data *ahp = x->data; struct ah_data *ahp = x->data;
if (ahp->work_digest) { if (ahp->work_icv) {
kfree(ahp->work_digest); kfree(ahp->work_icv);
ahp->work_digest = NULL; ahp->work_icv = NULL;
} }
if (ahp->tfm) { if (ahp->tfm) {
crypto_free_tfm(ahp->tfm); crypto_free_tfm(ahp->tfm);
...@@ -399,7 +431,7 @@ static struct inet_protocol ah4_protocol = { ...@@ -399,7 +431,7 @@ static struct inet_protocol ah4_protocol = {
.no_policy = 1, .no_policy = 1,
}; };
int __init ah4_init(void) static int __init ah4_init(void)
{ {
SET_MODULE_OWNER(&ah_type); SET_MODULE_OWNER(&ah_type);
if (xfrm_register_type(&ah_type) < 0) { if (xfrm_register_type(&ah_type) < 0) {
......
...@@ -137,12 +137,12 @@ static __inline__ struct fib_node * fz_chain(fn_key_t key, struct fn_zone *fz) ...@@ -137,12 +137,12 @@ static __inline__ struct fib_node * fz_chain(fn_key_t key, struct fn_zone *fz)
return fz->fz_hash[fn_hash(key, fz).datum]; return fz->fz_hash[fn_hash(key, fz).datum];
} }
extern __inline__ int fn_key_eq(fn_key_t a, fn_key_t b) static __inline__ int fn_key_eq(fn_key_t a, fn_key_t b)
{ {
return a.datum == b.datum; return a.datum == b.datum;
} }
extern __inline__ int fn_key_leq(fn_key_t a, fn_key_t b) static __inline__ int fn_key_leq(fn_key_t a, fn_key_t b)
{ {
return a.datum <= b.datum; return a.datum <= b.datum;
} }
...@@ -703,7 +703,7 @@ FTprint("tb(%d)_delete: %d %08x/%d %d\n", tb->tb_id, r->rtm_type, rta->rta_dst ? ...@@ -703,7 +703,7 @@ FTprint("tb(%d)_delete: %d %08x/%d %d\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
return -ESRCH; return -ESRCH;
} }
extern __inline__ int static __inline__ int
fn_flush_list(struct fib_node ** fp, int z, struct fn_hash *table) fn_flush_list(struct fib_node ** fp, int z, struct fn_hash *table)
{ {
int found = 0; int found = 0;
......
...@@ -185,7 +185,7 @@ static __inline__ void ipq_put(struct ipq *ipq) ...@@ -185,7 +185,7 @@ static __inline__ void ipq_put(struct ipq *ipq)
/* Kill ipq entry. It is not destroyed immediately, /* Kill ipq entry. It is not destroyed immediately,
* because caller (and someone more) holds reference count. * because caller (and someone more) holds reference count.
*/ */
static __inline__ void ipq_kill(struct ipq *ipq) static void ipq_kill(struct ipq *ipq)
{ {
if (del_timer(&ipq->timer)) if (del_timer(&ipq->timer))
atomic_dec(&ipq->refcnt); atomic_dec(&ipq->refcnt);
......
...@@ -198,7 +198,7 @@ static inline int ip_finish_output2(struct sk_buff *skb) ...@@ -198,7 +198,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
return -EINVAL; return -EINVAL;
} }
__inline__ int ip_finish_output(struct sk_buff *skb) int ip_finish_output(struct sk_buff *skb)
{ {
struct net_device *dev = skb->dst->dev; struct net_device *dev = skb->dst->dev;
...@@ -685,7 +685,7 @@ skb_can_coalesce(struct sk_buff *skb, int i, struct page *page, int off) ...@@ -685,7 +685,7 @@ skb_can_coalesce(struct sk_buff *skb, int i, struct page *page, int off)
return 0; return 0;
} }
static inline void static void
skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size) skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size)
{ {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
......
...@@ -201,7 +201,7 @@ struct rt_cache_stat *rt_cache_stat; ...@@ -201,7 +201,7 @@ struct rt_cache_stat *rt_cache_stat;
static int rt_intern_hash(unsigned hash, struct rtable *rth, static int rt_intern_hash(unsigned hash, struct rtable *rth,
struct rtable **res); struct rtable **res);
static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos) static unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
{ {
unsigned hash = ((daddr & 0xF0F0F0F0) >> 4) | unsigned hash = ((daddr & 0xF0F0F0F0) >> 4) |
((daddr & 0x0F0F0F0F) << 4); ((daddr & 0x0F0F0F0F) << 4);
...@@ -430,7 +430,7 @@ static __inline__ int rt_valuable(struct rtable *rth) ...@@ -430,7 +430,7 @@ static __inline__ int rt_valuable(struct rtable *rth)
rth->u.dst.expires; rth->u.dst.expires;
} }
static __inline__ int rt_may_expire(struct rtable *rth, int tmo1, int tmo2) static int rt_may_expire(struct rtable *rth, int tmo1, int tmo2)
{ {
int age; int age;
int ret = 0; int ret = 0;
......
...@@ -412,7 +412,7 @@ static void tcp_event_data_recv(struct sock *sk, struct tcp_opt *tp, struct sk_b ...@@ -412,7 +412,7 @@ static void tcp_event_data_recv(struct sock *sk, struct tcp_opt *tp, struct sk_b
* To save cycles in the RFC 1323 implementation it was better to break * To save cycles in the RFC 1323 implementation it was better to break
* it up into three procedures. -- erics * it up into three procedures. -- erics
*/ */
static __inline__ void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt) static void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt)
{ {
long m = mrtt; /* RTT */ long m = mrtt; /* RTT */
...@@ -2243,14 +2243,14 @@ static __inline__ int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr ...@@ -2243,14 +2243,14 @@ static __inline__ int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr
return 1; return 1;
} }
extern __inline__ void static __inline__ void
tcp_store_ts_recent(struct tcp_opt *tp) tcp_store_ts_recent(struct tcp_opt *tp)
{ {
tp->ts_recent = tp->rcv_tsval; tp->ts_recent = tp->rcv_tsval;
tp->ts_recent_stamp = xtime.tv_sec; tp->ts_recent_stamp = xtime.tv_sec;
} }
extern __inline__ void static __inline__ void
tcp_replace_ts_recent(struct tcp_opt *tp, u32 seq) tcp_replace_ts_recent(struct tcp_opt *tp, u32 seq)
{ {
if (tp->saw_tstamp && !after(seq, tp->rcv_wup)) { if (tp->saw_tstamp && !after(seq, tp->rcv_wup)) {
...@@ -2309,7 +2309,7 @@ static int tcp_disordered_ack(struct tcp_opt *tp, struct sk_buff *skb) ...@@ -2309,7 +2309,7 @@ static int tcp_disordered_ack(struct tcp_opt *tp, struct sk_buff *skb)
(s32)(tp->ts_recent - tp->rcv_tsval) <= (tp->rto*1024)/HZ); (s32)(tp->ts_recent - tp->rcv_tsval) <= (tp->rto*1024)/HZ);
} }
extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct sk_buff *skb) static __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct sk_buff *skb)
{ {
return ((s32)(tp->ts_recent - tp->rcv_tsval) > TCP_PAWS_WINDOW && return ((s32)(tp->ts_recent - tp->rcv_tsval) > TCP_PAWS_WINDOW &&
xtime.tv_sec < tp->ts_recent_stamp + TCP_PAWS_24DAYS && xtime.tv_sec < tp->ts_recent_stamp + TCP_PAWS_24DAYS &&
...@@ -3155,7 +3155,7 @@ static __inline__ void tcp_data_snd_check(struct sock *sk) ...@@ -3155,7 +3155,7 @@ static __inline__ void tcp_data_snd_check(struct sock *sk)
/* /*
* Check if sending an ack is needed. * Check if sending an ack is needed.
*/ */
static __inline__ void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
{ {
struct tcp_opt *tp = tcp_sk(sk); struct tcp_opt *tp = tcp_sk(sk);
...@@ -3265,7 +3265,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th) ...@@ -3265,7 +3265,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
} }
/* This is the 'fast' part of urgent handling. */ /* This is the 'fast' part of urgent handling. */
static inline void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th) static void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th)
{ {
struct tcp_opt *tp = tcp_sk(sk); struct tcp_opt *tp = tcp_sk(sk);
......
...@@ -286,7 +286,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum) ...@@ -286,7 +286,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
/* Get rid of any references to a local port held by the /* Get rid of any references to a local port held by the
* given sock. * given sock.
*/ */
__inline__ void __tcp_put_port(struct sock *sk) static void __tcp_put_port(struct sock *sk)
{ {
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(inet->num)]; struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(inet->num)];
...@@ -308,7 +308,7 @@ __inline__ void __tcp_put_port(struct sock *sk) ...@@ -308,7 +308,7 @@ __inline__ void __tcp_put_port(struct sock *sk)
spin_unlock(&head->lock); spin_unlock(&head->lock);
} }
void tcp_put_port(struct sock *sk) __inline__ void tcp_put_port(struct sock *sk)
{ {
local_bh_disable(); local_bh_disable();
__tcp_put_port(sk); __tcp_put_port(sk);
......
/*
* xfrm algorithm interface
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/pfkeyv2.h>
#include <net/xfrm.h>
/*
* Algorithms supported by IPsec. These entries contain properties which
* are used in key negotiation and xfrm processing, and are used to verify
* that instantiated crypto transforms have correct parameters for IPsec
* purposes.
*/
static struct xfrm_algo_desc aalg_list[] = {
{
.name = "digest_null",
.uinfo = {
.auth = {
.icv_truncbits = 0,
.icv_fullbits = 0,
}
},
.desc = {
.sadb_alg_id = SADB_X_AALG_NULL,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 0,
.sadb_alg_maxbits = 0
}
},
{
.name = "md5",
.uinfo = {
.auth = {
.icv_truncbits = 96,
.icv_fullbits = 128,
}
},
.desc = {
.sadb_alg_id = SADB_AALG_MD5HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 128,
.sadb_alg_maxbits = 128
}
},
{
.name = "sha1",
.uinfo = {
.auth = {
.icv_truncbits = 96,
.icv_fullbits = 160,
}
},
.desc = {
.sadb_alg_id = SADB_AALG_SHA1HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 160,
.sadb_alg_maxbits = 160
}
},
{
.name = "sha256",
.uinfo = {
.auth = {
.icv_truncbits = 128,
.icv_fullbits = 256,
}
},
.desc = {
.sadb_alg_id = SADB_X_AALG_SHA2_256HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 256,
.sadb_alg_maxbits = 256
}
},
{
.name = "ripemd160",
.uinfo = {
.auth = {
.icv_truncbits = 96,
.icv_fullbits = 160,
}
},
.desc = {
.sadb_alg_id = SADB_X_AALG_RIPEMD160HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 160,
.sadb_alg_maxbits = 160
}
},
};
static struct xfrm_algo_desc ealg_list[] = {
{
.name = "cipher_null",
.uinfo = {
.encr = {
.blockbits = 8,
.defkeybits = 0,
}
},
.desc = {
.sadb_alg_id = SADB_EALG_NULL,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 0,
.sadb_alg_maxbits = 0
}
},
{
.name = "des",
.uinfo = {
.encr = {
.blockbits = 64,
.defkeybits = 64,
}
},
.desc = {
.sadb_alg_id = SADB_EALG_DESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 64,
.sadb_alg_maxbits = 64
}
},
{
.name = "des3_ede",
.uinfo = {
.encr = {
.blockbits = 64,
.defkeybits = 192,
}
},
.desc = {
.sadb_alg_id = SADB_EALG_3DESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 192,
.sadb_alg_maxbits = 192
}
},
{
.name = "cast128",
.uinfo = {
.encr = {
.blockbits = 64,
.defkeybits = 128,
}
},
.desc = {
.sadb_alg_id = SADB_X_EALG_CASTCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 40,
.sadb_alg_maxbits = 128
}
},
{
.name = "blowfish",
.uinfo = {
.encr = {
.blockbits = 64,
.defkeybits = 128,
}
},
.desc = {
.sadb_alg_id = SADB_X_EALG_BLOWFISHCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 40,
.sadb_alg_maxbits = 448
}
},
{
.name = "aes",
.uinfo = {
.encr = {
.blockbits = 128,
.defkeybits = 128,
}
},
.desc = {
.sadb_alg_id = SADB_X_EALG_AESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 128,
.sadb_alg_maxbits = 256
}
},
};
static inline int aalg_entries(void)
{
return sizeof(aalg_list) / sizeof(aalg_list[0]);
}
static inline int ealg_entries(void)
{
return sizeof(ealg_list) / sizeof(ealg_list[0]);
}
struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
{
int i;
for (i = 0; i < aalg_entries(); i++) {
if (aalg_list[i].desc.sadb_alg_id == alg_id) {
if (aalg_list[i].available)
return &aalg_list[i];
else
break;
}
}
return NULL;
}
struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
{
int i;
for (i = 0; i < ealg_entries(); i++) {
if (ealg_list[i].desc.sadb_alg_id == alg_id) {
if (ealg_list[i].available)
return &ealg_list[i];
else
break;
}
}
return NULL;
}
struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name)
{
int i;
if (!name)
return NULL;
for (i=0; i < aalg_entries(); i++) {
if (strcmp(name, aalg_list[i].name) == 0) {
if (aalg_list[i].available)
return &aalg_list[i];
else
break;
}
}
return NULL;
}
struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name)
{
int i;
if (!name)
return NULL;
for (i=0; i < ealg_entries(); i++) {
if (strcmp(name, ealg_list[i].name) == 0) {
if (ealg_list[i].available)
return &ealg_list[i];
else
break;
}
}
return NULL;
}
struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
{
if (idx >= aalg_entries())
return NULL;
return &aalg_list[idx];
}
struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
{
if (idx >= ealg_entries())
return NULL;
return &ealg_list[idx];
}
/*
* Probe for the availability of crypto algorithms, and set the available
* flag for any algorithms found on the system. This is typically called by
* pfkey during userspace SA add, update or register.
*/
void xfrm_probe_algs(void)
{
int i, status;
BUG_ON(in_softirq());
for (i = 0; i < aalg_entries(); i++) {
status = crypto_alg_available(aalg_list[i].name, 0);
if (aalg_list[i].available != status)
aalg_list[i].available = status;
}
for (i = 0; i < ealg_entries(); i++) {
status = crypto_alg_available(ealg_list[i].name, 0);
if (ealg_list[i].available != status)
ealg_list[i].available = status;
}
}
int xfrm_count_auth_supported(void)
{
int i, n;
for (i = 0, n = 0; i < aalg_entries(); i++)
if (aalg_list[i].available)
n++;
return n;
}
int xfrm_count_enc_supported(void)
{
int i, n;
for (i = 0, n = 0; i < ealg_entries(); i++)
if (ealg_list[i].available)
n++;
return n;
}
...@@ -917,7 +917,7 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx) ...@@ -917,7 +917,7 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx)
return -1; return -1;
} }
static inline void static void
_decode_session(struct sk_buff *skb, struct flowi *fl) _decode_session(struct sk_buff *skb, struct flowi *fl)
{ {
struct iphdr *iph = skb->nh.iph; struct iphdr *iph = skb->nh.iph;
......
...@@ -553,118 +553,6 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void ** ...@@ -553,118 +553,6 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **
return x; return x;
} }
/* Table of algos supported by pfkeyv2 interface. */
struct algo_desc {
char *id;
struct sadb_alg desc;
};
struct algo_desc aalg_list[] = {
{ .id = NULL,
.desc = {
.sadb_alg_id = SADB_AALG_NONE,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 0,
.sadb_alg_maxbits = 0
}
},
{ .id = "md5",
.desc = {
.sadb_alg_id = SADB_AALG_MD5HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 128,
.sadb_alg_maxbits = 128
}
},
{ .id = "sha1",
.desc = {
.sadb_alg_id = SADB_AALG_SHA1HMAC,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 160,
.sadb_alg_maxbits = 160
}
}
};
struct algo_desc ealg_list[] = {
{ .id = NULL,
.desc = {
.sadb_alg_id = SADB_EALG_NONE,
.sadb_alg_ivlen = 0,
.sadb_alg_minbits = 0,
.sadb_alg_maxbits = 2048
}
},
{ .id = "des",
.desc = {
.sadb_alg_id = SADB_EALG_DESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 64,
.sadb_alg_maxbits = 64
}
},
{ .id = "des3_ede",
.desc = {
.sadb_alg_id = SADB_EALG_3DESCBC,
.sadb_alg_ivlen = 8,
.sadb_alg_minbits = 192,
.sadb_alg_maxbits = 192
}
}
};
static struct algo_desc *aalg_get_byid(int alg_id)
{
int i;
for (i=0; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) {
if (aalg_list[i].desc.sadb_alg_id == alg_id)
return &aalg_list[i];
}
return NULL;
}
static struct algo_desc *ealg_get_byid(int alg_id)
{
int i;
for (i=0; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) {
if (ealg_list[i].desc.sadb_alg_id == alg_id)
return &ealg_list[i];
}
return NULL;
}
static struct algo_desc *aalg_get_byname(char *name)
{
int i;
if (!name)
return NULL;
for (i=1; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) {
if (strcmp(name, aalg_list[i].id) == 0)
return &aalg_list[i];
}
return NULL;
}
static struct algo_desc *ealg_get_byname(char *name)
{
int i;
if (!name)
return NULL;
for (i=1; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) {
if (strcmp(name, ealg_list[i].id) == 0)
return &ealg_list[i];
}
return NULL;
}
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc) static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc)
{ {
...@@ -730,12 +618,12 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, ...@@ -730,12 +618,12 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
sa->sadb_sa_state = SADB_SASTATE_DEAD; sa->sadb_sa_state = SADB_SASTATE_DEAD;
sa->sadb_sa_auth = 0; sa->sadb_sa_auth = 0;
if (x->aalg) { if (x->aalg) {
struct algo_desc *a = aalg_get_byname(x->aalg->alg_name); struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name);
sa->sadb_sa_auth = a ? a->desc.sadb_alg_id : 0; sa->sadb_sa_auth = a ? a->desc.sadb_alg_id : 0;
} }
sa->sadb_sa_encrypt = 0; sa->sadb_sa_encrypt = 0;
if (x->ealg) { if (x->ealg) {
struct algo_desc *a = ealg_get_byname(x->ealg->alg_name); struct xfrm_algo_desc *a = xfrm_ealg_get_byname(x->ealg->alg_name);
sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0; sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0;
} }
sa->sadb_sa_flags = 0; sa->sadb_sa_flags = 0;
...@@ -938,7 +826,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -938,7 +826,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1]; key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
if (sa->sadb_sa_auth) { if (sa->sadb_sa_auth) {
int keysize = 0; int keysize = 0;
struct algo_desc *a = aalg_get_byid(sa->sadb_sa_auth); struct xfrm_algo_desc *a = xfrm_aalg_get_byid(sa->sadb_sa_auth);
if (!a) if (!a)
goto out; goto out;
if (key) if (key)
...@@ -946,7 +834,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -946,7 +834,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL); x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
if (!x->aalg) if (!x->aalg)
goto out; goto out;
strcpy(x->aalg->alg_name, a->id); strcpy(x->aalg->alg_name, a->name);
x->aalg->alg_key_len = 0; x->aalg->alg_key_len = 0;
if (key) { if (key) {
x->aalg->alg_key_len = key->sadb_key_bits; x->aalg->alg_key_len = key->sadb_key_bits;
...@@ -958,7 +846,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -958,7 +846,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
if (sa->sadb_sa_encrypt) { if (sa->sadb_sa_encrypt) {
int keysize = 0; int keysize = 0;
struct algo_desc *a = ealg_get_byid(sa->sadb_sa_encrypt); struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt);
if (!a) if (!a)
goto out; goto out;
if (key) if (key)
...@@ -966,7 +854,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -966,7 +854,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
if (!x->ealg) if (!x->ealg)
goto out; goto out;
strcpy(x->ealg->alg_name, a->id); strcpy(x->ealg->alg_name, a->name);
x->ealg->alg_key_len = 0; x->ealg->alg_key_len = 0;
if (key) { if (key) {
x->ealg->alg_key_len = key->sadb_key_bits; x->ealg->alg_key_len = key->sadb_key_bits;
...@@ -1131,6 +1019,8 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, ...@@ -1131,6 +1019,8 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
struct xfrm_state *x; struct xfrm_state *x;
struct xfrm_state *x1; struct xfrm_state *x1;
xfrm_probe_algs();
x = pfkey_msg2xfrm_state(hdr, ext_hdrs); x = pfkey_msg2xfrm_state(hdr, ext_hdrs);
if (IS_ERR(x)) if (IS_ERR(x))
return PTR_ERR(x); return PTR_ERR(x);
...@@ -1238,17 +1128,21 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat ...@@ -1238,17 +1128,21 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct sadb_msg *hdr; struct sadb_msg *hdr;
int len, ah_len, esp_len, i; int len, auth_len, enc_len, i;
ah_len = sizeof(aalg_list)/sizeof(aalg_list[0]) - 1; auth_len = xfrm_count_auth_supported();
ah_len *= sizeof(struct sadb_alg); if (auth_len) {
esp_len = sizeof(ealg_list)/sizeof(ealg_list[0]) - 1; auth_len *= sizeof(struct sadb_alg);
esp_len *= sizeof(struct sadb_alg); auth_len += sizeof(struct sadb_supported);
if (ah_len) }
ah_len += sizeof(struct sadb_supported);
if (esp_len) enc_len = xfrm_count_enc_supported();
esp_len += sizeof(struct sadb_supported); if (enc_len) {
len = esp_len + ah_len + sizeof(struct sadb_msg); enc_len *= sizeof(struct sadb_alg);
enc_len += sizeof(struct sadb_supported);
}
len = enc_len + auth_len + sizeof(struct sadb_msg);
skb = alloc_skb(len + 16, allocation); skb = alloc_skb(len + 16, allocation);
if (!skb) if (!skb)
...@@ -1259,32 +1153,42 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat ...@@ -1259,32 +1153,42 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat
hdr->sadb_msg_errno = 0; hdr->sadb_msg_errno = 0;
hdr->sadb_msg_len = len / sizeof(uint64_t); hdr->sadb_msg_len = len / sizeof(uint64_t);
if (ah_len) { if (auth_len) {
struct sadb_supported *sp; struct sadb_supported *sp;
struct sadb_alg *ap; struct sadb_alg *ap;
sp = (struct sadb_supported *) skb_put(skb, ah_len); sp = (struct sadb_supported *) skb_put(skb, auth_len);
ap = (struct sadb_alg *) (sp + 1); ap = (struct sadb_alg *) (sp + 1);
sp->sadb_supported_len = ah_len / sizeof(uint64_t); sp->sadb_supported_len = auth_len / sizeof(uint64_t);
sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH; sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH;
for (i=1; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) for (i = 0; ; i++) {
*ap++ = aalg_list[i].desc; struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
if (!aalg)
break;
if (aalg->available)
*ap++ = aalg->desc;
}
} }
if (esp_len) { if (enc_len) {
struct sadb_supported *sp; struct sadb_supported *sp;
struct sadb_alg *ap; struct sadb_alg *ap;
sp = (struct sadb_supported *) skb_put(skb, esp_len); sp = (struct sadb_supported *) skb_put(skb, enc_len);
ap = (struct sadb_alg *) (sp + 1); ap = (struct sadb_alg *) (sp + 1);
sp->sadb_supported_len = esp_len / sizeof(uint64_t); sp->sadb_supported_len = enc_len / sizeof(uint64_t);
sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT; sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT;
for (i=1; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) for (i = 0; ; i++) {
*ap++ = ealg_list[i].desc; struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
if (!ealg)
break;
if (ealg->available)
*ap++ = ealg->desc;
}
} }
out_put_algs: out_put_algs:
...@@ -1305,6 +1209,8 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg ...@@ -1305,6 +1209,8 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg
pfk->registered |= (1<<hdr->sadb_msg_satype); pfk->registered |= (1<<hdr->sadb_msg_satype);
} }
xfrm_probe_algs();
supp_skb = compose_sadb_supported(hdr, GFP_KERNEL); supp_skb = compose_sadb_supported(hdr, GFP_KERNEL);
if (!supp_skb) { if (!supp_skb) {
if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC) if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC)
...@@ -1955,35 +1861,55 @@ static struct sadb_msg *pfkey_get_base_msg(struct sk_buff *skb, int *errp) ...@@ -1955,35 +1861,55 @@ static struct sadb_msg *pfkey_get_base_msg(struct sk_buff *skb, int *errp)
return hdr; return hdr;
} }
int count_ah_combs(struct xfrm_tmpl *t) static inline int aalg_tmpl_set(struct xfrm_tmpl *t, struct xfrm_algo_desc *d)
{ {
int sz = 0; return t->aalgos & (1 << d->desc.sadb_alg_id);
int i; }
for (i=1; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) { static inline int ealg_tmpl_set(struct xfrm_tmpl *t, struct xfrm_algo_desc *d)
if (t->aalgos&(1<<aalg_list[i].desc.sadb_alg_id)) {
return t->ealgos & (1 << d->desc.sadb_alg_id);
}
static int count_ah_combs(struct xfrm_tmpl *t)
{
int i, sz = 0;
for (i = 0; ; i++) {
struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
if (!aalg)
break;
if (aalg_tmpl_set(t, aalg) && aalg->available)
sz += sizeof(struct sadb_comb); sz += sizeof(struct sadb_comb);
} }
return sz + sizeof(struct sadb_prop); return sz + sizeof(struct sadb_prop);
} }
int count_esp_combs(struct xfrm_tmpl *t) static int count_esp_combs(struct xfrm_tmpl *t)
{ {
int sz = 0; int i, k, sz = 0;
int i, k;
for (i = 0; ; i++) {
struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
if (!ealg)
break;
for (i=1; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) { if (!(ealg_tmpl_set(t, ealg) && ealg->available))
if (!(t->ealgos&(1<<ealg_list[i].desc.sadb_alg_id)))
continue; continue;
for (k=1; k<sizeof(aalg_list)/sizeof(aalg_list[0]); k++) {
if (t->aalgos&(1<<aalg_list[i].desc.sadb_alg_id)) for (k = 1; ; k++) {
struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
if (!aalg)
break;
if (aalg_tmpl_set(t, aalg) && aalg->available)
sz += sizeof(struct sadb_comb); sz += sizeof(struct sadb_comb);
} }
} }
return sz + sizeof(struct sadb_prop); return sz + sizeof(struct sadb_prop);
} }
void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t) static void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
{ {
struct sadb_prop *p; struct sadb_prop *p;
int i; int i;
...@@ -1993,15 +1919,19 @@ void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t) ...@@ -1993,15 +1919,19 @@ void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
p->sadb_prop_exttype = SADB_EXT_PROPOSAL; p->sadb_prop_exttype = SADB_EXT_PROPOSAL;
p->sadb_prop_replay = 32; p->sadb_prop_replay = 32;
for (i=1; i<sizeof(aalg_list)/sizeof(aalg_list[0]); i++) { for (i = 0; ; i++) {
if (t->aalgos&(1<<aalg_list[i].desc.sadb_alg_id)) { struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
if (!aalg)
break;
if (aalg_tmpl_set(t, aalg) && aalg->available) {
struct sadb_comb *c; struct sadb_comb *c;
c = (struct sadb_comb*)skb_put(skb, sizeof(struct sadb_comb)); c = (struct sadb_comb*)skb_put(skb, sizeof(struct sadb_comb));
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
p->sadb_prop_len += sizeof(struct sadb_comb)/8; p->sadb_prop_len += sizeof(struct sadb_comb)/8;
c->sadb_comb_auth = aalg_list[i].desc.sadb_alg_id; c->sadb_comb_auth = aalg->desc.sadb_alg_id;
c->sadb_comb_auth_minbits = aalg_list[i].desc.sadb_alg_minbits; c->sadb_comb_auth_minbits = aalg->desc.sadb_alg_minbits;
c->sadb_comb_auth_maxbits = aalg_list[i].desc.sadb_alg_maxbits; c->sadb_comb_auth_maxbits = aalg->desc.sadb_alg_maxbits;
c->sadb_comb_hard_addtime = 24*60*60; c->sadb_comb_hard_addtime = 24*60*60;
c->sadb_comb_soft_addtime = 20*60*60; c->sadb_comb_soft_addtime = 20*60*60;
c->sadb_comb_hard_usetime = 8*60*60; c->sadb_comb_hard_usetime = 8*60*60;
...@@ -2010,7 +1940,7 @@ void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t) ...@@ -2010,7 +1940,7 @@ void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
} }
} }
void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t) static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
{ {
struct sadb_prop *p; struct sadb_prop *p;
int i, k; int i, k;
...@@ -2020,22 +1950,30 @@ void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t) ...@@ -2020,22 +1950,30 @@ void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
p->sadb_prop_exttype = SADB_EXT_PROPOSAL; p->sadb_prop_exttype = SADB_EXT_PROPOSAL;
p->sadb_prop_replay = 32; p->sadb_prop_replay = 32;
for (i=1; i<sizeof(ealg_list)/sizeof(ealg_list[0]); i++) { for (i=0; ; i++) {
if (!(t->ealgos&(1<<ealg_list[i].desc.sadb_alg_id))) struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
if (!ealg)
break;
if (!(ealg_tmpl_set(t, ealg) && ealg->available))
continue; continue;
for (k=1; k<sizeof(aalg_list)/sizeof(aalg_list[0]); k++) {
for (k = 1; ; k++) {
struct sadb_comb *c; struct sadb_comb *c;
if (!(t->aalgos&(1<<aalg_list[i].desc.sadb_alg_id))) struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
if (!aalg)
break;
if (!(aalg_tmpl_set(t, aalg) && aalg->available))
continue; continue;
c = (struct sadb_comb*)skb_put(skb, sizeof(struct sadb_comb)); c = (struct sadb_comb*)skb_put(skb, sizeof(struct sadb_comb));
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
p->sadb_prop_len += sizeof(struct sadb_comb)/8; p->sadb_prop_len += sizeof(struct sadb_comb)/8;
c->sadb_comb_auth = aalg_list[k].desc.sadb_alg_id; c->sadb_comb_auth = aalg->desc.sadb_alg_id;
c->sadb_comb_auth_minbits = aalg_list[k].desc.sadb_alg_minbits; c->sadb_comb_auth_minbits = aalg->desc.sadb_alg_minbits;
c->sadb_comb_auth_maxbits = aalg_list[k].desc.sadb_alg_maxbits; c->sadb_comb_auth_maxbits = aalg->desc.sadb_alg_maxbits;
c->sadb_comb_encrypt = ealg_list[i].desc.sadb_alg_id; c->sadb_comb_encrypt = ealg->desc.sadb_alg_id;
c->sadb_comb_encrypt_minbits = ealg_list[i].desc.sadb_alg_minbits; c->sadb_comb_encrypt_minbits = ealg->desc.sadb_alg_minbits;
c->sadb_comb_encrypt_maxbits = ealg_list[i].desc.sadb_alg_maxbits; c->sadb_comb_encrypt_maxbits = ealg->desc.sadb_alg_maxbits;
c->sadb_comb_hard_addtime = 24*60*60; c->sadb_comb_hard_addtime = 24*60*60;
c->sadb_comb_soft_addtime = 20*60*60; c->sadb_comb_soft_addtime = 20*60*60;
c->sadb_comb_hard_usetime = 8*60*60; c->sadb_comb_hard_usetime = 8*60*60;
......
...@@ -323,6 +323,15 @@ EXPORT_SYMBOL(xfrm_policy_flush); ...@@ -323,6 +323,15 @@ EXPORT_SYMBOL(xfrm_policy_flush);
EXPORT_SYMBOL(xfrm_policy_byid); EXPORT_SYMBOL(xfrm_policy_byid);
EXPORT_SYMBOL(xfrm_policy_list); EXPORT_SYMBOL(xfrm_policy_list);
EXPORT_SYMBOL_GPL(xfrm_probe_algs);
EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx);
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE) #if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE)
/* inet functions common to v4 and v6 */ /* inet functions common to v4 and v6 */
...@@ -388,7 +397,6 @@ EXPORT_SYMBOL(tcp_v4_send_check); ...@@ -388,7 +397,6 @@ EXPORT_SYMBOL(tcp_v4_send_check);
EXPORT_SYMBOL(tcp_v4_conn_request); EXPORT_SYMBOL(tcp_v4_conn_request);
EXPORT_SYMBOL(tcp_create_openreq_child); EXPORT_SYMBOL(tcp_create_openreq_child);
EXPORT_SYMBOL(tcp_bucket_create); EXPORT_SYMBOL(tcp_bucket_create);
EXPORT_SYMBOL(__tcp_put_port);
EXPORT_SYMBOL(tcp_put_port); EXPORT_SYMBOL(tcp_put_port);
EXPORT_SYMBOL(tcp_inherit_port); EXPORT_SYMBOL(tcp_inherit_port);
EXPORT_SYMBOL(tcp_v4_syn_recv_sock); EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
......
...@@ -153,7 +153,7 @@ static inline int unix_may_send(unix_socket *sk, unix_socket *osk) ...@@ -153,7 +153,7 @@ static inline int unix_may_send(unix_socket *sk, unix_socket *osk)
return (unix_peer(osk) == NULL || unix_our_peer(sk, osk)); return (unix_peer(osk) == NULL || unix_our_peer(sk, osk));
} }
static inline unix_socket * unix_peer_get(unix_socket *s) static unix_socket *unix_peer_get(unix_socket *s)
{ {
unix_socket *peer; unix_socket *peer;
......
...@@ -92,7 +92,7 @@ static unix_socket *gc_current=GC_HEAD; /* stack of objects to mark */ ...@@ -92,7 +92,7 @@ static unix_socket *gc_current=GC_HEAD; /* stack of objects to mark */
atomic_t unix_tot_inflight = ATOMIC_INIT(0); atomic_t unix_tot_inflight = ATOMIC_INIT(0);
extern inline unix_socket *unix_get_socket(struct file *filp) static unix_socket *unix_get_socket(struct file *filp)
{ {
unix_socket * u_sock = NULL; unix_socket * u_sock = NULL;
struct inode *inode = filp->f_dentry->d_inode; struct inode *inode = filp->f_dentry->d_inode;
...@@ -141,19 +141,19 @@ void unix_notinflight(struct file *fp) ...@@ -141,19 +141,19 @@ void unix_notinflight(struct file *fp)
* Garbage Collector Support Functions * Garbage Collector Support Functions
*/ */
extern inline unix_socket *pop_stack(void) static inline unix_socket *pop_stack(void)
{ {
unix_socket *p=gc_current; unix_socket *p=gc_current;
gc_current = unix_sk(p)->gc_tree; gc_current = unix_sk(p)->gc_tree;
return p; return p;
} }
extern inline int empty_stack(void) static inline int empty_stack(void)
{ {
return gc_current == GC_HEAD; return gc_current == GC_HEAD;
} }
extern inline void maybe_unmark_and_push(unix_socket *x) static void maybe_unmark_and_push(unix_socket *x)
{ {
struct unix_sock *u = unix_sk(x); struct unix_sock *u = unix_sk(x);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment