diff options
-rw-r--r-- | crypto/asymmetric_keys/x509_cert_parser.c | 30 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_parser.h | 16 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 83 |
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 | */ |
35 | extern void x509_free_certificate(struct x509_certificate *cert); | 34 | extern void x509_free_certificate(struct x509_certificate *cert); |
36 | extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); | 35 | extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); |
36 | |||
37 | /* | ||
38 | * x509_public_key.c | ||
39 | */ | ||
40 | extern int x509_get_sig_params(struct x509_certificate *cert); | ||
41 | extern 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 | */ |
29 | static int x509_check_signature(const struct public_key *pub, | 30 | int 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); | ||
78 | error: | ||
79 | crypto_free_shash(tfm); | ||
80 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
81 | return ret; | ||
82 | } | ||
83 | EXPORT_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; | 88 | int 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 | |||
83 | error_mpi: | ||
84 | mpi_free(sig->rsa.s); | ||
85 | error: | ||
86 | kfree(sig); | ||
87 | error_no_sig: | ||
88 | crypto_free_shash(tfm); | ||
89 | |||
90 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
91 | return ret; | 101 | return ret; |
92 | } | 102 | } |
103 | EXPORT_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", |