[PATCH 10/21] KEYS: DSA signature verification algorithm [ver #3]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Implement the DSA algorithm (FIPS-186).  At this time, only signature
verification is supported.  This uses the asymmetric public key subtype to hold
its key data.

Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
---

 security/keys/Kconfig      |    7 ++
 security/keys/Makefile     |    1 
 security/keys/crypto_dsa.c |  126 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+), 0 deletions(-)
 create mode 100644 security/keys/crypto_dsa.c


diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 07c7f3b..76de2ba 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -86,3 +86,10 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
 	  If signature generation and/or verification are to be used,
 	  appropriate hash algorithms (such as SHA-1) must be available.
 	  ENOPKG will be reported if the requisite algorithm is unavailable.
+
+config CRYPTO_KEY_PKEY_ALGO_DSA
+	tristate "DSA public-key algorithm"
+	depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
+	help
+	  This option enables support for the DSA public key algorithm
+	  (FIPS-186).
diff --git a/security/keys/Makefile b/security/keys/Makefile
index dc3281f..5f1c627 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -26,5 +26,6 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
 obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
 obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
 obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
+obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_DSA) += crypto_dsa.o
 
 crypto_keys-y := crypto_type.o crypto_verify.o
diff --git a/security/keys/crypto_dsa.c b/security/keys/crypto_dsa.c
new file mode 100644
index 0000000..26b86f2
--- /dev/null
+++ b/security/keys/crypto_dsa.c
@@ -0,0 +1,126 @@
+/* DSA asymmetric public-key algorithm
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@xxxxxxxxxx)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "DSA: "fmt
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include "public_key.h"
+
+MODULE_LICENSE("GPL");
+
+#define kenter(FMT, ...) \
+	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+/*
+ * Perform the actual mathematical DSA signature verification.
+ */
+static int DSA_verify(const MPI datahash,
+		      const struct public_key_signature *sig,
+		      const struct public_key *key)
+{
+	MPI w = NULL, u1 = NULL, u2 = NULL, v = NULL;
+	MPI base[3];
+	MPI exp[3];
+	int rc;
+
+	kenter("");
+
+	if (!(mpi_cmp_ui(sig->dsa.r, 0) > 0 &&
+	      mpi_cmp(sig->dsa.r, key->dsa.q) < 0)) {
+		pr_warning("Assertion failed [0 < r < q]\n");
+		return -EKEYREJECTED;
+	}
+
+	if (!(mpi_cmp_ui(sig->dsa.s, 0) > 0 &&
+	      mpi_cmp(sig->dsa.s, key->dsa.q) < 0)) {
+		pr_warning("Assertion failed [0 < s < q]\n");
+		return -EKEYREJECTED;
+	}
+
+	rc = -ENOMEM;
+	w  = mpi_alloc(mpi_get_nlimbs(key->dsa.q)); if (!w ) goto cleanup;
+	u1 = mpi_alloc(mpi_get_nlimbs(key->dsa.q)); if (!u1) goto cleanup;
+	u2 = mpi_alloc(mpi_get_nlimbs(key->dsa.q)); if (!u2) goto cleanup;
+	v  = mpi_alloc(mpi_get_nlimbs(key->dsa.p)); if (!v ) goto cleanup;
+
+	/* w = s^(-1) mod q */
+	if (mpi_invm(w, sig->dsa.s, key->dsa.q) < 0)
+		goto cleanup;
+
+	/* u1 = (datahash * w) mod q */
+	if (mpi_mulm(u1, datahash, w, key->dsa.q) < 0)
+		goto cleanup;
+
+	/* u2 = r * w mod q  */
+	if (mpi_mulm(u2, sig->dsa.r, w, key->dsa.q) < 0)
+		goto cleanup;
+
+	/* v =  g^u1 * y^u2 mod p mod q */
+	base[0] = key->dsa.g;	exp[0] = u1;
+	base[1] = key->dsa.y;	exp[1] = u2;
+	base[2] = NULL;		exp[2] = NULL;
+
+	if (mpi_mulpowm(v, base, exp, key->dsa.p) < 0)
+		goto cleanup;
+
+	if (mpi_fdiv_r(v, v, key->dsa.q) < 0)
+		goto cleanup;
+
+	rc = (mpi_cmp(v, sig->dsa.r) == 0) ? 0 : -EKEYREJECTED;
+
+cleanup:
+	mpi_free(w);
+	mpi_free(u1);
+	mpi_free(u2);
+	mpi_free(v);
+	kleave(" = %d", rc);
+	return rc;
+}
+
+/*
+ * Perform the verification step.
+ */
+static int DSA_verify_signature(const struct public_key *key,
+				const struct public_key_signature *sig)
+{
+	MPI datahash = NULL;
+	int ret;
+
+	kenter("");
+
+	ret = -ENOMEM;
+	datahash = mpi_alloc((sig->digest_size + BYTES_PER_MPI_LIMB - 1) /
+			     BYTES_PER_MPI_LIMB);
+	if (!datahash)
+		goto error;
+
+	ret = mpi_set_buffer(datahash, sig->digest, sig->digest_size, 0);
+	if (ret < 0)
+		goto error;
+
+	ret = DSA_verify(datahash, sig, key);
+
+error:
+	mpi_free(datahash);
+	kleave(" = %d", ret);
+	return ret;
+}
+
+const struct public_key_algorithm DSA_public_key_algorithm = {
+	.name		= "DSA",
+	.n_pub_mpi	= 4,
+	.n_sec_mpi	= 1,
+	.n_sig_mpi	= 2,
+	.verify		= DSA_verify_signature,
+};
+EXPORT_SYMBOL_GPL(DSA_public_key_algorithm);

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux