mirror of https://github.com/apache/cloudstack.git
368 lines
8.8 KiB
C
368 lines
8.8 KiB
C
/*
|
|
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
|
|
* Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
|
*
|
|
* 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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free software Foundation, Inc.,
|
|
* 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
#include <linux/config.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/string.h>
|
|
#include <linux/crypto.h>
|
|
#include <linux/sched.h>
|
|
//#include <asm/softirq.h>
|
|
|
|
#include <sa_algorithm.h>
|
|
|
|
#define MODULE_NAME "IPSEC"
|
|
#define DEBUG 1
|
|
#undef DEBUG
|
|
#include "debug.h"
|
|
|
|
/** @file Tables of supported IPSEC algorithms.
|
|
* Has tables for digests, ciphers and compression algorithms.
|
|
*/
|
|
|
|
/*
|
|
* Algorithms supported by IPsec. These entries contain properties which
|
|
* are used in key negotiation and sa processing, and are used to verify
|
|
* that instantiated crypto transforms have correct parameters for IPsec
|
|
* purposes.
|
|
*/
|
|
|
|
/** Digests. */
|
|
static SAAlgorithm digest_alg[] = {
|
|
{
|
|
.name = "digest_null",
|
|
.info = {
|
|
.digest = {
|
|
.icv_truncbits = 0,
|
|
.icv_fullbits = 0,
|
|
}
|
|
},
|
|
.alg = {
|
|
.sadb_alg_id = SADB_X_AALG_NULL,
|
|
.sadb_alg_ivlen = 0,
|
|
.sadb_alg_minbits = 0,
|
|
.sadb_alg_maxbits = 0
|
|
}
|
|
},
|
|
{
|
|
.name = "md5",
|
|
.info = { .digest = {
|
|
.icv_truncbits = 96,
|
|
.icv_fullbits = 128,
|
|
} },
|
|
.alg = {
|
|
.sadb_alg_id = SADB_AALG_MD5HMAC,
|
|
.sadb_alg_ivlen = 0,
|
|
.sadb_alg_minbits = 128,
|
|
.sadb_alg_maxbits = 128
|
|
}
|
|
},
|
|
{
|
|
.name = "sha1",
|
|
.info = {
|
|
.digest = {
|
|
.icv_truncbits = 96,
|
|
.icv_fullbits = 160,
|
|
}
|
|
},
|
|
.alg = {
|
|
.sadb_alg_id = SADB_AALG_SHA1HMAC,
|
|
.sadb_alg_ivlen = 0,
|
|
.sadb_alg_minbits = 160,
|
|
.sadb_alg_maxbits = 160
|
|
}
|
|
},
|
|
{
|
|
.name = "sha256",
|
|
.info = {
|
|
.digest = {
|
|
.icv_truncbits = 128,
|
|
.icv_fullbits = 256,
|
|
}
|
|
},
|
|
.alg = {
|
|
.sadb_alg_id = SADB_X_AALG_SHA2_256HMAC,
|
|
.sadb_alg_ivlen = 0,
|
|
.sadb_alg_minbits = 256,
|
|
.sadb_alg_maxbits = 256
|
|
}
|
|
},
|
|
/* { */
|
|
/* .name = "ripemd160", */
|
|
/* .info = { */
|
|
/* .digest = { */
|
|
/* .icv_truncbits = 96, */
|
|
/* .icv_fullbits = 160, */
|
|
/* } */
|
|
/* }, */
|
|
/* .alg = { */
|
|
/* .sadb_alg_id = SADB_X_AALG_RIPEMD160HMAC, */
|
|
/* .sadb_alg_ivlen = 0, */
|
|
/* .sadb_alg_minbits = 160, */
|
|
/* .sadb_alg_maxbits = 160 */
|
|
/* } */
|
|
/* }, */
|
|
{ /* Terminator */ }
|
|
};
|
|
|
|
/** Ciphers. */
|
|
static SAAlgorithm cipher_alg[] = {
|
|
{
|
|
.name = "cipher_null",
|
|
.info = {
|
|
.cipher = {
|
|
.blockbits = 8,
|
|
.defkeybits = 0,
|
|
}
|
|
},
|
|
.alg = {
|
|
.sadb_alg_id = SADB_EALG_NULL,
|
|
.sadb_alg_ivlen = 0,
|
|
.sadb_alg_minbits = 0,
|
|
.sadb_alg_maxbits = 0
|
|
}
|
|
},
|
|
{
|
|
.name = "des",
|
|
.info = {
|
|
.cipher = {
|
|
.blockbits = 64,
|
|
.defkeybits = 64,
|
|
}
|
|
},
|
|
.alg = {
|
|
.sadb_alg_id = SADB_EALG_DESCBC,
|
|
.sadb_alg_ivlen = 8,
|
|
.sadb_alg_minbits = 64,
|
|
.sadb_alg_maxbits = 64
|
|
}
|
|
},
|
|
{
|
|
.name = "des3_ede",
|
|
.info = {
|
|
.cipher = {
|
|
.blockbits = 64,
|
|
.defkeybits = 192,
|
|
}
|
|
},
|
|
.alg = {
|
|
.sadb_alg_id = SADB_EALG_3DESCBC,
|
|
.sadb_alg_ivlen = 8,
|
|
.sadb_alg_minbits = 192,
|
|
.sadb_alg_maxbits = 192
|
|
}
|
|
},
|
|
/* { */
|
|
/* .name = "cast128", */ //cast5?
|
|
/* .info = { */
|
|
/* .cipher = { */
|
|
/* .blockbits = 64, */
|
|
/* .defkeybits = 128, */
|
|
/* } */
|
|
/* }, */
|
|
/* .alg = { */
|
|
/* .sadb_alg_id = SADB_X_EALG_CASTCBC, */
|
|
/* .sadb_alg_ivlen = 8, */
|
|
/* .sadb_alg_minbits = 40, */
|
|
/* .sadb_alg_maxbits = 128 */
|
|
/* } */
|
|
/* }, */
|
|
{
|
|
.name = "blowfish",
|
|
.info = {
|
|
.cipher = {
|
|
.blockbits = 64,
|
|
.defkeybits = 128,
|
|
}
|
|
},
|
|
.alg = {
|
|
.sadb_alg_id = SADB_X_EALG_BLOWFISHCBC,
|
|
.sadb_alg_ivlen = 8,
|
|
.sadb_alg_minbits = 40,
|
|
.sadb_alg_maxbits = 448
|
|
}
|
|
},
|
|
{
|
|
.name = "aes",
|
|
.info = {
|
|
.cipher = {
|
|
.blockbits = 128,
|
|
.defkeybits = 128,
|
|
}
|
|
},
|
|
.alg = {
|
|
.sadb_alg_id = SADB_X_EALG_AESCBC,
|
|
.sadb_alg_ivlen = 8,
|
|
.sadb_alg_minbits = 128,
|
|
.sadb_alg_maxbits = 256
|
|
}
|
|
},
|
|
{ /* Terminator */ }
|
|
};
|
|
|
|
/** Compressors. */
|
|
static SAAlgorithm compress_alg[] = {
|
|
{
|
|
.name = "deflate",
|
|
.info = {
|
|
.compress = {
|
|
.threshold = 90,
|
|
}
|
|
},
|
|
.alg = { .sadb_alg_id = SADB_X_CALG_DEFLATE }
|
|
},
|
|
/* { */
|
|
/* .name = "lzs", */
|
|
/* .info = { */
|
|
/* .compress = { */
|
|
/* .threshold = 90, */
|
|
/* } */
|
|
/* }, */
|
|
/* .alg = { .sadb_alg_id = SADB_X_CALG_LZS } */
|
|
/* }, */
|
|
/* { */
|
|
/* .name = "lzjh", */
|
|
/* .info = { */
|
|
/* .compress = { */
|
|
/* .threshold = 50, */
|
|
/* } */
|
|
/* }, */
|
|
/* .alg = { .sadb_alg_id = SADB_X_CALG_LZJH } */
|
|
/* }, */
|
|
{ /* Terminator */ }
|
|
};
|
|
|
|
static SAAlgorithm *sa_algorithm_by_id(SAAlgorithm *algo, int alg_id) {
|
|
for( ; algo && algo->name; algo++){
|
|
if (algo->alg.sadb_alg_id == alg_id) {
|
|
return (algo->available ? algo : NULL);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static SAAlgorithm *sa_algorithm_by_name(SAAlgorithm *algo, char *name) {
|
|
if (!name) return NULL;
|
|
for( ; algo && algo->name; algo++){
|
|
if (strcmp(name, algo->name) == 0) {
|
|
return (algo->available ? algo : NULL);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SAAlgorithm *sa_digest_by_id(int alg_id) {
|
|
return sa_algorithm_by_id(digest_alg, alg_id);
|
|
}
|
|
|
|
SAAlgorithm *sa_cipher_by_id(int alg_id) {
|
|
return sa_algorithm_by_id(cipher_alg, alg_id);
|
|
}
|
|
|
|
SAAlgorithm *sa_compress_by_id(int alg_id) {
|
|
return sa_algorithm_by_id(compress_alg, alg_id);
|
|
}
|
|
|
|
SAAlgorithm *sa_digest_by_name(char *name) {
|
|
return sa_algorithm_by_name(digest_alg, name);
|
|
}
|
|
|
|
SAAlgorithm *sa_cipher_by_name(char *name) {
|
|
return sa_algorithm_by_name(cipher_alg, name);
|
|
}
|
|
|
|
SAAlgorithm *sa_compress_by_name(char *name) {
|
|
return sa_algorithm_by_name(compress_alg, name);
|
|
}
|
|
|
|
SAAlgorithm *sa_digest_by_index(unsigned int idx) {
|
|
return digest_alg + idx;
|
|
}
|
|
|
|
SAAlgorithm *sa_cipher_by_index(unsigned int idx) {
|
|
return cipher_alg + idx;
|
|
}
|
|
|
|
SAAlgorithm *sa_compress_by_index(unsigned int idx) {
|
|
return compress_alg + idx;
|
|
}
|
|
|
|
static void sa_algorithm_probe(SAAlgorithm *algo){
|
|
int status;
|
|
dprintf("> algo=%p\n", algo);
|
|
for( ; algo && algo->name; algo++){
|
|
dprintf("> algorithm %s...\n", algo->name);
|
|
status = crypto_alg_available(algo->name, 0);
|
|
dprintf("> algorithm %s status=%d\n",algo->name, status);
|
|
if (algo->available != status){
|
|
algo->available = status;
|
|
}
|
|
}
|
|
dprintf("<\n");
|
|
}
|
|
|
|
/** Crypto api is broken. When an unregistered algorithm is requested it
|
|
* tries to load a module of the same name. But not all algorithms are
|
|
* defined by modules of the same name.
|
|
*/
|
|
static char *crypto_modules[] = {
|
|
"aes",
|
|
//"arc4",
|
|
"blowfish",
|
|
//"cast5",
|
|
//"cast6",
|
|
"crypto_null",
|
|
"des",
|
|
//"md4",
|
|
"md5",
|
|
//"serpent",
|
|
"sha1",
|
|
"sha256",
|
|
//"sha512",
|
|
//"twofish",
|
|
NULL
|
|
};
|
|
|
|
#include <linux/kmod.h>
|
|
|
|
static void sa_module_probe(char **modules){
|
|
char **p;
|
|
dprintf(">\n");
|
|
for(p = modules; *p; p++){
|
|
dprintf("> %s\n", *p);
|
|
request_module(*p);
|
|
}
|
|
dprintf("<\n");
|
|
}
|
|
|
|
/**
|
|
* 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 sa_algorithm_probe_all(void){
|
|
dprintf("> \n");
|
|
//BUG_ON(in_softirq());
|
|
sa_module_probe(crypto_modules);
|
|
sa_algorithm_probe(digest_alg);
|
|
sa_algorithm_probe(cipher_alg);
|
|
sa_algorithm_probe(compress_alg);
|
|
dprintf("<\n");
|
|
}
|