summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbeck <>2016-11-06 10:37:38 +0000
committerbeck <>2016-11-06 10:37:38 +0000
commit6732c1155155b36860bbe6f86c2525400918a716 (patch)
treefba04b377288b64ebf38d04431c7350aa560e660 /src
parentd53b4cfb1657b03af7f1654f76351dbb75a44d2f (diff)
downloadopenbsd-6732c1155155b36860bbe6f86c2525400918a716.tar.gz
openbsd-6732c1155155b36860bbe6f86c2525400918a716.tar.bz2
openbsd-6732c1155155b36860bbe6f86c2525400918a716.zip
Rework X509_verify_cert to support alt chains on certificate verification,
via boringssl. ok jsing@ miod@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c382
1 files changed, 265 insertions, 117 deletions
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index 7a6d272023..abd5c65e31 100644
--- a/src/lib/libcrypto/x509/x509_vfy.c
+++ b/src/lib/libcrypto/x509/x509_vfy.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_vfy.c,v 1.51 2016/11/04 18:07:23 beck Exp $ */ 1/* $OpenBSD: x509_vfy.c,v 1.52 2016/11/06 10:37:38 beck Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -74,6 +74,7 @@
74#include <openssl/x509.h> 74#include <openssl/x509.h>
75#include <openssl/x509v3.h> 75#include <openssl/x509v3.h>
76#include "x509_lcl.h" 76#include "x509_lcl.h"
77#include "vpm_int.h"
77 78
78/* CRL score values */ 79/* CRL score values */
79 80
@@ -153,41 +154,115 @@ x509_subject_cmp(X509 **a, X509 **b)
153} 154}
154#endif 155#endif
155 156
157/* Return 1 is a certificate is self signed */
158static int
159cert_self_signed(X509 *x)
160{
161 X509_check_purpose(x, -1, 0);
162 if (x->ex_flags & EXFLAG_SS)
163 return 1;
164 else
165 return 0;
166}
167
168static int
169check_id_error(X509_STORE_CTX *ctx, int errcode)
170{
171 ctx->error = errcode;
172 ctx->current_cert = ctx->cert;
173 ctx->error_depth = 0;
174 return ctx->verify_cb(0, ctx);
175}
176
177static int
178check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id)
179{
180 size_t i;
181 size_t n = sk_OPENSSL_STRING_num(id->hosts);
182 char *name;
183
184 free(id->peername);
185 id->peername = NULL;
186
187 for (i = 0; i < n; ++i) {
188 name = sk_OPENSSL_STRING_value(id->hosts, i);
189 if (X509_check_host(x, name, strlen(name), id->hostflags,
190 &id->peername) > 0)
191 return 1;
192 }
193 return n == 0;
194}
195
196static int
197check_id(X509_STORE_CTX *ctx)
198{
199 X509_VERIFY_PARAM *vpm = ctx->param;
200 X509_VERIFY_PARAM_ID *id = vpm->id;
201 X509 *x = ctx->cert;
202
203 if (id->hosts && check_hosts(x, id) <= 0) {
204 if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
205 return 0;
206 }
207 if (id->email != NULL && X509_check_email(x, id->email, id->emaillen, 0)
208 <= 0) {
209 if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
210 return 0;
211 }
212 if (id->ip != NULL && X509_check_ip(x, id->ip, id->iplen, 0) <= 0) {
213 if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
214 return 0;
215 }
216 return 1;
217}
218
156int 219int
157X509_verify_cert(X509_STORE_CTX *ctx) 220X509_verify_cert(X509_STORE_CTX *ctx)
158{ 221{
159 X509 *x, *xtmp, *chain_ss = NULL; 222 X509 *x, *xtmp, *xtmp2, *chain_ss = NULL;
160 int bad_chain = 0; 223 int bad_chain = 0;
161 X509_VERIFY_PARAM *param = ctx->param; 224 X509_VERIFY_PARAM *param = ctx->param;
162 int depth, i, ok = 0; 225 int depth, i, ok = 0;
163 int num; 226 int num, j, retry, trust;
164 int (*cb)(int xok, X509_STORE_CTX *xctx); 227 int (*cb) (int xok, X509_STORE_CTX *xctx);
165 STACK_OF(X509) *sktmp = NULL; 228 STACK_OF(X509) *sktmp = NULL;
166
167 if (ctx->cert == NULL) { 229 if (ctx->cert == NULL) {
168 X509err(X509_F_X509_VERIFY_CERT, 230 X509err(X509_F_X509_VERIFY_CERT,
169 X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); 231 X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
232 ctx->error = X509_V_ERR_INVALID_CALL;
233 return -1;
234 }
235 if (ctx->chain != NULL) {
236 /*
237 * This X509_STORE_CTX has already been used to verify
238 * a cert. We cannot do another one.
239 */
240 X509err(X509_F_X509_VERIFY_CERT,
241 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
242 ctx->error = X509_V_ERR_INVALID_CALL;
170 return -1; 243 return -1;
171 } 244 }
172 245
173 cb = ctx->verify_cb; 246 cb = ctx->verify_cb;
174 247
175 /* first we make sure the chain we are going to build is 248 /*
176 * present and that the first entry is in place */ 249 * First we make sure the chain we are going to build is
177 if (ctx->chain == NULL) { 250 * present and that the first entry is in place.
178 if (((ctx->chain = sk_X509_new_null()) == NULL) || 251 */
179 (!sk_X509_push(ctx->chain, ctx->cert))) { 252 ctx->chain = sk_X509_new_null();
180 X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); 253 if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) {
181 goto end; 254 X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
182 } 255 ctx->error = X509_V_ERR_OUT_OF_MEM;
183 CRYPTO_add(&ctx->cert->references, 1, CRYPTO_LOCK_X509); 256 goto end;
184 ctx->last_untrusted = 1;
185 } 257 }
258 X509_up_ref(ctx->cert);
259 ctx->last_untrusted = 1;
186 260
187 /* We use a temporary STACK so we can chop and hack at it */ 261 /* We use a temporary STACK so we can chop and hack at it */
188 if (ctx->untrusted != NULL && 262 if (ctx->untrusted != NULL &&
189 (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { 263 (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
190 X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); 264 X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
265 ctx->error = X509_V_ERR_OUT_OF_MEM;
191 goto end; 266 goto end;
192 } 267 }
193 268
@@ -197,17 +272,34 @@ X509_verify_cert(X509_STORE_CTX *ctx)
197 272
198 for (;;) { 273 for (;;) {
199 /* If we have enough, we break */ 274 /* If we have enough, we break */
275 /* FIXME: If this happens, we should take
276 * note of it and, if appropriate, use the
277 * X509_V_ERR_CERT_CHAIN_TOO_LONG error code
278 * later.
279 */
200 if (depth < num) 280 if (depth < num)
201 break; /* FIXME: If this happens, we should take 281 break;
202 * note of it and, if appropriate, use the
203 * X509_V_ERR_CERT_CHAIN_TOO_LONG error
204 * code later.
205 */
206
207 /* If we are self signed, we break */ 282 /* If we are self signed, we break */
208 if (ctx->check_issued(ctx, x, x)) 283 if (cert_self_signed(x))
209 break; 284 break;
210 285 /*
286 * If asked see if we can find issuer in trusted store first
287 */
288 if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) {
289 ok = ctx->get_issuer(&xtmp, ctx, x);
290 if (ok < 0) {
291 ctx->error = X509_V_ERR_STORE_LOOKUP;
292 goto end;
293 }
294 /*
295 * If successful for now free up cert so it
296 * will be picked up again later.
297 */
298 if (ok > 0) {
299 X509_free(xtmp);
300 break;
301 }
302 }
211 /* If we were passed a cert chain, use it first */ 303 /* If we were passed a cert chain, use it first */
212 if (ctx->untrusted != NULL) { 304 if (ctx->untrusted != NULL) {
213 xtmp = find_issuer(ctx, sktmp, x); 305 xtmp = find_issuer(ctx, sktmp, x);
@@ -215,109 +307,174 @@ X509_verify_cert(X509_STORE_CTX *ctx)
215 if (!sk_X509_push(ctx->chain, xtmp)) { 307 if (!sk_X509_push(ctx->chain, xtmp)) {
216 X509err(X509_F_X509_VERIFY_CERT, 308 X509err(X509_F_X509_VERIFY_CERT,
217 ERR_R_MALLOC_FAILURE); 309 ERR_R_MALLOC_FAILURE);
310 ctx->error = X509_V_ERR_OUT_OF_MEM;
311 ok = 0;
218 goto end; 312 goto end;
219 } 313 }
220 CRYPTO_add(&xtmp->references, 1, 314 X509_up_ref(xtmp);
221 CRYPTO_LOCK_X509);
222 (void)sk_X509_delete_ptr(sktmp, xtmp); 315 (void)sk_X509_delete_ptr(sktmp, xtmp);
223 ctx->last_untrusted++; 316 ctx->last_untrusted++;
224 x = xtmp; 317 x = xtmp;
225 num++; 318 num++;
226 /* reparse the full chain for 319 /*
227 * the next one */ 320 * reparse the full chain for the next one
321 */
228 continue; 322 continue;
229 } 323 }
230 } 324 }
231 break; 325 break;
232 } 326 }
233 sk_X509_free(sktmp); 327 /* Remember how many untrusted certs we have */
234 sktmp = NULL; 328 j = num;
235 329
236 /* at this point, chain should contain a list of untrusted 330 /*
331 * At this point, chain should contain a list of untrusted
237 * certificates. We now need to add at least one trusted one, 332 * certificates. We now need to add at least one trusted one,
238 * if possible, otherwise we complain. */ 333 * if possible, otherwise we complain.
239 334 */
240 /* Examine last certificate in chain and see if it 335
241 * is self signed. 336 do {
242 */ 337 /*
243 338 * Examine last certificate in chain and see if it is
244 i = sk_X509_num(ctx->chain); 339 * self signed.
245 x = sk_X509_value(ctx->chain, i - 1); 340 */
246 if (ctx->check_issued(ctx, x, x)) { 341 i = sk_X509_num(ctx->chain);
247 /* we have a self signed certificate */ 342 x = sk_X509_value(ctx->chain, i - 1);
248 if (sk_X509_num(ctx->chain) == 1) { 343 if (cert_self_signed(x)) {
249 /* We have a single self signed certificate: see if 344 /* we have a self signed certificate */
250 * we can find it in the store. We must have an exact 345 if (i == 1) {
251 * match to avoid possible impersonation. 346 /*
252 */ 347 * We have a single self signed
253 ok = ctx->get_issuer(&xtmp, ctx, x); 348 * certificate: see if we can find it
254 if ((ok <= 0) || X509_cmp(x, xtmp)) { 349 * in the store. We must have an exact
255 ctx->error = 350 * match to avoid possible
256 X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; 351 * impersonation.
257 ctx->current_cert = x; 352 */
258 ctx->error_depth = i - 1; 353 ok = ctx->get_issuer(&xtmp, ctx, x);
259 if (ok == 1) 354 if ((ok <= 0) || X509_cmp(x, xtmp)) {
260 X509_free(xtmp); 355 ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
261 bad_chain = 1; 356 ctx->current_cert = x;
262 ok = cb(0, ctx); 357 ctx->error_depth = i - 1;
263 if (!ok) 358 if (ok == 1)
264 goto end; 359 X509_free(xtmp);
360 bad_chain = 1;
361 ok = cb(0, ctx);
362 if (!ok)
363 goto end;
364 } else {
365 /*
366 * We have a match: replace
367 * certificate with store
368 * version so we get any trust
369 * settings.
370 */
371 X509_free(x);
372 x = xtmp;
373 (void)sk_X509_set(ctx->chain, i - 1, x);
374 ctx->last_untrusted = 0;
375 }
265 } else { 376 } else {
266 /* We have a match: replace certificate with store version 377 /*
267 * so we get any trust settings. 378 * extract and save self signed
379 * certificate for later use
268 */ 380 */
269 X509_free(x); 381 chain_ss = sk_X509_pop(ctx->chain);
270 x = xtmp; 382 ctx->last_untrusted--;
271 (void)sk_X509_set(ctx->chain, i - 1, x); 383 num--;
272 ctx->last_untrusted = 0; 384 j--;
385 x = sk_X509_value(ctx->chain, num - 1);
273 } 386 }
274 } else {
275 /* extract and save self signed certificate for later use */
276 chain_ss = sk_X509_pop(ctx->chain);
277 ctx->last_untrusted--;
278 num--;
279 x = sk_X509_value(ctx->chain, num - 1);
280 } 387 }
281 } 388 /* We now lookup certs from the certificate store */
282 389 for (;;) {
283 /* We now lookup certs from the certificate store */ 390 /* If we have enough, we break */
284 for (;;) { 391 if (depth < num)
285 /* If we have enough, we break */ 392 break;
286 if (depth < num) 393 /* If we are self signed, we break */
287 break; 394 if (cert_self_signed(x))
395 break;
396 ok = ctx->get_issuer(&xtmp, ctx, x);
288 397
289 /* If we are self signed, we break */ 398 if (ok < 0) {
290 if (ctx->check_issued(ctx, x, x)) 399 ctx->error = X509_V_ERR_STORE_LOOKUP;
291 break; 400 goto end;
401 }
402 if (ok == 0)
403 break;
404 x = xtmp;
405 if (!sk_X509_push(ctx->chain, x)) {
406 X509_free(xtmp);
407 X509err(X509_F_X509_VERIFY_CERT,
408 ERR_R_MALLOC_FAILURE);
409 ctx->error = X509_V_ERR_OUT_OF_MEM;
410 ok = 0;
411 goto end;
412 }
413 num++;
414 }
292 415
293 ok = ctx->get_issuer(&xtmp, ctx, x); 416 /* we now have our chain, lets check it... */
294 if (ok < 0) 417 trust = check_trust(ctx);
295 return ok;
296 if (ok == 0)
297 break;
298 418
299 x = xtmp; 419 /* If explicitly rejected error */
300 if (!sk_X509_push(ctx->chain, x)) { 420 if (trust == X509_TRUST_REJECTED) {
301 X509_free(xtmp); 421 ok = 0;
302 X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); 422 goto end;
303 return 0;
304 } 423 }
305 num++; 424 /*
306 } 425 * If it's not explicitly trusted then check if there
307 426 * is an alternative chain that could be used. We only
308 /* we now have our chain, lets check it... */ 427 * do this if we haven't already checked via
428 * TRUSTED_FIRST and the user hasn't switched off
429 * alternate chain checking
430 */
431 retry = 0;
432 if (trust != X509_TRUST_TRUSTED &&
433 !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) &&
434 !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
435 while (j-- > 1) {
436 xtmp2 = sk_X509_value(ctx->chain, j - 1);
437 ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
438 if (ok < 0)
439 goto end;
440 /* Check if we found an alternate chain */
441 if (ok > 0) {
442 /*
443 * Free up the found cert
444 * we'll add it again later
445 */
446 X509_free(xtmp);
447 /*
448 * Dump all the certs above
449 * this point - we've found an
450 * alternate chain
451 */
452 while (num > j) {
453 xtmp = sk_X509_pop(ctx->chain);
454 X509_free(xtmp);
455 num--;
456 }
457 ctx->last_untrusted = sk_X509_num(ctx->chain);
458 retry = 1;
459 break;
460 }
461 }
462 }
463 } while (retry);
309 464
310 /* Is last certificate looked up self signed? */ 465 /*
311 if (!ctx->check_issued(ctx, x, x)) { 466 * If not explicitly trusted then indicate error unless it's a single
312 if ((chain_ss == NULL) || 467 * self signed certificate in which case we've indicated an error already
313 !ctx->check_issued(ctx, x, chain_ss)) { 468 * and set bad_chain == 1
469 */
470 if (trust != X509_TRUST_TRUSTED && !bad_chain) {
471 if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) {
314 if (ctx->last_untrusted >= num) 472 if (ctx->last_untrusted >= num)
315 ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; 473 ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
316 else 474 else
317 ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; 475 ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
318 ctx->current_cert = x; 476 ctx->current_cert = x;
319 } else { 477 } else {
320
321 if (!sk_X509_push(ctx->chain, chain_ss)) { 478 if (!sk_X509_push(ctx->chain, chain_ss)) {
322 X509_free(chain_ss); 479 X509_free(chain_ss);
323 X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); 480 X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
@@ -350,19 +507,13 @@ X509_verify_cert(X509_STORE_CTX *ctx)
350 if (!ok) 507 if (!ok)
351 goto end; 508 goto end;
352 509
353 /* The chain extensions are OK: check trust */ 510 ok = check_id(ctx);
354
355 if (param->trust > 0)
356 ok = check_trust(ctx);
357 511
358 if (!ok) 512 if (!ok)
359 goto end; 513 goto end;
360 514 /*
361 /* We may as well copy down any DSA parameters that are required */ 515 * Check revocation status: we do this after copying parameters because
362 X509_get_pubkey_parameters(NULL, ctx->chain); 516 * they may be needed for CRL signature verification.
363
364 /* Check revocation status: we do this after copying parameters
365 * because they may be needed for CRL signature verification.
366 */ 517 */
367 518
368 ok = ctx->check_revocation(ctx); 519 ok = ctx->check_revocation(ctx);
@@ -376,23 +527,20 @@ X509_verify_cert(X509_STORE_CTX *ctx)
376 ok = internal_verify(ctx); 527 ok = internal_verify(ctx);
377 if (!ok) 528 if (!ok)
378 goto end; 529 goto end;
379
380 /* If we get this far evaluate policies */ 530 /* If we get this far evaluate policies */
381 if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)) 531 if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
382 ok = ctx->check_policy(ctx); 532 ok = ctx->check_policy(ctx);
383 if (!ok) 533 end:
384 goto end;
385 if (0) {
386end:
387 X509_get_pubkey_parameters(NULL, ctx->chain);
388 }
389 if (sktmp != NULL) 534 if (sktmp != NULL)
390 sk_X509_free(sktmp); 535 sk_X509_free(sktmp);
391 X509_free(chain_ss); 536 X509_free(chain_ss);
537
538 /* Safety net, error returns must set ctx->error */
539 if (ok <= 0 && ctx->error == X509_V_OK)
540 ctx->error = X509_V_ERR_UNSPECIFIED;
392 return ok; 541 return ok;
393} 542}
394 543
395
396/* Given a STACK_OF(X509) find the issuer of cert (if any) 544/* Given a STACK_OF(X509) find the issuer of cert (if any)
397 */ 545 */
398 546