From db6c43bd2132dc2dd63d73a6d1ed601cffd0ae06 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 2 Feb 2016 10:08:53 -0800 Subject: crypto: KEYS: convert public key and digsig asym to the akcipher api This patch converts the module verification code to the new akcipher API. Signed-off-by: Tadeusz Struk Acked-by: Herbert Xu Signed-off-by: David Howells --- 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 - 11 files changed, 124 insertions(+), 271 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 (limited to 'crypto') 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 #include #include -#include "public_key.h" +#include #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 #include #include -#include "public_key.h" +#include #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 #include #include -#include "public_key.h" +#include #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 #include #include -#include "public_key.h" +#include 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 - -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 -#include #include +#include +#include #include -#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 #include #include -#include "public_key.h" +#include #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 #include #include -#include -#include -#include #include #include #include #include #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 - } -- cgit v1.2.1 From 06aae592425701851e02bb850cb9f4997f0ae163 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 27 Feb 2016 12:45:26 +0000 Subject: PKCS#7: fix unitialized boolean 'want' The boolean want is not initialized and hence garbage. The default should be false (later it is only set to true on tne sinfo->authattrs check). Found with static analysis using CoverityScan Signed-off-by: Colin Ian King Signed-off-by: David Howells --- crypto/asymmetric_keys/pkcs7_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 3ef62dac9771..cbbd03fd94f8 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(pkcs7_free_message); static int pkcs7_check_authattrs(struct pkcs7_message *msg) { struct pkcs7_signed_info *sinfo; - bool want; + bool want = false; sinfo = msg->signed_infos; if (sinfo->authattrs) { -- cgit v1.2.1 From ac4cbedfdf55455b4c447f17f0fa027dbf02b2a6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 24 Feb 2016 14:37:15 +0000 Subject: X.509: Fix leap year handling again There are still a couple of minor issues in the X.509 leap year handling: (1) To avoid doing a modulus-by-400 in addition to a modulus-by-100 when determining whether the year is a leap year or not, I divided the year by 100 after doing the modulus-by-100, thereby letting the compiler do one instruction for both, and then did a modulus-by-4. Unfortunately, I then passed the now-modified year value to mktime64() to construct a time value. Since this isn't a fast path and since mktime64() does a bunch of divisions, just condense down to "% 400". It's also easier to read. (2) The default month length for any February where the year doesn't divide by four exactly is obtained from the month_length[] array where the value is 29, not 28. This is fixed by altering the table. Reported-by: Rudolf Polzer Signed-off-by: David Howells Acked-by: David Woodhouse Acked-by: Arnd Bergmann cc: stable@vger.kernel.org --- crypto/asymmetric_keys/x509_cert_parser.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 7502029e3385..794cf0eac2c9 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -471,7 +471,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen, unsigned char tag, const unsigned char *value, size_t vlen) { - static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30, + static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const unsigned char *p = value; unsigned year, mon, day, hour, min, sec, mon_len; @@ -517,9 +517,9 @@ int x509_decode_time(time64_t *_t, size_t hdrlen, if (year % 4 == 0) { mon_len = 29; if (year % 100 == 0) { - year /= 100; - if (year % 4 != 0) - mon_len = 28; + mon_len = 28; + if (year % 400 == 0) + mon_len = 29; } } } -- cgit v1.2.1 From da02559c9f864c8d62f524c1e0b64173711a16ab Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 24 Feb 2016 14:37:53 +0000 Subject: X.509: Support leap seconds The format of ASN.1 GeneralizedTime seems to be specified by ISO 8601 [X.680 46.3] and this apparently supports leap seconds (ie. the seconds field is 60). It's not entirely clear that ASN.1 expects it, but we can relax the seconds check slightly for GeneralizedTime. This results in us passing a time with sec as 60 to mktime64(), which handles it as being a duplicate of the 0th second of the next minute. We can't really do otherwise without giving the kernel much greater knowledge of where all the leap seconds are. Unfortunately, this would require change the mapping of the kernel's current-time-in-seconds. UTCTime, however, only supports a seconds value in the range 00-59, but for the sake of simplicity allow this with UTCTime also. Without this patch, certain X.509 certificates will be rejected, potentially making a kernel unbootable. Reported-by: Rudolf Polzer Signed-off-by: David Howells Acked-by: Arnd Bergmann cc: David Woodhouse cc: John Stultz --- crypto/asymmetric_keys/x509_cert_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 794cf0eac2c9..99ff5382b627 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -527,7 +527,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen, if (day < 1 || day > mon_len || hour > 23 || min > 59 || - sec > 59) + sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */ goto invalid_time; *_t = mktime64(year, mon, day, hour, min, sec); -- cgit v1.2.1 From 7650cb80e4e90b0fae7854b6008a46d24360515f Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 24 Feb 2016 14:37:54 +0000 Subject: X.509: Handle midnight alternative notation in GeneralizedTime The ASN.1 GeneralizedTime object carries an ISO 8601 format date and time. The time is permitted to show midnight as 00:00 or 24:00 (the latter being equivalent of 00:00 of the following day). The permitted value is checked in x509_decode_time() but the actual handling is left to mktime64(). Without this patch, certain X.509 certificates will be rejected and could lead to an unbootable kernel. Note that with this patch we also permit any 24:mm:ss time and extend this to UTCTime, which whilst not strictly correct don't permit much leeway in fiddling date strings. Reported-by: Rudolf Polzer Signed-off-by: David Howells Acked-by: Arnd Bergmann cc: David Woodhouse cc: John Stultz --- crypto/asymmetric_keys/x509_cert_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 99ff5382b627..c02c200a7136 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -525,7 +525,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen, } if (day < 1 || day > mon_len || - hour > 23 || + hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */ min > 59 || sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */ goto invalid_time; -- cgit v1.2.1 From a49de377e051eac5bc50a3b838614a05671da4e7 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Thu, 3 Mar 2016 21:49:26 +0000 Subject: crypto: Add hash param to pkcs1pad 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 Signed-off-by: David Howells Acked-by: Herbert Xu --- crypto/rsa-pkcs1pad.c | 182 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 156 insertions(+), 26 deletions(-) (limited to 'crypto') diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c index 50f5c97e1087..1cea67d43e1d 100644 --- a/crypto/rsa-pkcs1pad.c +++ b/crypto/rsa-pkcs1pad.c @@ -18,12 +18,89 @@ #include #include +/* + * 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: -- cgit v1.2.1 From d43de6c780a84def056afaf4fb3e66bdaa1efc00 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 3 Mar 2016 21:49:27 +0000 Subject: akcipher: Move the RSA DER encoding check to the crypto layer Move the RSA EMSA-PKCS1-v1_5 encoding from the asymmetric-key public_key subtype to the rsa crypto module's pkcs1pad template. This means that the public_key subtype no longer has any dependencies on public key type. To make this work, the following changes have been made: (1) The rsa pkcs1pad template is now used for RSA keys. This strips off the padding and returns just the message hash. (2) In a previous patch, the pkcs1pad template gained an optional second parameter that, if given, specifies the hash used. We now give this, and pkcs1pad checks the encoded message E(M) for the EMSA-PKCS1-v1_5 encoding and verifies that the correct digest OID is present. (3) 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. (4) 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 padding template? Should there be multiple padding templates registered that share most of the code? Signed-off-by: David Howells Signed-off-by: Tadeusz Struk Acked-by: Herbert Xu --- crypto/asymmetric_keys/Kconfig | 7 -- crypto/asymmetric_keys/Makefile | 1 - crypto/asymmetric_keys/public_key.c | 104 +++++++++++++++-- crypto/asymmetric_keys/rsa.c | 224 ------------------------------------ 4 files changed, 93 insertions(+), 243 deletions(-) delete mode 100644 crypto/asymmetric_keys/rsa.c (limited to 'crypto') 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..27ebc2f44394 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -17,8 +17,10 @@ #include #include #include +#include #include #include +#include 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,110 @@ 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; + const char *alg_name; + char alg_name_buf[CRYPTO_MAX_ALG_NAME]; + void *output; + unsigned int outlen; + 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; + alg_name = pkey_algo_name[sig->pkey_algo]; + if (sig->pkey_algo == PKEY_ALGO_RSA) { + /* The data wangled by the RSA algorithm is typically padded + * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 + * sec 8.2]. + */ + if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME, + "pkcs1pad(rsa,%s)", + hash_algo_name[sig->pkey_hash_algo] + ) >= CRYPTO_MAX_ALG_NAME) + return -EINVAL; + alg_name = alg_name_buf; + } + + tfm = crypto_alloc_akcipher(alg_name, 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; + + 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, 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, + public_key_verify_done, &compl); + + /* Perform the verification calculation. This doesn't actually do the + * verification, but rather calculates the hash expected by the + * signature and returns that to us. + */ + ret = crypto_akcipher_verify(req); + if (ret == -EINPROGRESS) { + wait_for_completion(&compl.completion); + ret = compl.err; + } + if (ret < 0) + goto out_free_output; - if (!alg_verify[pkey->pkey_algo]) - return -ENOPKG; + /* Do the actual verification step. */ + if (req->dst_len != sig->digest_size || + memcmp(sig->digest, output, sig->digest_size) != 0) + ret = -EKEYREJECTED; - return alg_verify[pkey->pkey_algo](pkey, sig); +out_free_output: + kfree(output); +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 -#include -#include -#include -#include - -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); -- cgit v1.2.1 From 4e8ae72a75aae285ec5b93518b9680da198afd0d Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 3 Mar 2016 21:49:27 +0000 Subject: X.509: Make algo identifiers text instead of enum Make the identifier public key and digest algorithm fields text instead of enum. Signed-off-by: David Howells Acked-by: Herbert Xu --- 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 | 24 ++++-------------------- 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 ++++++++--------- 8 files changed, 46 insertions(+), 67 deletions(-) (limited to 'crypto') 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 cbbd03fd94f8..40de03f49ff8 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 27ebc2f44394..0f8b264b3961 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); } /* @@ -103,15 +88,14 @@ int public_key_verify_signature(const struct public_key *pkey, BUG_ON(!sig->digest); BUG_ON(!sig->s); - alg_name = pkey_algo_name[sig->pkey_algo]; - if (sig->pkey_algo == PKEY_ALGO_RSA) { + alg_name = sig->pkey_algo; + if (strcmp(sig->pkey_algo, "rsa") == 0) { /* The data wangled by the RSA algorithm is typically padded * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 * sec 8.2]. */ if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME, - "pkcs1pad(rsa,%s)", - hash_algo_name[sig->pkey_hash_algo] + "pkcs1pad(rsa,%s)", sig->hash_algo ) >= CRYPTO_MAX_ALG_NAME) return -EINVAL; alg_name = alg_name_buf; 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 c02c200a7136..4a29bac70060 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) || -- cgit v1.2.1