diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile.in | 61 | ||||
-rw-r--r-- | kernel/ipt_CRYPT.c | 190 | ||||
-rw-r--r-- | kernel/ipt_CRYPT.h | 32 | ||||
-rw-r--r-- | kernel/ipt_DECRYPT.c | 197 | ||||
-rw-r--r-- | kernel/ipt_DECRYPT.h | 28 | ||||
-rw-r--r-- | kernel/seppl.c | 429 | ||||
-rw-r--r-- | kernel/seppl.h | 60 | ||||
-rw-r--r-- | kernel/seppl_protocol.h | 27 | ||||
-rwxr-xr-x | kernel/test.sh | 39 |
9 files changed, 1063 insertions, 0 deletions
diff --git a/kernel/Makefile.in b/kernel/Makefile.in new file mode 100644 index 0000000..3be3826 --- /dev/null +++ b/kernel/Makefile.in @@ -0,0 +1,61 @@ +# $Id: Makefile.am 40 2003-10-27 18:32:45Z lennart $ +# +# This file is part of seppl. +# +# seppl 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. +# +# seppl 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 seppl; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +# This Makefile is NOT created by automake! + +KERNELDIR=@KERNELDIR@ +SEPPL_MODDIR=@KERNELMODDIR@/seppl +PACKAGE=@PACKAGE@ +VERSION=@VERSION@ +DISTFILES=seppl.c seppl.h ipt_CRYPT.c ipt_CRYPT.h ipt_DECRYPT.c ipt_DECRYPT.h test.sh Makefile.in seppl_protocol.h +distdir = ../$(PACKAGE)-$(VERSION) +CFLAGS=-Wall -g -O2 +KERNEL_CFLAGS= -I$(KERNELDIR)/include -DLINUX -DMODULE -D__KERNEL__ -DEXPORT_SYMTAB -DPACKAGE_BUGREPORT="\"@PACKAGE_BUGREPORT@\"" + +all: Makefile ipt_CRYPT.o ipt_DECRYPT.o seppl.o + +Makefile: Makefile.in + cd .. && ./config.status kernel/Makefile + +ipt_CRYPT.o: ipt_CRYPT.c + $(CC) $(CFLAGS) -c $^ -o $@ $(KERNEL_CFLAGS) + +ipt_DECRYPT.o: ipt_DECRYPT.c + $(CC) $(CFLAGS) -c $^ -o $@ $(KERNEL_CFLAGS) + +seppl.o: seppl.c + $(CC) $(CFLAGS) -c $^ -o $@ $(KERNEL_CFLAGS) + +install: + mkdir -p $(SEPPL_MODDIR) + install -m644 seppl.o ipt_CRYPT.o ipt_DECRYPT.o $(SEPPL_MODDIR) + +distdir: + mkdir -p $(distdir) + cp -p $(DISTFILES) $(distdir) + +mostlyclean: clean +distclean: clean + +maintainer-clean: clean + rm -f Makefile + +clean: + rm -f *.o + +.PHONY: all clean maintainer-clean mostlyclean distclean distdir install diff --git a/kernel/ipt_CRYPT.c b/kernel/ipt_CRYPT.c new file mode 100644 index 0000000..9f7d055 --- /dev/null +++ b/kernel/ipt_CRYPT.c @@ -0,0 +1,190 @@ +/* $Id: newmail.c 31 2003-10-22 22:59:07Z lennart $ */ + +/*** + This file is part of seppl + + seppl 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. + + seppl 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 seppl; 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/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/ip.h> +#include <net/checksum.h> +struct in_device; +#include <net/route.h> +#include <linux/netfilter_ipv4/ip_tables.h> +#include <asm/scatterlist.h> + +#include "seppl.h" +#include "ipt_CRYPT.h" + +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +#ifdef MODULE_DESCRIPTION +MODULE_DESCRIPTION("SEPPL iptables Encryption Target"); +#endif +#ifdef MODULE_AUTHOR +MODULE_AUTHOR("Lennart Poettering <"PACKAGE_BUGREPORT">"); +#endif + +static unsigned int ipt_CRYPT_target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, const struct net_device *out, const void *_ti, void *userinfo) { + const struct ipt_crypt_info *ti = _ti; + struct iphdr *ih = (*pskb)->nh.iph; + unsigned d, new_l, crypt_l, ihl = ih->ihl<<2; + struct seppl_uncrypt_hdr *uh; + struct seppl_crypt_hdr *ch; + u8 *iv, *pl; + int ivs = ti->key->ivsize; + int bs = ti->key->blocksize; + struct sock *sk; + struct scatterlist sg[1]; + + // Calculate new packet size + new_l = ihl + sizeof(struct seppl_uncrypt_hdr) + ivs + ((sizeof(struct seppl_crypt_hdr) + ntohs(ih->tot_len) - ihl + bs - 1) / bs) * bs; + d = new_l - htons(ih->tot_len); + crypt_l = new_l - ihl - sizeof(struct seppl_uncrypt_hdr) - ivs; + + //DEBUGP("CRYPT: tot_len=%i, new_l=%i, d=%i, crypt_l=%i\n", htons(ih->tot_len), new_l, d, crypt_l); + + // Copy the skb if needed and increase it correctly + if (skb_tailroom(*pskb) < d || skb_cloned(*pskb)) { + struct sk_buff *n; + + if (!(n = skb_copy_expand(*pskb, skb_headroom(*pskb), d, GFP_ATOMIC))) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_CRYPT: Unable to allocate larger skb, dropping packet.\n"); + + return NF_DROP; + } + + if ((*pskb)->sk) + skb_set_owner_w(n, (*pskb)->sk); + + kfree_skb(*pskb); + *pskb = n; + ih = (*pskb)->nh.iph; + } + + skb_put(*pskb, d); + + // Calculate some pointers + //ih = ... /* IP-Header */ + uh = (struct seppl_uncrypt_hdr*) ((u8*) ih + ihl); /* Unencrypted header */ + iv = ((u8*) uh) + sizeof(struct seppl_uncrypt_hdr); /* IV */ + ch = (struct seppl_crypt_hdr*) (iv + ivs); /* Crypted header */ + pl = ((u8*) ch) + sizeof(struct seppl_crypt_hdr); /* Payload */ + + // Copy the payload + memmove(pl, uh, ntohs(ih->tot_len) - ihl); + + // Fill the uncrypted header + uh->algorithm = ti->key->algorithm; + strncpy(uh->key_name, ti->key->name, 7); + + // Copy the IV + seppl_copy_iv(ti->key, iv); + + // Fill the crypted header + ch->ident = 0x00; + ch->saved_protocol = ih->protocol; + ch->saved_tot_len = ih->tot_len; + ch->saved_frag_off = ih->frag_off; + + // Fill the IP header + ih->protocol = SEPPL_PROTOCOL; + ih->tot_len = htons(new_l); + ih->frag_off = 0; + + // Checksum FIXME: Is this really needed? + ih->check = 0; + ih->check = ip_fast_csum((char *) ih, ih->ihl); + + // Crypt + sg[0].page = virt_to_page((void*) ch); + sg[0].offset = (((long) (void *) ch) & ~PAGE_MASK); + sg[0].length = crypt_l; + + crypto_cipher_set_iv(ti->key->tfm, iv, ti->key->ivsize); + + if (crypto_cipher_encrypt(ti->key->tfm, sg, sg, sg[0].length)) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_CRYPT: encrypt() failure\n"); + return NF_DROP; + } + + // Finish + (*pskb)->ip_summed = CHECKSUM_NONE; + (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; + + return IPT_CONTINUE; +} + +static int ipt_CRYPT_check(const char *table, const struct ipt_entry *e, void *_ti, unsigned int ti_size, unsigned int hook_mask) { + struct ipt_crypt_info *ti = _ti; + + if (ti_size != IPT_ALIGN(sizeof(struct ipt_crypt_info))) { + printk(KERN_ERR "ipt_CRYPT: Structure too small\n"); + return 0; + } + + if (strcmp(table, "mangle") != 0) { + printk(KERN_ERR "ipt_CRYPT: Not in mangle table\n"); + return 0; + } + + if ((hook_mask & ~(1 << NF_IP_POST_ROUTING)) != 0) { + printk(KERN_ERR "ipt_CRYPT: Not in POSTROUTING chain\n"); + return 0; + } + + if (!(ti->key = seppl_claim_key(ti->algorithm, ti->name))) { + printk(KERN_ERR "ipt_CRYPT: Cannot find key\n"); + return 0; + } + + return 1; +} + +static void ipt_CRYPT_destroy(void *_ti, unsigned int ti_size) { + struct ipt_crypt_info *ti = _ti; + + seppl_release_key(ti->key); +} + +static struct ipt_target ipt_CRYPT_reg = { + { NULL, NULL }, + "CRYPT", + ipt_CRYPT_target, + ipt_CRYPT_check, + ipt_CRYPT_destroy, + THIS_MODULE +}; + +static int __init init(void) { + return ipt_register_target(&ipt_CRYPT_reg); +} + +static void __exit fini(void) { + ipt_unregister_target(&ipt_CRYPT_reg); +} + +module_init(init); +module_exit(fini); + +EXPORT_NO_SYMBOLS; diff --git a/kernel/ipt_CRYPT.h b/kernel/ipt_CRYPT.h new file mode 100644 index 0000000..f1602be --- /dev/null +++ b/kernel/ipt_CRYPT.h @@ -0,0 +1,32 @@ +#ifndef _IPT_CRYPT_H +#define _IPT_CRYPT_H + +/* $Id: newmail.c 31 2003-10-22 22:59:07Z lennart $ */ + +/*** + This file is part of seppl + + seppl 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. + + seppl 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 seppl; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA +***/ + +struct ipt_crypt_info { + unsigned char algorithm; + char name[7]; + + struct seppl_key *key; +}; + +#endif diff --git a/kernel/ipt_DECRYPT.c b/kernel/ipt_DECRYPT.c new file mode 100644 index 0000000..75db2bd --- /dev/null +++ b/kernel/ipt_DECRYPT.c @@ -0,0 +1,197 @@ +/* $Id: newmail.c 31 2003-10-22 22:59:07Z lennart $ */ + +/*** + This file is part of seppl + + seppl 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. + + seppl 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 seppl; 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/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/ip.h> +#include <net/checksum.h> +struct in_device; +#include <net/route.h> +#include <linux/netfilter_ipv4/ip_tables.h> +#include <asm/scatterlist.h> + +#include "seppl.h" +#include "ipt_DECRYPT.h" + +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +#ifdef MODULE_DESCRIPTION +MODULE_DESCRIPTION ("SEPPL iptables Decryption Target"); +#endif +#ifdef MODULE_AUTHOR +MODULE_AUTHOR("Lennart Poettering <"PACKAGE_BUGREPORT">"); +#endif + +static unsigned int ipt_DECRYPT_target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, const struct net_device *out, const void *_ti, void *userinfo) { + struct iphdr *ih = (*pskb)->nh.iph; + unsigned ihl = ih->ihl<<2; + struct seppl_key *key; + struct seppl_uncrypt_hdr *uh; + struct seppl_crypt_hdr *ch; + u8* iv, *pl; + int ivs; + int crypt_l, bs; + struct scatterlist sg[1]; + + if (ih->protocol != SEPPL_PROTOCOL) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_DECRYPT: Incorrect protocol\n"); + return NF_DROP; + } + + if (ntohs(ih->tot_len) <= ihl+sizeof(struct seppl_uncrypt_hdr)) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_DECRYPT: Packet too short (1)\n"); + return NF_DROP; + } + + uh = (struct seppl_uncrypt_hdr*) ((u8*) ih + ihl); /* Unencrypted header */ + + if (!(key = seppl_claim_key(uh->algorithm, uh->key_name))) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_DECRYPT: Recieved packet with unknown decryption key.\n"); + return NF_DROP; + } + + ivs = key->ivsize; + bs = key->blocksize; + + if (ntohs(ih->tot_len) <= ihl+sizeof(struct seppl_uncrypt_hdr)+ivs+sizeof(struct seppl_crypt_hdr)) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_DECRYPT: Packet too short (2)\n"); + seppl_release_key(key); + return NF_DROP; + } + + crypt_l = ntohs(ih->tot_len)-ihl-sizeof(struct seppl_uncrypt_hdr)-ivs; + + if (crypt_l % bs) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_DECRYPT: Packet too short (3)\n"); + seppl_release_key(key); + return NF_DROP; + } + + iv = ((u8*) uh) + sizeof(struct seppl_uncrypt_hdr); /* IV */ + ch = (struct seppl_crypt_hdr*) (iv + ivs); /* Crypted header */ + pl = ((u8*) ch) + sizeof(struct seppl_crypt_hdr); /* Payload */ + + sg[0].page = virt_to_page(ch); + sg[0].offset = ((long) ch & ~PAGE_MASK); + sg[0].length = crypt_l; + + crypto_cipher_set_iv(key->tfm, iv, key->ivsize); + + if (crypto_cipher_decrypt(key->tfm, sg, sg, sg[0].length)) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_DECRYPT: decrypt() failure\n"); + seppl_release_key(key); + return NF_DROP; + } + + seppl_release_key(key); + + if (ch->ident != 0x00) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_DECRYPT: Key not matching\n"); + return NF_DROP; + } + + if (ntohs(ch->saved_tot_len) > + ntohs(ih->tot_len) - + sizeof(struct seppl_uncrypt_hdr)- + ivs- + sizeof(struct seppl_crypt_hdr)) { + + if (net_ratelimit()) + printk(KERN_ERR "ipt_DECRYPT: Packet too short (4)"); + return NF_DROP; + } + + //DEBUGP("DECRYPT: tot_len=%i, real_l=%i, crypt_l=%i\n", htons(ih->tot_len), ntohs(ch->saved_tot_len), crypt_l); + + // Restore the IP header + ih->protocol = ch->saved_protocol; + ih->tot_len = ch->saved_tot_len; + ih->frag_off = ch->saved_frag_off; + + // The pay load + memmove(uh, pl, ntohs(ih->tot_len)-ihl); + + // Checksum + ih->check = 0; + ih->check = ip_fast_csum((char *) ih, ih->ihl); + + skb_trim(*pskb, ntohs(ih->tot_len)); + + // Finish + (*pskb)->ip_summed = CHECKSUM_NONE; + (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; + + return IPT_CONTINUE; +} + +static int ipt_DECRYPT_check(const char *table, const struct ipt_entry *e, void *_ti, unsigned int ti_size, unsigned int hook_mask) { + if (ti_size != IPT_ALIGN(sizeof(struct ipt_decrypt_info))) { + printk(KERN_ERR "ipt_DECRYPT: Structure too small"); + return 0; + } + + if (strcmp(table, "mangle") != 0) { + printk(KERN_ERR "ipt_DECRYPT: Not in mangle table\n"); + return 0; + } + + if ((hook_mask & ~(1 << NF_IP_PRE_ROUTING)) != 0) { + printk(KERN_ERR "ipt_DECRYPT: Not in PREROUTING chain"); + return 0; + } + + return 1; +} + +static struct ipt_target ipt_DECRYPT_reg = { + { NULL, NULL }, + "DECRYPT", + ipt_DECRYPT_target, + ipt_DECRYPT_check, + NULL, + THIS_MODULE +}; + +static int __init init(void) { + if (ipt_register_target(&ipt_DECRYPT_reg)) + return -EINVAL; + + return 0; +} + +static void __exit fini(void) { + ipt_unregister_target(&ipt_DECRYPT_reg); +} + +module_init(init); +module_exit(fini); + +EXPORT_NO_SYMBOLS; diff --git a/kernel/ipt_DECRYPT.h b/kernel/ipt_DECRYPT.h new file mode 100644 index 0000000..41f202a --- /dev/null +++ b/kernel/ipt_DECRYPT.h @@ -0,0 +1,28 @@ +#ifndef _IPT_DECRYPT_H +#define _IPT_DECRYPT_H + +/* $Id: newmail.c 31 2003-10-22 22:59:07Z lennart $ */ + +/*** + This file is part of seppl + + seppl 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. + + seppl 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 seppl; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA +***/ + +struct ipt_decrypt_info { +}; + +#endif diff --git a/kernel/seppl.c b/kernel/seppl.c new file mode 100644 index 0000000..de59eb1 --- /dev/null +++ b/kernel/seppl.c @@ -0,0 +1,429 @@ +/* $Id: newmail.c 31 2003-10-22 22:59:07Z lennart $ */ + +/*** + This file is part of seppl + + seppl 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. + + seppl 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 seppl; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA +***/ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/interrupt.h> +#include <linux/string.h> +#include <linux/random.h> +#include <linux/kmod.h> +#include <linux/proc_fs.h> +#include <asm/uaccess.h> + +#include "seppl.h" + +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +#ifdef MODULE_DESCRIPTION +MODULE_DESCRIPTION ("SEPPL Key Manager"); +#endif +#ifdef MODULE_AUTHOR +MODULE_AUTHOR("Lennart Poettering <"PACKAGE_BUGREPORT">"); +#endif + +static struct seppl_key *keyring = NULL; +static spinlock_t keyring_lock = SPIN_LOCK_UNLOCKED; + +#define PROC_FILE_NAME "seppl_keyring" +static struct proc_dir_entry* proc_file = NULL; + + +struct cipher_info { + char *name; + int bits; +}; + +#define CIPHER_DICT_MAX 2 + +static const struct cipher_info cipher_dict[CIPHER_DICT_MAX] = { + { "aes-cbc", 128 }, + { "aes-cbc", 192 } +}; + +const struct cipher_info *seppl_find_cipher(u8 id) { + if (id < CIPHER_DICT_MAX) + return &cipher_dict[id]; + + return NULL; +} + +struct seppl_key* seppl_find_key(u8 algorithm, const char *name, int r) { + struct seppl_key *key = NULL, *l; + + for (l = keyring; l; l = l->next) + if (l->algorithm == algorithm && strncmp(l->name, name, sizeof(l->name)) == 0) + if (!r || atomic_read(&l->ready)) { + key = l; + break; + } + + return key; +} + +struct seppl_key* seppl_claim_key(u8 algorithm, const char *name) { + struct seppl_key *key = NULL; + + spin_lock_bh(&keyring_lock); // FIXME: BH? + + if ((key = seppl_find_key(algorithm, name, 1))) { + atomic_inc(&key->usage); + MOD_INC_USE_COUNT; + } + + spin_unlock_bh(&keyring_lock); + + return key; +} + +void seppl_release_key(struct seppl_key* key) { + atomic_dec(&key->usage); + MOD_DEC_USE_COUNT; +} + +// not spinlocked! +static void seppl_next_iv(struct seppl_key *key) { + unsigned int i, m = key->ivsize; + + for (i = 0; i < m ; i++) { + key->iv[i]++; + if (key->iv[i] != 0) break; + } +} + +void seppl_copy_iv(struct seppl_key *key, u8* iv) { + spin_lock_bh(&key->iv_spinlock); // FIXME: BH? + + memcpy(iv, key->iv, key->ivsize); + seppl_next_iv(key); + + spin_unlock_bh(&key->iv_spinlock); +} + +int seppl_add_key(u8 algorithm, const char *name, const u8 *key_data) { + struct seppl_key* key = NULL; + int r = -EINVAL; + int locked = 1; + + spin_lock(&keyring_lock); + + if ((key = seppl_find_key(algorithm, name, 0))) { + + if (!atomic_read(&key->ready)) { + printk(KERN_ERR "SEPPL: Tried to replace incomplete key.\n"); + goto finish; + } + + memcpy(key->key, key_data, key->keysize); + if (crypto_cipher_setkey(key->tfm, key->key, key->keysize)) { + printk(KERN_ERR "SEPPL: Failed to set cipher key.\n"); + goto finish; + } + + printk(KERN_INFO "SEPPL: Replaced key sucessfully.\n"); + + r = 0; + goto finish; + } else { + const struct cipher_info* cinfo; + + if (!(cinfo = seppl_find_cipher(algorithm))) { + printk(KERN_ERR "SEPPL: Unknown cipher\n"); + goto finish; + } + + if(!(key = kmalloc(sizeof(struct seppl_key), GFP_KERNEL))) { + r = -ENOMEM; + printk(KERN_ERR "SEPPL: kmalloc() failed\n"); + goto finish; + } + + key->algorithm = algorithm; + memset(key->name, 0, 7); + strncpy(key->name, name, 7); + atomic_set(&key->ready, 0); + key->next = keyring; + keyring = key; + + spin_unlock(&keyring_lock); + locked = 0; + + key->key = key->iv = NULL; + key->tfm = NULL; + + atomic_set(&key->usage, 0); + spin_lock_init(&key->iv_spinlock); + + if (!(key->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_MODE_CBC))) { + printk(KERN_ERR "SEPPL: Failed to load cipher.\n"); + goto cleanup; + } + + /* Fill in key */ + if (!(key->key = kmalloc(key->keysize = cinfo->bits/8, GFP_KERNEL))) { + r = -ENOMEM; + printk(KERN_ERR "SEPPL: kmalloc() failed #2\n"); + goto cleanup; + } + memcpy(key->key, key_data, key->keysize); + + if (crypto_cipher_setkey(key->tfm, key->key, key->keysize)) { + printk(KERN_ERR "SEPPL: Failed to set cipher key.\n"); + goto cleanup; + } + + /* Fill in iv */ + if (!(key->iv = kmalloc(key->ivsize = crypto_tfm_alg_ivsize(key->tfm), GFP_KERNEL))) { + r = -ENOMEM; + printk(KERN_ERR "SEPPL: kmalloc() failed #3\n"); + goto cleanup; + } + get_random_bytes(key->iv, key->ivsize); + + key->blocksize = crypto_tfm_alg_blocksize(key->tfm); + + proc_file->size += 8 + key->keysize; + atomic_set(&key->ready, 1); + + printk(KERN_INFO "SEPPL: Added key sucessfully.\n"); + + r = 0; + goto finish; + } + +cleanup: + + if (key) { + struct seppl_key *i; + + spin_lock(&keyring_lock); + + if (keyring == key) + keyring = key->next; + else { + for (i = keyring; i; i = i->next) { + if (i->next == key) { + i->next = key->next; + break; + } + } + } + + spin_unlock(&keyring_lock); + + if (key->tfm) + crypto_free_tfm(key->tfm); + + if (key->key) + kfree(key->key); + + if (key->iv) + kfree(key->key); + + kfree(key); + } + +finish: + + if (locked) + spin_unlock(&keyring_lock); + + return r; +} + +void seppl_clear_keyring(void) { + struct seppl_key *key, *prev; + + printk(KERN_INFO "SEPPL: Clearing keyring\n"); + + spin_lock(&keyring_lock); + + prev = NULL; + key = keyring; + while (key) { + if (atomic_read(&key->ready) && !atomic_read(&key->usage)) { + struct seppl_key *k; + + atomic_set(&key->ready, 0); + + proc_file->size -= 8 + key->keysize; + + if (prev) + prev->next = key->next; + else + keyring = key->next; + + crypto_free_tfm(key->tfm); + kfree(key->key); + kfree(key->iv); + + k = key; + key = key->next; + kfree(k); + + continue; + } + + prev = key; + key = key->next; + } + + spin_unlock(&keyring_lock); +} + +#ifndef MIN +#define MIN(a,b) ((a)>(b)?(b):(a)) +#endif + +static int seppl_proc_read_func(char* page, char** start, off_t off, int count, int* eof, void* data) { + struct seppl_key *key; + char *e = page; + int d = 0; + + MOD_INC_USE_COUNT; + spin_lock(&keyring_lock); + + for (key = keyring; key; key = key->next) { + if (count <= 0) break; + + *e = key->algorithm; + e ++; count--; + + if (count <= 0) break; + + memcpy(e, key->name, d = MIN(7, count)); + e += d; count -= d; + + if (count <= 0) break; + + memcpy(e, key->key, d = MIN(key->keysize, count)); + e += d; count -= d; + + if (count <= 0) break; + + if (key->next == 0) + if (eof) + *eof = 1; + } + + spin_unlock(&keyring_lock); + MOD_DEC_USE_COUNT; + + return e-page; +} + + +static int seppl_proc_write_func(struct file* file, const char* buffer, unsigned long count, void* data) { + int r = -EINVAL; + u8* buf = NULL; + MOD_INC_USE_COUNT; + + count = count > 10*1024 ? 10*1024 : count; + + if (!(buf = kmalloc(count, GFP_ATOMIC))) { + r = -ENOMEM; + goto finish; + } + + if (copy_from_user(buf, buffer, count)) + goto finish; + + if (strcmp((char*) buf, "clear\n") == 0) { + seppl_clear_keyring(); + r = strlen(buf); + } else { + unsigned long n = count; + u8* p = buf; + + while (n >= 8) { + const struct cipher_info* ci = seppl_find_cipher(*p); + int l, t; + + if (!ci) { + printk(KERN_ERR "SEPPL: Unknown cipher\n"); + goto finish; + } + + l = 8+ci->bits/8; + + if (n < l) { + printk(KERN_ERR "SEPPL: Key data too short\n"); + goto finish; + } + + if ((t = seppl_add_key(*p, p+1, p+8)) < 0) { + r = t; + goto finish; + } + + p += l; + n -= l; + } + + if (n) { + printk(KERN_ERR "SEPPL: Data too short (%li)\n", n); + goto finish; + } + + r = (int) count; + } + +finish: + + if (buf) + kfree(buf); + + MOD_DEC_USE_COUNT; + return r; +} + +static int __init init(void) { + if (!(proc_file = create_proc_entry(PROC_FILE_NAME, 0600, proc_net))) + return -ENOMEM; + + proc_file->read_proc = seppl_proc_read_func; + proc_file->write_proc = seppl_proc_write_func; + proc_file->owner = THIS_MODULE; + proc_file->size = 0; + + printk("SEPPL: Loaded.\n"); + + return 0; +} + +static void __exit fini(void) { + seppl_clear_keyring(); + + if (keyring) + printk("SEPPL: Something wicked happened.\n"); + + remove_proc_entry(PROC_FILE_NAME, proc_net); + + printk("SEPPL: Unloaded.\n"); +} + +module_init(init); +module_exit(fini); + +EXPORT_SYMBOL(seppl_copy_iv); +EXPORT_SYMBOL(seppl_claim_key); +EXPORT_SYMBOL(seppl_release_key); + diff --git a/kernel/seppl.h b/kernel/seppl.h new file mode 100644 index 0000000..edc0d29 --- /dev/null +++ b/kernel/seppl.h @@ -0,0 +1,60 @@ +#ifndef _SEPPL_MODULE_H +#define _SEPPL_MODULE_H + +/* $Id: newmail.c 31 2003-10-22 22:59:07Z lennart $ */ + +/*** + This file is part of seppl + + seppl 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. + + seppl 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 seppl; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA +***/ + +#include <linux/spinlock.h> +#include <linux/crypto.h> + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +#include "seppl_protocol.h" + +struct seppl_key { + u8 algorithm; + char name[7]; + atomic_t ready; + atomic_t usage; + + struct crypto_tfm *tfm; + spinlock_t iv_spinlock; + u8 *iv; + u8 *key; + + unsigned int ivsize; + unsigned int keysize; + unsigned int blocksize; + + struct seppl_key *next; +}; + +struct seppl_key* seppl_claim_key(u8 algorithm, const char *name); +void seppl_release_key(struct seppl_key *key); +void seppl_copy_iv(struct seppl_key *key, u8* iv); +void seppl_clean_keys(void); +int seppl_add_key(u8 algorithm, const char *name, const u8* key_data); + +#endif diff --git a/kernel/seppl_protocol.h b/kernel/seppl_protocol.h new file mode 100644 index 0000000..08d4fa6 --- /dev/null +++ b/kernel/seppl_protocol.h @@ -0,0 +1,27 @@ +#ifndef _SEPPL_H +#define _SEPPL_H + +#define SEPPL_PROTOCOL 177 + +// Packet layout: +// 1. IP-Header PLAIN +// 2. Uncrypted header PLAIN +// 3. iv PLAIN +// 4. Crypted header CRYPTED +// 5. Payload (with TCP/UDP/...-Header) CRYPTED +// 6. Padding CRYPTED + +struct seppl_uncrypt_hdr { + uint8_t algorithm; + char key_name[7]; +} __attribute__((packed)) uncrypt_hdr; + +struct seppl_crypt_hdr{ + uint8_t ident; // 0x00 + uint8_t saved_protocol; + uint16_t saved_tot_len; + uint16_t saved_frag_off; +} __attribute__((packed)) crypt_hdr; + + +#endif diff --git a/kernel/test.sh b/kernel/test.sh new file mode 100755 index 0000000..fc41522 --- /dev/null +++ b/kernel/test.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# $Id: Makefile.am 40 2003-10-27 18:32:45Z lennart $ +# +# This file is part of seppl. +# +# seppl 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. +# +# seppl 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 seppl; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +dmesg -n 7 + +iptables -t mangle -F POSTROUTING +iptables -t mangle -F PREROUTING + +sync + +make unload +sleep 2 +make load + +../utils/seppl-ls -f /etc/seppl/ring2.keys > /proc/net/seppl_keyring +../utils/seppl-ls + +iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -d 10.0.0.0/8 -j TCPMSS --set-mss $((1500-40-8-6-16)) +iptables -t mangle -A POSTROUTING -d 10.0.0.0/8 -j CRYPT --key `hostname` +iptables -t mangle -A PREROUTING -d 10.0.0.0/8 -j DECRYPT + +iptables -t mangle -L |