summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509/x509_vfy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/x509/x509_vfy.c')
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c347
1 files changed, 307 insertions, 40 deletions
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index 0f4110cc64..db12f7bd35 100644
--- a/src/lib/libcrypto/x509/x509_vfy.c
+++ b/src/lib/libcrypto/x509/x509_vfy.c
@@ -75,15 +75,11 @@ static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
75static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x); 75static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
76static int check_chain_purpose(X509_STORE_CTX *ctx); 76static int check_chain_purpose(X509_STORE_CTX *ctx);
77static int check_trust(X509_STORE_CTX *ctx); 77static int check_trust(X509_STORE_CTX *ctx);
78static int check_revocation(X509_STORE_CTX *ctx);
79static int check_cert(X509_STORE_CTX *ctx);
78static int internal_verify(X509_STORE_CTX *ctx); 80static int internal_verify(X509_STORE_CTX *ctx);
79const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; 81const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
80 82
81static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_ctx_method=NULL;
82static int x509_store_ctx_num=0;
83#if 0
84static int x509_store_num=1;
85static STACK *x509_store_method=NULL;
86#endif
87 83
88static int null_callback(int ok, X509_STORE_CTX *e) 84static int null_callback(int ok, X509_STORE_CTX *e)
89 { 85 {
@@ -113,7 +109,6 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
113 } 109 }
114 110
115 cb=ctx->verify_cb; 111 cb=ctx->verify_cb;
116 if (cb == NULL) cb=null_callback;
117 112
118 /* first we make sure the chain we are going to build is 113 /* first we make sure the chain we are going to build is
119 * present and that the first entry is in place */ 114 * present and that the first entry is in place */
@@ -299,6 +294,13 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
299 /* We may as well copy down any DSA parameters that are required */ 294 /* We may as well copy down any DSA parameters that are required */
300 X509_get_pubkey_parameters(NULL,ctx->chain); 295 X509_get_pubkey_parameters(NULL,ctx->chain);
301 296
297 /* Check revocation status: we do this after copying parameters
298 * because they may be needed for CRL signature verification.
299 */
300
301 ok = ctx->check_revocation(ctx);
302 if(!ok) goto end;
303
302 /* At this point, we have a chain and just need to verify it */ 304 /* At this point, we have a chain and just need to verify it */
303 if (ctx->verify != NULL) 305 if (ctx->verify != NULL)
304 ok=ctx->verify(ctx); 306 ok=ctx->verify(ctx);
@@ -346,8 +348,7 @@ static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
346 ctx->error = ret; 348 ctx->error = ret;
347 ctx->current_cert = x; 349 ctx->current_cert = x;
348 ctx->current_issuer = issuer; 350 ctx->current_issuer = issuer;
349 if (ctx->verify_cb) 351 return ctx->verify_cb(0, ctx);
350 return ctx->verify_cb(0, ctx);
351 return 0; 352 return 0;
352} 353}
353 354
@@ -372,18 +373,26 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
372 373
373static int check_chain_purpose(X509_STORE_CTX *ctx) 374static int check_chain_purpose(X509_STORE_CTX *ctx)
374{ 375{
375#ifdef NO_CHAIN_VERIFY 376#ifdef OPENSSL_NO_CHAIN_VERIFY
376 return 1; 377 return 1;
377#else 378#else
378 int i, ok=0; 379 int i, ok=0;
379 X509 *x; 380 X509 *x;
380 int (*cb)(); 381 int (*cb)();
381 cb=ctx->verify_cb; 382 cb=ctx->verify_cb;
382 if (cb == NULL) cb=null_callback;
383 /* Check all untrusted certificates */ 383 /* Check all untrusted certificates */
384 for (i = 0; i < ctx->last_untrusted; i++) 384 for (i = 0; i < ctx->last_untrusted; i++)
385 { 385 {
386 x = sk_X509_value(ctx->chain, i); 386 x = sk_X509_value(ctx->chain, i);
387 if (!(ctx->flags & X509_V_FLAG_IGNORE_CRITICAL)
388 && (x->ex_flags & EXFLAG_CRITICAL))
389 {
390 ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
391 ctx->error_depth = i;
392 ctx->current_cert = x;
393 ok=cb(0,ctx);
394 if (!ok) goto end;
395 }
387 if (!X509_check_purpose(x, ctx->purpose, i)) 396 if (!X509_check_purpose(x, ctx->purpose, i))
388 { 397 {
389 if (i) 398 if (i)
@@ -414,21 +423,20 @@ static int check_chain_purpose(X509_STORE_CTX *ctx)
414 423
415static int check_trust(X509_STORE_CTX *ctx) 424static int check_trust(X509_STORE_CTX *ctx)
416{ 425{
417#ifdef NO_CHAIN_VERIFY 426#ifdef OPENSSL_NO_CHAIN_VERIFY
418 return 1; 427 return 1;
419#else 428#else
420 int i, ok; 429 int i, ok;
421 X509 *x; 430 X509 *x;
422 int (*cb)(); 431 int (*cb)();
423 cb=ctx->verify_cb; 432 cb=ctx->verify_cb;
424 if (cb == NULL) cb=null_callback;
425/* For now just check the last certificate in the chain */ 433/* For now just check the last certificate in the chain */
426 i = sk_X509_num(ctx->chain) - 1; 434 i = sk_X509_num(ctx->chain) - 1;
427 x = sk_X509_value(ctx->chain, i); 435 x = sk_X509_value(ctx->chain, i);
428 ok = X509_check_trust(x, ctx->trust, 0); 436 ok = X509_check_trust(x, ctx->trust, 0);
429 if (ok == X509_TRUST_TRUSTED) 437 if (ok == X509_TRUST_TRUSTED)
430 return 1; 438 return 1;
431 ctx->error_depth = sk_X509_num(ctx->chain) - 1; 439 ctx->error_depth = i;
432 ctx->current_cert = x; 440 ctx->current_cert = x;
433 if (ok == X509_TRUST_REJECTED) 441 if (ok == X509_TRUST_REJECTED)
434 ctx->error = X509_V_ERR_CERT_REJECTED; 442 ctx->error = X509_V_ERR_CERT_REJECTED;
@@ -439,6 +447,183 @@ static int check_trust(X509_STORE_CTX *ctx)
439#endif 447#endif
440} 448}
441 449
450static int check_revocation(X509_STORE_CTX *ctx)
451 {
452 int i, last, ok;
453 if (!(ctx->flags & X509_V_FLAG_CRL_CHECK))
454 return 1;
455 if (ctx->flags & X509_V_FLAG_CRL_CHECK_ALL)
456 last = 0;
457 else
458 last = sk_X509_num(ctx->chain) - 1;
459 for(i = 0; i <= last; i++)
460 {
461 ctx->error_depth = i;
462 ok = check_cert(ctx);
463 if (!ok) return ok;
464 }
465 return 1;
466 }
467
468static int check_cert(X509_STORE_CTX *ctx)
469 {
470 X509_CRL *crl = NULL;
471 X509 *x;
472 int ok, cnum;
473 cnum = ctx->error_depth;
474 x = sk_X509_value(ctx->chain, cnum);
475 ctx->current_cert = x;
476 /* Try to retrieve relevant CRL */
477 ok = ctx->get_crl(ctx, &crl, x);
478 /* If error looking up CRL, nothing we can do except
479 * notify callback
480 */
481 if(!ok)
482 {
483 ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
484 ok = ctx->verify_cb(0, ctx);
485 goto err;
486 }
487 ctx->current_crl = crl;
488 ok = ctx->check_crl(ctx, crl);
489 if (!ok) goto err;
490 ok = ctx->cert_crl(ctx, crl, x);
491 err:
492 ctx->current_crl = NULL;
493 X509_CRL_free(crl);
494 return ok;
495
496 }
497
498/* Retrieve CRL corresponding to certificate: currently just a
499 * subject lookup: maybe use AKID later...
500 * Also might look up any included CRLs too (e.g PKCS#7 signedData).
501 */
502static int get_crl(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x)
503 {
504 int ok;
505 X509_OBJECT xobj;
506 ok = X509_STORE_get_by_subject(ctx, X509_LU_CRL, X509_get_issuer_name(x), &xobj);
507 if (!ok) return 0;
508 *crl = xobj.data.crl;
509 return 1;
510 }
511
512/* Check CRL validity */
513static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
514 {
515 X509 *issuer = NULL;
516 EVP_PKEY *ikey = NULL;
517 int ok = 0, chnum, cnum, i;
518 time_t *ptime;
519 cnum = ctx->error_depth;
520 chnum = sk_X509_num(ctx->chain) - 1;
521 /* Find CRL issuer: if not last certificate then issuer
522 * is next certificate in chain.
523 */
524 if(cnum < chnum)
525 issuer = sk_X509_value(ctx->chain, cnum + 1);
526 else
527 {
528 issuer = sk_X509_value(ctx->chain, chnum);
529 /* If not self signed, can't check signature */
530 if(!ctx->check_issued(ctx, issuer, issuer))
531 {
532 ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
533 ok = ctx->verify_cb(0, ctx);
534 if(!ok) goto err;
535 }
536 }
537
538 if(issuer)
539 {
540
541 /* Attempt to get issuer certificate public key */
542 ikey = X509_get_pubkey(issuer);
543
544 if(!ikey)
545 {
546 ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
547 ok = ctx->verify_cb(0, ctx);
548 if (!ok) goto err;
549 }
550 else
551 {
552 /* Verify CRL signature */
553 if(X509_CRL_verify(crl, ikey) <= 0)
554 {
555 ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
556 ok = ctx->verify_cb(0, ctx);
557 if (!ok) goto err;
558 }
559 }
560 }
561
562 /* OK, CRL signature valid check times */
563 if (ctx->flags & X509_V_FLAG_USE_CHECK_TIME)
564 ptime = &ctx->check_time;
565 else
566 ptime = NULL;
567
568 i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
569 if (i == 0)
570 {
571 ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
572 ok = ctx->verify_cb(0, ctx);
573 if (!ok) goto err;
574 }
575
576 if (i > 0)
577 {
578 ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
579 ok = ctx->verify_cb(0, ctx);
580 if (!ok) goto err;
581 }
582
583 if(X509_CRL_get_nextUpdate(crl))
584 {
585 i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
586
587 if (i == 0)
588 {
589 ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
590 ok = ctx->verify_cb(0, ctx);
591 if (!ok) goto err;
592 }
593
594 if (i < 0)
595 {
596 ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
597 ok = ctx->verify_cb(0, ctx);
598 if (!ok) goto err;
599 }
600 }
601
602 ok = 1;
603
604 err:
605 EVP_PKEY_free(ikey);
606 return ok;
607 }
608
609/* Check certificate against CRL */
610static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
611 {
612 int idx, ok;
613 X509_REVOKED rtmp;
614 /* Look for serial number of certificate in CRL */
615 rtmp.serialNumber = X509_get_serialNumber(x);
616 idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
617 /* Not found: OK */
618 if(idx == -1) return 1;
619 /* Otherwise revoked: want something cleverer than
620 * this to handle entry extensions in V2 CRLs.
621 */
622 ctx->error = X509_V_ERR_CERT_REVOKED;
623 ok = ctx->verify_cb(0, ctx);
624 return ok;
625 }
626
442static int internal_verify(X509_STORE_CTX *ctx) 627static int internal_verify(X509_STORE_CTX *ctx)
443 { 628 {
444 int i,ok=0,n; 629 int i,ok=0,n;
@@ -448,7 +633,6 @@ static int internal_verify(X509_STORE_CTX *ctx)
448 int (*cb)(); 633 int (*cb)();
449 634
450 cb=ctx->verify_cb; 635 cb=ctx->verify_cb;
451 if (cb == NULL) cb=null_callback;
452 636
453 n=sk_X509_num(ctx->chain); 637 n=sk_X509_num(ctx->chain);
454 ctx->error_depth=n-1; 638 ctx->error_depth=n-1;
@@ -491,6 +675,13 @@ static int internal_verify(X509_STORE_CTX *ctx)
491 if (!ok) goto end; 675 if (!ok) goto end;
492 } 676 }
493 if (X509_verify(xs,pkey) <= 0) 677 if (X509_verify(xs,pkey) <= 0)
678 /* XXX For the final trusted self-signed cert,
679 * this is a waste of time. That check should
680 * optional so that e.g. 'openssl x509' can be
681 * used to detect invalid self-signatures, but
682 * we don't verify again and again in SSL
683 * handshakes and the like once the cert has
684 * been declared trusted. */
494 { 685 {
495 ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE; 686 ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
496 ctx->current_cert=xs; 687 ctx->current_cert=xs;
@@ -539,8 +730,6 @@ static int internal_verify(X509_STORE_CTX *ctx)
539 if (!ok) goto end; 730 if (!ok) goto end;
540 } 731 }
541 732
542 /* CRL CHECK */
543
544 /* The last error (if any) is still in the error value */ 733 /* The last error (if any) is still in the error value */
545 ctx->current_cert=xs; 734 ctx->current_cert=xs;
546 ok=(*cb)(1,ctx); 735 ok=(*cb)(1,ctx);
@@ -648,14 +837,16 @@ ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
648ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm) 837ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm)
649 { 838 {
650 time_t t; 839 time_t t;
840 int type = -1;
651 841
652 if (in_tm) t = *in_tm; 842 if (in_tm) t = *in_tm;
653 else time(&t); 843 else time(&t);
654 844
655 t+=adj; 845 t+=adj;
656 if (!s) return ASN1_TIME_set(s, t); 846 if (s) type = s->type;
657 if (s->type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t); 847 if (type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t);
658 return ASN1_GENERALIZEDTIME_set(s, t); 848 if (type == V_ASN1_GENERALIZEDTIME) return ASN1_GENERALIZEDTIME_set(s, t);
849 return ASN1_TIME_set(s, t);
659 } 850 }
660 851
661int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) 852int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
@@ -702,12 +893,12 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
702 893
703int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 894int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
704 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 895 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
705 { 896 {
706 x509_store_ctx_num++; 897 /* This function is (usually) called only once, by
707 return CRYPTO_get_ex_new_index(x509_store_ctx_num-1, 898 * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
708 &x509_store_ctx_method, 899 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp,
709 argl,argp,new_func,dup_func,free_func); 900 new_func, dup_func, free_func);
710 } 901 }
711 902
712int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) 903int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
713 { 904 {
@@ -831,8 +1022,8 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
831 } 1022 }
832 } 1023 }
833 1024
834 if (purpose) ctx->purpose = purpose; 1025 if (purpose && !ctx->purpose) ctx->purpose = purpose;
835 if (trust) ctx->trust = trust; 1026 if (trust && !ctx->trust) ctx->trust = trust;
836 return 1; 1027 return 1;
837} 1028}
838 1029
@@ -840,7 +1031,12 @@ X509_STORE_CTX *X509_STORE_CTX_new(void)
840{ 1031{
841 X509_STORE_CTX *ctx; 1032 X509_STORE_CTX *ctx;
842 ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX)); 1033 ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
843 if (ctx) memset(ctx, 0, sizeof(X509_STORE_CTX)); 1034 if (!ctx)
1035 {
1036 X509err(X509_F_X509_STORE_CTX_NEW,ERR_R_MALLOC_FAILURE);
1037 return NULL;
1038 }
1039 memset(ctx, 0, sizeof(X509_STORE_CTX));
844 return ctx; 1040 return ctx;
845} 1041}
846 1042
@@ -850,7 +1046,7 @@ void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
850 OPENSSL_free(ctx); 1046 OPENSSL_free(ctx);
851} 1047}
852 1048
853void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, 1049int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
854 STACK_OF(X509) *chain) 1050 STACK_OF(X509) *chain)
855 { 1051 {
856 ctx->ctx=store; 1052 ctx->ctx=store;
@@ -858,10 +1054,7 @@ void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
858 ctx->cert=x509; 1054 ctx->cert=x509;
859 ctx->untrusted=chain; 1055 ctx->untrusted=chain;
860 ctx->last_untrusted=0; 1056 ctx->last_untrusted=0;
861 ctx->purpose=0;
862 ctx->trust=0;
863 ctx->check_time=0; 1057 ctx->check_time=0;
864 ctx->flags=0;
865 ctx->other_ctx=NULL; 1058 ctx->other_ctx=NULL;
866 ctx->valid=0; 1059 ctx->valid=0;
867 ctx->chain=NULL; 1060 ctx->chain=NULL;
@@ -870,12 +1063,80 @@ void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
870 ctx->error_depth=0; 1063 ctx->error_depth=0;
871 ctx->current_cert=NULL; 1064 ctx->current_cert=NULL;
872 ctx->current_issuer=NULL; 1065 ctx->current_issuer=NULL;
873 ctx->check_issued = check_issued; 1066
874 ctx->get_issuer = X509_STORE_CTX_get1_issuer; 1067 /* Inherit callbacks and flags from X509_STORE if not set
875 ctx->verify_cb = store->verify_cb; 1068 * use defaults.
876 ctx->verify = store->verify; 1069 */
877 ctx->cleanup = 0; 1070
878 memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); 1071
1072 if (store)
1073 {
1074 ctx->purpose=store->purpose;
1075 ctx->trust=store->trust;
1076 ctx->flags = store->flags;
1077 ctx->cleanup = store->cleanup;
1078 }
1079 else
1080 {
1081 ctx->purpose = 0;
1082 ctx->trust = 0;
1083 ctx->flags = 0;
1084 ctx->cleanup = 0;
1085 }
1086
1087 if (store && store->check_issued)
1088 ctx->check_issued = store->check_issued;
1089 else
1090 ctx->check_issued = check_issued;
1091
1092 if (store && store->get_issuer)
1093 ctx->get_issuer = store->get_issuer;
1094 else
1095 ctx->get_issuer = X509_STORE_CTX_get1_issuer;
1096
1097 if (store && store->verify_cb)
1098 ctx->verify_cb = store->verify_cb;
1099 else
1100 ctx->verify_cb = null_callback;
1101
1102 if (store && store->verify)
1103 ctx->verify = store->verify;
1104 else
1105 ctx->verify = internal_verify;
1106
1107 if (store && store->check_revocation)
1108 ctx->check_revocation = store->check_revocation;
1109 else
1110 ctx->check_revocation = check_revocation;
1111
1112 if (store && store->get_crl)
1113 ctx->get_crl = store->get_crl;
1114 else
1115 ctx->get_crl = get_crl;
1116
1117 if (store && store->check_crl)
1118 ctx->check_crl = store->check_crl;
1119 else
1120 ctx->check_crl = check_crl;
1121
1122 if (store && store->cert_crl)
1123 ctx->cert_crl = store->cert_crl;
1124 else
1125 ctx->cert_crl = cert_crl;
1126
1127
1128 /* This memset() can't make any sense anyway, so it's removed. As
1129 * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
1130 * corresponding "new" here and remove this bogus initialisation. */
1131 /* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
1132 if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
1133 &(ctx->ex_data)))
1134 {
1135 OPENSSL_free(ctx);
1136 X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
1137 return 0;
1138 }
1139 return 1;
879 } 1140 }
880 1141
881/* Set alternative lookup method: just a STACK of trusted certificates. 1142/* Set alternative lookup method: just a STACK of trusted certificates.
@@ -896,7 +1157,7 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
896 sk_X509_pop_free(ctx->chain,X509_free); 1157 sk_X509_pop_free(ctx->chain,X509_free);
897 ctx->chain=NULL; 1158 ctx->chain=NULL;
898 } 1159 }
899 CRYPTO_free_ex_data(x509_store_ctx_method,ctx,&(ctx->ex_data)); 1160 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
900 memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA)); 1161 memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
901 } 1162 }
902 1163
@@ -911,6 +1172,12 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t)
911 ctx->flags |= X509_V_FLAG_USE_CHECK_TIME; 1172 ctx->flags |= X509_V_FLAG_USE_CHECK_TIME;
912 } 1173 }
913 1174
1175void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
1176 int (*verify_cb)(int, X509_STORE_CTX *))
1177 {
1178 ctx->verify_cb=verify_cb;
1179 }
1180
914IMPLEMENT_STACK_OF(X509) 1181IMPLEMENT_STACK_OF(X509)
915IMPLEMENT_ASN1_SET_OF(X509) 1182IMPLEMENT_ASN1_SET_OF(X509)
916 1183