diff options
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/Kconfig | 4 | ||||
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_type.c | 1 | ||||
-rw-r--r-- | crypto/asymmetric_keys/public_key.c | 66 | ||||
-rw-r--r-- | crypto/asymmetric_keys/public_key.h | 6 | ||||
-rw-r--r-- | crypto/asymmetric_keys/rsa.c | 19 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_cert_parser.c | 35 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_parser.h | 18 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 157 |
8 files changed, 144 insertions, 162 deletions
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 03a6eb9..6d2c2ea 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -12,8 +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. If signature generation and/or verification are to be used, @@ -22,8 +20,8 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE config PUBLIC_KEY_ALGO_RSA tristate "RSA public-key algorithm" + depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE select MPILIB_EXTRA - select MPILIB help This option enables support for the RSA algorithm (PKCS#1, RFC3447). diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index b77eb53..cf80765 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -209,7 +209,6 @@ struct key_type key_type_asymmetric = { .match = asymmetric_key_match, .destroy = asymmetric_key_destroy, .describe = asymmetric_key_describe, - .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE, }; EXPORT_SYMBOL_GPL(key_type_asymmetric); diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 97eb001..cb2e291 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -22,25 +22,29 @@ MODULE_LICENSE("GPL"); -const char *const pkey_algo_name[PKEY_ALGO__LAST] = { +const char *const pkey_algo[PKEY_ALGO__LAST] = { [PKEY_ALGO_DSA] = "DSA", [PKEY_ALGO_RSA] = "RSA", }; -EXPORT_SYMBOL_GPL(pkey_algo_name); +EXPORT_SYMBOL_GPL(pkey_algo); -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 +const char *const pkey_hash_algo[PKEY_HASH__LAST] = { + [PKEY_HASH_MD4] = "md4", + [PKEY_HASH_MD5] = "md5", + [PKEY_HASH_SHA1] = "sha1", + [PKEY_HASH_RIPE_MD_160] = "rmd160", + [PKEY_HASH_SHA256] = "sha256", + [PKEY_HASH_SHA384] = "sha384", + [PKEY_HASH_SHA512] = "sha512", + [PKEY_HASH_SHA224] = "sha224", }; -EXPORT_SYMBOL_GPL(pkey_algo); +EXPORT_SYMBOL_GPL(pkey_hash_algo); -const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { +const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { [PKEY_ID_PGP] = "PGP", [PKEY_ID_X509] = "X509", }; -EXPORT_SYMBOL_GPL(pkey_id_type_name); +EXPORT_SYMBOL_GPL(pkey_id_type); /* * Provide a part of a description of the key for /proc/keys. @@ -52,7 +56,7 @@ 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[key->id_type], key->algo->name); } /* @@ -74,45 +78,21 @@ EXPORT_SYMBOL_GPL(public_key_destroy); /* * Verify a signature using a public key. */ -int public_key_verify_signature(const struct public_key *pk, - const struct public_key_signature *sig) +static int public_key_verify_signature(const struct key *key, + 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(!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; - } + const struct public_key *pk = key->payload.data; - if (!algo->verify_signature) + if (!pk->algo->verify_signature) return -ENOTSUPP; - if (sig->nr_mpi != algo->n_sig_mpi) { + if (sig->nr_mpi != pk->algo->n_sig_mpi) { pr_debug("Signature has %u MPI not %u\n", - sig->nr_mpi, algo->n_sig_mpi); + sig->nr_mpi, pk->algo->n_sig_mpi); return -EINVAL; } - return algo->verify_signature(pk, sig); -} -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; - return public_key_verify_signature(pk, sig); + return pk->algo->verify_signature(pk, sig); } /* @@ -123,6 +103,6 @@ struct asymmetric_key_subtype public_key_subtype = { .name = "public_key", .describe = public_key_describe, .destroy = public_key_destroy, - .verify_signature = public_key_verify_signature_2, + .verify_signature = public_key_verify_signature, }; EXPORT_SYMBOL_GPL(public_key_subtype); diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h index 5c37a22..5e5e356 100644 --- a/crypto/asymmetric_keys/public_key.h +++ b/crypto/asymmetric_keys/public_key.h @@ -28,9 +28,3 @@ struct public_key_algorithm { }; 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 459cf97..4a6a069 100644 --- a/crypto/asymmetric_keys/rsa.c +++ b/crypto/asymmetric_keys/rsa.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> -#include <crypto/algapi.h> #include "public_key.h" MODULE_LICENSE("GPL"); @@ -74,13 +73,13 @@ static const struct { 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), + [PKEY_HASH_MD5] = _(MD5), + [PKEY_HASH_SHA1] = _(SHA1), + [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), + [PKEY_HASH_SHA256] = _(SHA256), + [PKEY_HASH_SHA384] = _(SHA384), + [PKEY_HASH_SHA512] = _(SHA512), + [PKEY_HASH_SHA224] = _(SHA224), #undef _ }; @@ -190,12 +189,12 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, } } - if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) { + if (memcmp(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) { + if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) { kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); return -EKEYREJECTED; } diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 2989316..facbf26 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -47,8 +47,6 @@ void x509_free_certificate(struct x509_certificate *cert) kfree(cert->subject); kfree(cert->fingerprint); kfree(cert->authority); - kfree(cert->sig.digest); - mpi_free(cert->sig.rsa.s); kfree(cert); } } @@ -154,33 +152,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 = PKEY_HASH_MD5; + ctx->cert->sig_pkey_algo = 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 = PKEY_HASH_SHA1; + ctx->cert->sig_pkey_algo = 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 = PKEY_HASH_SHA256; + ctx->cert->sig_pkey_algo = 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 = PKEY_HASH_SHA384; + ctx->cert->sig_pkey_algo = 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 = PKEY_HASH_SHA512; + ctx->cert->sig_pkey_algo = 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 = PKEY_HASH_SHA224; + ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; break; } @@ -205,8 +203,8 @@ int x509_note_signature(void *context, size_t hdrlen, return -EINVAL; } - ctx->cert->raw_sig = value; - ctx->cert->raw_sig_size = vlen; + ctx->cert->sig = value; + ctx->cert->sig_size = vlen; return 0; } @@ -345,9 +343,8 @@ 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 */ + /* There seems to be an extraneous 0 byte on the front of the data */ + ctx->cert->pkey_algo = PKEY_ALGO_RSA; ctx->key = value + 1; ctx->key_size = vlen - 1; return 0; diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 87d9cc2..f86dc5f 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -9,7 +9,6 @@ * 2 of the Licence, or (at your option) any later version. */ -#include <linux/time.h> #include <crypto/public_key.h> struct x509_certificate { @@ -21,11 +20,13 @@ struct x509_certificate { char *authority; /* Authority key fingerprint as hex */ struct tm valid_from; struct tm valid_to; + enum pkey_algo pkey_algo : 8; /* Public key algorithm */ + enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ + enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ const void *tbs; /* Signed data */ - unsigned tbs_size; /* Size of signed data */ - unsigned raw_sig_size; /* Size of sigature */ - const void *raw_sig; /* Signature data */ - struct public_key_signature sig; /* Signature parameters */ + size_t tbs_size; /* Size of signed data */ + const void *sig; /* Signature data */ + size_t sig_size; /* Size of sigature */ }; /* @@ -33,10 +34,3 @@ struct x509_certificate { */ extern void x509_free_certificate(struct x509_certificate *cert); extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); - -/* - * x509_public_key.c - */ -extern int x509_get_sig_params(struct x509_certificate *cert); -extern int x509_check_signature(const struct public_key *pub, - struct x509_certificate *cert); diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 382ef0d..06007f0 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -23,84 +23,82 @@ #include "public_key.h" #include "x509_parser.h" +static const +struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { + [PKEY_ALGO_DSA] = NULL, +#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ + defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) + [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, +#endif +}; + /* - * Set up the signature parameters in an X.509 certificate. This involves - * digesting the signed data and extracting the signature. + * Check the signature on a certificate using the provided public key */ -int x509_get_sig_params(struct x509_certificate *cert) +static int x509_check_signature(const struct public_key *pub, + const struct x509_certificate *cert) { + struct public_key_signature *sig; struct crypto_shash *tfm; struct shash_desc *desc; size_t digest_size, desc_size; - void *digest; int ret; pr_devel("==>%s()\n", __func__); - - if (cert->sig.rsa.s) - return 0; - - cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size); - if (!cert->sig.rsa.s) - return -ENOMEM; - cert->sig.nr_mpi = 1; - + /* 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(pkey_hash_algo[cert->sig_hash_algo], 0, 0); if (IS_ERR(tfm)) return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); digest_size = crypto_shash_digestsize(tfm); - /* We allocate the hash operational data storage on the end of the - * digest storage space. + /* We allocate the hash operational data storage on the end of our + * context data. */ ret = -ENOMEM; - digest = kzalloc(digest_size + desc_size, GFP_KERNEL); - if (!digest) - goto error; + sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); + if (!sig) + goto error_no_sig; - cert->sig.digest = digest; - cert->sig.digest_size = digest_size; + sig->pkey_hash_algo = cert->sig_hash_algo; + sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; + sig->digest_size = digest_size; - desc = digest + digest_size; - desc->tfm = tfm; - desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + desc = (void *)sig + sizeof(*sig); + desc->tfm = tfm; + desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ret = crypto_shash_init(desc); if (ret < 0) goto error; - might_sleep(); - ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); -error: - crypto_free_shash(tfm); - pr_devel("<==%s() = %d\n", __func__, ret); - return ret; -} -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, - struct x509_certificate *cert) -{ - int ret; - - pr_devel("==>%s()\n", __func__); + ret = -ENOMEM; + sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); + if (!sig->rsa.s) + goto error; - ret = x509_get_sig_params(cert); + ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); if (ret < 0) - return ret; + goto error_mpi; + + ret = pub->algo->verify_signature(pub, sig); - ret = public_key_verify_signature(pub, &cert->sig); pr_debug("Cert Verification: %d\n", ret); + +error_mpi: + mpi_free(sig->rsa.s); +error: + kfree(sig); +error_no_sig: + crypto_free_shash(tfm); + + pr_devel("<==%s() = %d\n", __func__, ret); return ret; } -EXPORT_SYMBOL_GPL(x509_check_signature); /* * Attempt to parse a data blob for a key as an X509 certificate. @@ -108,6 +106,7 @@ EXPORT_SYMBOL_GPL(x509_check_signature); static int x509_key_preparse(struct key_preparsed_payload *prep) { struct x509_certificate *cert; + struct tm now; size_t srlen, sulen; char *desc = NULL; int ret; @@ -118,18 +117,7 @@ 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] || - !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", pkey_algo[cert->pkey_algo]); 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, @@ -139,22 +127,58 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) 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], - hash_algo_name[cert->sig.pkey_hash_algo]); + pkey_algo[cert->sig_pkey_algo], + pkey_hash_algo[cert->sig_hash_algo]); - if (!cert->fingerprint) { - pr_warn("Cert for '%s' must have a SubjKeyId extension\n", + if (!cert->fingerprint || !cert->authority) { + pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", cert->subject); ret = -EKEYREJECTED; goto error_free_cert; } - cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; + time_to_tm(CURRENT_TIME.tv_sec, 0, &now); + pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", + now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, + now.tm_hour, now.tm_min, now.tm_sec); + if (now.tm_year < cert->valid_from.tm_year || + (now.tm_year == cert->valid_from.tm_year && + (now.tm_mon < cert->valid_from.tm_mon || + (now.tm_mon == cert->valid_from.tm_mon && + (now.tm_mday < cert->valid_from.tm_mday || + (now.tm_mday == cert->valid_from.tm_mday && + (now.tm_hour < cert->valid_from.tm_hour || + (now.tm_hour == cert->valid_from.tm_hour && + (now.tm_min < cert->valid_from.tm_min || + (now.tm_min == cert->valid_from.tm_min && + (now.tm_sec < cert->valid_from.tm_sec + ))))))))))) { + pr_warn("Cert %s is not yet valid\n", cert->fingerprint); + ret = -EKEYREJECTED; + goto error_free_cert; + } + if (now.tm_year > cert->valid_to.tm_year || + (now.tm_year == cert->valid_to.tm_year && + (now.tm_mon > cert->valid_to.tm_mon || + (now.tm_mon == cert->valid_to.tm_mon && + (now.tm_mday > cert->valid_to.tm_mday || + (now.tm_mday == cert->valid_to.tm_mday && + (now.tm_hour > cert->valid_to.tm_hour || + (now.tm_hour == cert->valid_to.tm_hour && + (now.tm_min > cert->valid_to.tm_min || + (now.tm_min == cert->valid_to.tm_min && + (now.tm_sec > cert->valid_to.tm_sec + ))))))))))) { + pr_warn("Cert %s has expired\n", cert->fingerprint); + ret = -EKEYEXPIRED; + goto error_free_cert; + } + + cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; cert->pub->id_type = PKEY_ID_X509; - /* Check the signature on the key if it appears to be self-signed */ - if (!cert->authority || - strcmp(cert->fingerprint, cert->authority) == 0) { + /* Check the signature on the key */ + if (strcmp(cert->fingerprint, cert->authority) == 0) { ret = x509_check_signature(cert->pub, cert); if (ret < 0) goto error_free_cert; @@ -213,6 +237,3 @@ static void __exit x509_key_exit(void) module_init(x509_key_init); module_exit(x509_key_exit); - -MODULE_DESCRIPTION("X.509 certificate parser"); -MODULE_LICENSE("GPL"); |