aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-08-30 11:18:02 -0400
committerDavid Howells <dhowells@redhat.com>2013-09-25 12:17:00 -0400
commitb426beb6eeb0c81aeaa419f7444064abc9cb04ae (patch)
treee704ed37a19ac0d9f572a8a45f4cf6228dd3ae5f /crypto
parent57be4a784bf58eb41784aa3431165b455cf7e9c6 (diff)
X.509: Embed public_key_signature struct and create filler function
Embed a public_key_signature struct in struct x509_certificate, eliminating now unnecessary fields, and split x509_check_signature() to create a filler function for it that attaches a digest of the signed data and an MPI that represents the signature data. x509_free_certificate() is then modified to deal with these. Whilst we're at it, export both x509_check_signature() and the new x509_get_sig_params(). Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Kees Cook <keescook@chromium.org> Reviewed-by: Josh Boyer <jwboyer@redhat.com>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c30
-rw-r--r--crypto/asymmetric_keys/x509_parser.h16
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c83
3 files changed, 74 insertions, 55 deletions
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 8cc253d2dc92..144201ccba0c 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -47,6 +47,8 @@ void x509_free_certificate(struct x509_certificate *cert)
47 kfree(cert->subject); 47 kfree(cert->subject);
48 kfree(cert->fingerprint); 48 kfree(cert->fingerprint);
49 kfree(cert->authority); 49 kfree(cert->authority);
50 kfree(cert->sig.digest);
51 mpi_free(cert->sig.rsa.s);
50 kfree(cert); 52 kfree(cert);
51 } 53 }
52} 54}
@@ -152,33 +154,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
152 return -ENOPKG; /* Unsupported combination */ 154 return -ENOPKG; /* Unsupported combination */
153 155
154 case OID_md4WithRSAEncryption: 156 case OID_md4WithRSAEncryption:
155 ctx->cert->sig_hash_algo = PKEY_HASH_MD5; 157 ctx->cert->sig.pkey_hash_algo = PKEY_HASH_MD5;
156 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 158 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
157 break; 159 break;
158 160
159 case OID_sha1WithRSAEncryption: 161 case OID_sha1WithRSAEncryption:
160 ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; 162 ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA1;
161 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 163 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
162 break; 164 break;
163 165
164 case OID_sha256WithRSAEncryption: 166 case OID_sha256WithRSAEncryption:
165 ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; 167 ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA256;
166 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 168 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
167 break; 169 break;
168 170
169 case OID_sha384WithRSAEncryption: 171 case OID_sha384WithRSAEncryption:
170 ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; 172 ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA384;
171 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 173 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
172 break; 174 break;
173 175
174 case OID_sha512WithRSAEncryption: 176 case OID_sha512WithRSAEncryption:
175 ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; 177 ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA512;
176 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 178 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
177 break; 179 break;
178 180
179 case OID_sha224WithRSAEncryption: 181 case OID_sha224WithRSAEncryption:
180 ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; 182 ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA224;
181 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 183 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
182 break; 184 break;
183 } 185 }
184 186
@@ -203,8 +205,8 @@ int x509_note_signature(void *context, size_t hdrlen,
203 return -EINVAL; 205 return -EINVAL;
204 } 206 }
205 207
206 ctx->cert->sig = value; 208 ctx->cert->raw_sig = value;
207 ctx->cert->sig_size = vlen; 209 ctx->cert->raw_sig_size = vlen;
208 return 0; 210 return 0;
209} 211}
210 212
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index 2d0118214770..87d9cc26f630 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -21,12 +21,11 @@ struct x509_certificate {
21 char *authority; /* Authority key fingerprint as hex */ 21 char *authority; /* Authority key fingerprint as hex */
22 struct tm valid_from; 22 struct tm valid_from;
23 struct tm valid_to; 23 struct tm valid_to;
24 enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */
25 enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */
26 const void *tbs; /* Signed data */ 24 const void *tbs; /* Signed data */
27 size_t tbs_size; /* Size of signed data */ 25 unsigned tbs_size; /* Size of signed data */
28 const void *sig; /* Signature data */ 26 unsigned raw_sig_size; /* Size of sigature */
29 size_t sig_size; /* Size of sigature */ 27 const void *raw_sig; /* Signature data */
28 struct public_key_signature sig; /* Signature parameters */
30}; 29};
31 30
32/* 31/*
@@ -34,3 +33,10 @@ struct x509_certificate {
34 */ 33 */
35extern void x509_free_certificate(struct x509_certificate *cert); 34extern void x509_free_certificate(struct x509_certificate *cert);
36extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); 35extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen);
36
37/*
38 * x509_public_key.c
39 */
40extern int x509_get_sig_params(struct x509_certificate *cert);
41extern int x509_check_signature(const struct public_key *pub,
42 struct x509_certificate *cert);
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 8cb2f7075479..b7c81d8df08b 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -24,72 +24,83 @@
24#include "x509_parser.h" 24#include "x509_parser.h"
25 25
26/* 26/*
27 * Check the signature on a certificate using the provided public key 27 * Set up the signature parameters in an X.509 certificate. This involves
28 * digesting the signed data and extracting the signature.
28 */ 29 */
29static int x509_check_signature(const struct public_key *pub, 30int x509_get_sig_params(struct x509_certificate *cert)
30 const struct x509_certificate *cert)
31{ 31{
32 struct public_key_signature *sig;
33 struct crypto_shash *tfm; 32 struct crypto_shash *tfm;
34 struct shash_desc *desc; 33 struct shash_desc *desc;
35 size_t digest_size, desc_size; 34 size_t digest_size, desc_size;
35 void *digest;
36 int ret; 36 int ret;
37 37
38 pr_devel("==>%s()\n", __func__); 38 pr_devel("==>%s()\n", __func__);
39 39
40 if (cert->sig.rsa.s)
41 return 0;
42
43 cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size);
44 if (!cert->sig.rsa.s)
45 return -ENOMEM;
46 cert->sig.nr_mpi = 1;
47
40 /* Allocate the hashing algorithm we're going to need and find out how 48 /* Allocate the hashing algorithm we're going to need and find out how
41 * big the hash operational data will be. 49 * big the hash operational data will be.
42 */ 50 */
43 tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0); 51 tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
44 if (IS_ERR(tfm)) 52 if (IS_ERR(tfm))
45 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 53 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
46 54
47 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 55 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
48 digest_size = crypto_shash_digestsize(tfm); 56 digest_size = crypto_shash_digestsize(tfm);
49 57
50 /* We allocate the hash operational data storage on the end of our 58 /* We allocate the hash operational data storage on the end of the
51 * context data. 59 * digest storage space.
52 */ 60 */
53 ret = -ENOMEM; 61 ret = -ENOMEM;
54 sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); 62 digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
55 if (!sig) 63 if (!digest)
56 goto error_no_sig; 64 goto error;
57 65
58 sig->pkey_hash_algo = cert->sig_hash_algo; 66 cert->sig.digest = digest;
59 sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; 67 cert->sig.digest_size = digest_size;
60 sig->digest_size = digest_size;
61 68
62 desc = (void *)sig + sizeof(*sig); 69 desc = digest + digest_size;
63 desc->tfm = tfm; 70 desc->tfm = tfm;
64 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 71 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
65 72
66 ret = crypto_shash_init(desc); 73 ret = crypto_shash_init(desc);
67 if (ret < 0) 74 if (ret < 0)
68 goto error; 75 goto error;
76 might_sleep();
77 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest);
78error:
79 crypto_free_shash(tfm);
80 pr_devel("<==%s() = %d\n", __func__, ret);
81 return ret;
82}
83EXPORT_SYMBOL_GPL(x509_get_sig_params);
69 84
70 ret = -ENOMEM; 85/*
71 sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); 86 * Check the signature on a certificate using the provided public key
72 if (!sig->rsa.s) 87 */
73 goto error; 88int x509_check_signature(const struct public_key *pub,
89 struct x509_certificate *cert)
90{
91 int ret;
74 92
75 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); 93 pr_devel("==>%s()\n", __func__);
76 if (ret < 0)
77 goto error_mpi;
78 94
79 ret = public_key_verify_signature(pub, sig); 95 ret = x509_get_sig_params(cert);
96 if (ret < 0)
97 return ret;
80 98
99 ret = public_key_verify_signature(pub, &cert->sig);
81 pr_debug("Cert Verification: %d\n", ret); 100 pr_debug("Cert Verification: %d\n", ret);
82
83error_mpi:
84 mpi_free(sig->rsa.s);
85error:
86 kfree(sig);
87error_no_sig:
88 crypto_free_shash(tfm);
89
90 pr_devel("<==%s() = %d\n", __func__, ret);
91 return ret; 101 return ret;
92} 102}
103EXPORT_SYMBOL_GPL(x509_check_signature);
93 104
94/* 105/*
95 * Attempt to parse a data blob for a key as an X509 certificate. 106 * Attempt to parse a data blob for a key as an X509 certificate.
@@ -118,8 +129,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
118 cert->valid_to.tm_mday, cert->valid_to.tm_hour, 129 cert->valid_to.tm_mday, cert->valid_to.tm_hour,
119 cert->valid_to.tm_min, cert->valid_to.tm_sec); 130 cert->valid_to.tm_min, cert->valid_to.tm_sec);
120 pr_devel("Cert Signature: %s + %s\n", 131 pr_devel("Cert Signature: %s + %s\n",
121 pkey_algo_name[cert->sig_pkey_algo], 132 pkey_algo_name[cert->sig.pkey_algo],
122 pkey_hash_algo_name[cert->sig_hash_algo]); 133 pkey_hash_algo_name[cert->sig.pkey_hash_algo]);
123 134
124 if (!cert->fingerprint || !cert->authority) { 135 if (!cert->fingerprint || !cert->authority) {
125 pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", 136 pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",