All of lore.kernel.org
 help / color / mirror / Atom feed
From: "David Härdeman" <david@2gen.com>
To: linux-kernel@vger.kernel.org
Cc: dhowells@redhat.com, keyrings@linux-nfs.org, david@2gen.com
Subject: [PATCH 02/04] Add dsa crypto ops
Date: Thu, 26 Jan 2006 22:58:15 +0100	[thread overview]
Message-ID: <1138312695326@2gen.com> (raw)
In-Reply-To: <1138312694656@2gen.com>


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

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

--
Index: dsa-kernel/crypto/Kconfig
===================================================================
--- dsa-kernel.orig/crypto/Kconfig	2006-01-25 20:40:03.000000000 +0100
+++ dsa-kernel/crypto/Kconfig	2006-01-25 20:46:45.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: dsa-kernel/crypto/Makefile
===================================================================
--- dsa-kernel.orig/crypto/Makefile	2006-01-25 20:40:03.000000000 +0100
+++ dsa-kernel/crypto/Makefile	2006-01-25 20:46:45.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: dsa-kernel/crypto/dsa.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ dsa-kernel/crypto/dsa.c	2006-01-25 23:26:19.000000000 +0100
@@ -0,0 +1,265 @@
+/*
+ * 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>
+
+#if 0
+#define dprintk(x...) printk(x)
+#else
+#define dprintk(x...) do { } while(0)
+#endif
+
+/****************
+ * Generate a random secret exponent k less than q
+ */
+static MPI
+dsa_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(KERN_ERR "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
+dsa_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 = dsa_gen_k(skey->part[DSA_PART_Q]);
+	if (!k) {
+		printk(KERN_ERR "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;
+	struct key_payload_dsa *dkey, *skey = (struct key_payload_dsa *)key;
+	int i, ret;
+
+	ret = -EINVAL;
+	if (keylen != sizeof(struct key_payload_dsa *)) {
+		printk(KERN_ERR "dsa: invalid key size in dsa_setkey\n");
+		goto out;
+	}
+
+	/* Make a copy of the key in case it later disappears */
+	ret = -ENOMEM;
+	dctx->key = kmalloc(sizeof(struct key_payload_dsa), GFP_KERNEL);
+	if (!dctx->key) {
+		printk(KERN_ERR "dsa: failed to allocate memory for key\n");
+		goto out;
+	}
+	dkey = dctx->key;
+
+	ret = 0;
+	for (i = 0; i < DSA_PARTS; i++)
+		if (mpi_copy(&dkey->part[i], skey->part[i]))
+			ret = -ENOMEM;
+
+	if (ret) {
+		for (i = 0; i < DSA_PARTS; i++)
+			mpi_free(dkey->part[i]);
+		kfree(dkey);
+	}
+
+out:
+	return ret;
+}
+
+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(KERN_ERR "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;
+	int i;
+
+	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(KERN_ERR "dsa: failed to allocate mpis\n");
+		goto out1;
+	}
+
+	mpi_set_buffer(hash, buffer, dsize, 0);
+	dsa_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(KERN_ERR "dsa: 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);
+
+	for (i = 0; i < DSA_PARTS; i++)
+		mpi_free(dctx->key->part[i]);
+	kfree(dctx->key);
+}
+
+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)
+{
+	printk(KERN_INFO "Registering Digital Signature Algorithm crypto\n");
+	return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+	printk(KERN_INFO "Unregistering Digital Signature Algorithm crypto\n");
+	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: dsa-kernel/include/linux/dsa.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ dsa-kernel/include/linux/dsa.h	2006-01-25 20:46:45.000000000 +0100
@@ -0,0 +1,33 @@
+/* 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 */
+};
+
+#endif
+#endif


  parent reply	other threads:[~2006-01-26 21:58 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-01-26 21:58 [PATCH 00/04] Add DSA key type David Härdeman
2006-01-26 21:58 ` [PATCH 03/04] Add encryption ops to the keyctl syscall 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 ` David Härdeman [this message]
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
     [not found] <11380489522552@2gen.com>
2006-01-23 20:42 ` [PATCH 02/04] Add dsa crypto ops David Härdeman
2006-01-24  1:22   ` Herbert Xu
2006-01-24  6:49     ` David Härdeman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1138312695326@2gen.com \
    --to=david@2gen.com \
    --cc=dhowells@redhat.com \
    --cc=keyrings@linux-nfs.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.