diff options
Diffstat (limited to 'crypto/asymmetric_keys/x509_public_key.c')
| -rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 157 | 
1 files changed, 68 insertions, 89 deletions
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 06007f0e880..382ef0d2ff2 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -23,82 +23,84 @@  #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 -}; -  /* - * Check the signature on a certificate using the provided public key + * Set up the signature parameters in an X.509 certificate.  This involves + * digesting the signed data and extracting the signature.   */ -static int x509_check_signature(const struct public_key *pub, -				const struct x509_certificate *cert) +int x509_get_sig_params(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(pkey_hash_algo[cert->sig_hash_algo], 0, 0); +	tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_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 our -	 * context data. +	/* We allocate the hash operational data storage on the end of the +	 * digest storage space.  	 */  	ret = -ENOMEM; -	sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); -	if (!sig) -		goto error_no_sig; +	digest = kzalloc(digest_size + desc_size, GFP_KERNEL); +	if (!digest) +		goto error; -	sig->pkey_hash_algo	= cert->sig_hash_algo; -	sig->digest		= (u8 *)sig + sizeof(*sig) + desc_size; -	sig->digest_size	= digest_size; +	cert->sig.digest = digest; +	cert->sig.digest_size = digest_size; -	desc = (void *)sig + sizeof(*sig); -	desc->tfm	= tfm; -	desc->flags	= CRYPTO_TFM_REQ_MAY_SLEEP; +	desc = digest + digest_size; +	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); -	ret = -ENOMEM; -	sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); -	if (!sig->rsa.s) -		goto error; +/* + * 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; -	ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); -	if (ret < 0) -		goto error_mpi; +	pr_devel("==>%s()\n", __func__); -	ret = pub->algo->verify_signature(pub, sig); +	ret = x509_get_sig_params(cert); +	if (ret < 0) +		return ret; +	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. @@ -106,7 +108,6 @@ error_no_sig:  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; @@ -117,7 +118,18 @@ 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); -	pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); + +	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 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, @@ -127,58 +139,22 @@ 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[cert->sig_pkey_algo], -		 pkey_hash_algo[cert->sig_hash_algo]); +		 pkey_algo_name[cert->sig.pkey_algo], +		 hash_algo_name[cert->sig.pkey_hash_algo]); -	if (!cert->fingerprint || !cert->authority) { -		pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", +	if (!cert->fingerprint) { +		pr_warn("Cert for '%s' must have a SubjKeyId extension\n",  			cert->subject);  		ret = -EKEYREJECTED;  		goto error_free_cert;  	} -	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->algo = pkey_algo[cert->pub->pkey_algo];  	cert->pub->id_type = PKEY_ID_X509; -	/* Check the signature on the key */ -	if (strcmp(cert->fingerprint, cert->authority) == 0) { +	/* Check the signature on the key if it appears to be self-signed */ +	if (!cert->authority || +	    strcmp(cert->fingerprint, cert->authority) == 0) {  		ret = x509_check_signature(cert->pub, cert);  		if (ret < 0)  			goto error_free_cert; @@ -237,3 +213,6 @@ 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");  | 
