@@ -89,11 +89,9 @@ inclusion is required:
#include <crypto/public_key.h>
This gives access to functions for dealing with asymmetric / public keys.
-Three enums are defined there for representing public-key cryptography
+Two enums are defined there for representing public-key cryptography
algorithms:
- enum pkey_algo
-
digest algorithms used by those:
enum pkey_hash_algo
@@ -102,6 +100,11 @@ and key identifier representations:
enum pkey_id_type
+Additionally public key algorithm names are defined:
+#define PKEY_ALGO_DSA "dsa"
+#define PKEY_ALGO_RSA "rsa"
+These will be used to allocate public key tfm instances.
+
Note that the key type representation types are required because key
identifiers from different standards aren't necessarily compatible. For
instance, PGP generates key identifiers by hashing the key data plus some
@@ -131,6 +134,7 @@ transferred the relevant bits to the structure pointed to by sig.
struct public_key_signature {
u8 *digest;
+ char *pkey_algo;
u8 digest_size;
enum pkey_hash_algo pkey_hash_algo : 8;
u8 nr_mpi;
@@ -23,6 +23,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
config PUBLIC_KEY_ALGO_RSA
tristate "RSA public-key algorithm"
select MPILIB
+ select CRYPTO_PKE
help
This option enables support for the RSA algorithm (PKCS#1, RFC3447).
@@ -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"
@@ -376,7 +376,7 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen,
struct pkcs7_parse_context *ctx = context;
MPI mpi;
- BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
+ BUG_ON(strcmp(ctx->sinfo->sig.pkey_algo, PKEY_ALGO_RSA));
mpi = mpi_read_raw_data(value, vlen);
if (!mpi)
@@ -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"
/**
@@ -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"
/*
@@ -144,7 +144,8 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
sinfo->index, certix);
- if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) {
+ if (strcmp(pke_alg_name(x509->pub->tfm),
+ sinfo->sig.pkey_algo)) {
pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
sinfo->index);
continue;
@@ -18,30 +18,21 @@
#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",
-};
-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",
};
EXPORT_SYMBOL_GPL(pkey_id_type_name);
+struct public_key_completion {
+ struct completion completion;
+ int err;
+};
+
/*
* Provide a part of a description of the key for /proc/keys.
*/
@@ -52,7 +43,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],
+ pke_alg_name(key->tfm));
}
/*
@@ -71,13 +63,27 @@ void public_key_destroy(void *payload)
}
EXPORT_SYMBOL_GPL(public_key_destroy);
+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 *pk,
const struct public_key_signature *sig)
{
- const struct public_key_algorithm *algo;
+ struct crypto_pke *tfm;
+ struct pke_request *req;
+ struct public_key_completion compl;
+ int ret;
BUG_ON(!pk);
BUG_ON(!pk->mpi[0]);
@@ -86,25 +92,32 @@ int public_key_verify_signature(const struct public_key *pk,
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;
- }
+ tfm = pk->tfm;
+ if (IS_ERR(tfm))
+ return -EINVAL;
- if (!algo->verify_signature)
- return -ENOTSUPP;
+ req = pke_request_alloc(tfm, GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
- if (sig->nr_mpi != algo->n_sig_mpi) {
+ if (sig->nr_mpi != pke_num_sig_mpi(tfm)) {
pr_debug("Signature has %u MPI not %u\n",
- sig->nr_mpi, algo->n_sig_mpi);
+ sig->nr_mpi, pke_num_sig_mpi(tfm));
return -EINVAL;
}
- return algo->verify_signature(pk, sig);
+ init_completion(&compl.completion);
+ pke_request_set_crypt(req, pk, sig);
+ pke_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ public_key_verify_done, &compl);
+ ret = crypto_pke_verify(req);
+ if (ret == -EINPROGRESS) {
+ wait_for_completion(&compl.completion);
+ ret = compl.err;
+ }
+ pke_request_free(req);
+ return ret;
}
EXPORT_SYMBOL_GPL(public_key_verify_signature);
deleted file mode 100644
@@ -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);
@@ -14,7 +14,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <crypto/algapi.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("RSA Public Key Algorithm");
@@ -207,9 +207,10 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
/*
* 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 int RSA_verify_signature(struct pke_request *req)
{
+ const struct public_key *key = req->pk;
+ const struct public_key_signature *sig = req->pks;
size_t tsize;
int ret;
@@ -268,11 +269,37 @@ error:
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,
+static struct crypto_alg rsa = {
+ .cra_name = "rsa",
+ .cra_driver_name = "rsa-keys",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_PKE,
+ .cra_ctxsize = 0,
+ .cra_alignmask = 0,
+ .cra_type = &crypto_pke_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .pke = {
+ .verify = RSA_verify_signature,
+ .capabilities = PKEY_CAN_VERIFY,
+ .pub_mpis = 2,
+ .sec_mpis = 3,
+ .sig_mpis = 1,
+ },
+ },
};
-EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);
+
+static int rsa_init(void)
+{
+ return crypto_register_alg(&rsa);
+}
+
+static void rsa_exit(void)
+{
+ if (crypto_unregister_alg(&rsa))
+ BUG();
+}
+
+module_init(rsa_init);
+module_exit(rsa_exit);
+MODULE_ALIAS_CRYPTO("rsa");
@@ -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 "x509_parser.h"
#include "x509-asn1.h"
#include "x509_rsakey-asn1.h"
@@ -43,6 +43,8 @@ struct x509_parse_context {
void x509_free_certificate(struct x509_certificate *cert)
{
if (cert) {
+ if (cert->pub && !IS_ERR(cert->pub->tfm))
+ crypto_free_pke(cert->pub->tfm);
public_key_destroy(cert->pub);
kfree(cert->issuer);
kfree(cert->subject);
@@ -100,6 +102,14 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
ret = PTR_ERR(kid);
goto error_decode;
}
+
+ cert->pub->tfm = crypto_alloc_pke(ctx->cert->sig.pkey_algo, 0, 0);
+ if (IS_ERR(cert->pub->tfm)) {
+ pr_err("Failed to alloc pkey algo %s\n",
+ ctx->cert->sig.pkey_algo);
+ goto error_decode;
+ }
+
cert->id = kid;
kfree(ctx);
@@ -378,8 +388,6 @@ 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;
-
/* Discard the BIT STRING metadata */
ctx->key = value + 1;
ctx->key_size = vlen - 1;
@@ -20,8 +20,8 @@
#include <keys/asymmetric-parser.h>
#include <keys/system_keyring.h>
#include <crypto/hash.h>
+#include <crypto/public_key.h>
#include "asymmetric_keys.h"
-#include "public_key.h"
#include "x509_parser.h"
static bool use_builtin_keys;
@@ -247,17 +247,13 @@ 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 ||
- !pkey_algo[cert->pub->pkey_algo] ||
- !pkey_algo[cert->sig.pkey_algo] ||
+ if (cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
!hash_algo_name[cert->sig.pkey_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", pke_alg_name(cert->pub->tfm));
pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
cert->valid_from.tm_mday, cert->valid_from.tm_hour,
@@ -266,11 +262,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1,
cert->valid_to.tm_mday, cert->valid_to.tm_hour,
cert->valid_to.tm_min, cert->valid_to.tm_sec);
- pr_devel("Cert Signature: %s + %s\n",
- pkey_algo_name[cert->sig.pkey_algo],
+ pr_devel("Cert Signature: %s + %s\n", 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 */
@@ -15,17 +15,12 @@
#define _LINUX_PUBLIC_KEY_H
#include <linux/mpi.h>
+#include <linux/crypto.h>
#include <keys/asymmetric-type.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];
-extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST];
+#define PKEY_ALGO_DSA "dsa"
+#define PKEY_ALGO_RSA "rsa"
/* asymmetric key implementation supports only up to SHA224 */
#define PKEY_HASH__LAST (HASH_ALGO_SHA224 + 1)
@@ -45,13 +40,7 @@ extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST];
* 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
- enum pkey_algo pkey_algo : 8;
+ struct crypto_pke *tfm;
enum pkey_id_type id_type : 8;
union {
MPI mpi[5];
@@ -79,9 +68,9 @@ extern void public_key_destroy(void *payload);
*/
struct public_key_signature {
u8 *digest;
+ char *pkey_algo;
u8 digest_size; /* Number of bytes in digest */
u8 nr_mpi; /* Occupancy of mpi[] */
- enum pkey_algo pkey_algo : 8;
enum hash_algo pkey_hash_algo : 8;
union {
MPI mpi[2];
@@ -95,6 +84,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);
@@ -104,4 +94,6 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring,
const struct asymmetric_key_id *kid,
bool partial);
+int public_key_verify_signature(const struct public_key *pk,
+ const struct public_key_signature *sig);
#endif /* _LINUX_PUBLIC_KEY_H */
@@ -28,7 +28,7 @@
* - Information block
*/
struct module_signature {
- u8 algo; /* Public-key crypto algorithm [enum pkey_algo] */
+ u8 algo; /* Public-key crypto algorithm */
u8 hash; /* Digest algorithm [enum hash_algo] */
u8 id_type; /* Key identifier type [enum pkey_id_type] */
u8 signer_len; /* Length of signer's name */
@@ -37,6 +37,10 @@ struct module_signature {
__be32 sig_len; /* Length of signature data */
};
+static const char *const pkey_algo_name[] = {
+ PKEY_ALGO_DSA, PKEY_ALGO_RSA
+};
+
/*
* Digest the module contents.
*/
@@ -213,7 +217,8 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
sig = mod + modlen;
/* For the moment, only support RSA and X.509 identifiers */
- if (ms.algo != PKEY_ALGO_RSA ||
+ if (ARRAY_SIZE(pkey_algo_name) - 1 < ms.algo ||
+ strcmp(pkey_algo_name[ms.algo], PKEY_ALGO_RSA) != 0 ||
ms.id_type != PKEY_ID_X509)
return -ENOPKG;
Change the existing rsa and public key code to integrate it with the new Public Key Encryption API. Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> --- Documentation/crypto/asymmetric-keys.txt | 10 +++- crypto/asymmetric_keys/Kconfig | 1 crypto/asymmetric_keys/pkcs7_parser.c | 4 +- crypto/asymmetric_keys/pkcs7_trust.c | 2 - crypto/asymmetric_keys/pkcs7_verify.c | 5 +- crypto/asymmetric_keys/public_key.c | 73 +++++++++++++++++------------ crypto/asymmetric_keys/public_key.h | 36 -------------- crypto/asymmetric_keys/rsa.c | 47 +++++++++++++++---- crypto/asymmetric_keys/x509_cert_parser.c | 14 ++++-- crypto/asymmetric_keys/x509_public_key.c | 14 ++---- include/crypto/public_key.h | 24 +++------- kernel/module_signing.c | 9 +++- 12 files changed, 124 insertions(+), 115 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html