aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.h1
-rw-r--r--crypto/asymmetric_keys/pkcs7_trust.c29
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c46
-rw-r--r--crypto/asymmetric_keys/x509_parser.h1
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c13
5 files changed, 74 insertions, 16 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h
index 91949f92bc72..efc7dc9b8f9c 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.h
+++ b/crypto/asymmetric_keys/pkcs7_parser.h
@@ -23,6 +23,7 @@ struct pkcs7_signed_info {
23 struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ 23 struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
24 unsigned index; 24 unsigned index;
25 bool trusted; 25 bool trusted;
26 bool unsupported_crypto; /* T if not usable due to missing crypto */
26 27
27 /* Message digest - the digest of the Content Data (or NULL) */ 28 /* Message digest - the digest of the Content Data (or NULL) */
28 const void *msgdigest; 29 const void *msgdigest;
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index 09197e50fa82..8bd474e5e706 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -35,6 +35,11 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
35 35
36 kenter(",%u,", sinfo->index); 36 kenter(",%u,", sinfo->index);
37 37
38 if (sinfo->unsupported_crypto) {
39 kleave(" = -ENOPKG [cached]");
40 return -ENOPKG;
41 }
42
38 for (x509 = sinfo->signer; x509; x509 = x509->signer) { 43 for (x509 = sinfo->signer; x509; x509 = x509->signer) {
39 if (x509->seen) { 44 if (x509->seen) {
40 if (x509->verified) { 45 if (x509->verified) {
@@ -139,24 +144,28 @@ int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
139{ 144{
140 struct pkcs7_signed_info *sinfo; 145 struct pkcs7_signed_info *sinfo;
141 struct x509_certificate *p; 146 struct x509_certificate *p;
142 int cached_ret = 0, ret; 147 int cached_ret = -ENOKEY;
148 int ret;
143 149
144 for (p = pkcs7->certs; p; p = p->next) 150 for (p = pkcs7->certs; p; p = p->next)
145 p->seen = false; 151 p->seen = false;
146 152
147 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { 153 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
148 ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring); 154 ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring);
149 if (ret < 0) { 155 switch (ret) {
150 if (ret == -ENOPKG) { 156 case -ENOKEY:
157 continue;
158 case -ENOPKG:
159 if (cached_ret == -ENOKEY)
151 cached_ret = -ENOPKG; 160 cached_ret = -ENOPKG;
152 } else if (ret == -ENOKEY) { 161 continue;
153 if (cached_ret == 0) 162 case 0:
154 cached_ret = -ENOKEY; 163 *_trusted |= sinfo->trusted;
155 } else { 164 cached_ret = 0;
156 return ret; 165 continue;
157 } 166 default:
167 return ret;
158 } 168 }
159 *_trusted |= sinfo->trusted;
160 } 169 }
161 170
162 return cached_ret; 171 return cached_ret;
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 57e90fa17f2b..bd264052f751 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -181,7 +181,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
181 x509->seen = true; 181 x509->seen = true;
182 ret = x509_get_sig_params(x509); 182 ret = x509_get_sig_params(x509);
183 if (ret < 0) 183 if (ret < 0)
184 return ret; 184 goto maybe_missing_crypto_in_x509;
185 185
186 pr_debug("- issuer %s\n", x509->issuer); 186 pr_debug("- issuer %s\n", x509->issuer);
187 if (x509->authority) 187 if (x509->authority)
@@ -203,7 +203,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
203 203
204 ret = x509_check_signature(x509->pub, x509); 204 ret = x509_check_signature(x509->pub, x509);
205 if (ret < 0) 205 if (ret < 0)
206 return ret; 206 goto maybe_missing_crypto_in_x509;
207 x509->signer = x509; 207 x509->signer = x509;
208 pr_debug("- self-signed\n"); 208 pr_debug("- self-signed\n");
209 return 0; 209 return 0;
@@ -245,6 +245,17 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
245 x509 = p; 245 x509 = p;
246 might_sleep(); 246 might_sleep();
247 } 247 }
248
249maybe_missing_crypto_in_x509:
250 /* Just prune the certificate chain at this point if we lack some
251 * crypto module to go further. Note, however, we don't want to set
252 * sinfo->missing_crypto as the signed info block may still be
253 * validatable against an X.509 cert lower in the chain that we have a
254 * trusted copy of.
255 */
256 if (ret == -ENOPKG)
257 return 0;
258 return ret;
248} 259}
249 260
250/* 261/*
@@ -286,11 +297,33 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
286/** 297/**
287 * pkcs7_verify - Verify a PKCS#7 message 298 * pkcs7_verify - Verify a PKCS#7 message
288 * @pkcs7: The PKCS#7 message to be verified 299 * @pkcs7: The PKCS#7 message to be verified
300 *
301 * Verify a PKCS#7 message is internally consistent - that is, the data digest
302 * matches the digest in the AuthAttrs and any signature in the message or one
303 * of the X.509 certificates it carries that matches another X.509 cert in the
304 * message can be verified.
305 *
306 * This does not look to match the contents of the PKCS#7 message against any
307 * external public keys.
308 *
309 * Returns, in order of descending priority:
310 *
311 * (*) -EKEYREJECTED if a signature failed to match for which we found an
312 * appropriate X.509 certificate, or:
313 *
314 * (*) -EBADMSG if some part of the message was invalid, or:
315 *
316 * (*) -ENOPKG if none of the signature chains are verifiable because suitable
317 * crypto modules couldn't be found, or:
318 *
319 * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified
320 * (note that a signature chain may be of zero length), or:
289 */ 321 */
290int pkcs7_verify(struct pkcs7_message *pkcs7) 322int pkcs7_verify(struct pkcs7_message *pkcs7)
291{ 323{
292 struct pkcs7_signed_info *sinfo; 324 struct pkcs7_signed_info *sinfo;
293 struct x509_certificate *x509; 325 struct x509_certificate *x509;
326 int enopkg = -ENOPKG;
294 int ret, n; 327 int ret, n;
295 328
296 kenter(""); 329 kenter("");
@@ -306,12 +339,17 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
306 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { 339 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
307 ret = pkcs7_verify_one(pkcs7, sinfo); 340 ret = pkcs7_verify_one(pkcs7, sinfo);
308 if (ret < 0) { 341 if (ret < 0) {
342 if (ret == -ENOPKG) {
343 sinfo->unsupported_crypto = true;
344 continue;
345 }
309 kleave(" = %d", ret); 346 kleave(" = %d", ret);
310 return ret; 347 return ret;
311 } 348 }
349 enopkg = 0;
312 } 350 }
313 351
314 kleave(" = 0"); 352 kleave(" = %d", enopkg);
315 return 0; 353 return enopkg;
316} 354}
317EXPORT_SYMBOL_GPL(pkcs7_verify); 355EXPORT_SYMBOL_GPL(pkcs7_verify);
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index 0e8d59b010fb..4e1a384901ed 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -38,6 +38,7 @@ struct x509_certificate {
38 bool seen; /* Infinite recursion prevention */ 38 bool seen; /* Infinite recursion prevention */
39 bool verified; 39 bool verified;
40 bool trusted; 40 bool trusted;
41 bool unsupported_crypto; /* T if can't be verified due to missing crypto */
41}; 42};
42 43
43/* 44/*
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index c60905c3f4d2..1d9a4c555376 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -115,6 +115,8 @@ int x509_get_sig_params(struct x509_certificate *cert)
115 115
116 pr_devel("==>%s()\n", __func__); 116 pr_devel("==>%s()\n", __func__);
117 117
118 if (cert->unsupported_crypto)
119 return -ENOPKG;
118 if (cert->sig.rsa.s) 120 if (cert->sig.rsa.s)
119 return 0; 121 return 0;
120 122
@@ -127,8 +129,13 @@ int x509_get_sig_params(struct x509_certificate *cert)
127 * big the hash operational data will be. 129 * big the hash operational data will be.
128 */ 130 */
129 tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); 131 tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
130 if (IS_ERR(tfm)) 132 if (IS_ERR(tfm)) {
131 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 133 if (PTR_ERR(tfm) == -ENOENT) {
134 cert->unsupported_crypto = true;
135 return -ENOPKG;
136 }
137 return PTR_ERR(tfm);
138 }
132 139
133 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 140 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
134 digest_size = crypto_shash_digestsize(tfm); 141 digest_size = crypto_shash_digestsize(tfm);
@@ -175,6 +182,8 @@ int x509_check_signature(const struct public_key *pub,
175 return ret; 182 return ret;
176 183
177 ret = public_key_verify_signature(pub, &cert->sig); 184 ret = public_key_verify_signature(pub, &cert->sig);
185 if (ret == -ENOPKG)
186 cert->unsupported_crypto = true;
178 pr_debug("Cert Verification: %d\n", ret); 187 pr_debug("Cert Verification: %d\n", ret);
179 return ret; 188 return ret;
180} 189}