public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/04] Add DSA key type
@ 2006-01-26 21:58 David Härdeman
  2006-01-26 21:58 ` [PATCH 02/04] Add dsa crypto ops David Härdeman
                   ` (4 more replies)
  0 siblings, 5 replies; 55+ messages in thread
From: David Härdeman @ 2006-01-26 21:58 UTC (permalink / raw)
  To: linux-kernel; +Cc: dhowells, keyrings, david


The following four patches add support for DSA keys to the in-kernel key 
management system. 

In-kernel dsa keys allows a process to use the request_key mechanism to 
request such keys on demand. One such example is a backup script that,
when done, could issue a request for an appropriate ssh key. The request
would then be forwarded by /sbin/request-key to the appropriate user who
could supply the key which is in turn used by the backup script to transfer
the results to a backup server. This allows for much more flexible and
interesting solutions than passwordless ssh key files or shared ssh
agents would ever be able to support. (I have a separate patch for 
openssh which allows ssh-add and ssh to work with in-kernel keys).

In addition, the in-kernel keys have the advantage of being non-ptraceable, 
will not be swapped out to disk, and does not run the risk of being included
in coredumps. The functionality added by these patches should also be 
interesting to some other security features (such as signed modules, signed
binaries and possibly some encrypted filesystems).

The patch is split into four sub-patches:

1) Adds a multi-precision-integer maths library

2) Adds dsa cryptographic operations. Since a dsa signature is always two 
   160-bit integer, I've modeled the dsa crypto as a hash algorithm.

3) Adds encryption as one of the supported ops for in-kernel keys.

4) Adds the dsa in-kernel key type.

This is the second version of these patches with the following changes from 
the first version:

* Make sure all functions have proper dsa_ prefixes
* Use kenter/kleave/kdebug in dsa_key.c instead of duplicated versions
* Let key type decide which locking to use for encrypt ops (semaphore or rcu)
* Add KERN_XXX levels for printk's
* Merge newer mpilib from Fedora kernel 2.6.15-1.1871_FC5
* Change some non-tab whitespace to tabs
* Change mpilib exports from EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
* Change crypto/dsa.c to copy key instead of referencing it
* Add documentation

Regards,
David Härdeman

--
 Documentation/keys.txt            |   77 +
 crypto/Kconfig                    |   15 
 crypto/Makefile                   |    2 
 crypto/dsa.c                      |  265 ++++++
 crypto/mpi/Makefile               |   31 
 crypto/mpi/generic_mpi-asm-defs.h |   10 
 crypto/mpi/generic_mpih-add1.c    |   64 +
 crypto/mpi/generic_mpih-lshift.c  |   66 +
 crypto/mpi/generic_mpih-mul1.c    |   60 +
 crypto/mpi/generic_mpih-mul2.c    |   63 +
 crypto/mpi/generic_mpih-mul3.c    |   64 +
 crypto/mpi/generic_mpih-rshift.c  |   66 +
 crypto/mpi/generic_mpih-sub1.c    |   63 +
 crypto/mpi/generic_udiv-w-sdiv.c  |  108 ++
 crypto/mpi/longlong.h             | 1502 ++++++++++++++++++++++++++++++++++++++
 crypto/mpi/mpi-add.c              |  241 ++++++
 crypto/mpi/mpi-bit.c              |  240 ++++++
 crypto/mpi/mpi-cmp.c              |   70 +
 crypto/mpi/mpi-div.c              |  342 ++++++++
 crypto/mpi/mpi-gcd.c              |   62 +
 crypto/mpi/mpi-inline.c           |   32 
 crypto/mpi/mpi-inline.h           |  128 +++
 crypto/mpi/mpi-internal.h         |  265 ++++++
 crypto/mpi/mpi-inv.c              |  189 ++++
 crypto/mpi/mpi-mpow.c             |  136 +++
 crypto/mpi/mpi-mul.c              |  199 +++++
 crypto/mpi/mpi-pow.c              |  324 ++++++++
 crypto/mpi/mpi-scan.c             |  127 +++
 crypto/mpi/mpicoder.c             |  388 +++++++++
 crypto/mpi/mpih-cmp.c             |   58 +
 crypto/mpi/mpih-div.c             |  545 +++++++++++++
 crypto/mpi/mpih-mul.c             |  537 +++++++++++++
 crypto/mpi/mpiutil.c              |  224 +++++
 include/linux/compat.h            |    4 
 include/linux/dsa.h               |   33 
 include/linux/key.h               |   10 
 include/linux/keyctl.h            |    1 
 include/linux/mpi.h               |  154 +++
 include/linux/syscalls.h          |    5 
 security/Kconfig                  |    8 
 security/keys/Makefile            |    1 
 security/keys/compat.c            |    9 
 security/keys/dsa_key.c           |  376 +++++++++
 security/keys/keyctl.c            |   67 +
 44 files changed, 7221 insertions(+), 10 deletions(-)


^ permalink raw reply	[flat|nested] 55+ messages in thread
* [PATCH 02/04] Add dsa crypto ops
@ 2006-01-23 20:42 David Härdeman
  2006-01-23 20:42 ` [PATCH 03/04] Add encryption ops to the keyctl syscall David Härdeman
  0 siblings, 1 reply; 55+ messages in thread
From: David Härdeman @ 2006-01-23 20:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: dhowells, david


Adds dsa cryptographic operations. Since a dsa signature is always two
160-bit integer, I've modeled the dsa crypto as a hash algorithm.

Signed-off-by: David Härdeman <david@2gen.com>

--

Index: vanilla-kernel/crypto/Kconfig
===================================================================
--- vanilla-kernel.orig/crypto/Kconfig	2006-01-22 22:02:20.000000000 +0100
+++ vanilla-kernel/crypto/Kconfig	2006-01-22 22:08:27.000000000 +0100
@@ -342,6 +342,13 @@
 	  Multiprecision maths library from GnuPG. Used for some
 	  crypto algorithms.
 
+config CRYPTO_DSA
+	tristate "Digital Signature Algorithm (EXPERIMENTAL)"
+	depends on CRYPTO && CRYPTO_MPILIB && EXPERIMENTAL
+	help
+	  Digital Signature Algorithm is used in a number of applications
+	  such as ssh and gpg.
+
 config CRYPTO_TEST
 	tristate "Testing module"
 	depends on CRYPTO
Index: vanilla-kernel/crypto/Makefile
===================================================================
--- vanilla-kernel.orig/crypto/Makefile	2006-01-22 22:02:37.000000000 +0100
+++ vanilla-kernel/crypto/Makefile	2006-01-22 22:08:27.000000000 +0100
@@ -30,6 +30,7 @@
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
+obj-$(CONFIG_CRYPTO_DSA) += dsa.o
 obj-$(CONFIG_CRYPTO_MPILIB) += mpi/
 
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
Index: vanilla-kernel/crypto/dsa.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ vanilla-kernel/crypto/dsa.c	2006-01-22 22:08:11.000000000 +0100
@@ -0,0 +1,230 @@
+/*
+ * DSA Digital Signature Algorithm (FIPS-186).
+ *
+ * Copyright (c) 2005 David Härdeman <david@2gen.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.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/mpi.h>
+#include <linux/dsa.h>
+#include <linux/random.h>
+#include "../security/keys/internal.h"
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+
+/****************
+ * Generate a random secret exponent k less than q
+ */
+static MPI
+gen_k(MPI q)
+{
+	MPI k = mpi_alloc(mpi_get_nlimbs(q));
+	unsigned int nbits = mpi_get_nbits(q);
+	unsigned int nbytes = (nbits + 7)/8;
+	char *rndbuf = NULL;
+
+	dprintk("dsa: choosing a random k\n");
+
+	while(1) {
+		if (!rndbuf) {
+			rndbuf = kmalloc(nbytes, GFP_KERNEL);
+			if (!rndbuf) {
+				printk("dsa: failed to create buffer\n");
+				return NULL;
+			}
+			get_random_bytes(rndbuf, nbytes);
+		} else {
+			/* change only some of the higher bits */
+			get_random_bytes(rndbuf, min(nbytes, (unsigned int)4));
+		}
+
+		mpi_set_buffer(k, rndbuf, nbytes, 0);
+		if(mpi_test_bit( k, nbits - 1)) {
+			mpi_set_highbit(k, nbits - 1);
+		} else {
+			mpi_set_highbit(k, nbits - 1);
+			mpi_clear_bit(k, nbits - 1);
+		}
+
+		/* check: k < q */
+		if(!(mpi_cmp(k, q) < 0))
+			continue;
+
+		/* check: k > 0 */
+		if(!(mpi_cmp_ui(k, 0) > 0))
+			continue;
+
+		/* okay */
+		break;
+	}
+
+	kfree(rndbuf);
+	return k;
+}
+
+static void
+sign_hash(MPI r, MPI s, MPI hash, struct key_payload_dsa *skey)
+{
+	MPI k, kinv, tmp;
+
+	/* select a random k with 0 < k < q */
+	k = gen_k(skey->part[DSA_PART_Q]);
+	if (!k) {
+		printk("dsa: failed to create buffer\n");
+		return;
+	}
+
+	/* r = (g^k mod p) mod q */
+	mpi_powm(r, skey->part[DSA_PART_G], k, skey->part[DSA_PART_P]);
+	mpi_fdiv_r(r, r, skey->part[DSA_PART_Q]);
+
+	/* kinv = k^(-1) mod q */
+	kinv = mpi_alloc(mpi_get_nlimbs(k));
+	mpi_invm(kinv, k, skey->part[DSA_PART_Q]);
+
+	/* s = (kinv * ( hash + x * r)) mod q */
+	tmp = mpi_alloc(mpi_get_nlimbs(skey->part[DSA_PART_P]));
+	mpi_mul(tmp, skey->part[DSA_PART_X], r);
+	mpi_add(tmp, tmp, hash);
+	mpi_mulm(s , kinv, tmp, skey->part[DSA_PART_Q]);
+
+	mpi_free(k);
+	mpi_free(kinv);
+	mpi_free(tmp);
+}
+
+struct dsa_ctx {
+	struct crypto_tfm *sha1;
+	struct key_payload_dsa *key;
+};
+
+static int dsa_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+{
+	struct dsa_ctx *dctx = ctx;
+
+	if (keylen != sizeof(struct key_payload_dsa *)) {
+		printk("Invalid key size in dsa_setkey\n");
+		return -EINVAL;
+	}
+
+	dctx->key = (struct key_payload_dsa *)key;
+	return 0;
+}
+
+static void dsa_init(void *ctx)
+{
+	struct dsa_ctx *dctx = ctx;
+
+	dctx->key = NULL;
+	dctx->sha1 = crypto_alloc_tfm("sha1", 0);
+	if (!dctx->sha1)
+		printk("dsa_init: failed to allocate sha1 tfm\n");
+	else
+		crypto_digest_init(dctx->sha1);
+}
+
+static void dsa_update(void *ctx, const u8 *data, unsigned int dlen)
+{
+	struct scatterlist sg[1];
+	struct dsa_ctx *dctx = ctx;
+
+	if (!dctx->sha1)
+		return;
+
+	sg_init_one(sg, (u8 *)data, dlen);
+	crypto_digest_update(dctx->sha1, sg, 1);
+}
+
+static void dsa_final(void *ctx, u8 *out)
+{
+	struct dsa_ctx *dctx = ctx;
+	unsigned int dsize = crypto_tfm_alg_digestsize(dctx->sha1);
+	u8 buffer[dsize];
+	MPI hash, r, s;
+	u8 *outp = out;
+	unsigned int rbytes, rbits, sbytes, sbits;
+	char *rbuf, *sbuf;
+
+	if (!dctx->sha1)
+		return;
+
+	crypto_digest_final(dctx->sha1, buffer);
+	crypto_free_tfm(dctx->sha1);
+	dctx->sha1 = NULL;
+
+	hash = mpi_alloc(1);
+	r = mpi_alloc(1);
+	s = mpi_alloc(1);
+	if (!hash || !r || !s) {
+		printk("dsa_final: failed to allocate mpis\n");
+		goto out1;
+	}
+
+	mpi_set_buffer(hash, buffer, dsize, 0);
+	sign_hash(r, s, hash, dctx->key);
+	rbuf = mpi_get_buffer(r, &rbytes, NULL);
+	sbuf = mpi_get_buffer(s, &sbytes, NULL);
+	if (!rbuf || !sbuf) {
+		printk("dsa_final: failed to allocate buffers\n");
+		goto out2;
+	}
+
+	rbits = mpi_get_nbits(r);
+	MPI_WSIZE(outp, rbits);
+	memcpy(outp, rbuf, rbytes);
+	outp += rbytes;
+
+	sbits = mpi_get_nbits(s);
+	MPI_WSIZE(outp, sbits);
+	memcpy(outp, sbuf, sbytes);
+
+out2:
+	kfree(rbuf);
+	kfree(sbuf);
+out1:
+	mpi_free(hash);
+	mpi_free(r);
+	mpi_free(s);
+}
+
+static struct crypto_alg alg = {
+	.cra_name	=	"dsa",
+	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	=	DSA_HMAC_BLOCK_SIZE,
+	.cra_ctxsize	=	sizeof(struct dsa_ctx),
+	.cra_module	=	THIS_MODULE,
+	.cra_list	=	LIST_HEAD_INIT(alg.cra_list),
+	.cra_u		=	{ .digest = {
+	.dia_digestsize	=	DSA_DIGEST_SIZE,
+	.dia_init   	= 	dsa_init,
+	.dia_update 	=	dsa_update,
+	.dia_final  	=	dsa_final,
+	.dia_setkey  	=	dsa_setkey } }
+};
+
+static int __init init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("David Härdeman");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DSA Digital Signature Algorithm");
Index: vanilla-kernel/include/linux/dsa.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ vanilla-kernel/include/linux/dsa.h	2006-01-22 22:07:58.000000000 +0100
@@ -0,0 +1,39 @@
+/* dsa.h: digital signature architecture
+ *
+ * Copyright (C) 2005 David Härdeman (david@2gen.com).
+ * All Rights Reserved.
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_DSA_H
+#define _LINUX_DSA_H
+#ifdef __KERNEL__
+
+#include <linux/mpi.h>
+
+#define DSA_DIGEST_SIZE         44
+#define DSA_HMAC_BLOCK_SIZE     64
+#define DSA_PART_P              0
+#define DSA_PART_Q              1
+#define DSA_PART_G              2
+#define DSA_PART_Y              3
+#define DSA_PART_X              4
+#define DSA_PARTS               5
+#define DSA_PUBLIC_PARTS        4
+
+struct key_payload_dsa {
+    MPI part[DSA_PARTS]; /* p,q,g,y,x */
+};
+
+#if 0
+#define dprintk(x...) printk(x)
+#else
+#define dprintk(x...) do { } while(0)
+#endif
+
+#endif
+#endif


^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2006-02-06 12:31 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-01-26 21:58 [PATCH 00/04] Add DSA key type David Härdeman
2006-01-26 21:58 ` [PATCH 02/04] Add dsa crypto ops David Härdeman
2006-01-26 21:58 ` [PATCH 01/04] Add multi-precision-integer maths library David Härdeman
2006-01-27  9:28   ` Christoph Hellwig
2006-01-27 20:07     ` David Howells
2006-01-27 20:41       ` David Härdeman
2006-01-27 22:19         ` [Keyrings] " Trond Myklebust
2006-01-27 23:35           ` Kyle Moffett
2006-01-28  0:27             ` Adrian Bunk
2006-01-28  3:45             ` Trond Myklebust
2006-01-28  7:17               ` Kyle Moffett
2006-01-28 10:39                 ` Adrian Bunk
2006-01-28  0:22         ` Adrian Bunk
2006-01-28 10:46           ` David Härdeman
2006-01-28 13:03             ` Adrian Bunk
2006-01-28 17:09               ` David Härdeman
2006-01-28 16:37             ` [Keyrings] " Trond Myklebust
2006-01-28 16:57               ` David Härdeman
2006-01-29  3:20                 ` Trond Myklebust
2006-01-29 11:33                   ` David Härdeman
2006-01-29 12:29                     ` Adrian Bunk
2006-01-29 13:09                       ` Arjan van de Ven
2006-01-29 20:05                         ` Steve French
2006-01-29 20:52                           ` Arjan van de Ven
2006-01-29 21:41                             ` Steve French
2006-02-06 12:31                             ` David Howells
2006-01-29 23:18                         ` Adrian Bunk
2006-01-29 13:18                       ` David Härdeman
2006-01-29 23:36                         ` Adrian Bunk
2006-01-30 18:09                           ` Nix
2006-01-29 16:38                     ` Trond Myklebust
2006-01-29 18:49                       ` Dax Kelson
2006-01-29 19:10                         ` Trond Myklebust
2006-01-29 21:29                           ` David Härdeman
2006-01-29 21:46                             ` Trond Myklebust
2006-01-29 21:13                       ` David Härdeman
2006-01-29 21:28                         ` Trond Myklebust
2006-01-29 22:02                           ` David Härdeman
2006-01-29 22:05                             ` Trond Myklebust
2006-01-29 22:54                               ` Kyle Moffett
2006-01-29 23:07                                 ` Trond Myklebust
2006-01-29 23:15                                 ` Adrian Bunk
2006-01-29 21:09             ` Pavel Machek
2006-01-26 21:58 ` [PATCH 03/04] Add encryption ops to the keyctl syscall David Härdeman
2006-01-26 21:58 ` [PATCH 04/04] Add dsa key type David Härdeman
2006-01-27  1:10 ` [PATCH 00/04] Add DSA " Herbert Xu
2006-01-27  7:18   ` David Härdeman
2006-01-27 20:11     ` David Howells
2006-01-27 23:22       ` Herbert Xu
  -- strict thread matches above, loose matches on Subject: below --
2006-01-23 20:42 [PATCH 02/04] Add dsa crypto ops David Härdeman
2006-01-23 20:42 ` [PATCH 03/04] Add encryption ops to the keyctl syscall David Härdeman
2006-01-24  4:33   ` Randy.Dunlap
2006-01-24 10:58   ` David Howells
2006-01-25 20:40     ` David Härdeman
2006-01-26  9:43       ` David Howells
2006-01-24 11:09   ` David Howells

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox