All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] X.509: Software public key subtype changes
@ 2016-02-19 17:18 David Howells
  2016-02-19 17:18 ` [PATCH 1/8] crypto: KEYS: convert public key and digsig asym to the akcipher api David Howells
                   ` (10 more replies)
  0 siblings, 11 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:18 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk


Here's a set of patches that cleans up the public key handling in the
asymmetric key functions:

 (1) - (3) These are Tadeusz's RSA akcipher conversion.

 (4) This removes all knowledge of RSA from the software public key
     asymmetric key subtype.  Instead, the public key type and the hash
     type are indicated to the crypto layer and the RSA module there does
     all the appropriate encoding.

 (5) This changes the various algorithm IDs to text labels instead of enums
     as the strings are what we actually deal with (printing, passing to
     the crypto layer).

 (6) This separates the private parts of the software public key subtype
     into a private header in the implementation directory.

 (7) This renames public_key.c to software_pkey.c and changes the Kconfig
     symbol to match.

 (8) This renames symbols beginning "public_key" to "software_pkey" except
     struct for public_key_signature which is a wider API component.

The patches can be found here also:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-rsa

David
---
David Howells (5):
      akcipher: Move the RSA DER encoding to the crypto layer
      X.509: Make algo identifiers text instead of enum
      X.509: Make the public_key asymmetric key type internal data private
      X.509: Rename public_key.c to software_pkey.c
      X.509: Rename public_key* to software_pkey*

Tadeusz Struk (3):
      crypto: KEYS: convert public key and digsig asym to the akcipher api
      integrity: convert digsig to akcipher api
      crypto: public_key: remove MPIs from public_key_signature struct


 arch/s390/configs/default_defconfig       |    2 
 arch/s390/configs/gcov_defconfig          |    2 
 arch/s390/configs/performance_defconfig   |    2 
 crypto/asymmetric_keys/Kconfig            |   17 +-
 crypto/asymmetric_keys/Makefile           |   10 -
 crypto/asymmetric_keys/mscode_parser.c    |   14 +
 crypto/asymmetric_keys/pkcs7_parser.c     |   30 +--
 crypto/asymmetric_keys/pkcs7_trust.c      |    2 
 crypto/asymmetric_keys/pkcs7_verify.c     |   12 +
 crypto/asymmetric_keys/public_key.c       |  130 --------------
 crypto/asymmetric_keys/public_key.h       |   36 ----
 crypto/asymmetric_keys/rsa.c              |  278 -----------------------------
 crypto/asymmetric_keys/software_pkey.c    |  142 +++++++++++++++
 crypto/asymmetric_keys/software_pkey.h    |   33 +++
 crypto/asymmetric_keys/verify_pefile.c    |    4 
 crypto/asymmetric_keys/verify_pefile.h    |    2 
 crypto/asymmetric_keys/x509_cert_parser.c |   67 ++-----
 crypto/asymmetric_keys/x509_parser.h      |    4 
 crypto/asymmetric_keys/x509_public_key.c  |   43 ++--
 crypto/asymmetric_keys/x509_rsakey.asn1   |    4 
 crypto/rsa.c                              |  210 +++++++++++++++++++---
 crypto/testmgr.c                          |    5 -
 include/crypto/akcipher.h                 |    7 +
 include/crypto/public_key.h               |   79 +-------
 init/Kconfig                              |    4 
 kernel/module_signing.c                   |    6 +
 security/integrity/Kconfig                |    3 
 security/integrity/digsig_asymmetric.c    |   16 +-
 28 files changed, 467 insertions(+), 697 deletions(-)
 delete mode 100644 crypto/asymmetric_keys/public_key.c
 delete mode 100644 crypto/asymmetric_keys/public_key.h
 delete mode 100644 crypto/asymmetric_keys/rsa.c
 create mode 100644 crypto/asymmetric_keys/software_pkey.c
 create mode 100644 crypto/asymmetric_keys/software_pkey.h
 delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1

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

* [PATCH 1/8] crypto: KEYS: convert public key and digsig asym to the akcipher api
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
@ 2016-02-19 17:18 ` David Howells
  2016-02-19 17:18 ` [PATCH 2/8] integrity: convert digsig to " David Howells
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:18 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk

From: Tadeusz Struk <tadeusz.struk@intel.com>

This patch converts the module verification code to the new akcipher API.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 crypto/asymmetric_keys/Kconfig            |    2 
 crypto/asymmetric_keys/Makefile           |    7 -
 crypto/asymmetric_keys/pkcs7_parser.c     |   12 +-
 crypto/asymmetric_keys/pkcs7_trust.c      |    2 
 crypto/asymmetric_keys/pkcs7_verify.c     |    2 
 crypto/asymmetric_keys/public_key.c       |   64 +++------
 crypto/asymmetric_keys/public_key.h       |   36 -----
 crypto/asymmetric_keys/rsa.c              |  212 +++++++++++------------------
 crypto/asymmetric_keys/x509_cert_parser.c |   37 +----
 crypto/asymmetric_keys/x509_public_key.c  |   17 +-
 crypto/asymmetric_keys/x509_rsakey.asn1   |    4 -
 include/crypto/public_key.h               |   34 +----
 12 files changed, 134 insertions(+), 295 deletions(-)
 delete mode 100644 crypto/asymmetric_keys/public_key.h
 delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1

diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 4870f28403f5..905d745c2f85 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -22,7 +22,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
 
 config PUBLIC_KEY_ALGO_RSA
 	tristate "RSA public-key algorithm"
-	select MPILIB
+	select CRYPTO_RSA
 	help
 	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
 
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index cd1406f9b14a..b78a194ea014 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -16,21 +16,18 @@ obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
 x509_key_parser-y := \
 	x509-asn1.o \
 	x509_akid-asn1.o \
-	x509_rsakey-asn1.o \
 	x509_cert_parser.o \
 	x509_public_key.o
 
 $(obj)/x509_cert_parser.o: \
 	$(obj)/x509-asn1.h \
-	$(obj)/x509_akid-asn1.h \
-	$(obj)/x509_rsakey-asn1.h
+	$(obj)/x509_akid-asn1.h
+
 $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h
 $(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h
-$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h
 
 clean-files	+= x509-asn1.c x509-asn1.h
 clean-files	+= x509_akid-asn1.c x509_akid-asn1.h
-clean-files	+= x509_rsakey-asn1.c x509_rsakey-asn1.h
 
 #
 # PKCS#7 message handling
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 8f3056cd0399..3ef62dac9771 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -15,7 +15,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/oid_registry.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
 #include "pkcs7_parser.h"
 #include "pkcs7-asn1.h"
 
@@ -44,7 +44,7 @@ struct pkcs7_parse_context {
 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
 {
 	if (sinfo) {
-		mpi_free(sinfo->sig.mpi[0]);
+		kfree(sinfo->sig.s);
 		kfree(sinfo->sig.digest);
 		kfree(sinfo->signing_cert_id);
 		kfree(sinfo);
@@ -614,16 +614,14 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen,
 			     const void *value, size_t vlen)
 {
 	struct pkcs7_parse_context *ctx = context;
-	MPI mpi;
 
 	BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
 
-	mpi = mpi_read_raw_data(value, vlen);
-	if (!mpi)
+	ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL);
+	if (!ctx->sinfo->sig.s)
 		return -ENOMEM;
 
-	ctx->sinfo->sig.mpi[0] = mpi;
-	ctx->sinfo->sig.nr_mpi = 1;
+	ctx->sinfo->sig.s_size = vlen;
 	return 0;
 }
 
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index 90d6d47965b0..3bbdcc79a3d3 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -17,7 +17,7 @@
 #include <linux/asn1.h>
 #include <linux/key.h>
 #include <keys/asymmetric-type.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
 #include "pkcs7_parser.h"
 
 /**
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 325575caf6b4..f5db1378c096 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -16,7 +16,7 @@
 #include <linux/err.h>
 #include <linux/asn1.h>
 #include <crypto/hash.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
 #include "pkcs7_parser.h"
 
 /*
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 6db4c01c6503..b383629b9e62 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -18,24 +18,16 @@
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <keys/asymmetric-subtype.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
 
 MODULE_LICENSE("GPL");
 
 const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
-	[PKEY_ALGO_DSA]		= "DSA",
-	[PKEY_ALGO_RSA]		= "RSA",
+	[PKEY_ALGO_DSA]		= "dsa",
+	[PKEY_ALGO_RSA]		= "rsa",
 };
 EXPORT_SYMBOL_GPL(pkey_algo_name);
 
-const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = {
-#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
-	defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
-	[PKEY_ALGO_RSA]		= &RSA_public_key_algorithm,
-#endif
-};
-EXPORT_SYMBOL_GPL(pkey_algo);
-
 const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
 	[PKEY_ID_PGP]		= "PGP",
 	[PKEY_ID_X509]		= "X509",
@@ -43,6 +35,12 @@ const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
 };
 EXPORT_SYMBOL_GPL(pkey_id_type_name);
 
+static int (*alg_verify[PKEY_ALGO__LAST])(const struct public_key *pkey,
+	const struct public_key_signature *sig) = {
+	NULL,
+	rsa_verify_signature
+};
+
 /*
  * Provide a part of a description of the key for /proc/keys.
  */
@@ -53,7 +51,8 @@ static void public_key_describe(const struct key *asymmetric_key,
 
 	if (key)
 		seq_printf(m, "%s.%s",
-			   pkey_id_type_name[key->id_type], key->algo->name);
+			   pkey_id_type_name[key->id_type],
+			   pkey_algo_name[key->pkey_algo]);
 }
 
 /*
@@ -62,50 +61,31 @@ static void public_key_describe(const struct key *asymmetric_key,
 void public_key_destroy(void *payload)
 {
 	struct public_key *key = payload;
-	int i;
 
-	if (key) {
-		for (i = 0; i < ARRAY_SIZE(key->mpi); i++)
-			mpi_free(key->mpi[i]);
-		kfree(key);
-	}
+	if (key)
+		kfree(key->key);
+	kfree(key);
 }
 EXPORT_SYMBOL_GPL(public_key_destroy);
 
 /*
  * Verify a signature using a public key.
  */
-int public_key_verify_signature(const struct public_key *pk,
+int public_key_verify_signature(const struct public_key *pkey,
 				const struct public_key_signature *sig)
 {
-	const struct public_key_algorithm *algo;
-
-	BUG_ON(!pk);
-	BUG_ON(!pk->mpi[0]);
-	BUG_ON(!pk->mpi[1]);
+	BUG_ON(!pkey);
 	BUG_ON(!sig);
 	BUG_ON(!sig->digest);
-	BUG_ON(!sig->mpi[0]);
-
-	algo = pk->algo;
-	if (!algo) {
-		if (pk->pkey_algo >= PKEY_ALGO__LAST)
-			return -ENOPKG;
-		algo = pkey_algo[pk->pkey_algo];
-		if (!algo)
-			return -ENOPKG;
-	}
+	BUG_ON(!sig->s);
 
-	if (!algo->verify_signature)
-		return -ENOTSUPP;
+	if (pkey->pkey_algo >= PKEY_ALGO__LAST)
+		return -ENOPKG;
 
-	if (sig->nr_mpi != algo->n_sig_mpi) {
-		pr_debug("Signature has %u MPI not %u\n",
-			 sig->nr_mpi, algo->n_sig_mpi);
-		return -EINVAL;
-	}
+	if (!alg_verify[pkey->pkey_algo])
+		return -ENOPKG;
 
-	return algo->verify_signature(pk, sig);
+	return alg_verify[pkey->pkey_algo](pkey, sig);
 }
 EXPORT_SYMBOL_GPL(public_key_verify_signature);
 
diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h
deleted file mode 100644
index 5c37a22a0637..000000000000
--- a/crypto/asymmetric_keys/public_key.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Public key algorithm internals
- *
- * See Documentation/crypto/asymmetric-keys.txt
- *
- * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * 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.
- */
-
-#include <crypto/public_key.h>
-
-extern struct asymmetric_key_subtype public_key_subtype;
-
-/*
- * Public key algorithm definition.
- */
-struct public_key_algorithm {
-	const char	*name;
-	u8		n_pub_mpi;	/* Number of MPIs in public key */
-	u8		n_sec_mpi;	/* Number of MPIs in secret key */
-	u8		n_sig_mpi;	/* Number of MPIs in a signature */
-	int (*verify_signature)(const struct public_key *key,
-				const struct public_key_signature *sig);
-};
-
-extern const struct public_key_algorithm RSA_public_key_algorithm;
-
-/*
- * public_key.c
- */
-extern int public_key_verify_signature(const struct public_key *pk,
-				       const struct public_key_signature *sig);
diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
index 508b57b77474..51502bca65e7 100644
--- a/crypto/asymmetric_keys/rsa.c
+++ b/crypto/asymmetric_keys/rsa.c
@@ -11,10 +11,10 @@
 
 #define pr_fmt(fmt) "RSA: "fmt
 #include <linux/module.h>
-#include <linux/kernel.h>
 #include <linux/slab.h>
+#include <crypto/akcipher.h>
+#include <crypto/public_key.h>
 #include <crypto/algapi.h>
-#include "public_key.h"
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("RSA Public Key Algorithm");
@@ -84,72 +84,10 @@ static const struct {
 #undef _
 };
 
-/*
- * RSAVP1() function [RFC3447 sec 5.2.2]
- */
-static int RSAVP1(const struct public_key *key, MPI s, MPI *_m)
-{
-	MPI m;
-	int ret;
-
-	/* (1) Validate 0 <= s < n */
-	if (mpi_cmp_ui(s, 0) < 0) {
-		kleave(" = -EBADMSG [s < 0]");
-		return -EBADMSG;
-	}
-	if (mpi_cmp(s, key->rsa.n) >= 0) {
-		kleave(" = -EBADMSG [s >= n]");
-		return -EBADMSG;
-	}
-
-	m = mpi_alloc(0);
-	if (!m)
-		return -ENOMEM;
-
-	/* (2) m = s^e mod n */
-	ret = mpi_powm(m, s, key->rsa.e, key->rsa.n);
-	if (ret < 0) {
-		mpi_free(m);
-		return ret;
-	}
-
-	*_m = m;
-	return 0;
-}
-
-/*
- * Integer to Octet String conversion [RFC3447 sec 4.1]
- */
-static int RSA_I2OSP(MPI x, size_t xLen, u8 **pX)
-{
-	unsigned X_size, x_size;
-	int X_sign;
-	u8 *X;
-
-	/* Make sure the string is the right length.  The number should begin
-	 * with { 0x00, 0x01, ... } so we have to account for 15 leading zero
-	 * bits not being reported by MPI.
-	 */
-	x_size = mpi_get_nbits(x);
-	pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8);
-	if (x_size != xLen * 8 - 15)
-		return -ERANGE;
-
-	X = mpi_get_buffer(x, &X_size, &X_sign);
-	if (!X)
-		return -ENOMEM;
-	if (X_sign < 0) {
-		kfree(X);
-		return -EBADMSG;
-	}
-	if (X_size != xLen - 1) {
-		kfree(X);
-		return -EBADMSG;
-	}
-
-	*pX = X;
-	return 0;
-}
+struct rsa_completion {
+	struct completion completion;
+	int err;
+};
 
 /*
  * Perform the RSA signature verification.
@@ -160,7 +98,7 @@ static int RSA_I2OSP(MPI x, size_t xLen, u8 **pX)
  * @asn1_template: The DigestInfo ASN.1 template
  * @asn1_size: Size of asm1_template[]
  */
-static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
+static int rsa_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
 		      const u8 *asn1_template, size_t asn1_size)
 {
 	unsigned PS_end, T_offset, i;
@@ -170,9 +108,11 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
 	if (k < 2 + 1 + asn1_size + hash_size)
 		return -EBADMSG;
 
-	/* Decode the EMSA-PKCS1-v1_5 */
-	if (EM[1] != 0x01) {
-		kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]);
+	/* Decode the EMSA-PKCS1-v1_5
+	 * note: leading zeros are stripped by the RSA implementation
+	 */
+	if (EM[0] != 0x01) {
+		kleave(" = -EBADMSG [EM[0] == %02u]", EM[0]);
 		return -EBADMSG;
 	}
 
@@ -183,7 +123,7 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
 		return -EBADMSG;
 	}
 
-	for (i = 2; i < PS_end; i++) {
+	for (i = 1; i < PS_end; i++) {
 		if (EM[i] != 0xff) {
 			kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]);
 			return -EBADMSG;
@@ -204,75 +144,81 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
 	return 0;
 }
 
-/*
- * Perform the verification step [RFC3447 sec 8.2.2].
- */
-static int RSA_verify_signature(const struct public_key *key,
-				const struct public_key_signature *sig)
+static void public_key_verify_done(struct crypto_async_request *req, int err)
 {
-	size_t tsize;
-	int ret;
+	struct rsa_completion *compl = req->data;
 
-	/* Variables as per RFC3447 sec 8.2.2 */
-	const u8 *H = sig->digest;
-	u8 *EM = NULL;
-	MPI m = NULL;
-	size_t k;
+	if (err == -EINPROGRESS)
+		return;
 
-	kenter("");
-
-	if (!RSA_ASN1_templates[sig->pkey_hash_algo].data)
-		return -ENOTSUPP;
-
-	/* (1) Check the signature size against the public key modulus size */
-	k = mpi_get_nbits(key->rsa.n);
-	tsize = mpi_get_nbits(sig->rsa.s);
+	compl->err = err;
+	complete(&compl->completion);
+}
 
-	/* According to RFC 4880 sec 3.2, length of MPI is computed starting
-	 * from most significant bit.  So the RFC 3447 sec 8.2.2 size check
-	 * must be relaxed to conform with shorter signatures - so we fail here
-	 * only if signature length is longer than modulus size.
-	 */
-	pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
-	if (k < tsize) {
-		ret = -EBADMSG;
-		goto error;
+int rsa_verify_signature(const struct public_key *pkey,
+			 const struct public_key_signature *sig)
+{
+	struct crypto_akcipher *tfm;
+	struct akcipher_request *req;
+	struct rsa_completion compl;
+	struct scatterlist sig_sg, sg_out;
+	void *outbuf = NULL;
+	unsigned int outlen = 0;
+	int ret = -ENOMEM;
+
+	tfm = crypto_alloc_akcipher("rsa", 0, 0);
+	if (IS_ERR(tfm))
+		goto error_out;
+
+	req = akcipher_request_alloc(tfm, GFP_KERNEL);
+	if (!req)
+		goto error_free_tfm;
+
+	ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
+	if (ret)
+		goto error_free_req;
+
+	ret = -EINVAL;
+	outlen = crypto_akcipher_maxsize(tfm);
+	if (!outlen)
+		goto error_free_req;
+
+	/* Initialize the output buffer */
+	ret = -ENOMEM;
+	outbuf = kmalloc(outlen, GFP_KERNEL);
+	if (!outbuf)
+		goto error_free_req;
+
+	sg_init_one(&sig_sg, sig->s, sig->s_size);
+	sg_init_one(&sg_out, outbuf, outlen);
+	akcipher_request_set_crypt(req, &sig_sg, &sg_out, sig->s_size, outlen);
+	init_completion(&compl.completion);
+	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+				      CRYPTO_TFM_REQ_MAY_SLEEP,
+				      public_key_verify_done, &compl);
+
+	ret = crypto_akcipher_verify(req);
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&compl.completion);
+		ret = compl.err;
 	}
 
-	/* Round up and convert to octets */
-	k = (k + 7) / 8;
+	if (ret)
+		goto error_free_req;
 
-	/* (2b) Apply the RSAVP1 verification primitive to the public key */
-	ret = RSAVP1(key, sig->rsa.s, &m);
-	if (ret < 0)
-		goto error;
-
-	/* (2c) Convert the message representative (m) to an encoded message
-	 *      (EM) of length k octets.
-	 *
-	 *      NOTE!  The leading zero byte is suppressed by MPI, so we pass a
-	 *      pointer to the _preceding_ byte to RSA_verify()!
+	/* Output from the operation is an encoded message (EM) of
+	 * length k octets.
 	 */
-	ret = RSA_I2OSP(m, k, &EM);
-	if (ret < 0)
-		goto error;
-
-	ret = RSA_verify(H, EM - 1, k, sig->digest_size,
+	outlen = req->dst_len;
+	ret = rsa_verify(sig->digest, outbuf, outlen, sig->digest_size,
 			 RSA_ASN1_templates[sig->pkey_hash_algo].data,
 			 RSA_ASN1_templates[sig->pkey_hash_algo].size);
-
-error:
-	kfree(EM);
-	mpi_free(m);
-	kleave(" = %d", ret);
+error_free_req:
+	akcipher_request_free(req);
+error_free_tfm:
+	crypto_free_akcipher(tfm);
+error_out:
+	kfree(outbuf);
 	return ret;
 }
-
-const struct public_key_algorithm RSA_public_key_algorithm = {
-	.name		= "RSA",
-	.n_pub_mpi	= 2,
-	.n_sec_mpi	= 3,
-	.n_sig_mpi	= 1,
-	.verify_signature = RSA_verify_signature,
-};
-EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);
+EXPORT_SYMBOL_GPL(rsa_verify_signature);
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 021d39c0ba75..7502029e3385 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -15,11 +15,10 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/oid_registry.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
 #include "x509_parser.h"
 #include "x509-asn1.h"
 #include "x509_akid-asn1.h"
-#include "x509_rsakey-asn1.h"
 
 struct x509_parse_context {
 	struct x509_certificate	*cert;		/* Certificate being constructed */
@@ -56,7 +55,7 @@ void x509_free_certificate(struct x509_certificate *cert)
 		kfree(cert->akid_id);
 		kfree(cert->akid_skid);
 		kfree(cert->sig.digest);
-		mpi_free(cert->sig.rsa.s);
+		kfree(cert->sig.s);
 		kfree(cert);
 	}
 }
@@ -103,12 +102,12 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
 		}
 	}
 
-	/* Decode the public key */
-	ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx,
-			       ctx->key, ctx->key_size);
-	if (ret < 0)
+	cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL);
+	if (!cert->pub->key)
 		goto error_decode;
 
+	cert->pub->keylen = ctx->key_size;
+
 	/* Generate cert issuer + serial number key ID */
 	kid = asymmetric_key_generate_id(cert->raw_serial,
 					 cert->raw_serial_size,
@@ -124,6 +123,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
 	return cert;
 
 error_decode:
+	kfree(cert->pub->key);
 	kfree(ctx);
 error_no_ctx:
 	x509_free_certificate(cert);
@@ -404,29 +404,6 @@ int x509_extract_key_data(void *context, size_t hdrlen,
 	return 0;
 }
 
-/*
- * Extract a RSA public key value
- */
-int rsa_extract_mpi(void *context, size_t hdrlen,
-		    unsigned char tag,
-		    const void *value, size_t vlen)
-{
-	struct x509_parse_context *ctx = context;
-	MPI mpi;
-
-	if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) {
-		pr_err("Too many public key MPIs in certificate\n");
-		return -EBADMSG;
-	}
-
-	mpi = mpi_read_raw_data(value, vlen);
-	if (!mpi)
-		return -ENOMEM;
-
-	ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi;
-	return 0;
-}
-
 /* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */
 #define SEQ_TAG_KEYID (ASN1_CONT << 6)
 
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 9e9e5a6a9ed6..7092d5cbb5d3 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -13,15 +13,11 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/mpi.h>
-#include <linux/asn1_decoder.h>
 #include <keys/asymmetric-subtype.h>
 #include <keys/asymmetric-parser.h>
 #include <keys/system_keyring.h>
 #include <crypto/hash.h>
 #include "asymmetric_keys.h"
-#include "public_key.h"
 #include "x509_parser.h"
 
 static bool use_builtin_keys;
@@ -167,13 +163,15 @@ int x509_get_sig_params(struct x509_certificate *cert)
 
 	if (cert->unsupported_crypto)
 		return -ENOPKG;
-	if (cert->sig.rsa.s)
+	if (cert->sig.s)
 		return 0;
 
-	cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size);
-	if (!cert->sig.rsa.s)
+	cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size,
+			      GFP_KERNEL);
+	if (!cert->sig.s)
 		return -ENOMEM;
-	cert->sig.nr_mpi = 1;
+
+	cert->sig.s_size = cert->raw_sig_size;
 
 	/* Allocate the hashing algorithm we're going to need and find out how
 	 * big the hash operational data will be.
@@ -296,8 +294,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
 	if (cert->pub->pkey_algo >= PKEY_ALGO__LAST ||
 	    cert->sig.pkey_algo >= PKEY_ALGO__LAST ||
 	    cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
-	    !pkey_algo[cert->pub->pkey_algo] ||
-	    !pkey_algo[cert->sig.pkey_algo] ||
 	    !hash_algo_name[cert->sig.pkey_hash_algo]) {
 		ret = -ENOPKG;
 		goto error_free_cert;
@@ -309,7 +305,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
 		 pkey_algo_name[cert->sig.pkey_algo],
 		 hash_algo_name[cert->sig.pkey_hash_algo]);
 
-	cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
 	cert->pub->id_type = PKEY_ID_X509;
 
 	/* Check the signature on the key if it appears to be self-signed */
diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1
deleted file mode 100644
index 4ec7cc6532c1..000000000000
--- a/crypto/asymmetric_keys/x509_rsakey.asn1
+++ /dev/null
@@ -1,4 +0,0 @@
-RSAPublicKey ::= SEQUENCE {
-	modulus			INTEGER ({ rsa_extract_mpi }),	-- n
-	publicExponent		INTEGER ({ rsa_extract_mpi })	-- e
-	}
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index cc2516df0efa..50ac8759d7ee 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -24,7 +24,6 @@ enum pkey_algo {
 };
 
 extern const char *const pkey_algo_name[PKEY_ALGO__LAST];
-extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST];
 
 /* asymmetric key implementation supports only up to SHA224 */
 #define PKEY_HASH__LAST		(HASH_ALGO_SHA224 + 1)
@@ -59,31 +58,10 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
  * part.
  */
 struct public_key {
-	const struct public_key_algorithm *algo;
-	u8	capabilities;
-#define PKEY_CAN_ENCRYPT	0x01
-#define PKEY_CAN_DECRYPT	0x02
-#define PKEY_CAN_SIGN		0x04
-#define PKEY_CAN_VERIFY		0x08
+	void *key;
+	u32 keylen;
 	enum pkey_algo pkey_algo : 8;
 	enum pkey_id_type id_type : 8;
-	union {
-		MPI	mpi[5];
-		struct {
-			MPI	p;	/* DSA prime */
-			MPI	q;	/* DSA group order */
-			MPI	g;	/* DSA group generator */
-			MPI	y;	/* DSA public-key value = g^x mod p */
-			MPI	x;	/* DSA secret exponent (if present) */
-		} dsa;
-		struct {
-			MPI	n;	/* RSA public modulus */
-			MPI	e;	/* RSA public encryption exponent */
-			MPI	d;	/* RSA secret encryption exponent (if present) */
-			MPI	p;	/* RSA secret prime (if present) */
-			MPI	q;	/* RSA secret prime (if present) */
-		} rsa;
-	};
 };
 
 extern void public_key_destroy(void *payload);
@@ -92,6 +70,8 @@ extern void public_key_destroy(void *payload);
  * Public key cryptography signature data
  */
 struct public_key_signature {
+	u8 *s;			/* Signature */
+	u32 s_size;		/* Number of bytes in signature */
 	u8 *digest;
 	u8 digest_size;			/* Number of bytes in digest */
 	u8 nr_mpi;			/* Occupancy of mpi[] */
@@ -109,6 +89,7 @@ struct public_key_signature {
 	};
 };
 
+extern struct asymmetric_key_subtype public_key_subtype;
 struct key;
 extern int verify_signature(const struct key *key,
 			    const struct public_key_signature *sig);
@@ -119,4 +100,9 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring,
 					       const struct asymmetric_key_id *skid,
 					       bool partial);
 
+int public_key_verify_signature(const struct public_key *pkey,
+				const struct public_key_signature *sig);
+
+int rsa_verify_signature(const struct public_key *pkey,
+			 const struct public_key_signature *sig);
 #endif /* _LINUX_PUBLIC_KEY_H */

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

* [PATCH 2/8] integrity: convert digsig to akcipher api
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
  2016-02-19 17:18 ` [PATCH 1/8] crypto: KEYS: convert public key and digsig asym to the akcipher api David Howells
@ 2016-02-19 17:18 ` David Howells
  2016-02-19 17:18 ` [PATCH 3/8] crypto: public_key: remove MPIs from public_key_signature struct David Howells
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:18 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk

From: Tadeusz Struk <tadeusz.struk@intel.com>

Convert asymmetric_verify to akcipher api.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 security/integrity/Kconfig             |    1 +
 security/integrity/digsig_asymmetric.c |   10 +++-------
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 21d756832b75..5533a011b58e 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -36,6 +36,7 @@ config INTEGRITY_ASYMMETRIC_KEYS
         select ASYMMETRIC_KEY_TYPE
         select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
         select PUBLIC_KEY_ALGO_RSA
+        select CRYPTO_RSA
         select X509_CERTIFICATE_PARSER
 	help
 	  This option enables digital signature verification using
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index 5ade2a7517a6..2fa3bc681a1b 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -106,13 +106,9 @@ int asymmetric_verify(struct key *keyring, const char *sig,
 	pks.pkey_hash_algo = hdr->hash_algo;
 	pks.digest = (u8 *)data;
 	pks.digest_size = datalen;
-	pks.nr_mpi = 1;
-	pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
-
-	if (pks.rsa.s)
-		ret = verify_signature(key, &pks);
-
-	mpi_free(pks.rsa.s);
+	pks.s = hdr->sig;
+	pks.s_size = siglen;
+	ret = verify_signature(key, &pks);
 	key_put(key);
 	pr_debug("%s() = %d\n", __func__, ret);
 	return ret;

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

* [PATCH 3/8] crypto: public_key: remove MPIs from public_key_signature struct
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
  2016-02-19 17:18 ` [PATCH 1/8] crypto: KEYS: convert public key and digsig asym to the akcipher api David Howells
  2016-02-19 17:18 ` [PATCH 2/8] integrity: convert digsig to " David Howells
@ 2016-02-19 17:18 ` David Howells
  2016-02-19 17:18 ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:18 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk

From: Tadeusz Struk <tadeusz.struk@intel.com>

After digsig_asymmetric.c is converted the MPIs can be now
safely removed from the public_key_signature structure.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 include/crypto/public_key.h |   14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 50ac8759d7ee..a1693ed77be6 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -14,7 +14,6 @@
 #ifndef _LINUX_PUBLIC_KEY_H
 #define _LINUX_PUBLIC_KEY_H
 
-#include <linux/mpi.h>
 #include <crypto/hash_info.h>
 
 enum pkey_algo {
@@ -73,20 +72,9 @@ struct public_key_signature {
 	u8 *s;			/* Signature */
 	u32 s_size;		/* Number of bytes in signature */
 	u8 *digest;
-	u8 digest_size;			/* Number of bytes in digest */
-	u8 nr_mpi;			/* Occupancy of mpi[] */
+	u8 digest_size;		/* Number of bytes in digest */
 	enum pkey_algo pkey_algo : 8;
 	enum hash_algo pkey_hash_algo : 8;
-	union {
-		MPI mpi[2];
-		struct {
-			MPI s;		/* m^d mod n */
-		} rsa;
-		struct {
-			MPI r;
-			MPI s;
-		} dsa;
-	};
 };
 
 extern struct asymmetric_key_subtype public_key_subtype;

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

* [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
                   ` (2 preceding siblings ...)
  2016-02-19 17:18 ` [PATCH 3/8] crypto: public_key: remove MPIs from public_key_signature struct David Howells
@ 2016-02-19 17:18 ` David Howells
  2016-02-22 19:59   ` Tadeusz Struk
                     ` (2 more replies)
  2016-02-19 17:18 ` [PATCH 5/8] X.509: Make algo identifiers text instead of enum David Howells
                   ` (6 subsequent siblings)
  10 siblings, 3 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:18 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk

Move the RSA EMSA-PKCS1-v1_5 encoding from the asymmetric-key public_key
subtype to the rsa crypto module.  This means that the public_key subtype
no longer has any dependencies on public key type.

To make this work, I've made the following changes:

 (1) An indicator as to the hash algorithm employed must be passed to the
     public key algorithm.  I have made this a string, equivalent to the
     name in the matching crypto module and placed it in akcipher_request.

 (2) The RSA module builds the EMSA-PKCS1-v1_5 encoded message (EM) and
     then compares that to the 'decrypted' signature.  This function can
     then be reused for signing.

 (3) The destination buffer in akcipher_request is now an input buffer
     holding the message digest (M) for the verify operation.  The output
     of the verify operation is purely the error code.

 (4) The crypto driver in crypto/asymmetric_keys/rsa.c is now reduced to
     something that doesn't care about what the encryption actually does
     and and has been merged into public_key.c.

 (5) The test drivers set a NULL hash algorithm as I'm not sure what they
     should be.

 (6) CONFIG_PUBLIC_KEY_ALGO_RSA is gone.  Module signing must set
     CONFIG_CRYPTO_RSA=y instead.

Thoughts:

 (*) Should the encoding style (eg. raw, EMSA-PKCS1-v1_5) also be passed to
     the public key algorithm?

Signed-off-by: David Howells <dhowells@redhat.com>
---

 crypto/asymmetric_keys/Kconfig      |    7 -
 crypto/asymmetric_keys/Makefile     |    1 
 crypto/asymmetric_keys/public_key.c |   69 +++++++++--
 crypto/asymmetric_keys/rsa.c        |  224 -----------------------------------
 crypto/rsa.c                        |  210 ++++++++++++++++++++++++++++-----
 crypto/testmgr.c                    |    5 -
 include/crypto/akcipher.h           |    7 +
 include/crypto/public_key.h         |    2 
 init/Kconfig                        |    2 
 9 files changed, 248 insertions(+), 279 deletions(-)
 delete mode 100644 crypto/asymmetric_keys/rsa.c

diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 905d745c2f85..91a7e047a765 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -12,7 +12,6 @@ if ASYMMETRIC_KEY_TYPE
 config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
 	tristate "Asymmetric public-key crypto algorithm subtype"
 	select MPILIB
-	select PUBLIC_KEY_ALGO_RSA
 	select CRYPTO_HASH_INFO
 	help
 	  This option provides support for asymmetric public key type handling.
@@ -20,12 +19,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
 	  appropriate hash algorithms (such as SHA-1) must be available.
 	  ENOPKG will be reported if the requisite algorithm is unavailable.
 
-config PUBLIC_KEY_ALGO_RSA
-	tristate "RSA public-key algorithm"
-	select CRYPTO_RSA
-	help
-	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
-
 config X509_CERTIFICATE_PARSER
 	tristate "X.509 certificate parser"
 	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index b78a194ea014..f90486256f01 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
 asymmetric_keys-y := asymmetric_type.o signature.o
 
 obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
-obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
 
 #
 # X.509 Certificate handling
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index b383629b9e62..66727a13d561 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -17,8 +17,10 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/scatterlist.h>
 #include <keys/asymmetric-subtype.h>
 #include <crypto/public_key.h>
+#include <crypto/akcipher.h>
 
 MODULE_LICENSE("GPL");
 
@@ -35,12 +37,6 @@ const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
 };
 EXPORT_SYMBOL_GPL(pkey_id_type_name);
 
-static int (*alg_verify[PKEY_ALGO__LAST])(const struct public_key *pkey,
-	const struct public_key_signature *sig) = {
-	NULL,
-	rsa_verify_signature
-};
-
 /*
  * Provide a part of a description of the key for /proc/keys.
  */
@@ -68,24 +64,75 @@ void public_key_destroy(void *payload)
 }
 EXPORT_SYMBOL_GPL(public_key_destroy);
 
+struct public_key_completion {
+	struct completion completion;
+	int err;
+};
+
+static void public_key_verify_done(struct crypto_async_request *req, int err)
+{
+	struct public_key_completion *compl = req->data;
+
+	if (err == -EINPROGRESS)
+		return;
+
+	compl->err = err;
+	complete(&compl->completion);
+}
+
 /*
  * Verify a signature using a public key.
  */
 int public_key_verify_signature(const struct public_key *pkey,
 				const struct public_key_signature *sig)
 {
+	struct public_key_completion compl;
+	struct crypto_akcipher *tfm;
+	struct akcipher_request *req;
+	struct scatterlist sig_sg, digest_sg;
+	int ret = -ENOMEM;
+
+	pr_devel("==>%s()\n", __func__);
+
 	BUG_ON(!pkey);
 	BUG_ON(!sig);
 	BUG_ON(!sig->digest);
 	BUG_ON(!sig->s);
 
-	if (pkey->pkey_algo >= PKEY_ALGO__LAST)
-		return -ENOPKG;
+	tfm = crypto_alloc_akcipher(pkey_algo_name[sig->pkey_algo], 0, 0);
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	req = akcipher_request_alloc(tfm, GFP_KERNEL);
+	if (!req)
+		goto error_free_tfm;
+
+	ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
+	if (ret)
+		goto error_free_req;
+
+	sg_init_one(&sig_sg, sig->s, sig->s_size);
+	sg_init_one(&digest_sg, sig->digest, sig->digest_size);
+	akcipher_request_set_crypt(req, &sig_sg, &digest_sg,
+				   sig->s_size, sig->digest_size,
+				   hash_algo_name[sig->pkey_hash_algo]);
+	init_completion(&compl.completion);
+	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+				      CRYPTO_TFM_REQ_MAY_SLEEP,
+				      public_key_verify_done, &compl);
 
-	if (!alg_verify[pkey->pkey_algo])
-		return -ENOPKG;
+	ret = crypto_akcipher_verify(req);
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&compl.completion);
+		ret = compl.err;
+	}
 
-	return alg_verify[pkey->pkey_algo](pkey, sig);
+error_free_req:
+	akcipher_request_free(req);
+error_free_tfm:
+	crypto_free_akcipher(tfm);
+	pr_devel("<==%s() = %d\n", __func__, ret);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(public_key_verify_signature);
 
diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
deleted file mode 100644
index 51502bca65e7..000000000000
--- a/crypto/asymmetric_keys/rsa.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/* RSA asymmetric public-key algorithm [RFC3447]
- *
- * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * 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) "RSA: "fmt
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <crypto/akcipher.h>
-#include <crypto/public_key.h>
-#include <crypto/algapi.h>
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("RSA Public Key Algorithm");
-
-#define kenter(FMT, ...) \
-	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
-#define kleave(FMT, ...) \
-	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
-
-/*
- * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
- */
-static const u8 RSA_digest_info_MD5[] = {
-	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
-	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
-	0x05, 0x00, 0x04, 0x10
-};
-
-static const u8 RSA_digest_info_SHA1[] = {
-	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
-	0x2B, 0x0E, 0x03, 0x02, 0x1A,
-	0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 RSA_digest_info_RIPE_MD_160[] = {
-	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
-	0x2B, 0x24, 0x03, 0x02, 0x01,
-	0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 RSA_digest_info_SHA224[] = {
-	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
-	0x05, 0x00, 0x04, 0x1C
-};
-
-static const u8 RSA_digest_info_SHA256[] = {
-	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
-	0x05, 0x00, 0x04, 0x20
-};
-
-static const u8 RSA_digest_info_SHA384[] = {
-	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
-	0x05, 0x00, 0x04, 0x30
-};
-
-static const u8 RSA_digest_info_SHA512[] = {
-	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
-	0x05, 0x00, 0x04, 0x40
-};
-
-static const struct {
-	const u8 *data;
-	size_t size;
-} RSA_ASN1_templates[PKEY_HASH__LAST] = {
-#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
-	[HASH_ALGO_MD5]		= _(MD5),
-	[HASH_ALGO_SHA1]	= _(SHA1),
-	[HASH_ALGO_RIPE_MD_160]	= _(RIPE_MD_160),
-	[HASH_ALGO_SHA256]	= _(SHA256),
-	[HASH_ALGO_SHA384]	= _(SHA384),
-	[HASH_ALGO_SHA512]	= _(SHA512),
-	[HASH_ALGO_SHA224]	= _(SHA224),
-#undef _
-};
-
-struct rsa_completion {
-	struct completion completion;
-	int err;
-};
-
-/*
- * Perform the RSA signature verification.
- * @H: Value of hash of data and metadata
- * @EM: The computed signature value
- * @k: The size of EM (EM[0] is an invalid location but should hold 0x00)
- * @hash_size: The size of H
- * @asn1_template: The DigestInfo ASN.1 template
- * @asn1_size: Size of asm1_template[]
- */
-static int rsa_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
-		      const u8 *asn1_template, size_t asn1_size)
-{
-	unsigned PS_end, T_offset, i;
-
-	kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size);
-
-	if (k < 2 + 1 + asn1_size + hash_size)
-		return -EBADMSG;
-
-	/* Decode the EMSA-PKCS1-v1_5
-	 * note: leading zeros are stripped by the RSA implementation
-	 */
-	if (EM[0] != 0x01) {
-		kleave(" = -EBADMSG [EM[0] == %02u]", EM[0]);
-		return -EBADMSG;
-	}
-
-	T_offset = k - (asn1_size + hash_size);
-	PS_end = T_offset - 1;
-	if (EM[PS_end] != 0x00) {
-		kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]);
-		return -EBADMSG;
-	}
-
-	for (i = 1; i < PS_end; i++) {
-		if (EM[i] != 0xff) {
-			kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]);
-			return -EBADMSG;
-		}
-	}
-
-	if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) {
-		kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
-		return -EBADMSG;
-	}
-
-	if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) {
-		kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
-		return -EKEYREJECTED;
-	}
-
-	kleave(" = 0");
-	return 0;
-}
-
-static void public_key_verify_done(struct crypto_async_request *req, int err)
-{
-	struct rsa_completion *compl = req->data;
-
-	if (err == -EINPROGRESS)
-		return;
-
-	compl->err = err;
-	complete(&compl->completion);
-}
-
-int rsa_verify_signature(const struct public_key *pkey,
-			 const struct public_key_signature *sig)
-{
-	struct crypto_akcipher *tfm;
-	struct akcipher_request *req;
-	struct rsa_completion compl;
-	struct scatterlist sig_sg, sg_out;
-	void *outbuf = NULL;
-	unsigned int outlen = 0;
-	int ret = -ENOMEM;
-
-	tfm = crypto_alloc_akcipher("rsa", 0, 0);
-	if (IS_ERR(tfm))
-		goto error_out;
-
-	req = akcipher_request_alloc(tfm, GFP_KERNEL);
-	if (!req)
-		goto error_free_tfm;
-
-	ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
-	if (ret)
-		goto error_free_req;
-
-	ret = -EINVAL;
-	outlen = crypto_akcipher_maxsize(tfm);
-	if (!outlen)
-		goto error_free_req;
-
-	/* Initialize the output buffer */
-	ret = -ENOMEM;
-	outbuf = kmalloc(outlen, GFP_KERNEL);
-	if (!outbuf)
-		goto error_free_req;
-
-	sg_init_one(&sig_sg, sig->s, sig->s_size);
-	sg_init_one(&sg_out, outbuf, outlen);
-	akcipher_request_set_crypt(req, &sig_sg, &sg_out, sig->s_size, outlen);
-	init_completion(&compl.completion);
-	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
-				      CRYPTO_TFM_REQ_MAY_SLEEP,
-				      public_key_verify_done, &compl);
-
-	ret = crypto_akcipher_verify(req);
-	if (ret == -EINPROGRESS) {
-		wait_for_completion(&compl.completion);
-		ret = compl.err;
-	}
-
-	if (ret)
-		goto error_free_req;
-
-	/* Output from the operation is an encoded message (EM) of
-	 * length k octets.
-	 */
-	outlen = req->dst_len;
-	ret = rsa_verify(sig->digest, outbuf, outlen, sig->digest_size,
-			 RSA_ASN1_templates[sig->pkey_hash_algo].data,
-			 RSA_ASN1_templates[sig->pkey_hash_algo].size);
-error_free_req:
-	akcipher_request_free(req);
-error_free_tfm:
-	crypto_free_akcipher(tfm);
-error_out:
-	kfree(outbuf);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(rsa_verify_signature);
diff --git a/crypto/rsa.c b/crypto/rsa.c
index 77d737f52147..9a7c9ca9eafc 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -16,6 +16,78 @@
 #include <crypto/algapi.h>
 
 /*
+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
+ */
+static const u8 rsa_digest_info_md5[] = {
+	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
+	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
+	0x05, 0x00, 0x04, 0x10
+};
+
+static const u8 rsa_digest_info_sha1[] = {
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+	0x2b, 0x0e, 0x03, 0x02, 0x1a,
+	0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 rsa_digest_info_rmd160[] = {
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+	0x2b, 0x24, 0x03, 0x02, 0x01,
+	0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 rsa_digest_info_sha224[] = {
+	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+	0x05, 0x00, 0x04, 0x1c
+};
+
+static const u8 rsa_digest_info_sha256[] = {
+	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+	0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 rsa_digest_info_sha384[] = {
+	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+	0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 rsa_digest_info_sha512[] = {
+	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+	0x05, 0x00, 0x04, 0x40
+};
+
+static const struct rsa_asn1_template {
+	const char	*name;
+	const u8	*data;
+	size_t		size;
+} rsa_asn1_templates[] = {
+#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
+	_(md5),
+	_(sha1),
+	_(rmd160),
+	_(sha256),
+	_(sha384),
+	_(sha512),
+	_(sha224),
+	{ NULL }
+#undef _
+};
+
+static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
+{
+	const struct rsa_asn1_template *p;
+
+	for (p = rsa_asn1_templates; p->name; p++)
+		if (strcmp(name, p->name) == 0)
+			return p;
+	return NULL;
+}
+
+/*
  * RSAEP function [RFC3447 sec 5.1.1]
  * c = m^e mod n;
  */
@@ -71,6 +143,13 @@ static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
 	return mpi_powm(m, s, key->e, key->n);
 }
 
+static int rsa_max_size(struct crypto_akcipher *tfm)
+{
+	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+
+	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
+}
+
 static inline struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm)
 {
 	return akcipher_tfm_ctx(tfm);
@@ -192,44 +271,122 @@ err_free_s:
 	return ret;
 }
 
-static int rsa_verify(struct akcipher_request *req)
+static int rsa_verify_raw(struct akcipher_request *req, MPI EM)
 {
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	const struct rsa_key *pkey = rsa_get_key(tfm);
-	MPI s, m = mpi_alloc(0);
-	int ret = 0;
-	int sign;
+	MPI s, m_calc;
+	int ret;
 
-	if (!m)
+	m_calc = mpi_alloc(0);
+	if (!m_calc)
 		return -ENOMEM;
 
-	if (unlikely(!pkey->n || !pkey->e)) {
-		ret = -EINVAL;
-		goto err_free_m;
-	}
-
 	ret = -ENOMEM;
 	s = mpi_read_raw_from_sgl(req->src, req->src_len);
-	if (!s) {
-		ret = -ENOMEM;
-		goto err_free_m;
-	}
+	if (!s)
+		goto err_free_m_calc;
 
-	ret = _rsa_verify(pkey, m, s);
+	ret = _rsa_verify(pkey, m_calc, s);
 	if (ret)
 		goto err_free_s;
 
-	ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
-	if (ret)
+	ret = -EKEYREJECTED;
+	if (mpi_cmp(m_calc, EM) != 0)
 		goto err_free_s;
 
-	if (sign < 0)
-		ret = -EBADMSG;
-
+	ret = 0;
 err_free_s:
 	mpi_free(s);
-err_free_m:
-	mpi_free(m);
+err_free_m_calc:
+	mpi_free(m_calc);
+	return ret;
+}
+
+/*
+ * Turn Hash(M) into EM for a key of size k and a specified hash algorithm as
+ * per EMSA-PKCS1-v1_5:
+ *
+ *	EM = 0x00 || 0x01 || PS || 0x00 || T
+ */
+static MPI rsa_emsa_pkcs1_v1_5(struct scatterlist *H, int H_size, int k,
+			       const char *hash_algo)
+{
+	const struct rsa_asn1_template *asn1;
+	MPI EM;
+	int PS_end, T_offset;
+	u8 *buf;
+
+	asn1 = rsa_lookup_asn1(hash_algo);
+	if (!asn1)
+		return ERR_PTR(-ENOPKG);
+
+	if (k < 2 + 1 + asn1->size + H_size)
+		return ERR_PTR(-EMSGSIZE);
+
+	T_offset = k - (asn1->size + H_size);
+	PS_end = T_offset - 1;
+	if (PS_end - 2 < 8)
+		return ERR_PTR(-EMSGSIZE);
+
+	buf = kmalloc(k, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	/* Set the initial zero and block type octets */
+	buf[0] = 0x00;
+	buf[1] = 0x01;
+
+	/* Set the padding string and the divider */
+	memset(buf + 2, 0xff, PS_end - 2);
+	buf[PS_end] = 0x00;
+
+	/* Set the DER-encoded DigestInfo */
+	memcpy(buf + T_offset, asn1->data, asn1->size);
+
+	/* Finally set the  */
+	if (sg_copy_to_buffer(H, sg_nents(H),
+			      buf + T_offset + asn1->size,
+			      H_size) != H_size) {
+		EM = ERR_PTR(-EMSGSIZE);
+		goto error_free_buf;
+	}
+
+	EM = mpi_read_raw_data(buf, k);
+	if (!EM)
+		EM = ERR_PTR(-ENOMEM);
+	
+error_free_buf:
+	kfree(buf);
+	return EM;
+}
+
+static int rsa_verify_encoded(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	const struct rsa_key *pkey = rsa_get_key(tfm);
+	MPI EM;
+	int ret, k;
+
+	pr_devel("==>%s(%u,%u,%s)\n",
+		 __func__, req->src_len, req->dst_len, req->hash_algo);
+
+	if (unlikely(!pkey->n || !pkey->e || !req->hash_algo))
+		return -EINVAL;
+
+	/* Find k - the size of E(M). */
+	k = rsa_max_size(tfm);
+	if (k < 0)
+		return k;
+
+	EM = rsa_emsa_pkcs1_v1_5(req->dst, req->dst_len, k, req->hash_algo);
+	if (IS_ERR(EM))
+		return PTR_ERR(EM);
+
+	ret = rsa_verify_raw(req, EM);
+
+	mpi_free(EM);
+	pr_devel("<==%s() = %d\n", __func__, ret);
 	return ret;
 }
 
@@ -282,13 +439,6 @@ static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
 	return ret;
 }
 
-static int rsa_max_size(struct crypto_akcipher *tfm)
-{
-	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
-
-	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
-}
-
 static void rsa_exit_tfm(struct crypto_akcipher *tfm)
 {
 	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
@@ -300,7 +450,7 @@ static struct akcipher_alg rsa = {
 	.encrypt = rsa_enc,
 	.decrypt = rsa_dec,
 	.sign = rsa_sign,
-	.verify = rsa_verify,
+	.verify = rsa_verify_encoded,
 	.set_priv_key = rsa_set_priv_key,
 	.set_pub_key = rsa_set_pub_key,
 	.max_size = rsa_max_size,
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ae8c57fd8bc7..94879a3d2ef7 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1882,7 +1882,7 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
 	sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8);
 	sg_init_one(&dst, outbuf_enc, out_len_max);
 	akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
-				   out_len_max);
+				   out_len_max, NULL);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				      tcrypt_complete, &result);
 
@@ -1916,7 +1916,8 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
 	sg_init_one(&src, vecs->c, vecs->c_size);
 	sg_init_one(&dst, outbuf_dec, out_len_max);
 	init_completion(&result.completion);
-	akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max);
+	akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max,
+				   NULL);
 
 	/* Run RSA decrypt - m = c^d mod n;*/
 	err = wait_async_op(&result, crypto_akcipher_decrypt(req));
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index 354de15cea6b..a59a6a0d6784 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -27,6 +27,7 @@
  *		result.
  *		In case of error where the dst sgl size was insufficient,
  *		it will be updated to the size required for the operation.
+ * @hash_algo:	The hash algorithm used for sign/verify operations.
  * @__ctx:	Start of private context data
  */
 struct akcipher_request {
@@ -35,6 +36,7 @@ struct akcipher_request {
 	struct scatterlist *dst;
 	unsigned int src_len;
 	unsigned int dst_len;
+	const char *hash_algo;
 	void *__ctx[] CRYPTO_MINALIGN_ATTR;
 };
 
@@ -241,17 +243,20 @@ static inline void akcipher_request_set_callback(struct akcipher_request *req,
  * @dst:	ptr to output scatter list
  * @src_len:	size of the src input scatter list to be processed
  * @dst_len:	size of the dst output scatter list
+ * @hash_algo:	The hash algorithm that was used for a signature (or NULL).
  */
 static inline void akcipher_request_set_crypt(struct akcipher_request *req,
 					      struct scatterlist *src,
 					      struct scatterlist *dst,
 					      unsigned int src_len,
-					      unsigned int dst_len)
+					      unsigned int dst_len,
+					      const char *hash_algo)
 {
 	req->src = src;
 	req->dst = dst;
 	req->src_len = src_len;
 	req->dst_len = dst_len;
+	req->hash_algo = hash_algo;
 }
 
 /**
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index a1693ed77be6..80ab099a3edf 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -91,6 +91,4 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring,
 int public_key_verify_signature(const struct public_key *pkey,
 				const struct public_key_signature *sig);
 
-int rsa_verify_signature(const struct public_key *pkey,
-			 const struct public_key_signature *sig);
 #endif /* _LINUX_PUBLIC_KEY_H */
diff --git a/init/Kconfig b/init/Kconfig
index 22320804fbaf..af4de4f1b02c 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1757,9 +1757,9 @@ config SYSTEM_DATA_VERIFICATION
 	select SYSTEM_TRUSTED_KEYRING
 	select KEYS
 	select CRYPTO
+	select CRYPTO_RSA
 	select ASYMMETRIC_KEY_TYPE
 	select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
-	select PUBLIC_KEY_ALGO_RSA
 	select ASN1
 	select OID_REGISTRY
 	select X509_CERTIFICATE_PARSER

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

* [PATCH 5/8] X.509: Make algo identifiers text instead of enum
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
                   ` (3 preceding siblings ...)
  2016-02-19 17:18 ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
@ 2016-02-19 17:18 ` David Howells
  2016-02-19 17:18 ` [PATCH 6/8] X.509: Make the public_key asymmetric key type internal data private David Howells
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:18 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk

Make the identifier public key and digest algorithm fields text instead of
enum.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 crypto/asymmetric_keys/mscode_parser.c    |   14 +++++++-------
 crypto/asymmetric_keys/pkcs7_parser.c     |   18 ++++++++---------
 crypto/asymmetric_keys/pkcs7_verify.c     |    8 +++-----
 crypto/asymmetric_keys/public_key.c       |   21 +++-----------------
 crypto/asymmetric_keys/verify_pefile.c    |    4 ++--
 crypto/asymmetric_keys/verify_pefile.h    |    2 +-
 crypto/asymmetric_keys/x509_cert_parser.c |   26 +++++++++++++------------
 crypto/asymmetric_keys/x509_public_key.c  |   17 ++++++++--------
 include/crypto/public_key.h               |   30 ++++-------------------------
 kernel/module_signing.c                   |    6 ++++++
 security/integrity/digsig_asymmetric.c    |    6 ++----
 11 files changed, 57 insertions(+), 95 deletions(-)

diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c
index adcef59eec0b..3242cbfaeaa2 100644
--- a/crypto/asymmetric_keys/mscode_parser.c
+++ b/crypto/asymmetric_keys/mscode_parser.c
@@ -86,25 +86,25 @@ int mscode_note_digest_algo(void *context, size_t hdrlen,
 	oid = look_up_OID(value, vlen);
 	switch (oid) {
 	case OID_md4:
-		ctx->digest_algo = HASH_ALGO_MD4;
+		ctx->digest_algo = "md4";
 		break;
 	case OID_md5:
-		ctx->digest_algo = HASH_ALGO_MD5;
+		ctx->digest_algo = "md5";
 		break;
 	case OID_sha1:
-		ctx->digest_algo = HASH_ALGO_SHA1;
+		ctx->digest_algo = "sha1";
 		break;
 	case OID_sha256:
-		ctx->digest_algo = HASH_ALGO_SHA256;
+		ctx->digest_algo = "sha256";
 		break;
 	case OID_sha384:
-		ctx->digest_algo = HASH_ALGO_SHA384;
+		ctx->digest_algo = "sha384";
 		break;
 	case OID_sha512:
-		ctx->digest_algo = HASH_ALGO_SHA512;
+		ctx->digest_algo = "sha512";
 		break;
 	case OID_sha224:
-		ctx->digest_algo = HASH_ALGO_SHA224;
+		ctx->digest_algo = "sha224";
 		break;
 
 	case OID__NR:
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 3ef62dac9771..1c4f715efdde 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -218,25 +218,25 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
 
 	switch (ctx->last_oid) {
 	case OID_md4:
-		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4;
+		ctx->sinfo->sig.hash_algo = "md4";
 		break;
 	case OID_md5:
-		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5;
+		ctx->sinfo->sig.hash_algo = "md5";
 		break;
 	case OID_sha1:
-		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1;
+		ctx->sinfo->sig.hash_algo = "sha1";
 		break;
 	case OID_sha256:
-		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256;
+		ctx->sinfo->sig.hash_algo = "sha256";
 		break;
 	case OID_sha384:
-		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA384;
+		ctx->sinfo->sig.hash_algo = "sha384";
 		break;
 	case OID_sha512:
-		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA512;
+		ctx->sinfo->sig.hash_algo = "sha512";
 		break;
 	case OID_sha224:
-		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA224;
+		ctx->sinfo->sig.hash_algo = "sha224";
 	default:
 		printk("Unsupported digest algo: %u\n", ctx->last_oid);
 		return -ENOPKG;
@@ -255,7 +255,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
 
 	switch (ctx->last_oid) {
 	case OID_rsaEncryption:
-		ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA;
+		ctx->sinfo->sig.pkey_algo = "rsa";
 		break;
 	default:
 		printk("Unsupported pkey algo: %u\n", ctx->last_oid);
@@ -615,8 +615,6 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen,
 {
 	struct pkcs7_parse_context *ctx = context;
 
-	BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
-
 	ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL);
 	if (!ctx->sinfo->sig.s)
 		return -ENOMEM;
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index f5db1378c096..50be2a15e531 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -31,17 +31,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
 	void *digest;
 	int ret;
 
-	kenter(",%u,%u", sinfo->index, sinfo->sig.pkey_hash_algo);
+	kenter(",%u,%s", sinfo->index, sinfo->sig.hash_algo);
 
-	if (sinfo->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
-	    !hash_algo_name[sinfo->sig.pkey_hash_algo])
+	if (!sinfo->sig.hash_algo)
 		return -ENOPKG;
 
 	/* Allocate the hashing algorithm we're going to need and find out how
 	 * big the hash operational data will be.
 	 */
-	tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo],
-				 0, 0);
+	tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0);
 	if (IS_ERR(tfm))
 		return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
 
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 66727a13d561..16895996c2e2 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -24,19 +24,6 @@
 
 MODULE_LICENSE("GPL");
 
-const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
-	[PKEY_ALGO_DSA]		= "dsa",
-	[PKEY_ALGO_RSA]		= "rsa",
-};
-EXPORT_SYMBOL_GPL(pkey_algo_name);
-
-const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
-	[PKEY_ID_PGP]		= "PGP",
-	[PKEY_ID_X509]		= "X509",
-	[PKEY_ID_PKCS7]		= "PKCS#7",
-};
-EXPORT_SYMBOL_GPL(pkey_id_type_name);
-
 /*
  * Provide a part of a description of the key for /proc/keys.
  */
@@ -46,9 +33,7 @@ static void public_key_describe(const struct key *asymmetric_key,
 	struct public_key *key = asymmetric_key->payload.data[asym_crypto];
 
 	if (key)
-		seq_printf(m, "%s.%s",
-			   pkey_id_type_name[key->id_type],
-			   pkey_algo_name[key->pkey_algo]);
+		seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
 }
 
 /*
@@ -99,7 +84,7 @@ int public_key_verify_signature(const struct public_key *pkey,
 	BUG_ON(!sig->digest);
 	BUG_ON(!sig->s);
 
-	tfm = crypto_alloc_akcipher(pkey_algo_name[sig->pkey_algo], 0, 0);
+	tfm = crypto_alloc_akcipher(sig->pkey_algo, 0, 0);
 	if (IS_ERR(tfm))
 		return PTR_ERR(tfm);
 
@@ -115,7 +100,7 @@ int public_key_verify_signature(const struct public_key *pkey,
 	sg_init_one(&digest_sg, sig->digest, sig->digest_size);
 	akcipher_request_set_crypt(req, &sig_sg, &digest_sg,
 				   sig->s_size, sig->digest_size,
-				   hash_algo_name[sig->pkey_hash_algo]);
+				   sig->hash_algo);
 	init_completion(&compl.completion);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
 				      CRYPTO_TFM_REQ_MAY_SLEEP,
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c
index 897b734dabf9..7e8c2338ae25 100644
--- a/crypto/asymmetric_keys/verify_pefile.c
+++ b/crypto/asymmetric_keys/verify_pefile.c
@@ -328,12 +328,12 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
 	void *digest;
 	int ret;
 
-	kenter(",%u", ctx->digest_algo);
+	kenter(",%s", ctx->digest_algo);
 
 	/* Allocate the hashing algorithm we're going to need and find out how
 	 * big the hash operational data will be.
 	 */
-	tfm = crypto_alloc_shash(hash_algo_name[ctx->digest_algo], 0, 0);
+	tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0);
 	if (IS_ERR(tfm))
 		return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
 
diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h
index 55d5f7ebc45a..a133eb81a492 100644
--- a/crypto/asymmetric_keys/verify_pefile.h
+++ b/crypto/asymmetric_keys/verify_pefile.h
@@ -28,7 +28,7 @@ struct pefile_context {
 	/* PKCS#7 MS Individual Code Signing content */
 	const void	*digest;		/* Digest */
 	unsigned	digest_len;		/* Digest length */
-	enum hash_algo	digest_algo;		/* Digest algorithm */
+	const char	*digest_algo;		/* Digest algorithm */
 };
 
 #define kenter(FMT, ...)					\
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 7502029e3385..dffd30f107cd 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
 		return -ENOPKG; /* Unsupported combination */
 
 	case OID_md4WithRSAEncryption:
-		ctx->cert->sig.pkey_hash_algo = HASH_ALGO_MD5;
-		ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+		ctx->cert->sig.hash_algo = "md4";
+		ctx->cert->sig.pkey_algo = "rsa";
 		break;
 
 	case OID_sha1WithRSAEncryption:
-		ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA1;
-		ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+		ctx->cert->sig.hash_algo = "sha1";
+		ctx->cert->sig.pkey_algo = "rsa";
 		break;
 
 	case OID_sha256WithRSAEncryption:
-		ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA256;
-		ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+		ctx->cert->sig.hash_algo = "sha256";
+		ctx->cert->sig.pkey_algo = "rsa";
 		break;
 
 	case OID_sha384WithRSAEncryption:
-		ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA384;
-		ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+		ctx->cert->sig.hash_algo = "sha384";
+		ctx->cert->sig.pkey_algo = "rsa";
 		break;
 
 	case OID_sha512WithRSAEncryption:
-		ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA512;
-		ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+		ctx->cert->sig.hash_algo = "sha512";
+		ctx->cert->sig.pkey_algo = "rsa";
 		break;
 
 	case OID_sha224WithRSAEncryption:
-		ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA224;
-		ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+		ctx->cert->sig.hash_algo = "sha224";
+		ctx->cert->sig.pkey_algo = "rsa";
 		break;
 	}
 
@@ -396,7 +396,7 @@ int x509_extract_key_data(void *context, size_t hdrlen,
 	if (ctx->last_oid != OID_rsaEncryption)
 		return -ENOPKG;
 
-	ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA;
+	ctx->cert->pub->pkey_algo = "rsa";
 
 	/* Discard the BIT STRING metadata */
 	ctx->key = value + 1;
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 7092d5cbb5d3..733c046aacc6 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -176,7 +176,7 @@ int x509_get_sig_params(struct x509_certificate *cert)
 	/* Allocate the hashing algorithm we're going to need and find out how
 	 * big the hash operational data will be.
 	 */
-	tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
+	tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0);
 	if (IS_ERR(tfm)) {
 		if (PTR_ERR(tfm) == -ENOENT) {
 			cert->unsupported_crypto = true;
@@ -291,21 +291,20 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
 	pr_devel("Cert Issuer: %s\n", cert->issuer);
 	pr_devel("Cert Subject: %s\n", cert->subject);
 
-	if (cert->pub->pkey_algo >= PKEY_ALGO__LAST ||
-	    cert->sig.pkey_algo >= PKEY_ALGO__LAST ||
-	    cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
-	    !hash_algo_name[cert->sig.pkey_hash_algo]) {
+	if (!cert->pub->pkey_algo ||
+	    !cert->sig.pkey_algo ||
+	    !cert->sig.hash_algo) {
 		ret = -ENOPKG;
 		goto error_free_cert;
 	}
 
-	pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]);
+	pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
 	pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
 	pr_devel("Cert Signature: %s + %s\n",
-		 pkey_algo_name[cert->sig.pkey_algo],
-		 hash_algo_name[cert->sig.pkey_hash_algo]);
+		 cert->sig.pkey_algo,
+		 cert->sig.hash_algo);
 
-	cert->pub->id_type = PKEY_ID_X509;
+	cert->pub->id_type = "X509";
 
 	/* Check the signature on the key if it appears to be self-signed */
 	if ((!cert->akid_skid && !cert->akid_id) ||
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 80ab099a3edf..aa730ea7faf8 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -14,28 +14,6 @@
 #ifndef _LINUX_PUBLIC_KEY_H
 #define _LINUX_PUBLIC_KEY_H
 
-#include <crypto/hash_info.h>
-
-enum pkey_algo {
-	PKEY_ALGO_DSA,
-	PKEY_ALGO_RSA,
-	PKEY_ALGO__LAST
-};
-
-extern const char *const pkey_algo_name[PKEY_ALGO__LAST];
-
-/* asymmetric key implementation supports only up to SHA224 */
-#define PKEY_HASH__LAST		(HASH_ALGO_SHA224 + 1)
-
-enum pkey_id_type {
-	PKEY_ID_PGP,		/* OpenPGP generated key ID */
-	PKEY_ID_X509,		/* X.509 arbitrary subjectKeyIdentifier */
-	PKEY_ID_PKCS7,		/* Signature in PKCS#7 message */
-	PKEY_ID_TYPE__LAST
-};
-
-extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST];
-
 /*
  * The use to which an asymmetric key is being put.
  */
@@ -59,8 +37,8 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
 struct public_key {
 	void *key;
 	u32 keylen;
-	enum pkey_algo pkey_algo : 8;
-	enum pkey_id_type id_type : 8;
+	const char *id_type;
+	const char *pkey_algo;
 };
 
 extern void public_key_destroy(void *payload);
@@ -73,8 +51,8 @@ struct public_key_signature {
 	u32 s_size;		/* Number of bytes in signature */
 	u8 *digest;
 	u8 digest_size;		/* Number of bytes in digest */
-	enum pkey_algo pkey_algo : 8;
-	enum hash_algo pkey_hash_algo : 8;
+	const char *pkey_algo;
+	const char *hash_algo;
 };
 
 extern struct asymmetric_key_subtype public_key_subtype;
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index 6528a79d998d..518efd683b4f 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -15,6 +15,12 @@
 #include <crypto/public_key.h>
 #include "module-internal.h"
 
+enum pkey_id_type {
+	PKEY_ID_PGP,		/* OpenPGP generated key ID */
+	PKEY_ID_X509,		/* X.509 arbitrary subjectKeyIdentifier */
+	PKEY_ID_PKCS7,		/* Signature in PKCS#7 message */
+};
+
 /*
  * Module signature information block.
  *
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index 2fa3bc681a1b..f44610189bf2 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -16,6 +16,7 @@
 #include <linux/ratelimit.h>
 #include <linux/key-type.h>
 #include <crypto/public_key.h>
+#include <crypto/hash_info.h>
 #include <keys/asymmetric-type.h>
 #include <keys/system_keyring.h>
 
@@ -94,16 +95,13 @@ int asymmetric_verify(struct key *keyring, const char *sig,
 	if (siglen != __be16_to_cpu(hdr->sig_size))
 		return -EBADMSG;
 
-	if (hdr->hash_algo >= PKEY_HASH__LAST)
-		return -ENOPKG;
-
 	key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
 	if (IS_ERR(key))
 		return PTR_ERR(key);
 
 	memset(&pks, 0, sizeof(pks));
 
-	pks.pkey_hash_algo = hdr->hash_algo;
+	pks.hash_algo = hash_algo_name[hdr->hash_algo];
 	pks.digest = (u8 *)data;
 	pks.digest_size = datalen;
 	pks.s = hdr->sig;

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

* [PATCH 6/8] X.509: Make the public_key asymmetric key type internal data private
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
                   ` (4 preceding siblings ...)
  2016-02-19 17:18 ` [PATCH 5/8] X.509: Make algo identifiers text instead of enum David Howells
@ 2016-02-19 17:18 ` David Howells
  2016-02-19 17:18 ` [PATCH 7/8] X.509: Rename public_key.c to software_pkey.c David Howells
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:18 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk

Make the public_key asymmetric key type internal data (struct public_key)
private by moving it to the asymmetric keys directory.

Whilst struct public_key_signature needs to be available, since that's part
of the asymmetric key API to verify a signature, anyone using asymmetric
keys should not be poking around inside the subtype internals, but should
rather use API functions, such as verify_signature(), in case the internals
turn out not to be of the subtype expected.

An exception is made for the X.509 and PKCS#7 parsers as they don't create
keys but rather use the public key routines directly.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 crypto/asymmetric_keys/pkcs7_verify.c     |    2 +-
 crypto/asymmetric_keys/public_key.c       |    2 +-
 crypto/asymmetric_keys/software_pkey.h    |   33 +++++++++++++++++++++++++++++
 crypto/asymmetric_keys/x509_cert_parser.c |    2 +-
 crypto/asymmetric_keys/x509_public_key.c  |    1 +
 include/crypto/public_key.h               |   19 -----------------
 6 files changed, 37 insertions(+), 22 deletions(-)
 create mode 100644 crypto/asymmetric_keys/software_pkey.h

diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 50be2a15e531..6aad267f19bb 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -16,7 +16,7 @@
 #include <linux/err.h>
 #include <linux/asn1.h>
 #include <crypto/hash.h>
-#include <crypto/public_key.h>
+#include "software_pkey.h"
 #include "pkcs7_parser.h"
 
 /*
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 16895996c2e2..3024081026c1 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -19,7 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/scatterlist.h>
 #include <keys/asymmetric-subtype.h>
-#include <crypto/public_key.h>
+#include "software_pkey.h"
 #include <crypto/akcipher.h>
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/asymmetric_keys/software_pkey.h b/crypto/asymmetric_keys/software_pkey.h
new file mode 100644
index 000000000000..06d6500e5825
--- /dev/null
+++ b/crypto/asymmetric_keys/software_pkey.h
@@ -0,0 +1,33 @@
+/* Internal definitions for the software public key subtype
+ *
+ * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#include <crypto/public_key.h>
+
+extern struct asymmetric_key_subtype public_key_subtype;
+
+/*
+ * Cryptographic data for the software public-key subtype of the asymmetric key
+ * type.
+ *
+ * Note that this may include private part of the key as well as the public
+ * part.
+ */
+struct public_key {
+	void *key;
+	u32 keylen;
+	const char *id_type;
+	const char *pkey_algo;
+};
+
+extern void public_key_destroy(void *payload);
+
+extern int public_key_verify_signature(const struct public_key *pkey,
+				       const struct public_key_signature *sig);
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index dffd30f107cd..a008a945aa82 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -15,7 +15,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/oid_registry.h>
-#include <crypto/public_key.h>
+#include "software_pkey.h"
 #include "x509_parser.h"
 #include "x509-asn1.h"
 #include "x509_akid-asn1.h"
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 733c046aacc6..0896f784cfda 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -18,6 +18,7 @@
 #include <keys/system_keyring.h>
 #include <crypto/hash.h>
 #include "asymmetric_keys.h"
+#include "software_pkey.h"
 #include "x509_parser.h"
 
 static bool use_builtin_keys;
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index aa730ea7faf8..d55f9f9bfd65 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -29,21 +29,6 @@ enum key_being_used_for {
 extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
 
 /*
- * Cryptographic data for the public-key subtype of the asymmetric key type.
- *
- * Note that this may include private part of the key as well as the public
- * part.
- */
-struct public_key {
-	void *key;
-	u32 keylen;
-	const char *id_type;
-	const char *pkey_algo;
-};
-
-extern void public_key_destroy(void *payload);
-
-/*
  * Public key cryptography signature data
  */
 struct public_key_signature {
@@ -55,7 +40,6 @@ struct public_key_signature {
 	const char *hash_algo;
 };
 
-extern struct asymmetric_key_subtype public_key_subtype;
 struct key;
 extern int verify_signature(const struct key *key,
 			    const struct public_key_signature *sig);
@@ -66,7 +50,4 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring,
 					       const struct asymmetric_key_id *skid,
 					       bool partial);
 
-int public_key_verify_signature(const struct public_key *pkey,
-				const struct public_key_signature *sig);
-
 #endif /* _LINUX_PUBLIC_KEY_H */

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

* [PATCH 7/8] X.509: Rename public_key.c to software_pkey.c
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
                   ` (5 preceding siblings ...)
  2016-02-19 17:18 ` [PATCH 6/8] X.509: Make the public_key asymmetric key type internal data private David Howells
@ 2016-02-19 17:18 ` David Howells
  2016-02-19 17:19 ` [PATCH 8/8] X.509: Rename public_key* to software_pkey* David Howells
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:18 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk

Rename public_key.c to software_pkey.c as it's not the only possible
subtype for doing public_key operations - there can conceivably be
hardware-offload subtypes that do public key operations (such as in the
TPM) too.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 arch/s390/configs/default_defconfig     |    2 
 arch/s390/configs/gcov_defconfig        |    2 
 arch/s390/configs/performance_defconfig |    2 
 crypto/asymmetric_keys/Kconfig          |   10 +-
 crypto/asymmetric_keys/Makefile         |    2 
 crypto/asymmetric_keys/public_key.c     |  142 -------------------------------
 crypto/asymmetric_keys/software_pkey.c  |  142 +++++++++++++++++++++++++++++++
 init/Kconfig                            |    2 
 security/integrity/Kconfig              |    2 
 9 files changed, 153 insertions(+), 153 deletions(-)
 delete mode 100644 crypto/asymmetric_keys/public_key.c
 create mode 100644 crypto/asymmetric_keys/software_pkey.c

diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig
index 0ac42cc4f880..b1b7b22688d5 100644
--- a/arch/s390/configs/default_defconfig
+++ b/arch/s390/configs/default_defconfig
@@ -665,7 +665,7 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_ASYMMETRIC_KEY_TYPE=m
-CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_SOFTWARE_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig
index a31dcd56f7c0..ce8e7e492af5 100644
--- a/arch/s390/configs/gcov_defconfig
+++ b/arch/s390/configs/gcov_defconfig
@@ -611,7 +611,7 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_ASYMMETRIC_KEY_TYPE=m
-CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_SOFTWARE_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig
index 7b73bf353345..a176e84e6c61 100644
--- a/arch/s390/configs/performance_defconfig
+++ b/arch/s390/configs/performance_defconfig
@@ -608,7 +608,7 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_ASYMMETRIC_KEY_TYPE=m
-CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_SOFTWARE_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 91a7e047a765..e42c42b10d7a 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -9,19 +9,19 @@ menuconfig ASYMMETRIC_KEY_TYPE
 
 if ASYMMETRIC_KEY_TYPE
 
-config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+config SOFTWARE_PUBLIC_KEY_SUBTYPE
 	tristate "Asymmetric public-key crypto algorithm subtype"
 	select MPILIB
 	select CRYPTO_HASH_INFO
 	help
-	  This option provides support for asymmetric public key type handling.
-	  If signature generation and/or verification are to be used,
-	  appropriate hash algorithms (such as SHA-1) must be available.
+	  This option provides support for software-based asymmetric public key
+	  type handling.  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 X509_CERTIFICATE_PARSER
 	tristate "X.509 certificate parser"
-	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+	depends on SOFTWARE_PUBLIC_KEY_SUBTYPE
 	select ASN1
 	select OID_REGISTRY
 	help
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index f90486256f01..bb86e5d157b2 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
 
 asymmetric_keys-y := asymmetric_type.o signature.o
 
-obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
+obj-$(CONFIG_SOFTWARE_PUBLIC_KEY_SUBTYPE) += software_pkey.o
 
 #
 # X.509 Certificate handling
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
deleted file mode 100644
index 3024081026c1..000000000000
--- a/crypto/asymmetric_keys/public_key.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* In-software asymmetric public-key crypto subtype
- *
- * See Documentation/crypto/asymmetric-keys.txt
- *
- * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * 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) "PKEY: "fmt
-#include <linux/module.h>
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
-#include <linux/scatterlist.h>
-#include <keys/asymmetric-subtype.h>
-#include "software_pkey.h"
-#include <crypto/akcipher.h>
-
-MODULE_LICENSE("GPL");
-
-/*
- * Provide a part of a description of the key for /proc/keys.
- */
-static void public_key_describe(const struct key *asymmetric_key,
-				struct seq_file *m)
-{
-	struct public_key *key = asymmetric_key->payload.data[asym_crypto];
-
-	if (key)
-		seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
-}
-
-/*
- * Destroy a public key algorithm key.
- */
-void public_key_destroy(void *payload)
-{
-	struct public_key *key = payload;
-
-	if (key)
-		kfree(key->key);
-	kfree(key);
-}
-EXPORT_SYMBOL_GPL(public_key_destroy);
-
-struct public_key_completion {
-	struct completion completion;
-	int err;
-};
-
-static void public_key_verify_done(struct crypto_async_request *req, int err)
-{
-	struct public_key_completion *compl = req->data;
-
-	if (err == -EINPROGRESS)
-		return;
-
-	compl->err = err;
-	complete(&compl->completion);
-}
-
-/*
- * Verify a signature using a public key.
- */
-int public_key_verify_signature(const struct public_key *pkey,
-				const struct public_key_signature *sig)
-{
-	struct public_key_completion compl;
-	struct crypto_akcipher *tfm;
-	struct akcipher_request *req;
-	struct scatterlist sig_sg, digest_sg;
-	int ret = -ENOMEM;
-
-	pr_devel("==>%s()\n", __func__);
-
-	BUG_ON(!pkey);
-	BUG_ON(!sig);
-	BUG_ON(!sig->digest);
-	BUG_ON(!sig->s);
-
-	tfm = crypto_alloc_akcipher(sig->pkey_algo, 0, 0);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
-
-	req = akcipher_request_alloc(tfm, GFP_KERNEL);
-	if (!req)
-		goto error_free_tfm;
-
-	ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
-	if (ret)
-		goto error_free_req;
-
-	sg_init_one(&sig_sg, sig->s, sig->s_size);
-	sg_init_one(&digest_sg, sig->digest, sig->digest_size);
-	akcipher_request_set_crypt(req, &sig_sg, &digest_sg,
-				   sig->s_size, sig->digest_size,
-				   sig->hash_algo);
-	init_completion(&compl.completion);
-	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
-				      CRYPTO_TFM_REQ_MAY_SLEEP,
-				      public_key_verify_done, &compl);
-
-	ret = crypto_akcipher_verify(req);
-	if (ret == -EINPROGRESS) {
-		wait_for_completion(&compl.completion);
-		ret = compl.err;
-	}
-
-error_free_req:
-	akcipher_request_free(req);
-error_free_tfm:
-	crypto_free_akcipher(tfm);
-	pr_devel("<==%s() = %d\n", __func__, ret);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(public_key_verify_signature);
-
-static int public_key_verify_signature_2(const struct key *key,
-					 const struct public_key_signature *sig)
-{
-	const struct public_key *pk = key->payload.data[asym_crypto];
-	return public_key_verify_signature(pk, sig);
-}
-
-/*
- * Public key algorithm asymmetric key subtype
- */
-struct asymmetric_key_subtype public_key_subtype = {
-	.owner			= THIS_MODULE,
-	.name			= "public_key",
-	.name_len		= sizeof("public_key") - 1,
-	.describe		= public_key_describe,
-	.destroy		= public_key_destroy,
-	.verify_signature	= public_key_verify_signature_2,
-};
-EXPORT_SYMBOL_GPL(public_key_subtype);
diff --git a/crypto/asymmetric_keys/software_pkey.c b/crypto/asymmetric_keys/software_pkey.c
new file mode 100644
index 000000000000..3024081026c1
--- /dev/null
+++ b/crypto/asymmetric_keys/software_pkey.c
@@ -0,0 +1,142 @@
+/* In-software asymmetric public-key crypto subtype
+ *
+ * See Documentation/crypto/asymmetric-keys.txt
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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) "PKEY: "fmt
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/scatterlist.h>
+#include <keys/asymmetric-subtype.h>
+#include "software_pkey.h"
+#include <crypto/akcipher.h>
+
+MODULE_LICENSE("GPL");
+
+/*
+ * Provide a part of a description of the key for /proc/keys.
+ */
+static void public_key_describe(const struct key *asymmetric_key,
+				struct seq_file *m)
+{
+	struct public_key *key = asymmetric_key->payload.data[asym_crypto];
+
+	if (key)
+		seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
+}
+
+/*
+ * Destroy a public key algorithm key.
+ */
+void public_key_destroy(void *payload)
+{
+	struct public_key *key = payload;
+
+	if (key)
+		kfree(key->key);
+	kfree(key);
+}
+EXPORT_SYMBOL_GPL(public_key_destroy);
+
+struct public_key_completion {
+	struct completion completion;
+	int err;
+};
+
+static void public_key_verify_done(struct crypto_async_request *req, int err)
+{
+	struct public_key_completion *compl = req->data;
+
+	if (err == -EINPROGRESS)
+		return;
+
+	compl->err = err;
+	complete(&compl->completion);
+}
+
+/*
+ * Verify a signature using a public key.
+ */
+int public_key_verify_signature(const struct public_key *pkey,
+				const struct public_key_signature *sig)
+{
+	struct public_key_completion compl;
+	struct crypto_akcipher *tfm;
+	struct akcipher_request *req;
+	struct scatterlist sig_sg, digest_sg;
+	int ret = -ENOMEM;
+
+	pr_devel("==>%s()\n", __func__);
+
+	BUG_ON(!pkey);
+	BUG_ON(!sig);
+	BUG_ON(!sig->digest);
+	BUG_ON(!sig->s);
+
+	tfm = crypto_alloc_akcipher(sig->pkey_algo, 0, 0);
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	req = akcipher_request_alloc(tfm, GFP_KERNEL);
+	if (!req)
+		goto error_free_tfm;
+
+	ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
+	if (ret)
+		goto error_free_req;
+
+	sg_init_one(&sig_sg, sig->s, sig->s_size);
+	sg_init_one(&digest_sg, sig->digest, sig->digest_size);
+	akcipher_request_set_crypt(req, &sig_sg, &digest_sg,
+				   sig->s_size, sig->digest_size,
+				   sig->hash_algo);
+	init_completion(&compl.completion);
+	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+				      CRYPTO_TFM_REQ_MAY_SLEEP,
+				      public_key_verify_done, &compl);
+
+	ret = crypto_akcipher_verify(req);
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&compl.completion);
+		ret = compl.err;
+	}
+
+error_free_req:
+	akcipher_request_free(req);
+error_free_tfm:
+	crypto_free_akcipher(tfm);
+	pr_devel("<==%s() = %d\n", __func__, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(public_key_verify_signature);
+
+static int public_key_verify_signature_2(const struct key *key,
+					 const struct public_key_signature *sig)
+{
+	const struct public_key *pk = key->payload.data[asym_crypto];
+	return public_key_verify_signature(pk, sig);
+}
+
+/*
+ * Public key algorithm asymmetric key subtype
+ */
+struct asymmetric_key_subtype public_key_subtype = {
+	.owner			= THIS_MODULE,
+	.name			= "public_key",
+	.name_len		= sizeof("public_key") - 1,
+	.describe		= public_key_describe,
+	.destroy		= public_key_destroy,
+	.verify_signature	= public_key_verify_signature_2,
+};
+EXPORT_SYMBOL_GPL(public_key_subtype);
diff --git a/init/Kconfig b/init/Kconfig
index af4de4f1b02c..58194e40ff3c 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1759,7 +1759,7 @@ config SYSTEM_DATA_VERIFICATION
 	select CRYPTO
 	select CRYPTO_RSA
 	select ASYMMETRIC_KEY_TYPE
-	select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+	select SOFTWARE_PUBLIC_KEY_SUBTYPE
 	select ASN1
 	select OID_REGISTRY
 	select X509_CERTIFICATE_PARSER
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 5533a011b58e..f2dd41bcf19c 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -34,7 +34,7 @@ config INTEGRITY_ASYMMETRIC_KEYS
 	depends on INTEGRITY_SIGNATURE
 	default n
         select ASYMMETRIC_KEY_TYPE
-        select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+        select SOFTWARE_PUBLIC_KEY_SUBTYPE
         select PUBLIC_KEY_ALGO_RSA
         select CRYPTO_RSA
         select X509_CERTIFICATE_PARSER

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

* [PATCH 8/8] X.509: Rename public_key* to software_pkey*
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
                   ` (6 preceding siblings ...)
  2016-02-19 17:18 ` [PATCH 7/8] X.509: Rename public_key.c to software_pkey.c David Howells
@ 2016-02-19 17:19 ` David Howells
  2016-02-22 18:57 ` [PATCH 0/8] X.509: Software public key subtype changes Mimi Zohar
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-19 17:19 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, linux-security-module, zohar, linux-kernel, tadeusz.struk

Rename symbols beginning with "public_key" to symbols beginning with
"software_pkey" to reflect that this is the software implementation private
data rather than the only possible asymmetric key subtype that does public
key handling.

Note that struct public_key_signature is left unrenamed as that's a more
general feature.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 crypto/asymmetric_keys/pkcs7_verify.c     |    2 +
 crypto/asymmetric_keys/software_pkey.c    |   48 +++++++++++++++--------------
 crypto/asymmetric_keys/software_pkey.h    |   10 +++---
 crypto/asymmetric_keys/x509_cert_parser.c |    4 +-
 crypto/asymmetric_keys/x509_parser.h      |    4 +-
 crypto/asymmetric_keys/x509_public_key.c  |    8 ++---
 6 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 6aad267f19bb..3828e801e003 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -332,7 +332,7 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
 	}
 
 	/* Verify the PKCS#7 binary against the key */
-	ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig);
+	ret = software_pkey_verify_signature(sinfo->signer->pub, &sinfo->sig);
 	if (ret < 0)
 		return ret;
 
diff --git a/crypto/asymmetric_keys/software_pkey.c b/crypto/asymmetric_keys/software_pkey.c
index 3024081026c1..8732a41b1001 100644
--- a/crypto/asymmetric_keys/software_pkey.c
+++ b/crypto/asymmetric_keys/software_pkey.c
@@ -27,10 +27,10 @@ MODULE_LICENSE("GPL");
 /*
  * Provide a part of a description of the key for /proc/keys.
  */
-static void public_key_describe(const struct key *asymmetric_key,
+static void software_pkey_describe(const struct key *asymmetric_key,
 				struct seq_file *m)
 {
-	struct public_key *key = asymmetric_key->payload.data[asym_crypto];
+	struct software_pkey *key = asymmetric_key->payload.data[asym_crypto];
 
 	if (key)
 		seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
@@ -39,24 +39,24 @@ static void public_key_describe(const struct key *asymmetric_key,
 /*
  * Destroy a public key algorithm key.
  */
-void public_key_destroy(void *payload)
+void software_pkey_destroy(void *payload)
 {
-	struct public_key *key = payload;
+	struct software_pkey *key = payload;
 
 	if (key)
 		kfree(key->key);
 	kfree(key);
 }
-EXPORT_SYMBOL_GPL(public_key_destroy);
+EXPORT_SYMBOL_GPL(software_pkey_destroy);
 
-struct public_key_completion {
+struct software_pkey_completion {
 	struct completion completion;
 	int err;
 };
 
-static void public_key_verify_done(struct crypto_async_request *req, int err)
+static void software_pkey_verify_done(struct crypto_async_request *req, int err)
 {
-	struct public_key_completion *compl = req->data;
+	struct software_pkey_completion *compl = req->data;
 
 	if (err == -EINPROGRESS)
 		return;
@@ -68,10 +68,10 @@ static void public_key_verify_done(struct crypto_async_request *req, int err)
 /*
  * Verify a signature using a public key.
  */
-int public_key_verify_signature(const struct public_key *pkey,
-				const struct public_key_signature *sig)
+int software_pkey_verify_signature(const struct software_pkey *pkey,
+				   const struct public_key_signature *sig)
 {
-	struct public_key_completion compl;
+	struct software_pkey_completion compl;
 	struct crypto_akcipher *tfm;
 	struct akcipher_request *req;
 	struct scatterlist sig_sg, digest_sg;
@@ -104,7 +104,7 @@ int public_key_verify_signature(const struct public_key *pkey,
 	init_completion(&compl.completion);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
 				      CRYPTO_TFM_REQ_MAY_SLEEP,
-				      public_key_verify_done, &compl);
+				      software_pkey_verify_done, &compl);
 
 	ret = crypto_akcipher_verify(req);
 	if (ret == -EINPROGRESS) {
@@ -119,24 +119,24 @@ error_free_tfm:
 	pr_devel("<==%s() = %d\n", __func__, ret);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(public_key_verify_signature);
+EXPORT_SYMBOL_GPL(software_pkey_verify_signature);
 
-static int public_key_verify_signature_2(const struct key *key,
-					 const struct public_key_signature *sig)
+static int software_pkey_verify_signature_2(const struct key *key,
+					    const struct public_key_signature *sig)
 {
-	const struct public_key *pk = key->payload.data[asym_crypto];
-	return public_key_verify_signature(pk, sig);
+	const struct software_pkey *pk = key->payload.data[asym_crypto];
+	return software_pkey_verify_signature(pk, sig);
 }
 
 /*
  * Public key algorithm asymmetric key subtype
  */
-struct asymmetric_key_subtype public_key_subtype = {
+struct asymmetric_key_subtype software_pkey_subtype = {
 	.owner			= THIS_MODULE,
-	.name			= "public_key",
-	.name_len		= sizeof("public_key") - 1,
-	.describe		= public_key_describe,
-	.destroy		= public_key_destroy,
-	.verify_signature	= public_key_verify_signature_2,
+	.name			= "software_pkey",
+	.name_len		= sizeof("software_pkey") - 1,
+	.describe		= software_pkey_describe,
+	.destroy		= software_pkey_destroy,
+	.verify_signature	= software_pkey_verify_signature_2,
 };
-EXPORT_SYMBOL_GPL(public_key_subtype);
+EXPORT_SYMBOL_GPL(software_pkey_subtype);
diff --git a/crypto/asymmetric_keys/software_pkey.h b/crypto/asymmetric_keys/software_pkey.h
index 06d6500e5825..696bce5daf08 100644
--- a/crypto/asymmetric_keys/software_pkey.h
+++ b/crypto/asymmetric_keys/software_pkey.h
@@ -11,7 +11,7 @@
 
 #include <crypto/public_key.h>
 
-extern struct asymmetric_key_subtype public_key_subtype;
+extern struct asymmetric_key_subtype software_pkey_subtype;
 
 /*
  * Cryptographic data for the software public-key subtype of the asymmetric key
@@ -20,14 +20,14 @@ extern struct asymmetric_key_subtype public_key_subtype;
  * Note that this may include private part of the key as well as the public
  * part.
  */
-struct public_key {
+struct software_pkey {
 	void *key;
 	u32 keylen;
 	const char *id_type;
 	const char *pkey_algo;
 };
 
-extern void public_key_destroy(void *payload);
+extern void software_pkey_destroy(void *payload);
 
-extern int public_key_verify_signature(const struct public_key *pkey,
-				       const struct public_key_signature *sig);
+extern int software_pkey_verify_signature(const struct software_pkey *pkey,
+					  const struct public_key_signature *sig);
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index a008a945aa82..9cc629261fee 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -47,7 +47,7 @@ struct x509_parse_context {
 void x509_free_certificate(struct x509_certificate *cert)
 {
 	if (cert) {
-		public_key_destroy(cert->pub);
+		software_pkey_destroy(cert->pub);
 		kfree(cert->issuer);
 		kfree(cert->subject);
 		kfree(cert->id);
@@ -75,7 +75,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
 	cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL);
 	if (!cert)
 		goto error_no_cert;
-	cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
+	cert->pub = kzalloc(sizeof(struct software_pkey), GFP_KERNEL);
 	if (!cert->pub)
 		goto error_no_ctx;
 	ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL);
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index dbeed6018e63..f9fe7c8b2002 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -16,7 +16,7 @@
 struct x509_certificate {
 	struct x509_certificate *next;
 	struct x509_certificate *signer;	/* Certificate that signed this one */
-	struct public_key *pub;			/* Public key details */
+	struct software_pkey *pub;		/* Public key details */
 	struct public_key_signature sig;	/* Signature parameters */
 	char		*issuer;		/* Name of certificate issuer */
 	char		*subject;		/* Name of certificate subject */
@@ -58,5 +58,5 @@ extern int x509_decode_time(time64_t *_t,  size_t hdrlen,
  * x509_public_key.c
  */
 extern int x509_get_sig_params(struct x509_certificate *cert);
-extern int x509_check_signature(const struct public_key *pub,
+extern int x509_check_signature(const struct software_pkey *pub,
 				struct x509_certificate *cert);
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 0896f784cfda..55fdefc12069 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -220,7 +220,7 @@ EXPORT_SYMBOL_GPL(x509_get_sig_params);
 /*
  * Check the signature on a certificate using the provided public key
  */
-int x509_check_signature(const struct public_key *pub,
+int x509_check_signature(const struct software_pkey *pub,
 			 struct x509_certificate *cert)
 {
 	int ret;
@@ -231,7 +231,7 @@ int x509_check_signature(const struct public_key *pub,
 	if (ret < 0)
 		return ret;
 
-	ret = public_key_verify_signature(pub, &cert->sig);
+	ret = software_pkey_verify_signature(pub, &cert->sig);
 	if (ret == -ENOPKG)
 		cert->unsupported_crypto = true;
 	pr_debug("Cert Verification: %d\n", ret);
@@ -350,8 +350,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
 	kids->id[1] = cert->skid;
 
 	/* We're pinning the module by being linked against it */
-	__module_get(public_key_subtype.owner);
-	prep->payload.data[asym_subtype] = &public_key_subtype;
+	__module_get(software_pkey_subtype.owner);
+	prep->payload.data[asym_subtype] = &software_pkey_subtype;
 	prep->payload.data[asym_key_ids] = kids;
 	prep->payload.data[asym_crypto] = cert->pub;
 	prep->description = desc;

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

* Re: [PATCH 0/8] X.509: Software public key subtype changes
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
                   ` (7 preceding siblings ...)
  2016-02-19 17:19 ` [PATCH 8/8] X.509: Rename public_key* to software_pkey* David Howells
@ 2016-02-22 18:57 ` Mimi Zohar
  2016-02-22 19:59 ` Tadeusz Struk
  2016-02-22 22:29 ` David Howells
  10 siblings, 0 replies; 35+ messages in thread
From: Mimi Zohar @ 2016-02-22 18:57 UTC (permalink / raw)
  To: David Howells
  Cc: keyrings, linux-security-module, linux-kernel, tadeusz.struk

On Fri, 2016-02-19 at 17:18 +0000, David Howells wrote:
> Here's a set of patches that cleans up the public key handling in the
> asymmetric key functions:
> 
>  (1) - (3) These are Tadeusz's RSA akcipher conversion.

Up to here, IMA-appraisal works properly.

Mimi  

>  (4) This removes all knowledge of RSA from the software public key
>      asymmetric key subtype.  Instead, the public key type and the hash
>      type are indicated to the crypto layer and the RSA module there does
>      all the appropriate encoding.
> 
>  (5) This changes the various algorithm IDs to text labels instead of enums
>      as the strings are what we actually deal with (printing, passing to
>      the crypto layer).
> 
>  (6) This separates the private parts of the software public key subtype
>      into a private header in the implementation directory.
> 
>  (7) This renames public_key.c to software_pkey.c and changes the Kconfig
>      symbol to match.
> 
>  (8) This renames symbols beginning "public_key" to "software_pkey" except
>      struct for public_key_signature which is a wider API component.
> 
> The patches can be found here also:
> 
> 	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-rsa
> 
> David
> ---
> David Howells (5):
>       akcipher: Move the RSA DER encoding to the crypto layer
>       X.509: Make algo identifiers text instead of enum
>       X.509: Make the public_key asymmetric key type internal data private
>       X.509: Rename public_key.c to software_pkey.c
>       X.509: Rename public_key* to software_pkey*
> 
> Tadeusz Struk (3):
>       crypto: KEYS: convert public key and digsig asym to the akcipher api
>       integrity: convert digsig to akcipher api
>       crypto: public_key: remove MPIs from public_key_signature struct
> 
> 
>  arch/s390/configs/default_defconfig       |    2 
>  arch/s390/configs/gcov_defconfig          |    2 
>  arch/s390/configs/performance_defconfig   |    2 
>  crypto/asymmetric_keys/Kconfig            |   17 +-
>  crypto/asymmetric_keys/Makefile           |   10 -
>  crypto/asymmetric_keys/mscode_parser.c    |   14 +
>  crypto/asymmetric_keys/pkcs7_parser.c     |   30 +--
>  crypto/asymmetric_keys/pkcs7_trust.c      |    2 
>  crypto/asymmetric_keys/pkcs7_verify.c     |   12 +
>  crypto/asymmetric_keys/public_key.c       |  130 --------------
>  crypto/asymmetric_keys/public_key.h       |   36 ----
>  crypto/asymmetric_keys/rsa.c              |  278 -----------------------------
>  crypto/asymmetric_keys/software_pkey.c    |  142 +++++++++++++++
>  crypto/asymmetric_keys/software_pkey.h    |   33 +++
>  crypto/asymmetric_keys/verify_pefile.c    |    4 
>  crypto/asymmetric_keys/verify_pefile.h    |    2 
>  crypto/asymmetric_keys/x509_cert_parser.c |   67 ++-----
>  crypto/asymmetric_keys/x509_parser.h      |    4 
>  crypto/asymmetric_keys/x509_public_key.c  |   43 ++--
>  crypto/asymmetric_keys/x509_rsakey.asn1   |    4 
>  crypto/rsa.c                              |  210 +++++++++++++++++++---
>  crypto/testmgr.c                          |    5 -
>  include/crypto/akcipher.h                 |    7 +
>  include/crypto/public_key.h               |   79 +-------
>  init/Kconfig                              |    4 
>  kernel/module_signing.c                   |    6 +
>  security/integrity/Kconfig                |    3 
>  security/integrity/digsig_asymmetric.c    |   16 +-
>  28 files changed, 467 insertions(+), 697 deletions(-)
>  delete mode 100644 crypto/asymmetric_keys/public_key.c
>  delete mode 100644 crypto/asymmetric_keys/public_key.h
>  delete mode 100644 crypto/asymmetric_keys/rsa.c
>  create mode 100644 crypto/asymmetric_keys/software_pkey.c
>  create mode 100644 crypto/asymmetric_keys/software_pkey.h
>  delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH 0/8] X.509: Software public key subtype changes
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
                   ` (8 preceding siblings ...)
  2016-02-22 18:57 ` [PATCH 0/8] X.509: Software public key subtype changes Mimi Zohar
@ 2016-02-22 19:59 ` Tadeusz Struk
  2016-02-22 22:29 ` David Howells
  10 siblings, 0 replies; 35+ messages in thread
From: Tadeusz Struk @ 2016-02-22 19:59 UTC (permalink / raw)
  To: David Howells, keyrings
  Cc: linux-security-module, zohar, linux-kernel, Linux Crypto Mailing List

On 02/19/2016 09:18 AM, David Howells wrote:
> 
> Here's a set of patches that cleans up the public key handling in the
> asymmetric key functions:
> 
>  (1) - (3) These are Tadeusz's RSA akcipher conversion.

Thanks for taking this David.

> 
>  (4) This removes all knowledge of RSA from the software public key
>      asymmetric key subtype.  Instead, the public key type and the hash
>      type are indicated to the crypto layer and the RSA module there does
>      all the appropriate encoding.
> 
>  (5) This changes the various algorithm IDs to text labels instead of enums
>      as the strings are what we actually deal with (printing, passing to
>      the crypto layer).
> 
>  (6) This separates the private parts of the software public key subtype
>      into a private header in the implementation directory.
> 
>  (7) This renames public_key.c to software_pkey.c and changes the Kconfig
>      symbol to match.
> 
>  (8) This renames symbols beginning "public_key" to "software_pkey" except
>      struct for public_key_signature which is a wider API component.
> 
> The patches can be found here also:
> 
> 	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-rsa
> 
> David
> ---
> David Howells (5):
>       akcipher: Move the RSA DER encoding to the crypto layer
>       X.509: Make algo identifiers text instead of enum
>       X.509: Make the public_key asymmetric key type internal data private
>       X.509: Rename public_key.c to software_pkey.c
>       X.509: Rename public_key* to software_pkey*
> 
> Tadeusz Struk (3):
>       crypto: KEYS: convert public key and digsig asym to the akcipher api
>       integrity: convert digsig to akcipher api
>       crypto: public_key: remove MPIs from public_key_signature struct
> 
> 
>  arch/s390/configs/default_defconfig       |    2 
>  arch/s390/configs/gcov_defconfig          |    2 
>  arch/s390/configs/performance_defconfig   |    2 
>  crypto/asymmetric_keys/Kconfig            |   17 +-
>  crypto/asymmetric_keys/Makefile           |   10 -
>  crypto/asymmetric_keys/mscode_parser.c    |   14 +
>  crypto/asymmetric_keys/pkcs7_parser.c     |   30 +--
>  crypto/asymmetric_keys/pkcs7_trust.c      |    2 
>  crypto/asymmetric_keys/pkcs7_verify.c     |   12 +
>  crypto/asymmetric_keys/public_key.c       |  130 --------------
>  crypto/asymmetric_keys/public_key.h       |   36 ----
>  crypto/asymmetric_keys/rsa.c              |  278 -----------------------------
>  crypto/asymmetric_keys/software_pkey.c    |  142 +++++++++++++++
>  crypto/asymmetric_keys/software_pkey.h    |   33 +++
>  crypto/asymmetric_keys/verify_pefile.c    |    4 
>  crypto/asymmetric_keys/verify_pefile.h    |    2 
>  crypto/asymmetric_keys/x509_cert_parser.c |   67 ++-----
>  crypto/asymmetric_keys/x509_parser.h      |    4 
>  crypto/asymmetric_keys/x509_public_key.c  |   43 ++--
>  crypto/asymmetric_keys/x509_rsakey.asn1   |    4 
>  crypto/rsa.c                              |  210 +++++++++++++++++++---
>  crypto/testmgr.c                          |    5 -
>  include/crypto/akcipher.h                 |    7 +
>  include/crypto/public_key.h               |   79 +-------
>  init/Kconfig                              |    4 
>  kernel/module_signing.c                   |    6 +
>  security/integrity/Kconfig                |    3 
>  security/integrity/digsig_asymmetric.c    |   16 +-
>  28 files changed, 467 insertions(+), 697 deletions(-)
>  delete mode 100644 crypto/asymmetric_keys/public_key.c
>  delete mode 100644 crypto/asymmetric_keys/public_key.h
>  delete mode 100644 crypto/asymmetric_keys/rsa.c
>  create mode 100644 crypto/asymmetric_keys/software_pkey.c
>  create mode 100644 crypto/asymmetric_keys/software_pkey.h
>  delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1
> 

-- 
TS

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-19 17:18 ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
@ 2016-02-22 19:59   ` Tadeusz Struk
  2016-02-22 22:28   ` David Howells
  2016-02-24  5:04   ` Mimi Zohar
  2 siblings, 0 replies; 35+ messages in thread
From: Tadeusz Struk @ 2016-02-22 19:59 UTC (permalink / raw)
  To: David Howells, keyrings
  Cc: linux-security-module, zohar, linux-kernel, Linux Crypto Mailing List

On 02/19/2016 09:18 AM, David Howells wrote:
> Move the RSA EMSA-PKCS1-v1_5 encoding from the asymmetric-key public_key
> subtype to the rsa crypto module.  This means that the public_key subtype
> no longer has any dependencies on public key type.
> 
> To make this work, I've made the following changes:
> 
>  (1) An indicator as to the hash algorithm employed must be passed to the
>      public key algorithm.  I have made this a string, equivalent to the
>      name in the matching crypto module and placed it in akcipher_request.
> 
>  (2) The RSA module builds the EMSA-PKCS1-v1_5 encoded message (EM) and
>      then compares that to the 'decrypted' signature.  This function can
>      then be reused for signing.
> 
>  (3) The destination buffer in akcipher_request is now an input buffer
>      holding the message digest (M) for the verify operation.  The output
>      of the verify operation is purely the error code.
> 
>  (4) The crypto driver in crypto/asymmetric_keys/rsa.c is now reduced to
>      something that doesn't care about what the encryption actually does
>      and and has been merged into public_key.c.
> 
>  (5) The test drivers set a NULL hash algorithm as I'm not sure what they
>      should be.
> 
>  (6) CONFIG_PUBLIC_KEY_ALGO_RSA is gone.  Module signing must set
>      CONFIG_CRYPTO_RSA=y instead.
> 
> Thoughts:
> 
>  (*) Should the encoding style (eg. raw, EMSA-PKCS1-v1_5) also be passed to
>      the public key algorithm?

I wonder if this should be merged with the crypto/rsa-pkcs1pad.c template
that we already have. Looks like the two do the same padding now.
Should we merge then and pass the hash param as a separate template param,
e.g the public_key would allocate "pkcs1pad(rsa, sha1)"?

> 
> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
> 
>  crypto/asymmetric_keys/Kconfig      |    7 -
>  crypto/asymmetric_keys/Makefile     |    1 
>  crypto/asymmetric_keys/public_key.c |   69 +++++++++--
>  crypto/asymmetric_keys/rsa.c        |  224 -----------------------------------
>  crypto/rsa.c                        |  210 ++++++++++++++++++++++++++++-----
>  crypto/testmgr.c                    |    5 -
>  include/crypto/akcipher.h           |    7 +
>  include/crypto/public_key.h         |    2 
>  init/Kconfig                        |    2 
>  9 files changed, 248 insertions(+), 279 deletions(-)
>  delete mode 100644 crypto/asymmetric_keys/rsa.c
> 
> diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
> index 905d745c2f85..91a7e047a765 100644
> --- a/crypto/asymmetric_keys/Kconfig
> +++ b/crypto/asymmetric_keys/Kconfig
> @@ -12,7 +12,6 @@ if ASYMMETRIC_KEY_TYPE
>  config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
>  	tristate "Asymmetric public-key crypto algorithm subtype"
>  	select MPILIB
> -	select PUBLIC_KEY_ALGO_RSA
>  	select CRYPTO_HASH_INFO
>  	help
>  	  This option provides support for asymmetric public key type handling.
> @@ -20,12 +19,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
>  	  appropriate hash algorithms (such as SHA-1) must be available.
>  	  ENOPKG will be reported if the requisite algorithm is unavailable.
>  
> -config PUBLIC_KEY_ALGO_RSA
> -	tristate "RSA public-key algorithm"
> -	select CRYPTO_RSA
> -	help
> -	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
> -
>  config X509_CERTIFICATE_PARSER
>  	tristate "X.509 certificate parser"
>  	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
> diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
> index b78a194ea014..f90486256f01 100644
> --- a/crypto/asymmetric_keys/Makefile
> +++ b/crypto/asymmetric_keys/Makefile
> @@ -7,7 +7,6 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
>  asymmetric_keys-y := asymmetric_type.o signature.o
>  
>  obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
> -obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
>  
>  #
>  # X.509 Certificate handling
> diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
> index b383629b9e62..66727a13d561 100644
> --- a/crypto/asymmetric_keys/public_key.c
> +++ b/crypto/asymmetric_keys/public_key.c
> @@ -17,8 +17,10 @@
>  #include <linux/kernel.h>
>  #include <linux/slab.h>
>  #include <linux/seq_file.h>
> +#include <linux/scatterlist.h>
>  #include <keys/asymmetric-subtype.h>
>  #include <crypto/public_key.h>
> +#include <crypto/akcipher.h>
>  
>  MODULE_LICENSE("GPL");
>  
> @@ -35,12 +37,6 @@ const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
>  };
>  EXPORT_SYMBOL_GPL(pkey_id_type_name);
>  
> -static int (*alg_verify[PKEY_ALGO__LAST])(const struct public_key *pkey,
> -	const struct public_key_signature *sig) = {
> -	NULL,
> -	rsa_verify_signature
> -};
> -
>  /*
>   * Provide a part of a description of the key for /proc/keys.
>   */
> @@ -68,24 +64,75 @@ void public_key_destroy(void *payload)
>  }
>  EXPORT_SYMBOL_GPL(public_key_destroy);
>  
> +struct public_key_completion {
> +	struct completion completion;
> +	int err;
> +};
> +
> +static void public_key_verify_done(struct crypto_async_request *req, int err)
> +{
> +	struct public_key_completion *compl = req->data;
> +
> +	if (err == -EINPROGRESS)
> +		return;
> +
> +	compl->err = err;
> +	complete(&compl->completion);
> +}
> +
>  /*
>   * Verify a signature using a public key.
>   */
>  int public_key_verify_signature(const struct public_key *pkey,
>  				const struct public_key_signature *sig)
>  {
> +	struct public_key_completion compl;
> +	struct crypto_akcipher *tfm;
> +	struct akcipher_request *req;
> +	struct scatterlist sig_sg, digest_sg;
> +	int ret = -ENOMEM;
> +
> +	pr_devel("==>%s()\n", __func__);
> +
>  	BUG_ON(!pkey);
>  	BUG_ON(!sig);
>  	BUG_ON(!sig->digest);
>  	BUG_ON(!sig->s);
>  
> -	if (pkey->pkey_algo >= PKEY_ALGO__LAST)
> -		return -ENOPKG;
> +	tfm = crypto_alloc_akcipher(pkey_algo_name[sig->pkey_algo], 0, 0);
> +	if (IS_ERR(tfm))
> +		return PTR_ERR(tfm);
> +
> +	req = akcipher_request_alloc(tfm, GFP_KERNEL);
> +	if (!req)
> +		goto error_free_tfm;
> +
> +	ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
> +	if (ret)
> +		goto error_free_req;
> +
> +	sg_init_one(&sig_sg, sig->s, sig->s_size);
> +	sg_init_one(&digest_sg, sig->digest, sig->digest_size);
> +	akcipher_request_set_crypt(req, &sig_sg, &digest_sg,
> +				   sig->s_size, sig->digest_size,
> +				   hash_algo_name[sig->pkey_hash_algo]);
> +	init_completion(&compl.completion);
> +	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
> +				      CRYPTO_TFM_REQ_MAY_SLEEP,
> +				      public_key_verify_done, &compl);
>  
> -	if (!alg_verify[pkey->pkey_algo])
> -		return -ENOPKG;
> +	ret = crypto_akcipher_verify(req);
> +	if (ret == -EINPROGRESS) {
> +		wait_for_completion(&compl.completion);
> +		ret = compl.err;
> +	}
>  
> -	return alg_verify[pkey->pkey_algo](pkey, sig);
> +error_free_req:
> +	akcipher_request_free(req);
> +error_free_tfm:
> +	crypto_free_akcipher(tfm);
> +	pr_devel("<==%s() = %d\n", __func__, ret);
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(public_key_verify_signature);
>  
> diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
> deleted file mode 100644
> index 51502bca65e7..000000000000
> --- a/crypto/asymmetric_keys/rsa.c
> +++ /dev/null
> @@ -1,224 +0,0 @@
> -/* RSA asymmetric public-key algorithm [RFC3447]
> - *
> - * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
> - * Written by David Howells (dhowells@redhat.com)
> - *
> - * 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) "RSA: "fmt
> -#include <linux/module.h>
> -#include <linux/slab.h>
> -#include <crypto/akcipher.h>
> -#include <crypto/public_key.h>
> -#include <crypto/algapi.h>
> -
> -MODULE_LICENSE("GPL");
> -MODULE_DESCRIPTION("RSA Public Key Algorithm");
> -
> -#define kenter(FMT, ...) \
> -	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
> -#define kleave(FMT, ...) \
> -	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
> -
> -/*
> - * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
> - */
> -static const u8 RSA_digest_info_MD5[] = {
> -	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
> -	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
> -	0x05, 0x00, 0x04, 0x10
> -};
> -
> -static const u8 RSA_digest_info_SHA1[] = {
> -	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> -	0x2B, 0x0E, 0x03, 0x02, 0x1A,
> -	0x05, 0x00, 0x04, 0x14
> -};
> -
> -static const u8 RSA_digest_info_RIPE_MD_160[] = {
> -	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> -	0x2B, 0x24, 0x03, 0x02, 0x01,
> -	0x05, 0x00, 0x04, 0x14
> -};
> -
> -static const u8 RSA_digest_info_SHA224[] = {
> -	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
> -	0x05, 0x00, 0x04, 0x1C
> -};
> -
> -static const u8 RSA_digest_info_SHA256[] = {
> -	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
> -	0x05, 0x00, 0x04, 0x20
> -};
> -
> -static const u8 RSA_digest_info_SHA384[] = {
> -	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
> -	0x05, 0x00, 0x04, 0x30
> -};
> -
> -static const u8 RSA_digest_info_SHA512[] = {
> -	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
> -	0x05, 0x00, 0x04, 0x40
> -};
> -
> -static const struct {
> -	const u8 *data;
> -	size_t size;
> -} RSA_ASN1_templates[PKEY_HASH__LAST] = {
> -#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
> -	[HASH_ALGO_MD5]		= _(MD5),
> -	[HASH_ALGO_SHA1]	= _(SHA1),
> -	[HASH_ALGO_RIPE_MD_160]	= _(RIPE_MD_160),
> -	[HASH_ALGO_SHA256]	= _(SHA256),
> -	[HASH_ALGO_SHA384]	= _(SHA384),
> -	[HASH_ALGO_SHA512]	= _(SHA512),
> -	[HASH_ALGO_SHA224]	= _(SHA224),
> -#undef _
> -};
> -
> -struct rsa_completion {
> -	struct completion completion;
> -	int err;
> -};
> -
> -/*
> - * Perform the RSA signature verification.
> - * @H: Value of hash of data and metadata
> - * @EM: The computed signature value
> - * @k: The size of EM (EM[0] is an invalid location but should hold 0x00)
> - * @hash_size: The size of H
> - * @asn1_template: The DigestInfo ASN.1 template
> - * @asn1_size: Size of asm1_template[]
> - */
> -static int rsa_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
> -		      const u8 *asn1_template, size_t asn1_size)
> -{
> -	unsigned PS_end, T_offset, i;
> -
> -	kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size);
> -
> -	if (k < 2 + 1 + asn1_size + hash_size)
> -		return -EBADMSG;
> -
> -	/* Decode the EMSA-PKCS1-v1_5
> -	 * note: leading zeros are stripped by the RSA implementation
> -	 */
> -	if (EM[0] != 0x01) {
> -		kleave(" = -EBADMSG [EM[0] == %02u]", EM[0]);
> -		return -EBADMSG;
> -	}
> -
> -	T_offset = k - (asn1_size + hash_size);
> -	PS_end = T_offset - 1;
> -	if (EM[PS_end] != 0x00) {
> -		kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]);
> -		return -EBADMSG;
> -	}
> -
> -	for (i = 1; i < PS_end; i++) {
> -		if (EM[i] != 0xff) {
> -			kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]);
> -			return -EBADMSG;
> -		}
> -	}
> -
> -	if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) {
> -		kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
> -		return -EBADMSG;
> -	}
> -
> -	if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) {
> -		kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
> -		return -EKEYREJECTED;
> -	}
> -
> -	kleave(" = 0");
> -	return 0;
> -}
> -
> -static void public_key_verify_done(struct crypto_async_request *req, int err)
> -{
> -	struct rsa_completion *compl = req->data;
> -
> -	if (err == -EINPROGRESS)
> -		return;
> -
> -	compl->err = err;
> -	complete(&compl->completion);
> -}
> -
> -int rsa_verify_signature(const struct public_key *pkey,
> -			 const struct public_key_signature *sig)
> -{
> -	struct crypto_akcipher *tfm;
> -	struct akcipher_request *req;
> -	struct rsa_completion compl;
> -	struct scatterlist sig_sg, sg_out;
> -	void *outbuf = NULL;
> -	unsigned int outlen = 0;
> -	int ret = -ENOMEM;
> -
> -	tfm = crypto_alloc_akcipher("rsa", 0, 0);
> -	if (IS_ERR(tfm))
> -		goto error_out;
> -
> -	req = akcipher_request_alloc(tfm, GFP_KERNEL);
> -	if (!req)
> -		goto error_free_tfm;
> -
> -	ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
> -	if (ret)
> -		goto error_free_req;
> -
> -	ret = -EINVAL;
> -	outlen = crypto_akcipher_maxsize(tfm);
> -	if (!outlen)
> -		goto error_free_req;
> -
> -	/* Initialize the output buffer */
> -	ret = -ENOMEM;
> -	outbuf = kmalloc(outlen, GFP_KERNEL);
> -	if (!outbuf)
> -		goto error_free_req;
> -
> -	sg_init_one(&sig_sg, sig->s, sig->s_size);
> -	sg_init_one(&sg_out, outbuf, outlen);
> -	akcipher_request_set_crypt(req, &sig_sg, &sg_out, sig->s_size, outlen);
> -	init_completion(&compl.completion);
> -	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
> -				      CRYPTO_TFM_REQ_MAY_SLEEP,
> -				      public_key_verify_done, &compl);
> -
> -	ret = crypto_akcipher_verify(req);
> -	if (ret == -EINPROGRESS) {
> -		wait_for_completion(&compl.completion);
> -		ret = compl.err;
> -	}
> -
> -	if (ret)
> -		goto error_free_req;
> -
> -	/* Output from the operation is an encoded message (EM) of
> -	 * length k octets.
> -	 */
> -	outlen = req->dst_len;
> -	ret = rsa_verify(sig->digest, outbuf, outlen, sig->digest_size,
> -			 RSA_ASN1_templates[sig->pkey_hash_algo].data,
> -			 RSA_ASN1_templates[sig->pkey_hash_algo].size);
> -error_free_req:
> -	akcipher_request_free(req);
> -error_free_tfm:
> -	crypto_free_akcipher(tfm);
> -error_out:
> -	kfree(outbuf);
> -	return ret;
> -}
> -EXPORT_SYMBOL_GPL(rsa_verify_signature);
> diff --git a/crypto/rsa.c b/crypto/rsa.c
> index 77d737f52147..9a7c9ca9eafc 100644
> --- a/crypto/rsa.c
> +++ b/crypto/rsa.c
> @@ -16,6 +16,78 @@
>  #include <crypto/algapi.h>
>  
>  /*
> + * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
> + */
> +static const u8 rsa_digest_info_md5[] = {
> +	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
> +	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
> +	0x05, 0x00, 0x04, 0x10
> +};
> +
> +static const u8 rsa_digest_info_sha1[] = {
> +	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> +	0x2b, 0x0e, 0x03, 0x02, 0x1a,
> +	0x05, 0x00, 0x04, 0x14
> +};
> +
> +static const u8 rsa_digest_info_rmd160[] = {
> +	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> +	0x2b, 0x24, 0x03, 0x02, 0x01,
> +	0x05, 0x00, 0x04, 0x14
> +};
> +
> +static const u8 rsa_digest_info_sha224[] = {
> +	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
> +	0x05, 0x00, 0x04, 0x1c
> +};
> +
> +static const u8 rsa_digest_info_sha256[] = {
> +	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
> +	0x05, 0x00, 0x04, 0x20
> +};
> +
> +static const u8 rsa_digest_info_sha384[] = {
> +	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
> +	0x05, 0x00, 0x04, 0x30
> +};
> +
> +static const u8 rsa_digest_info_sha512[] = {
> +	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
> +	0x05, 0x00, 0x04, 0x40
> +};
> +
> +static const struct rsa_asn1_template {
> +	const char	*name;
> +	const u8	*data;
> +	size_t		size;
> +} rsa_asn1_templates[] = {
> +#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
> +	_(md5),
> +	_(sha1),
> +	_(rmd160),
> +	_(sha256),
> +	_(sha384),
> +	_(sha512),
> +	_(sha224),
> +	{ NULL }
> +#undef _
> +};
> +
> +static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
> +{
> +	const struct rsa_asn1_template *p;
> +
> +	for (p = rsa_asn1_templates; p->name; p++)
> +		if (strcmp(name, p->name) == 0)
> +			return p;
> +	return NULL;
> +}
> +
> +/*
>   * RSAEP function [RFC3447 sec 5.1.1]
>   * c = m^e mod n;
>   */
> @@ -71,6 +143,13 @@ static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
>  	return mpi_powm(m, s, key->e, key->n);
>  }
>  
> +static int rsa_max_size(struct crypto_akcipher *tfm)
> +{
> +	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> +
> +	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
> +}
> +
>  static inline struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm)
>  {
>  	return akcipher_tfm_ctx(tfm);
> @@ -192,44 +271,122 @@ err_free_s:
>  	return ret;
>  }
>  
> -static int rsa_verify(struct akcipher_request *req)
> +static int rsa_verify_raw(struct akcipher_request *req, MPI EM)
>  {
>  	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
>  	const struct rsa_key *pkey = rsa_get_key(tfm);
> -	MPI s, m = mpi_alloc(0);
> -	int ret = 0;
> -	int sign;
> +	MPI s, m_calc;
> +	int ret;
>  
> -	if (!m)
> +	m_calc = mpi_alloc(0);
> +	if (!m_calc)
>  		return -ENOMEM;
>  
> -	if (unlikely(!pkey->n || !pkey->e)) {
> -		ret = -EINVAL;
> -		goto err_free_m;
> -	}
> -
>  	ret = -ENOMEM;
>  	s = mpi_read_raw_from_sgl(req->src, req->src_len);
> -	if (!s) {
> -		ret = -ENOMEM;
> -		goto err_free_m;
> -	}
> +	if (!s)
> +		goto err_free_m_calc;
>  
> -	ret = _rsa_verify(pkey, m, s);
> +	ret = _rsa_verify(pkey, m_calc, s);
>  	if (ret)
>  		goto err_free_s;
>  
> -	ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
> -	if (ret)
> +	ret = -EKEYREJECTED;
> +	if (mpi_cmp(m_calc, EM) != 0)
>  		goto err_free_s;
>  
> -	if (sign < 0)
> -		ret = -EBADMSG;
> -
> +	ret = 0;
>  err_free_s:
>  	mpi_free(s);
> -err_free_m:
> -	mpi_free(m);
> +err_free_m_calc:
> +	mpi_free(m_calc);
> +	return ret;
> +}
> +
> +/*
> + * Turn Hash(M) into EM for a key of size k and a specified hash algorithm as
> + * per EMSA-PKCS1-v1_5:
> + *
> + *	EM = 0x00 || 0x01 || PS || 0x00 || T
> + */
> +static MPI rsa_emsa_pkcs1_v1_5(struct scatterlist *H, int H_size, int k,
> +			       const char *hash_algo)
> +{
> +	const struct rsa_asn1_template *asn1;
> +	MPI EM;
> +	int PS_end, T_offset;
> +	u8 *buf;
> +
> +	asn1 = rsa_lookup_asn1(hash_algo);
> +	if (!asn1)
> +		return ERR_PTR(-ENOPKG);
> +
> +	if (k < 2 + 1 + asn1->size + H_size)
> +		return ERR_PTR(-EMSGSIZE);
> +
> +	T_offset = k - (asn1->size + H_size);
> +	PS_end = T_offset - 1;
> +	if (PS_end - 2 < 8)
> +		return ERR_PTR(-EMSGSIZE);
> +
> +	buf = kmalloc(k, GFP_KERNEL);
> +	if (!buf)
> +		return ERR_PTR(-ENOMEM);
> +
> +	/* Set the initial zero and block type octets */
> +	buf[0] = 0x00;
> +	buf[1] = 0x01;
> +
> +	/* Set the padding string and the divider */
> +	memset(buf + 2, 0xff, PS_end - 2);
> +	buf[PS_end] = 0x00;
> +
> +	/* Set the DER-encoded DigestInfo */
> +	memcpy(buf + T_offset, asn1->data, asn1->size);
> +
> +	/* Finally set the  */
> +	if (sg_copy_to_buffer(H, sg_nents(H),
> +			      buf + T_offset + asn1->size,
> +			      H_size) != H_size) {
> +		EM = ERR_PTR(-EMSGSIZE);
> +		goto error_free_buf;
> +	}
> +
> +	EM = mpi_read_raw_data(buf, k);
> +	if (!EM)
> +		EM = ERR_PTR(-ENOMEM);
> +	
> +error_free_buf:
> +	kfree(buf);
> +	return EM;
> +}
> +
> +static int rsa_verify_encoded(struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	const struct rsa_key *pkey = rsa_get_key(tfm);
> +	MPI EM;
> +	int ret, k;
> +
> +	pr_devel("==>%s(%u,%u,%s)\n",
> +		 __func__, req->src_len, req->dst_len, req->hash_algo);
> +
> +	if (unlikely(!pkey->n || !pkey->e || !req->hash_algo))
> +		return -EINVAL;
> +
> +	/* Find k - the size of E(M). */
> +	k = rsa_max_size(tfm);
> +	if (k < 0)
> +		return k;
> +
> +	EM = rsa_emsa_pkcs1_v1_5(req->dst, req->dst_len, k, req->hash_algo);
> +	if (IS_ERR(EM))
> +		return PTR_ERR(EM);
> +
> +	ret = rsa_verify_raw(req, EM);
> +
> +	mpi_free(EM);
> +	pr_devel("<==%s() = %d\n", __func__, ret);
>  	return ret;
>  }
>  
> @@ -282,13 +439,6 @@ static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
>  	return ret;
>  }
>  
> -static int rsa_max_size(struct crypto_akcipher *tfm)
> -{
> -	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> -
> -	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
> -}
> -
>  static void rsa_exit_tfm(struct crypto_akcipher *tfm)
>  {
>  	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> @@ -300,7 +450,7 @@ static struct akcipher_alg rsa = {
>  	.encrypt = rsa_enc,
>  	.decrypt = rsa_dec,
>  	.sign = rsa_sign,
> -	.verify = rsa_verify,
> +	.verify = rsa_verify_encoded,
>  	.set_priv_key = rsa_set_priv_key,
>  	.set_pub_key = rsa_set_pub_key,
>  	.max_size = rsa_max_size,
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index ae8c57fd8bc7..94879a3d2ef7 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -1882,7 +1882,7 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
>  	sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8);
>  	sg_init_one(&dst, outbuf_enc, out_len_max);
>  	akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
> -				   out_len_max);
> +				   out_len_max, NULL);
>  	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
>  				      tcrypt_complete, &result);
>  
> @@ -1916,7 +1916,8 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
>  	sg_init_one(&src, vecs->c, vecs->c_size);
>  	sg_init_one(&dst, outbuf_dec, out_len_max);
>  	init_completion(&result.completion);
> -	akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max);
> +	akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max,
> +				   NULL);
>  
>  	/* Run RSA decrypt - m = c^d mod n;*/
>  	err = wait_async_op(&result, crypto_akcipher_decrypt(req));
> diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
> index 354de15cea6b..a59a6a0d6784 100644
> --- a/include/crypto/akcipher.h
> +++ b/include/crypto/akcipher.h
> @@ -27,6 +27,7 @@
>   *		result.
>   *		In case of error where the dst sgl size was insufficient,
>   *		it will be updated to the size required for the operation.
> + * @hash_algo:	The hash algorithm used for sign/verify operations.
>   * @__ctx:	Start of private context data
>   */
>  struct akcipher_request {
> @@ -35,6 +36,7 @@ struct akcipher_request {
>  	struct scatterlist *dst;
>  	unsigned int src_len;
>  	unsigned int dst_len;
> +	const char *hash_algo;
>  	void *__ctx[] CRYPTO_MINALIGN_ATTR;
>  };
>  
> @@ -241,17 +243,20 @@ static inline void akcipher_request_set_callback(struct akcipher_request *req,
>   * @dst:	ptr to output scatter list
>   * @src_len:	size of the src input scatter list to be processed
>   * @dst_len:	size of the dst output scatter list
> + * @hash_algo:	The hash algorithm that was used for a signature (or NULL).
>   */
>  static inline void akcipher_request_set_crypt(struct akcipher_request *req,
>  					      struct scatterlist *src,
>  					      struct scatterlist *dst,
>  					      unsigned int src_len,
> -					      unsigned int dst_len)
> +					      unsigned int dst_len,
> +					      const char *hash_algo)
>  {
>  	req->src = src;
>  	req->dst = dst;
>  	req->src_len = src_len;
>  	req->dst_len = dst_len;
> +	req->hash_algo = hash_algo;
>  }
>  
>  /**
> diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
> index a1693ed77be6..80ab099a3edf 100644
> --- a/include/crypto/public_key.h
> +++ b/include/crypto/public_key.h
> @@ -91,6 +91,4 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring,
>  int public_key_verify_signature(const struct public_key *pkey,
>  				const struct public_key_signature *sig);
>  
> -int rsa_verify_signature(const struct public_key *pkey,
> -			 const struct public_key_signature *sig);
>  #endif /* _LINUX_PUBLIC_KEY_H */
> diff --git a/init/Kconfig b/init/Kconfig
> index 22320804fbaf..af4de4f1b02c 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1757,9 +1757,9 @@ config SYSTEM_DATA_VERIFICATION
>  	select SYSTEM_TRUSTED_KEYRING
>  	select KEYS
>  	select CRYPTO
> +	select CRYPTO_RSA
>  	select ASYMMETRIC_KEY_TYPE
>  	select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
> -	select PUBLIC_KEY_ALGO_RSA
>  	select ASN1
>  	select OID_REGISTRY
>  	select X509_CERTIFICATE_PARSER
> 


-- 
TS

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-19 17:18 ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
  2016-02-22 19:59   ` Tadeusz Struk
@ 2016-02-22 22:28   ` David Howells
  2016-02-22 23:35     ` Tadeusz Struk
                       ` (3 more replies)
  2016-02-24  5:04   ` Mimi Zohar
  2 siblings, 4 replies; 35+ messages in thread
From: David Howells @ 2016-02-22 22:28 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells, keyrings, linux-security-module, zohar, linux-kernel,
	Linux Crypto Mailing List

Tadeusz Struk <tadeusz.struk@intel.com> wrote:

> I wonder if this should be merged with the crypto/rsa-pkcs1pad.c template
> that we already have. Looks like the two do the same padding now.
> Should we merge then and pass the hash param as a separate template param,
> e.g the public_key would allocate "pkcs1pad(rsa, sha1)"?

Ummm...  Possibly.  Is that how it's used?

	warthog>git grep pkcs1pad -- Documentation
	warthog1>

Anyway, the problem I have with this is that I want to get that knowledge out
of the asymmetric key in-software public key subtype.  It knows "rsa", "dsa",
"ecdsa", ... because that's all the OIDs tell it.

I guess if I have to, I can stoop to converting "rsa" to "pkcs1pad(rsa, sha1)".

Can you do me a really quick merge?  -rc5 is already out, and I want to get it
to James pronto - plus I have things that are pending on this change being
made.

Oh - and how does the padding template find the algorithm DER encoding string
to use?  I have wondered whether it should be stored in with the hash
algorithm, but it probably makes more sense to keep it with the rsa module.

David

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

* Re: [PATCH 0/8] X.509: Software public key subtype changes
  2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
                   ` (9 preceding siblings ...)
  2016-02-22 19:59 ` Tadeusz Struk
@ 2016-02-22 22:29 ` David Howells
  2016-02-23  0:03   ` Mimi Zohar
  2016-02-23 10:16   ` David Howells
  10 siblings, 2 replies; 35+ messages in thread
From: David Howells @ 2016-02-22 22:29 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: dhowells, keyrings, linux-security-module, linux-kernel, tadeusz.struk

Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:

> >  (1) - (3) These are Tadeusz's RSA akcipher conversion.
> 
> Up to here, IMA-appraisal works properly.

I don't have IMA set up anywhere.

David

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-22 22:28   ` David Howells
@ 2016-02-22 23:35     ` Tadeusz Struk
  2016-02-23  0:01     ` Andrew Zaborowski
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 35+ messages in thread
From: Tadeusz Struk @ 2016-02-22 23:35 UTC (permalink / raw)
  To: David Howells
  Cc: keyrings, linux-security-module, zohar, linux-kernel,
	Linux Crypto Mailing List

On 02/22/2016 02:28 PM, David Howells wrote:
> Tadeusz Struk <tadeusz.struk@intel.com> wrote:
> 
>> I wonder if this should be merged with the crypto/rsa-pkcs1pad.c template
>> that we already have. Looks like the two do the same padding now.
>> Should we merge then and pass the hash param as a separate template param,
>> e.g the public_key would allocate "pkcs1pad(rsa, sha1)"?
> 
> Ummm...  Possibly.  Is that how it's used?
> 
> 	warthog>git grep pkcs1pad -- Documentation
> 	warthog1>

Yes, no docs. Sorry.

> 
> Anyway, the problem I have with this is that I want to get that knowledge out
> of the asymmetric key in-software public key subtype.  It knows "rsa", "dsa",
> "ecdsa", ... because that's all the OIDs tell it.

Rigth, for now the public_key would need to build the full algorithm string as
follows:

vsprintf(name, "pkcs1pad(%s, %s)", pkey_algo_name[sig->pkey_algo],
         hash_algo_name[sig->pkey_hash_algo]);

Do you plan to add more padding schemes later? 

> 
> I guess if I have to, I can stoop to converting "rsa" to "pkcs1pad(rsa, sha1)".
> 
> Can you do me a really quick merge?  -rc5 is already out, and I want to get it
> to James pronto - plus I have things that are pending on this change being
> made.

Yes, I can start woring on a subsequent patch based on your changes in
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-rsa
Is that ok with you?

> 
> Oh - and how does the padding template find the algorithm DER encoding string
> to use?  I have wondered whether it should be stored in with the hash
> algorithm, but it probably makes more sense to keep it with the rsa module.

We can put everything into the crypto/rsa-pkcs1pad.c
This is where all the padding logic should be, I think.
Thanks,
-- 
TS

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-22 22:28   ` David Howells
  2016-02-22 23:35     ` Tadeusz Struk
@ 2016-02-23  0:01     ` Andrew Zaborowski
  2016-02-23 10:53     ` David Howells
  2016-02-23 10:55     ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
  3 siblings, 0 replies; 35+ messages in thread
From: Andrew Zaborowski @ 2016-02-23  0:01 UTC (permalink / raw)
  To: David Howells
  Cc: Tadeusz Struk, keyrings, linux-security-module, zohar,
	linux-kernel, Linux Crypto Mailing List

Hi,

On 22 February 2016 at 23:28, David Howells <dhowells@redhat.com> wrote:
> Tadeusz Struk <tadeusz.struk@intel.com> wrote:
>
>> I wonder if this should be merged with the crypto/rsa-pkcs1pad.c template
>> that we already have. Looks like the two do the same padding now.

I think that'd be a good thing to do.

>> Should we merge then and pass the hash param as a separate template param,
>> e.g the public_key would allocate "pkcs1pad(rsa, sha1)"?
>
> Ummm...  Possibly.  Is that how it's used?

Currently it only does the padding and doesn't care about the hash.
The input is expected to be the entire DigestInfo struct.

AIUI Tadeusz is proposing adding the hashing as a new feature.  Note
though that the hash paremeter won't make sense for the encrypt,
decrypt or verify operations.

Also note that TLS 1.0 uses the padding to sign data that is not a
DigestInfo structure and even for 1.2 there are situations where
you'll be hashing the data yourself over some time and then you'll
want the algorithm to only do the padding and RSA signing.

Cheers

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

* Re: [PATCH 0/8] X.509: Software public key subtype changes
  2016-02-22 22:29 ` David Howells
@ 2016-02-23  0:03   ` Mimi Zohar
  2016-02-23 10:16   ` David Howells
  1 sibling, 0 replies; 35+ messages in thread
From: Mimi Zohar @ 2016-02-23  0:03 UTC (permalink / raw)
  To: David Howells
  Cc: keyrings, linux-security-module, linux-kernel, tadeusz.struk

On Mon, 2016-02-22 at 22:29 +0000, David Howells wrote:
> Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:
> 
> > >  (1) - (3) These are Tadeusz's RSA akcipher conversion.
> > 
> > Up to here, IMA-appraisal works properly.
> 
> I don't have IMA set up anywhere.

I know.  With the "vfs: support for a common kernel file loader" patch
set, setting up a simple test becomes a lot simpler.  With this patch
set you can measure and appraise just the kexec image and initramfs,
firmware and/or kernel modules.

Create two key pairs.  Add one to the system keyring.*   The other key
load on the IMA keyring.  (Remember it needs to be signed with the
private key of a key on the system keyring.**)

To measure and appraise just the kexec initramfs, define a policy
containing:
measure func=INITRAMFS_CHECK
appraise func=INITRAMFS_CHECK appraise_type=imasig

To load the IMA policy, write the policy to the securityfs IMA policy
file:
cat <IMA policy> > /sys/kernel/securityfs/ima/policy.

Sign the kexec initramfs using evmctl:
evmctl ima_sign -k <privkey.pem> -a sha256 /boot/<initramfs>.img

Execute:  kexec -s -l /boot/<image> --initrd=/boot/<initramfs>.img
--reuse-cmdline
Failures to appraise the initramfs are audit logged.  The IMA
measurement list will contain the initramfs file hash.

*There are two or three methods for loading the key onto the system
keyring depending on the distro.
- builtin
- enroll in MoK db (on some distros)
- Mehmet's patch  (needs to be upstreamed)

** Refer to the ima-evm-utils package README for further details on
creating and signing a certificate to be loaded on the IMA keyring.

Mimi

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

* Re: [PATCH 0/8] X.509: Software public key subtype changes
  2016-02-22 22:29 ` David Howells
  2016-02-23  0:03   ` Mimi Zohar
@ 2016-02-23 10:16   ` David Howells
  2016-02-23 12:28     ` Mimi Zohar
  1 sibling, 1 reply; 35+ messages in thread
From: David Howells @ 2016-02-23 10:16 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: dhowells, keyrings, linux-security-module, linux-kernel, tadeusz.struk

Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:

> To measure and appraise just the kexec initramfs, define a policy
> containing:

Doesn't this require a TPM?

David

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-22 22:28   ` David Howells
  2016-02-22 23:35     ` Tadeusz Struk
  2016-02-23  0:01     ` Andrew Zaborowski
@ 2016-02-23 10:53     ` David Howells
  2016-02-24 17:12         ` Tadeusz Struk
  2016-02-24 17:28       ` [PATCH 0/2] KEYS: Use pkcs1pad for padding in software_pkey David Howells
  2016-02-23 10:55     ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
  3 siblings, 2 replies; 35+ messages in thread
From: David Howells @ 2016-02-23 10:53 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells, keyrings, linux-security-module, zohar, linux-kernel,
	Linux Crypto Mailing List

Tadeusz Struk <tadeusz.struk@intel.com> wrote:

> > Ummm...  Possibly.  Is that how it's used?
> > 
> > 	warthog>git grep pkcs1pad -- Documentation
> > 	warthog1>
> 
> Yes, no docs. Sorry.

Can I suggest you at least stick a quick usage summary in the banner comment
at the top of the file?

> > Anyway, the problem I have with this is that I want to get that knowledge
> > out of the asymmetric key in-software public key subtype.  It knows "rsa",
> > "dsa", "ecdsa", ... because that's all the OIDs tell it.
> 
> Rigth, for now the public_key would need to build the full algorithm string as
> follows:
> 
> vsprintf(name, "pkcs1pad(%s, %s)", pkey_algo_name[sig->pkey_algo],
>          hash_algo_name[sig->pkey_hash_algo]);

Does this apply to anything other than RSA?

> Do you plan to add more padding schemes later? 

No plans to, but one never knows.  I'm *assuming* that OID_rsaEncryption and
OID_sha256WithRSAEncryption, for example, must implicitly specify the padding
scheme (RFC4055 suggests I'm right in this assumption).

We might have to suppose RSASSA-SSP at some point.

> Yes, I can start woring on a subsequent patch based on your changes in
> http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-rsa
> Is that ok with you?

Sure.

David

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-22 22:28   ` David Howells
                       ` (2 preceding siblings ...)
  2016-02-23 10:53     ` David Howells
@ 2016-02-23 10:55     ` David Howells
  2016-02-23 11:25       ` Andrew Zaborowski
  2016-02-26 11:42       ` David Howells
  3 siblings, 2 replies; 35+ messages in thread
From: David Howells @ 2016-02-23 10:55 UTC (permalink / raw)
  To: Andrew Zaborowski
  Cc: dhowells, Tadeusz Struk, keyrings, linux-security-module, zohar,
	linux-kernel, Linux Crypto Mailing List

Andrew Zaborowski <balrogg@googlemail.com> wrote:

> AIUI Tadeusz is proposing adding the hashing as a new feature.  Note
> though that the hash paremeter won't make sense for the encrypt,
> decrypt or verify operations.

The hash parameter is necessary for the verify operation.  From my
perspective, I want a verify operation that takes the signature, the message
hash and the hash name and gives me back an error code.

David

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-23 10:55     ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
@ 2016-02-23 11:25       ` Andrew Zaborowski
  2016-02-26 11:42       ` David Howells
  1 sibling, 0 replies; 35+ messages in thread
From: Andrew Zaborowski @ 2016-02-23 11:25 UTC (permalink / raw)
  To: David Howells
  Cc: Tadeusz Struk, keyrings, linux-security-module, zohar,
	linux-kernel, Linux Crypto Mailing List

Hi David,

On 23 February 2016 at 11:55, David Howells <dhowells@redhat.com> wrote:
> Andrew Zaborowski <balrogg@googlemail.com> wrote:
>
>> AIUI Tadeusz is proposing adding the hashing as a new feature.  Note
>> though that the hash paremeter won't make sense for the encrypt,
>> decrypt or verify operations.
>
> The hash parameter is necessary for the verify operation.  From my
> perspective, I want a verify operation that takes the signature, the message
> hash and the hash name and gives me back an error code.

>From the certificates point of view yes, but the akcipher API only has
the four operations each of which has one input buffer and out output
buffer.

Without overhauling akcipher you could modify pkcs1pad so that sign
takes the hash as input, adds the DER struct in front of it to build
the signature, and the verify operation could at most check that the
DER string matches the hash type and return the hash.  But I think
RFC2437 suggests that you rather compare the signatures, not the
hashes.

Cheers

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

* Re: [PATCH 0/8] X.509: Software public key subtype changes
  2016-02-23 10:16   ` David Howells
@ 2016-02-23 12:28     ` Mimi Zohar
  0 siblings, 0 replies; 35+ messages in thread
From: Mimi Zohar @ 2016-02-23 12:28 UTC (permalink / raw)
  To: David Howells
  Cc: keyrings, linux-security-module, linux-kernel, tadeusz.struk

On Tue, 2016-02-23 at 10:16 +0000, David Howells wrote:
> Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:
> 
> > To measure and appraise just the kexec initramfs, define a policy
> > containing:
> 
> Doesn't this require a TPM?

For appraising file signatures, a TPM is definitely not required!   Even
in the case of making sure that the file measurements are being taken, a
TPM is not required.  For purposes of testing changes to the asymmetric
keys or the key subsystem in general, a TPM is not required.

The TPM is needed for quoting PCRs.  When a TPM is available, IMA, in
addition to adding the file measurements to the run time measurement
list, extends a TPM PCR with the file measurements.  A trusted third
party, can then validate the measurement list against the PCR quote.

The real question is which files need to be measured and appraised in
order to either prevent or, at least, to be able to detect a system
compromise.  But for your use case scenario, of making sure that changes
to the asymmetric keys or the key subsystem in general has not broken
IMA, measuring and appraising a single file should be enough.

Mimi

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-19 17:18 ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
  2016-02-22 19:59   ` Tadeusz Struk
  2016-02-22 22:28   ` David Howells
@ 2016-02-24  5:04   ` Mimi Zohar
  2016-02-24  5:59     ` Mimi Zohar
  2016-02-29 15:37     ` David Howells
  2 siblings, 2 replies; 35+ messages in thread
From: Mimi Zohar @ 2016-02-24  5:04 UTC (permalink / raw)
  To: David Howells
  Cc: keyrings, linux-security-module, linux-kernel, tadeusz.struk

On Fri, 2016-02-19 at 17:18 +0000, David Howells wrote:

>  /*
>   * Verify a signature using a public key.
>   */
>  int public_key_verify_signature(const struct public_key *pkey,
>  				const struct public_key_signature *sig)
>  {
> +	struct public_key_completion compl;
> +	struct crypto_akcipher *tfm;
> +	struct akcipher_request *req;
> +	struct scatterlist sig_sg, digest_sg;
> +	int ret = -ENOMEM;
> +
> +	pr_devel("==>%s()\n", __func__);
> +
>  	BUG_ON(!pkey);
>  	BUG_ON(!sig);
>  	BUG_ON(!sig->digest);
>  	BUG_ON(!sig->s);
> 
> -	if (pkey->pkey_algo >= PKEY_ALGO__LAST)
> -		return -ENOPKG;
> +	tfm = crypto_alloc_akcipher(pkey_algo_name[sig->pkey_algo], 0, 0);
> +	if (IS_ERR(tfm))
> +		return PTR_ERR(tfm);

IMA fails here.   The security.ima xattr header includes the hash
algorithm as defined in 
include/uapi/linux/hash_info.h.

struct signature_v2_hdr {
        uint8_t type;           /* xattr type */
        uint8_t version;        /* signature format version */
        uint8_t hash_algo;      /* Digest algorithm [enum pkey_hash_algo] */
        uint32_t keyid;         /* IMA key identifier - not X509/PGP specific */
        uint16_t sig_size;      /* signature size */
        uint8_t sig[0];         /* signature payload */
} __packed;

Mimi

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-24  5:04   ` Mimi Zohar
@ 2016-02-24  5:59     ` Mimi Zohar
  2016-02-29 15:37     ` David Howells
  1 sibling, 0 replies; 35+ messages in thread
From: Mimi Zohar @ 2016-02-24  5:59 UTC (permalink / raw)
  To: David Howells
  Cc: keyrings, linux-security-module, linux-kernel, tadeusz.struk

On Wed, 2016-02-24 at 00:04 -0500, Mimi Zohar wrote:
> On Fri, 2016-02-19 at 17:18 +0000, David Howells wrote:
> 
> >  /*
> >   * Verify a signature using a public key.
> >   */
> >  int public_key_verify_signature(const struct public_key *pkey,
> >  				const struct public_key_signature *sig)
> >  {
> > +	struct public_key_completion compl;
> > +	struct crypto_akcipher *tfm;
> > +	struct akcipher_request *req;
> > +	struct scatterlist sig_sg, digest_sg;
> > +	int ret = -ENOMEM;
> > +
> > +	pr_devel("==>%s()\n", __func__);
> > +
> >  	BUG_ON(!pkey);
> >  	BUG_ON(!sig);
> >  	BUG_ON(!sig->digest);
> >  	BUG_ON(!sig->s);
> > 
> > -	if (pkey->pkey_algo >= PKEY_ALGO__LAST)
> > -		return -ENOPKG;
> > +	tfm = crypto_alloc_akcipher(pkey_algo_name[sig->pkey_algo], 0, 0);
> > +	if (IS_ERR(tfm))
> > +		return PTR_ERR(tfm);
> 
> IMA fails here.

Please include the following fix in this patch.

diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index 2fa3bc6..69a92e6 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -103,6 +103,7 @@ int asymmetric_verify(struct key *keyring, const char *sig,
 
 	memset(&pks, 0, sizeof(pks));
 
+	pks.pkey_algo = PKEY_ALGO_RSA;
 	pks.pkey_hash_algo = hdr->hash_algo;
 	pks.digest = (u8 *)data;
 	pks.digest_size = datalen;
-- 
2.1.0

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

* [PATCH 0/2] KEYS: Use pkcs1pad for padding in software_pkey
  2016-02-23 10:53     ` David Howells
@ 2016-02-24 17:12         ` Tadeusz Struk
  2016-02-24 17:28       ` [PATCH 0/2] KEYS: Use pkcs1pad for padding in software_pkey David Howells
  1 sibling, 0 replies; 35+ messages in thread
From: Tadeusz Struk @ 2016-02-24 17:12 UTC (permalink / raw)
  To: dhowells
  Cc: tadeusz.struk, linux-kernel, balrogg, linux-security-module,
	keyrings, linux-crypto, zohar

Hi David,
I have converted the software_pkey to make use of the pkcs1pad
template. The rsa.c is reverted back to what it was i.e. just
math primitives and all padding is done in rsa-pkcs1padd.c
software_pkey.c just allocates pksc1padd(alg,hash)

This is incremental series on top of the current
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-rsa

---

Tadeusz Struk (2):
      crypto: Add hash param to pkcs1pad
      crypto: remove paddings logic from rsa.c


 crypto/asymmetric_keys/software_pkey.c |   28 ++++
 crypto/rsa-pkcs1pad.c                  |  182 ++++++++++++++++++++++++----
 crypto/rsa.c                           |  210 +++++---------------------------
 crypto/testmgr.c                       |    5 -
 include/crypto/akcipher.h              |    7 -
 5 files changed, 212 insertions(+), 220 deletions(-)

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

* [PATCH 0/2] KEYS: Use pkcs1pad for padding in software_pkey
@ 2016-02-24 17:12         ` Tadeusz Struk
  0 siblings, 0 replies; 35+ messages in thread
From: Tadeusz Struk @ 2016-02-24 17:12 UTC (permalink / raw)
  To: dhowells
  Cc: tadeusz.struk, linux-kernel, balrogg, linux-security-module,
	keyrings, linux-crypto, zohar

Hi David,
I have converted the software_pkey to make use of the pkcs1pad
template. The rsa.c is reverted back to what it was i.e. just
math primitives and all padding is done in rsa-pkcs1padd.c
software_pkey.c just allocates pksc1padd(alg,hash)

This is incremental series on top of the current
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-rsa

---

Tadeusz Struk (2):
      crypto: Add hash param to pkcs1pad
      crypto: remove paddings logic from rsa.c


 crypto/asymmetric_keys/software_pkey.c |   28 ++++
 crypto/rsa-pkcs1pad.c                  |  182 ++++++++++++++++++++++++----
 crypto/rsa.c                           |  210 +++++---------------------------
 crypto/testmgr.c                       |    5 -
 include/crypto/akcipher.h              |    7 -
 5 files changed, 212 insertions(+), 220 deletions(-)

--

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

* [PATCH 1/2] crypto: Add hash param to pkcs1pad
  2016-02-24 17:12         ` Tadeusz Struk
  (?)
@ 2016-02-24 17:12         ` Tadeusz Struk
  -1 siblings, 0 replies; 35+ messages in thread
From: Tadeusz Struk @ 2016-02-24 17:12 UTC (permalink / raw)
  To: dhowells
  Cc: tadeusz.struk, linux-kernel, balrogg, linux-security-module,
	keyrings, linux-crypto, zohar

This adds hash param to pkcs1pad.
The pkcs1pad template can work with or without the hash.
When hash param is provided then the verify operation will
also verify the output against the known digest.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
---
 crypto/rsa-pkcs1pad.c |  182 ++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 156 insertions(+), 26 deletions(-)

diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 50f5c97..1cea67d 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -18,12 +18,89 @@
 #include <linux/module.h>
 #include <linux/random.h>
 
+/*
+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
+ */
+static const u8 rsa_digest_info_md5[] = {
+	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
+	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
+	0x05, 0x00, 0x04, 0x10
+};
+
+static const u8 rsa_digest_info_sha1[] = {
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+	0x2b, 0x0e, 0x03, 0x02, 0x1a,
+	0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 rsa_digest_info_rmd160[] = {
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+	0x2b, 0x24, 0x03, 0x02, 0x01,
+	0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 rsa_digest_info_sha224[] = {
+	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+	0x05, 0x00, 0x04, 0x1c
+};
+
+static const u8 rsa_digest_info_sha256[] = {
+	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+	0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 rsa_digest_info_sha384[] = {
+	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+	0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 rsa_digest_info_sha512[] = {
+	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+	0x05, 0x00, 0x04, 0x40
+};
+
+static const struct rsa_asn1_template {
+	const char	*name;
+	const u8	*data;
+	size_t		size;
+} rsa_asn1_templates[] = {
+#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
+	_(md5),
+	_(sha1),
+	_(rmd160),
+	_(sha256),
+	_(sha384),
+	_(sha512),
+	_(sha224),
+	{ NULL }
+#undef _
+};
+
+static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
+{
+	const struct rsa_asn1_template *p;
+
+	for (p = rsa_asn1_templates; p->name; p++)
+		if (strcmp(name, p->name) == 0)
+			return p;
+	return NULL;
+}
+
 struct pkcs1pad_ctx {
 	struct crypto_akcipher *child;
-
+	const char *hash_name;
 	unsigned int key_size;
 };
 
+struct pkcs1pad_inst_ctx {
+	struct crypto_akcipher_spawn spawn;
+	const char *hash_name;
+};
+
 struct pkcs1pad_request {
 	struct akcipher_request child_req;
 
@@ -339,13 +416,22 @@ static int pkcs1pad_sign(struct akcipher_request *req)
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
 	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
+	const struct rsa_asn1_template *digest_info = NULL;
 	int err;
-	unsigned int ps_end;
+	unsigned int ps_end, digest_size = 0;
 
 	if (!ctx->key_size)
 		return -EINVAL;
 
-	if (req->src_len > ctx->key_size - 11)
+	if (ctx->hash_name) {
+		digest_info = rsa_lookup_asn1(ctx->hash_name);
+		if (!digest_info)
+			return -EINVAL;
+
+		digest_size = digest_info->size;
+	}
+
+	if (req->src_len + digest_size > ctx->key_size - 11)
 		return -EOVERFLOW;
 
 	if (req->dst_len < ctx->key_size) {
@@ -371,11 +457,16 @@ static int pkcs1pad_sign(struct akcipher_request *req)
 	if (!req_ctx->in_buf)
 		return -ENOMEM;
 
-	ps_end = ctx->key_size - req->src_len - 2;
+	ps_end = ctx->key_size - digest_size - req->src_len - 2;
 	req_ctx->in_buf[0] = 0x01;
 	memset(req_ctx->in_buf + 1, 0xff, ps_end - 1);
 	req_ctx->in_buf[ps_end] = 0x00;
 
+	if (digest_info) {
+		memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data,
+		       digest_info->size);
+	}
+
 	pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
 			ctx->key_size - 1 - req->src_len, req->src);
 
@@ -408,6 +499,7 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
 	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
+	const struct rsa_asn1_template *digest_info;
 	unsigned int pos;
 
 	if (err == -EOVERFLOW)
@@ -422,20 +514,33 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
 		goto done;
 	}
 
-	if (req_ctx->out_buf[0] != 0x01) {
-		err = -EINVAL;
+	err = -EBADMSG;
+	if (req_ctx->out_buf[0] != 0x01)
 		goto done;
-	}
+
 	for (pos = 1; pos < req_ctx->child_req.dst_len; pos++)
 		if (req_ctx->out_buf[pos] != 0xff)
 			break;
+
 	if (pos < 9 || pos == req_ctx->child_req.dst_len ||
-			req_ctx->out_buf[pos] != 0x00) {
-		err = -EINVAL;
+	    req_ctx->out_buf[pos] != 0x00)
 		goto done;
-	}
 	pos++;
 
+	if (ctx->hash_name) {
+		digest_info = rsa_lookup_asn1(ctx->hash_name);
+		if (!digest_info)
+			goto done;
+
+		if (memcmp(req_ctx->out_buf + pos, digest_info->data,
+			   digest_info->size))
+			goto done;
+
+		pos += digest_info->size;
+	}
+
+	err = 0;
+
 	if (req->dst_len < req_ctx->child_req.dst_len - pos)
 		err = -EOVERFLOW;
 	req->dst_len = req_ctx->child_req.dst_len - pos;
@@ -444,7 +549,6 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
 		sg_copy_from_buffer(req->dst,
 				sg_nents_for_len(req->dst, req->dst_len),
 				req_ctx->out_buf + pos, req->dst_len);
-
 done:
 	kzfree(req_ctx->out_buf);
 
@@ -481,7 +585,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
 	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
 	int err;
 
-	if (!ctx->key_size || req->src_len != ctx->key_size)
+	if (!ctx->key_size || req->src_len < ctx->key_size)
 		return -EINVAL;
 
 	if (ctx->key_size > PAGE_SIZE)
@@ -518,6 +622,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
 static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
 {
 	struct akcipher_instance *inst = akcipher_alg_instance(tfm);
+	struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
 	struct crypto_akcipher *child_tfm;
 
@@ -526,7 +631,7 @@ static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
 		return PTR_ERR(child_tfm);
 
 	ctx->child = child_tfm;
-
+	ctx->hash_name = ictx->hash_name;
 	return 0;
 }
 
@@ -539,10 +644,11 @@ static void pkcs1pad_exit_tfm(struct crypto_akcipher *tfm)
 
 static void pkcs1pad_free(struct akcipher_instance *inst)
 {
-	struct crypto_akcipher_spawn *spawn = akcipher_instance_ctx(inst);
+	struct pkcs1pad_inst_ctx *ctx = akcipher_instance_ctx(inst);
+	struct crypto_akcipher_spawn *spawn = &ctx->spawn;
 
 	crypto_drop_akcipher(spawn);
-
+	kfree(ctx->hash_name);
 	kfree(inst);
 }
 
@@ -550,9 +656,11 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
 {
 	struct crypto_attr_type *algt;
 	struct akcipher_instance *inst;
+	struct pkcs1pad_inst_ctx *ctx;
 	struct crypto_akcipher_spawn *spawn;
 	struct akcipher_alg *rsa_alg;
 	const char *rsa_alg_name;
+	const char *hash_name;
 	int err;
 
 	algt = crypto_get_attr_type(tb);
@@ -566,11 +674,18 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
 	if (IS_ERR(rsa_alg_name))
 		return PTR_ERR(rsa_alg_name);
 
-	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+	hash_name = crypto_attr_alg_name(tb[2]);
+	if (IS_ERR(hash_name))
+		hash_name = NULL;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
 	if (!inst)
 		return -ENOMEM;
 
-	spawn = akcipher_instance_ctx(inst);
+	ctx = akcipher_instance_ctx(inst);
+	spawn = &ctx->spawn;
+	ctx->hash_name = hash_name ? kstrdup(hash_name, GFP_KERNEL) : NULL;
+
 	crypto_set_spawn(&spawn->base, akcipher_crypto_instance(inst));
 	err = crypto_grab_akcipher(spawn, rsa_alg_name, 0,
 			crypto_requires_sync(algt->type, algt->mask));
@@ -580,15 +695,28 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
 	rsa_alg = crypto_spawn_akcipher_alg(spawn);
 
 	err = -ENAMETOOLONG;
-	if (snprintf(inst->alg.base.cra_name,
-				CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
-				rsa_alg->base.cra_name) >=
-			CRYPTO_MAX_ALG_NAME ||
-			snprintf(inst->alg.base.cra_driver_name,
-				CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
-				rsa_alg->base.cra_driver_name) >=
-			CRYPTO_MAX_ALG_NAME)
+
+	if (!hash_name) {
+		if (snprintf(inst->alg.base.cra_name,
+			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
+			     rsa_alg->base.cra_name) >=
+					CRYPTO_MAX_ALG_NAME ||
+		    snprintf(inst->alg.base.cra_driver_name,
+			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
+			     rsa_alg->base.cra_driver_name) >=
+					CRYPTO_MAX_ALG_NAME)
 		goto out_drop_alg;
+	} else {
+		if (snprintf(inst->alg.base.cra_name,
+			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
+			     rsa_alg->base.cra_name, hash_name) >=
+				CRYPTO_MAX_ALG_NAME ||
+		    snprintf(inst->alg.base.cra_driver_name,
+			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
+			     rsa_alg->base.cra_driver_name, hash_name) >=
+					CRYPTO_MAX_ALG_NAME)
+		goto out_free_hash;
+	}
 
 	inst->alg.base.cra_flags = rsa_alg->base.cra_flags & CRYPTO_ALG_ASYNC;
 	inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
@@ -610,10 +738,12 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
 
 	err = akcipher_register_instance(tmpl, inst);
 	if (err)
-		goto out_drop_alg;
+		goto out_free_hash;
 
 	return 0;
 
+out_free_hash:
+	kfree(ctx->hash_name);
 out_drop_alg:
 	crypto_drop_akcipher(spawn);
 out_free_inst:

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

* [PATCH 2/2] crypto: remove padding logic from rsa.c
  2016-02-24 17:12         ` Tadeusz Struk
  (?)
  (?)
@ 2016-02-24 17:12         ` Tadeusz Struk
  2016-02-27 18:40           ` Herbert Xu
  -1 siblings, 1 reply; 35+ messages in thread
From: Tadeusz Struk @ 2016-02-24 17:12 UTC (permalink / raw)
  To: dhowells
  Cc: tadeusz.struk, linux-kernel, balrogg, linux-security-module,
	keyrings, linux-crypto, zohar

This reverts back the rsa.c to do the math primitives only.
It also reverts the akcipher api changes as the hash param
will be passed to the rsa-pkcs1 template.
All padding and encoding logic is moved to the rsa-pkcs1pad.
The software_pkey.c uses pkcs1pad template to allocate the akcipher
and the hash param is passed via pksc1pad.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
---
 crypto/asymmetric_keys/software_pkey.c |   28 ++++
 crypto/rsa.c                           |  210 +++++---------------------------
 crypto/testmgr.c                       |    5 -
 include/crypto/akcipher.h              |    7 -
 4 files changed, 56 insertions(+), 194 deletions(-)

diff --git a/crypto/asymmetric_keys/software_pkey.c b/crypto/asymmetric_keys/software_pkey.c
index 8732a41..69693fd 100644
--- a/crypto/asymmetric_keys/software_pkey.c
+++ b/crypto/asymmetric_keys/software_pkey.c
@@ -75,6 +75,9 @@ int software_pkey_verify_signature(const struct software_pkey *pkey,
 	struct crypto_akcipher *tfm;
 	struct akcipher_request *req;
 	struct scatterlist sig_sg, digest_sg;
+	char alg_name[CRYPTO_MAX_ALG_NAME];
+	void *output;
+	unsigned int outlen;
 	int ret = -ENOMEM;
 
 	pr_devel("==>%s()\n", __func__);
@@ -84,7 +87,11 @@ int software_pkey_verify_signature(const struct software_pkey *pkey,
 	BUG_ON(!sig->digest);
 	BUG_ON(!sig->s);
 
-	tfm = crypto_alloc_akcipher(sig->pkey_algo, 0, 0);
+	if (snprintf(alg_name, CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
+		     sig->pkey_algo, sig->hash_algo) >= CRYPTO_MAX_ALG_NAME)
+		return -EINVAL;
+
+	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 	if (IS_ERR(tfm))
 		return PTR_ERR(tfm);
 
@@ -96,11 +103,15 @@ int software_pkey_verify_signature(const struct software_pkey *pkey,
 	if (ret)
 		goto error_free_req;
 
+	outlen = crypto_akcipher_maxsize(tfm);
+	output = kmalloc(outlen, GFP_KERNEL);
+	if (!output)
+		goto error_free_req;
+
 	sg_init_one(&sig_sg, sig->s, sig->s_size);
-	sg_init_one(&digest_sg, sig->digest, sig->digest_size);
-	akcipher_request_set_crypt(req, &sig_sg, &digest_sg,
-				   sig->s_size, sig->digest_size,
-				   sig->hash_algo);
+	sg_init_one(&digest_sg, output, outlen);
+	akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size,
+				   outlen);
 	init_completion(&compl.completion);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
 				      CRYPTO_TFM_REQ_MAY_SLEEP,
@@ -112,6 +123,13 @@ int software_pkey_verify_signature(const struct software_pkey *pkey,
 		ret = compl.err;
 	}
 
+	if (!ret) {
+		if (memcmp(sig->digest, output, sig->digest_size) ||
+		    req->dst_len != sig->digest_size)
+			ret = -EBADMSG;
+	}
+
+	kfree(output);
 error_free_req:
 	akcipher_request_free(req);
 error_free_tfm:
diff --git a/crypto/rsa.c b/crypto/rsa.c
index 9a7c9ca..77d737f 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -16,78 +16,6 @@
 #include <crypto/algapi.h>
 
 /*
- * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
- */
-static const u8 rsa_digest_info_md5[] = {
-	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
-	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
-	0x05, 0x00, 0x04, 0x10
-};
-
-static const u8 rsa_digest_info_sha1[] = {
-	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
-	0x2b, 0x0e, 0x03, 0x02, 0x1a,
-	0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 rsa_digest_info_rmd160[] = {
-	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
-	0x2b, 0x24, 0x03, 0x02, 0x01,
-	0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 rsa_digest_info_sha224[] = {
-	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
-	0x05, 0x00, 0x04, 0x1c
-};
-
-static const u8 rsa_digest_info_sha256[] = {
-	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
-	0x05, 0x00, 0x04, 0x20
-};
-
-static const u8 rsa_digest_info_sha384[] = {
-	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
-	0x05, 0x00, 0x04, 0x30
-};
-
-static const u8 rsa_digest_info_sha512[] = {
-	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
-	0x05, 0x00, 0x04, 0x40
-};
-
-static const struct rsa_asn1_template {
-	const char	*name;
-	const u8	*data;
-	size_t		size;
-} rsa_asn1_templates[] = {
-#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
-	_(md5),
-	_(sha1),
-	_(rmd160),
-	_(sha256),
-	_(sha384),
-	_(sha512),
-	_(sha224),
-	{ NULL }
-#undef _
-};
-
-static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
-{
-	const struct rsa_asn1_template *p;
-
-	for (p = rsa_asn1_templates; p->name; p++)
-		if (strcmp(name, p->name) == 0)
-			return p;
-	return NULL;
-}
-
-/*
  * RSAEP function [RFC3447 sec 5.1.1]
  * c = m^e mod n;
  */
@@ -143,13 +71,6 @@ static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
 	return mpi_powm(m, s, key->e, key->n);
 }
 
-static int rsa_max_size(struct crypto_akcipher *tfm)
-{
-	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
-
-	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
-}
-
 static inline struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm)
 {
 	return akcipher_tfm_ctx(tfm);
@@ -271,122 +192,44 @@ err_free_s:
 	return ret;
 }
 
-static int rsa_verify_raw(struct akcipher_request *req, MPI EM)
+static int rsa_verify(struct akcipher_request *req)
 {
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	const struct rsa_key *pkey = rsa_get_key(tfm);
-	MPI s, m_calc;
-	int ret;
+	MPI s, m = mpi_alloc(0);
+	int ret = 0;
+	int sign;
 
-	m_calc = mpi_alloc(0);
-	if (!m_calc)
+	if (!m)
 		return -ENOMEM;
 
+	if (unlikely(!pkey->n || !pkey->e)) {
+		ret = -EINVAL;
+		goto err_free_m;
+	}
+
 	ret = -ENOMEM;
 	s = mpi_read_raw_from_sgl(req->src, req->src_len);
-	if (!s)
-		goto err_free_m_calc;
+	if (!s) {
+		ret = -ENOMEM;
+		goto err_free_m;
+	}
 
-	ret = _rsa_verify(pkey, m_calc, s);
+	ret = _rsa_verify(pkey, m, s);
 	if (ret)
 		goto err_free_s;
 
-	ret = -EKEYREJECTED;
-	if (mpi_cmp(m_calc, EM) != 0)
+	ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
+	if (ret)
 		goto err_free_s;
 
-	ret = 0;
+	if (sign < 0)
+		ret = -EBADMSG;
+
 err_free_s:
 	mpi_free(s);
-err_free_m_calc:
-	mpi_free(m_calc);
-	return ret;
-}
-
-/*
- * Turn Hash(M) into EM for a key of size k and a specified hash algorithm as
- * per EMSA-PKCS1-v1_5:
- *
- *	EM = 0x00 || 0x01 || PS || 0x00 || T
- */
-static MPI rsa_emsa_pkcs1_v1_5(struct scatterlist *H, int H_size, int k,
-			       const char *hash_algo)
-{
-	const struct rsa_asn1_template *asn1;
-	MPI EM;
-	int PS_end, T_offset;
-	u8 *buf;
-
-	asn1 = rsa_lookup_asn1(hash_algo);
-	if (!asn1)
-		return ERR_PTR(-ENOPKG);
-
-	if (k < 2 + 1 + asn1->size + H_size)
-		return ERR_PTR(-EMSGSIZE);
-
-	T_offset = k - (asn1->size + H_size);
-	PS_end = T_offset - 1;
-	if (PS_end - 2 < 8)
-		return ERR_PTR(-EMSGSIZE);
-
-	buf = kmalloc(k, GFP_KERNEL);
-	if (!buf)
-		return ERR_PTR(-ENOMEM);
-
-	/* Set the initial zero and block type octets */
-	buf[0] = 0x00;
-	buf[1] = 0x01;
-
-	/* Set the padding string and the divider */
-	memset(buf + 2, 0xff, PS_end - 2);
-	buf[PS_end] = 0x00;
-
-	/* Set the DER-encoded DigestInfo */
-	memcpy(buf + T_offset, asn1->data, asn1->size);
-
-	/* Finally set the  */
-	if (sg_copy_to_buffer(H, sg_nents(H),
-			      buf + T_offset + asn1->size,
-			      H_size) != H_size) {
-		EM = ERR_PTR(-EMSGSIZE);
-		goto error_free_buf;
-	}
-
-	EM = mpi_read_raw_data(buf, k);
-	if (!EM)
-		EM = ERR_PTR(-ENOMEM);
-	
-error_free_buf:
-	kfree(buf);
-	return EM;
-}
-
-static int rsa_verify_encoded(struct akcipher_request *req)
-{
-	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
-	const struct rsa_key *pkey = rsa_get_key(tfm);
-	MPI EM;
-	int ret, k;
-
-	pr_devel("==>%s(%u,%u,%s)\n",
-		 __func__, req->src_len, req->dst_len, req->hash_algo);
-
-	if (unlikely(!pkey->n || !pkey->e || !req->hash_algo))
-		return -EINVAL;
-
-	/* Find k - the size of E(M). */
-	k = rsa_max_size(tfm);
-	if (k < 0)
-		return k;
-
-	EM = rsa_emsa_pkcs1_v1_5(req->dst, req->dst_len, k, req->hash_algo);
-	if (IS_ERR(EM))
-		return PTR_ERR(EM);
-
-	ret = rsa_verify_raw(req, EM);
-
-	mpi_free(EM);
-	pr_devel("<==%s() = %d\n", __func__, ret);
+err_free_m:
+	mpi_free(m);
 	return ret;
 }
 
@@ -439,6 +282,13 @@ static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
 	return ret;
 }
 
+static int rsa_max_size(struct crypto_akcipher *tfm)
+{
+	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+
+	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
+}
+
 static void rsa_exit_tfm(struct crypto_akcipher *tfm)
 {
 	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
@@ -450,7 +300,7 @@ static struct akcipher_alg rsa = {
 	.encrypt = rsa_enc,
 	.decrypt = rsa_dec,
 	.sign = rsa_sign,
-	.verify = rsa_verify_encoded,
+	.verify = rsa_verify,
 	.set_priv_key = rsa_set_priv_key,
 	.set_pub_key = rsa_set_pub_key,
 	.max_size = rsa_max_size,
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 94879a3..ae8c57fd 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1882,7 +1882,7 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
 	sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8);
 	sg_init_one(&dst, outbuf_enc, out_len_max);
 	akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
-				   out_len_max, NULL);
+				   out_len_max);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				      tcrypt_complete, &result);
 
@@ -1916,8 +1916,7 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
 	sg_init_one(&src, vecs->c, vecs->c_size);
 	sg_init_one(&dst, outbuf_dec, out_len_max);
 	init_completion(&result.completion);
-	akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max,
-				   NULL);
+	akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max);
 
 	/* Run RSA decrypt - m = c^d mod n;*/
 	err = wait_async_op(&result, crypto_akcipher_decrypt(req));
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index a59a6a0..354de15 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -27,7 +27,6 @@
  *		result.
  *		In case of error where the dst sgl size was insufficient,
  *		it will be updated to the size required for the operation.
- * @hash_algo:	The hash algorithm used for sign/verify operations.
  * @__ctx:	Start of private context data
  */
 struct akcipher_request {
@@ -36,7 +35,6 @@ struct akcipher_request {
 	struct scatterlist *dst;
 	unsigned int src_len;
 	unsigned int dst_len;
-	const char *hash_algo;
 	void *__ctx[] CRYPTO_MINALIGN_ATTR;
 };
 
@@ -243,20 +241,17 @@ static inline void akcipher_request_set_callback(struct akcipher_request *req,
  * @dst:	ptr to output scatter list
  * @src_len:	size of the src input scatter list to be processed
  * @dst_len:	size of the dst output scatter list
- * @hash_algo:	The hash algorithm that was used for a signature (or NULL).
  */
 static inline void akcipher_request_set_crypt(struct akcipher_request *req,
 					      struct scatterlist *src,
 					      struct scatterlist *dst,
 					      unsigned int src_len,
-					      unsigned int dst_len,
-					      const char *hash_algo)
+					      unsigned int dst_len)
 {
 	req->src = src;
 	req->dst = dst;
 	req->src_len = src_len;
 	req->dst_len = dst_len;
-	req->hash_algo = hash_algo;
 }
 
 /**

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

* Re: [PATCH 0/2] KEYS: Use pkcs1pad for padding in software_pkey
  2016-02-23 10:53     ` David Howells
  2016-02-24 17:12         ` Tadeusz Struk
@ 2016-02-24 17:28       ` David Howells
  1 sibling, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-24 17:28 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells, linux-kernel, balrogg, linux-security-module, keyrings,
	linux-crypto, zohar

Tadeusz Struk <tadeusz.struk@intel.com> wrote:

> I have converted the software_pkey to make use of the pkcs1pad
> template. The rsa.c is reverted back to what it was i.e. just
> math primitives and all padding is done in rsa-pkcs1padd.c
> software_pkey.c just allocates pksc1padd(alg,hash)

Okay, thanks - I'll take a look at that later.

One thought that just occurred to me: would it make sense to make a second
crypto template in rsa-pkcs1pad.c and call it "rsassa-pkcs1-v1_5" that does
this padding variant?  It can share most of its code with the generic pkcs1pad
algorithm.

We could then also add a third variant "rsassa-pss" at a later date.

David

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-23 10:55     ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
  2016-02-23 11:25       ` Andrew Zaborowski
@ 2016-02-26 11:42       ` David Howells
  1 sibling, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-26 11:42 UTC (permalink / raw)
  To: Andrew Zaborowski
  Cc: dhowells, Tadeusz Struk, keyrings, linux-security-module, zohar,
	linux-kernel, Linux Crypto Mailing List

Andrew Zaborowski <balrogg@googlemail.com> wrote:

> Without overhauling akcipher you could modify pkcs1pad so that sign
> takes the hash as input, adds the DER struct in front of it to build
> the signature, and the verify operation could at most check that the
> DER string matches the hash type and return the hash.  But I think
> RFC2437 suggests that you rather compare the signatures, not the
> hashes.

Whilst that is true about what RFC2437 shows, I wonder how strict it wants to
be about that rather than it just being a convenient way of describing the
algorithm.

The advantage of doing it the way the RFC suggests is that you get to use the
EMSA-PKCS1-V1_5-ENCODE operation twice, thereby saving code and only having
one place for bugs to occur instead of two - but you can argue this either
way.

That said, I would be okay with it returning just the message hash with the
padding stripped off, providing the padding is validated in the crypto layer,
if that's necessary.

David

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

* Re: [PATCH 2/2] crypto: remove padding logic from rsa.c
  2016-02-24 17:12         ` Tadeusz Struk
                           ` (2 preceding siblings ...)
  (?)
@ 2016-02-26 14:00         ` David Howells
  -1 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-26 14:00 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells, linux-kernel, balrogg, linux-security-module, keyrings,
	linux-crypto, zohar

Tadeusz Struk <tadeusz.struk@intel.com> wrote:

> +		if (memcmp(sig->digest, output, sig->digest_size) ||

I've added " != 0" after the memcmp().

> +		    req->dst_len != sig->digest_size)
> +			ret = -EBADMSG;

Btw, this has to be -EKEYREJECTED; -EBADMSG would indicate that the container
is unparseable.  I wonder if we should propose a -ESIGREJECTED error...

David

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

* Re: [PATCH 2/2] crypto: remove padding logic from rsa.c
  2016-02-24 17:12         ` Tadeusz Struk
                           ` (3 preceding siblings ...)
  (?)
@ 2016-02-26 15:02         ` David Howells
  -1 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-26 15:02 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells, linux-kernel, balrogg, linux-security-module, keyrings,
	linux-crypto, zohar

Tadeusz Struk <tadeusz.struk@intel.com> wrote:

> +		if (memcmp(sig->digest, output, sig->digest_size) ||
> +		    req->dst_len != sig->digest_size)

You must always do the size check first!

David

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

* Re: [PATCH 2/2] crypto: remove padding logic from rsa.c
  2016-02-24 17:12         ` [PATCH 2/2] crypto: remove padding logic from rsa.c Tadeusz Struk
@ 2016-02-27 18:40           ` Herbert Xu
  2016-02-28  3:20             ` Tadeusz Struk
  0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2016-02-27 18:40 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells, tadeusz.struk, linux-kernel, balrogg,
	linux-security-module, keyrings, linux-crypto, zohar,
	James Morris

Tadeusz Struk <tadeusz.struk@intel.com> wrote:
>
> diff --git a/crypto/rsa.c b/crypto/rsa.c
> index 9a7c9ca..77d737f 100644
> --- a/crypto/rsa.c
> +++ b/crypto/rsa.c
> @@ -16,78 +16,6 @@
> #include <crypto/algapi.h>
> 
> /*
> - * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
> - */
> -static const u8 rsa_digest_info_md5[] = {
> -       0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
> -       0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
> -       0x05, 0x00, 0x04, 0x10
> -};

Where did this come from? It's not in my tree.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* Re: [PATCH 2/2] crypto: remove padding logic from rsa.c
  2016-02-27 18:40           ` Herbert Xu
@ 2016-02-28  3:20             ` Tadeusz Struk
  0 siblings, 0 replies; 35+ messages in thread
From: Tadeusz Struk @ 2016-02-28  3:20 UTC (permalink / raw)
  To: Herbert Xu
  Cc: dhowells, linux-kernel, balrogg, linux-security-module, keyrings,
	linux-crypto, zohar, James Morris

Hi Herbert,
On 02/27/2016 10:40 AM, Herbert Xu wrote:
> Tadeusz Struk <tadeusz.struk@intel.com> wrote:
>>
>> diff --git a/crypto/rsa.c b/crypto/rsa.c
>> index 9a7c9ca..77d737f 100644
>> --- a/crypto/rsa.c
>> +++ b/crypto/rsa.c
>> @@ -16,78 +16,6 @@
>> #include <crypto/algapi.h>
>>
>> /*
>> - * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
>> - */
>> -static const u8 rsa_digest_info_md5[] = {
>> -       0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
>> -       0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
>> -       0x05, 0x00, 0x04, 0x10
>> -};
> 
> Where did this come from? It's not in my tree.

These are generated on top of
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-rsa
Thanks,
-- 
TS

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

* Re: [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer
  2016-02-24  5:04   ` Mimi Zohar
  2016-02-24  5:59     ` Mimi Zohar
@ 2016-02-29 15:37     ` David Howells
  1 sibling, 0 replies; 35+ messages in thread
From: David Howells @ 2016-02-29 15:37 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: dhowells, keyrings, linux-security-module, linux-kernel, tadeusz.struk

Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:

>  	memset(&pks, 0, sizeof(pks));
>  
> +	pks.pkey_algo = PKEY_ALGO_RSA;
>  	pks.pkey_hash_algo = hdr->hash_algo;
>  	pks.digest = (u8 *)data;
>  	pks.digest_size = datalen;

I've updated the patch.

David

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

end of thread, other threads:[~2016-02-29 15:38 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-19 17:18 [PATCH 0/8] X.509: Software public key subtype changes David Howells
2016-02-19 17:18 ` [PATCH 1/8] crypto: KEYS: convert public key and digsig asym to the akcipher api David Howells
2016-02-19 17:18 ` [PATCH 2/8] integrity: convert digsig to " David Howells
2016-02-19 17:18 ` [PATCH 3/8] crypto: public_key: remove MPIs from public_key_signature struct David Howells
2016-02-19 17:18 ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
2016-02-22 19:59   ` Tadeusz Struk
2016-02-22 22:28   ` David Howells
2016-02-22 23:35     ` Tadeusz Struk
2016-02-23  0:01     ` Andrew Zaborowski
2016-02-23 10:53     ` David Howells
2016-02-24 17:12       ` [PATCH 0/2] KEYS: Use pkcs1pad for padding in software_pkey Tadeusz Struk
2016-02-24 17:12         ` Tadeusz Struk
2016-02-24 17:12         ` [PATCH 1/2] crypto: Add hash param to pkcs1pad Tadeusz Struk
2016-02-24 17:12         ` [PATCH 2/2] crypto: remove padding logic from rsa.c Tadeusz Struk
2016-02-27 18:40           ` Herbert Xu
2016-02-28  3:20             ` Tadeusz Struk
2016-02-26 14:00         ` David Howells
2016-02-26 15:02         ` David Howells
2016-02-24 17:28       ` [PATCH 0/2] KEYS: Use pkcs1pad for padding in software_pkey David Howells
2016-02-23 10:55     ` [PATCH 4/8] akcipher: Move the RSA DER encoding to the crypto layer David Howells
2016-02-23 11:25       ` Andrew Zaborowski
2016-02-26 11:42       ` David Howells
2016-02-24  5:04   ` Mimi Zohar
2016-02-24  5:59     ` Mimi Zohar
2016-02-29 15:37     ` David Howells
2016-02-19 17:18 ` [PATCH 5/8] X.509: Make algo identifiers text instead of enum David Howells
2016-02-19 17:18 ` [PATCH 6/8] X.509: Make the public_key asymmetric key type internal data private David Howells
2016-02-19 17:18 ` [PATCH 7/8] X.509: Rename public_key.c to software_pkey.c David Howells
2016-02-19 17:19 ` [PATCH 8/8] X.509: Rename public_key* to software_pkey* David Howells
2016-02-22 18:57 ` [PATCH 0/8] X.509: Software public key subtype changes Mimi Zohar
2016-02-22 19:59 ` Tadeusz Struk
2016-02-22 22:29 ` David Howells
2016-02-23  0:03   ` Mimi Zohar
2016-02-23 10:16   ` David Howells
2016-02-23 12:28     ` Mimi Zohar

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.