aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-09-16 12:36:17 -0400
committerDavid Howells <dhowells@redhat.com>2014-09-16 12:36:17 -0400
commit757932e6da6de05b91cc4cb85493b17de48c2667 (patch)
treead9bf9a2fa35fa4dbb1a4402f1c3d6b092fc7f28
parent41559420003cfe99522257dded7793192c77b4e9 (diff)
PKCS#7: Handle PKCS#7 messages that contain no X.509 certs
The X.509 certificate list in a PKCS#7 message is optional. To save space, we can omit the inclusion of any X.509 certificates if we are sure that we can look the relevant public key up by the serial number and issuer given in a signed info block. This also supports use of a signed info block for which we can't find a matching X.509 cert in the certificate list, though it be populated. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Vivek Goyal <vgoyal@redhat.com>
-rw-r--r--crypto/asymmetric_keys/pkcs7_trust.c48
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c16
2 files changed, 47 insertions, 17 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index 8bd474e5e706..ae47be6128c4 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -55,13 +55,16 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
55 * keys. 55 * keys.
56 */ 56 */
57 key = x509_request_asymmetric_key(trust_keyring, x509->id); 57 key = x509_request_asymmetric_key(trust_keyring, x509->id);
58 if (!IS_ERR(key)) 58 if (!IS_ERR(key)) {
59 /* One of the X.509 certificates in the PKCS#7 message 59 /* One of the X.509 certificates in the PKCS#7 message
60 * is apparently the same as one we already trust. 60 * is apparently the same as one we already trust.
61 * Verify that the trusted variant can also validate 61 * Verify that the trusted variant can also validate
62 * the signature on the descendant. 62 * the signature on the descendant.
63 */ 63 */
64 pr_devel("sinfo %u: Cert %u as key %x\n",
65 sinfo->index, x509->index, key_serial(key));
64 goto matched; 66 goto matched;
67 }
65 if (key == ERR_PTR(-ENOMEM)) 68 if (key == ERR_PTR(-ENOMEM))
66 return -ENOMEM; 69 return -ENOMEM;
67 70
@@ -81,15 +84,34 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
81 /* No match - see if the root certificate has a signer amongst the 84 /* No match - see if the root certificate has a signer amongst the
82 * trusted keys. 85 * trusted keys.
83 */ 86 */
84 if (!last || !last->issuer || !last->authority) { 87 if (last && last->authority) {
85 kleave(" = -ENOKEY [no backref]"); 88 key = x509_request_asymmetric_key(trust_keyring, last->authority);
86 return -ENOKEY; 89 if (!IS_ERR(key)) {
90 x509 = last;
91 pr_devel("sinfo %u: Root cert %u signer is key %x\n",
92 sinfo->index, x509->index, key_serial(key));
93 goto matched;
94 }
95 if (PTR_ERR(key) != -ENOKEY)
96 return PTR_ERR(key);
87 } 97 }
88 98
89 key = x509_request_asymmetric_key(trust_keyring, last->authority); 99 /* As a last resort, see if we have a trusted public key that matches
90 if (IS_ERR(key)) 100 * the signed info directly.
91 return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY; 101 */
92 x509 = last; 102 key = x509_request_asymmetric_key(trust_keyring,
103 sinfo->signing_cert_id);
104 if (!IS_ERR(key)) {
105 pr_devel("sinfo %u: Direct signer is key %x\n",
106 sinfo->index, key_serial(key));
107 x509 = NULL;
108 goto matched;
109 }
110 if (PTR_ERR(key) != -ENOKEY)
111 return PTR_ERR(key);
112
113 kleave(" = -ENOKEY [no backref]");
114 return -ENOKEY;
93 115
94matched: 116matched:
95 ret = verify_signature(key, sig); 117 ret = verify_signature(key, sig);
@@ -103,10 +125,12 @@ matched:
103 } 125 }
104 126
105verified: 127verified:
106 x509->verified = true; 128 if (x509) {
107 for (p = sinfo->signer; p != x509; p = p->signer) { 129 x509->verified = true;
108 p->verified = true; 130 for (p = sinfo->signer; p != x509; p = p->signer) {
109 p->trusted = trusted; 131 p->verified = true;
132 p->trusted = trusted;
133 }
110 } 134 }
111 sinfo->trusted = trusted; 135 sinfo->trusted = trusted;
112 kleave(" = 0"); 136 kleave(" = 0");
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index bd264052f751..cd455450b069 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -154,10 +154,13 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
154 return 0; 154 return 0;
155 } 155 }
156 156
157 pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n", 157 /* The relevant X.509 cert isn't found here, but it might be found in
158 sinfo->index, 158 * the trust keyring.
159 sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); 159 */
160 return -ENOKEY; 160 pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n",
161 sinfo->index,
162 sinfo->signing_cert_id->len, sinfo->signing_cert_id->data);
163 return 0;
161} 164}
162 165
163/* 166/*
@@ -275,11 +278,14 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
275 if (ret < 0) 278 if (ret < 0)
276 return ret; 279 return ret;
277 280
278 /* Find the key for the signature */ 281 /* Find the key for the signature if there is one */
279 ret = pkcs7_find_key(pkcs7, sinfo); 282 ret = pkcs7_find_key(pkcs7, sinfo);
280 if (ret < 0) 283 if (ret < 0)
281 return ret; 284 return ret;
282 285
286 if (!sinfo->signer)
287 return 0;
288
283 pr_devel("Using X.509[%u] for sig %u\n", 289 pr_devel("Using X.509[%u] for sig %u\n",
284 sinfo->signer->index, sinfo->index); 290 sinfo->signer->index, sinfo->index);
285 291