summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2003-11-05 10:44:19 +0000
committerLennart Poettering <lennart@poettering.net>2003-11-05 10:44:19 +0000
commit7ec5099b5f5c79419a54a6cdedea618d98b60569 (patch)
treef1bed2425e622919435fe4580b15dbfddb3137bf /kernel
parent8bc528bfd9d8c17d25eec2ca1686513679ba3e55 (diff)
Commit initial version
git-svn-id: file:///home/lennart/svn/public/seppl/trunk@2 91a2fd9b-5dcb-0310-a70a-d71e310228e6
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile.in61
-rw-r--r--kernel/ipt_CRYPT.c190
-rw-r--r--kernel/ipt_CRYPT.h32
-rw-r--r--kernel/ipt_DECRYPT.c197
-rw-r--r--kernel/ipt_DECRYPT.h28
-rw-r--r--kernel/seppl.c429
-rw-r--r--kernel/seppl.h60
-rw-r--r--kernel/seppl_protocol.h27
-rwxr-xr-xkernel/test.sh39
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