aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/asymmetric_keys
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-07-01 11:40:19 -0400
committerDavid Howells <dhowells@redhat.com>2014-07-08 08:50:11 -0400
commit8c76d79393ccc9b89d9af402d79a49a9cd43c5aa (patch)
tree482d70a25d548d0a82d08ac0bb9e2749b388d633 /crypto/asymmetric_keys
parenta4730357ee724f8c64f0292541ba3da8a95510fb (diff)
PKCS#7: Verify internal certificate chain
Verify certificate chain in the X.509 certificates contained within the PKCS#7 message as far as possible. If any signature that we should be able to verify fails, we reject the whole lot. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Vivek Goyal <vgoyal@redhat.com> Reviewed-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c88
1 files changed, 87 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 745e5c86a35e..51ff36f3a913 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -170,6 +170,91 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
170} 170}
171 171
172/* 172/*
173 * Verify the internal certificate chain as best we can.
174 */
175static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
176 struct pkcs7_signed_info *sinfo)
177{
178 struct x509_certificate *x509 = sinfo->signer, *p;
179 int ret;
180
181 kenter("");
182
183 for (p = pkcs7->certs; p; p = p->next)
184 p->seen = false;
185
186 for (;;) {
187 pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint);
188 x509->seen = true;
189 ret = x509_get_sig_params(x509);
190 if (ret < 0)
191 return ret;
192
193 if (x509->issuer)
194 pr_debug("- issuer %s\n", x509->issuer);
195 if (x509->authority)
196 pr_debug("- authkeyid %s\n", x509->authority);
197
198 if (!x509->authority ||
199 (x509->subject &&
200 strcmp(x509->subject, x509->issuer) == 0)) {
201 /* If there's no authority certificate specified, then
202 * the certificate must be self-signed and is the root
203 * of the chain. Likewise if the cert is its own
204 * authority.
205 */
206 pr_debug("- no auth?\n");
207 if (x509->raw_subject_size != x509->raw_issuer_size ||
208 memcmp(x509->raw_subject, x509->raw_issuer,
209 x509->raw_issuer_size) != 0)
210 return 0;
211
212 ret = x509_check_signature(x509->pub, x509);
213 if (ret < 0)
214 return ret;
215 x509->signer = x509;
216 pr_debug("- self-signed\n");
217 return 0;
218 }
219
220 /* Look through the X.509 certificates in the PKCS#7 message's
221 * list to see if the next one is there.
222 */
223 pr_debug("- want %s\n", x509->authority);
224 for (p = pkcs7->certs; p; p = p->next) {
225 pr_debug("- cmp [%u] %s\n", p->index, p->fingerprint);
226 if (p->raw_subject_size == x509->raw_issuer_size &&
227 strcmp(p->fingerprint, x509->authority) == 0 &&
228 memcmp(p->raw_subject, x509->raw_issuer,
229 x509->raw_issuer_size) == 0)
230 goto found_issuer;
231 }
232
233 /* We didn't find the root of this chain */
234 pr_debug("- top\n");
235 return 0;
236
237 found_issuer:
238 pr_debug("- issuer %s\n", p->subject);
239 if (p->seen) {
240 pr_warn("Sig %u: X.509 chain contains loop\n",
241 sinfo->index);
242 return 0;
243 }
244 ret = x509_check_signature(p->pub, x509);
245 if (ret < 0)
246 return ret;
247 x509->signer = p;
248 if (x509 == p) {
249 pr_debug("- self-signed\n");
250 return 0;
251 }
252 x509 = p;
253 might_sleep();
254 }
255}
256
257/*
173 * Verify one signed information block from a PKCS#7 message. 258 * Verify one signed information block from a PKCS#7 message.
174 */ 259 */
175static int pkcs7_verify_one(struct pkcs7_message *pkcs7, 260static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
@@ -201,7 +286,8 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
201 286
202 pr_devel("Verified signature %u\n", sinfo->index); 287 pr_devel("Verified signature %u\n", sinfo->index);
203 288
204 return 0; 289 /* Verify the internal certificate chain */
290 return pkcs7_verify_sig_chain(pkcs7, sinfo);
205} 291}
206 292
207/** 293/**