diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-08 01:00:49 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-08 19:58:35 (GMT) |
commit | 47d2261a3fa71cde24263559a4219a25e50d8c89 (patch) | |
tree | 28774d5b330ccf1b777a3af222d8356918328013 /crypto/asymmetric_keys/x509_public_key.c | |
parent | fb7f27080adc65cd5f341bdf56a1d0c14f316c1b (diff) | |
parent | 5fb9d37f27351e42f002e372074249f92cbdf815 (diff) | |
download | linux-fsl-qoriq-47d2261a3fa71cde24263559a4219a25e50d8c89.tar.xz |
Merge branch 'merge' into sdk-v1.6.x
This reverts v3.13-rc3+ (78fd82238d0e5716) to v3.12, except for
commits which I noticed which appear relevant to the SDK.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Conflicts:
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/e500.c
arch/powerpc/kvm/e500mc.c
arch/powerpc/sysdev/fsl_soc.h
drivers/Kconfig
drivers/cpufreq/ppc-corenet-cpufreq.c
drivers/dma/fsldma.c
drivers/dma/s3c24xx-dma.c
drivers/misc/Makefile
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mtd/devices/m25p80.c
drivers/net/ethernet/freescale/gianfar.h
drivers/platform/Kconfig
drivers/platform/Makefile
drivers/spi/spi-fsl-espi.c
include/crypto/algapi.h
include/linux/netdev_features.h
include/linux/skbuff.h
include/net/ip.h
net/core/ethtool.c
Diffstat (limited to 'crypto/asymmetric_keys/x509_public_key.c')
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 157 |
1 files changed, 89 insertions, 68 deletions
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"); |