diff options
Diffstat (limited to 'src/lib/libcrypto/x509/x509_vfy.c')
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 206 |
1 files changed, 186 insertions, 20 deletions
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index c72ee4a385..4fdff54124 100644 --- a/src/lib/libcrypto/x509/x509_vfy.c +++ b/src/lib/libcrypto/x509/x509_vfy.c | |||
@@ -59,23 +59,24 @@ | |||
59 | #include <stdio.h> | 59 | #include <stdio.h> |
60 | #include <time.h> | 60 | #include <time.h> |
61 | #include <errno.h> | 61 | #include <errno.h> |
62 | #include <sys/types.h> | ||
63 | #include <sys/stat.h> | ||
64 | 62 | ||
65 | #include <openssl/crypto.h> | ||
66 | #include "cryptlib.h" | 63 | #include "cryptlib.h" |
64 | #include <openssl/crypto.h> | ||
67 | #include <openssl/lhash.h> | 65 | #include <openssl/lhash.h> |
68 | #include <openssl/buffer.h> | 66 | #include <openssl/buffer.h> |
69 | #include <openssl/evp.h> | 67 | #include <openssl/evp.h> |
70 | #include <openssl/asn1.h> | 68 | #include <openssl/asn1.h> |
71 | #include <openssl/x509.h> | 69 | #include <openssl/x509.h> |
70 | #include <openssl/x509v3.h> | ||
72 | #include <openssl/objects.h> | 71 | #include <openssl/objects.h> |
73 | 72 | ||
74 | static int null_callback(int ok,X509_STORE_CTX *e); | 73 | static int null_callback(int ok,X509_STORE_CTX *e); |
74 | static int check_chain_purpose(X509_STORE_CTX *ctx); | ||
75 | static int check_trust(X509_STORE_CTX *ctx); | ||
75 | static int internal_verify(X509_STORE_CTX *ctx); | 76 | static int internal_verify(X509_STORE_CTX *ctx); |
76 | const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; | 77 | const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; |
77 | 78 | ||
78 | static STACK *x509_store_ctx_method=NULL; | 79 | static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_ctx_method=NULL; |
79 | static int x509_store_ctx_num=0; | 80 | static int x509_store_ctx_num=0; |
80 | #if 0 | 81 | #if 0 |
81 | static int x509_store_num=1; | 82 | static int x509_store_num=1; |
@@ -127,7 +128,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) | |||
127 | ctx->last_untrusted=1; | 128 | ctx->last_untrusted=1; |
128 | } | 129 | } |
129 | 130 | ||
130 | /* We use a temporary so we can chop and hack at it */ | 131 | /* We use a temporary STACK so we can chop and hack at it */ |
131 | if (ctx->untrusted != NULL | 132 | if (ctx->untrusted != NULL |
132 | && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL) | 133 | && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL) |
133 | { | 134 | { |
@@ -184,17 +185,37 @@ int X509_verify_cert(X509_STORE_CTX *ctx) | |||
184 | 185 | ||
185 | i=sk_X509_num(ctx->chain); | 186 | i=sk_X509_num(ctx->chain); |
186 | x=sk_X509_value(ctx->chain,i-1); | 187 | x=sk_X509_value(ctx->chain,i-1); |
187 | if (X509_NAME_cmp(X509_get_subject_name(x),X509_get_issuer_name(x)) | 188 | xn = X509_get_subject_name(x); |
189 | if (X509_NAME_cmp(xn,X509_get_issuer_name(x)) | ||
188 | == 0) | 190 | == 0) |
189 | { | 191 | { |
190 | /* we have a self signed certificate */ | 192 | /* we have a self signed certificate */ |
191 | if (sk_X509_num(ctx->chain) == 1) | 193 | if (sk_X509_num(ctx->chain) == 1) |
192 | { | 194 | { |
193 | ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; | 195 | /* We have a single self signed certificate: see if |
194 | ctx->current_cert=x; | 196 | * we can find it in the store. We must have an exact |
195 | ctx->error_depth=i-1; | 197 | * match to avoid possible impersonation. |
196 | ok=cb(0,ctx); | 198 | */ |
197 | if (!ok) goto end; | 199 | ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj); |
200 | if ((ok != X509_LU_X509) || X509_cmp(x, obj.data.x509)) | ||
201 | { | ||
202 | ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; | ||
203 | ctx->current_cert=x; | ||
204 | ctx->error_depth=i-1; | ||
205 | if(ok == X509_LU_X509) X509_OBJECT_free_contents(&obj); | ||
206 | ok=cb(0,ctx); | ||
207 | if (!ok) goto end; | ||
208 | } | ||
209 | else | ||
210 | { | ||
211 | /* We have a match: replace certificate with store version | ||
212 | * so we get any trust settings. | ||
213 | */ | ||
214 | X509_free(x); | ||
215 | x = obj.data.x509; | ||
216 | sk_X509_set(ctx->chain, i - 1, x); | ||
217 | ctx->last_untrusted=0; | ||
218 | } | ||
198 | } | 219 | } |
199 | else | 220 | else |
200 | { | 221 | { |
@@ -272,6 +293,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) | |||
272 | if (!ok) goto end; | 293 | if (!ok) goto end; |
273 | } | 294 | } |
274 | 295 | ||
296 | /* We have the chain complete: now we need to check its purpose */ | ||
297 | if(ctx->purpose > 0) ok = check_chain_purpose(ctx); | ||
298 | |||
299 | if(!ok) goto end; | ||
300 | |||
301 | /* The chain extensions are OK: check trust */ | ||
302 | |||
303 | if(ctx->trust > 0) ok = check_trust(ctx); | ||
304 | |||
305 | if(!ok) goto end; | ||
306 | |||
275 | /* We may as well copy down any DSA parameters that are required */ | 307 | /* We may as well copy down any DSA parameters that are required */ |
276 | X509_get_pubkey_parameters(NULL,ctx->chain); | 308 | X509_get_pubkey_parameters(NULL,ctx->chain); |
277 | 309 | ||
@@ -290,6 +322,71 @@ end: | |||
290 | return(ok); | 322 | return(ok); |
291 | } | 323 | } |
292 | 324 | ||
325 | /* Check a certificate chains extensions for consistency | ||
326 | * with the supplied purpose | ||
327 | */ | ||
328 | |||
329 | static int check_chain_purpose(X509_STORE_CTX *ctx) | ||
330 | { | ||
331 | #ifdef NO_CHAIN_VERIFY | ||
332 | return 1; | ||
333 | #else | ||
334 | int i, ok=0; | ||
335 | X509 *x; | ||
336 | int (*cb)(); | ||
337 | cb=ctx->ctx->verify_cb; | ||
338 | if (cb == NULL) cb=null_callback; | ||
339 | /* Check all untrusted certificates */ | ||
340 | for(i = 0; i < ctx->last_untrusted; i++) { | ||
341 | x = sk_X509_value(ctx->chain, i); | ||
342 | if(!X509_check_purpose(x, ctx->purpose, i)) { | ||
343 | if(i) ctx->error = X509_V_ERR_INVALID_CA; | ||
344 | else ctx->error = X509_V_ERR_INVALID_PURPOSE; | ||
345 | ctx->error_depth = i; | ||
346 | ctx->current_cert = x; | ||
347 | ok=cb(0,ctx); | ||
348 | if(!ok) goto end; | ||
349 | } | ||
350 | /* Check pathlen */ | ||
351 | if((i > 1) && (x->ex_pathlen != -1) | ||
352 | && (i > (x->ex_pathlen + 1))) { | ||
353 | ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; | ||
354 | ctx->error_depth = i; | ||
355 | ctx->current_cert = x; | ||
356 | ok=cb(0,ctx); | ||
357 | if(!ok) goto end; | ||
358 | } | ||
359 | } | ||
360 | ok = 1; | ||
361 | end: | ||
362 | return(ok); | ||
363 | #endif | ||
364 | } | ||
365 | |||
366 | static int check_trust(X509_STORE_CTX *ctx) | ||
367 | { | ||
368 | #ifdef NO_CHAIN_VERIFY | ||
369 | return 1; | ||
370 | #else | ||
371 | int i, ok; | ||
372 | X509 *x; | ||
373 | int (*cb)(); | ||
374 | cb=ctx->ctx->verify_cb; | ||
375 | if (cb == NULL) cb=null_callback; | ||
376 | /* For now just check the last certificate in the chain */ | ||
377 | i = sk_X509_num(ctx->chain) - 1; | ||
378 | x = sk_X509_value(ctx->chain, i); | ||
379 | ok = X509_check_trust(x, ctx->trust, 0); | ||
380 | if(ok == X509_TRUST_TRUSTED) return 1; | ||
381 | ctx->error_depth = sk_X509_num(ctx->chain) - 1; | ||
382 | ctx->current_cert = x; | ||
383 | if(ok == X509_TRUST_REJECTED) ctx->error = X509_V_ERR_CERT_REJECTED; | ||
384 | else ctx->error = X509_V_ERR_CERT_UNTRUSTED; | ||
385 | ok = cb(0, ctx); | ||
386 | return(ok); | ||
387 | #endif | ||
388 | } | ||
389 | |||
293 | static int internal_verify(X509_STORE_CTX *ctx) | 390 | static int internal_verify(X509_STORE_CTX *ctx) |
294 | { | 391 | { |
295 | int i,ok=0,n; | 392 | int i,ok=0,n; |
@@ -439,7 +536,7 @@ int X509_cmp_current_time(ASN1_UTCTIME *ctm) | |||
439 | atm.length=sizeof(buff2); | 536 | atm.length=sizeof(buff2); |
440 | atm.data=(unsigned char *)buff2; | 537 | atm.data=(unsigned char *)buff2; |
441 | 538 | ||
442 | X509_gmtime_adj(&atm,-offset); | 539 | X509_gmtime_adj(&atm,-offset*60); |
443 | 540 | ||
444 | i=(buff1[0]-'0')*10+(buff1[1]-'0'); | 541 | i=(buff1[0]-'0')*10+(buff1[1]-'0'); |
445 | if (i < 50) i+=100; /* cf. RFC 2459 */ | 542 | if (i < 50) i+=100; /* cf. RFC 2459 */ |
@@ -525,13 +622,13 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) | |||
525 | 622 | ||
526 | X509_OBJECT_up_ref_count(obj); | 623 | X509_OBJECT_up_ref_count(obj); |
527 | 624 | ||
528 | r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj); | 625 | r=(X509_OBJECT *)lh_insert(ctx->certs,obj); |
529 | if (r != NULL) | 626 | if (r != NULL) |
530 | { /* oops, put it back */ | 627 | { /* oops, put it back */ |
531 | lh_delete(ctx->certs,(char *)obj); | 628 | lh_delete(ctx->certs,obj); |
532 | X509_OBJECT_free_contents(obj); | 629 | X509_OBJECT_free_contents(obj); |
533 | Free(obj); | 630 | Free(obj); |
534 | lh_insert(ctx->certs,(char *)r); | 631 | lh_insert(ctx->certs,r); |
535 | X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE); | 632 | X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE); |
536 | ret=0; | 633 | ret=0; |
537 | } | 634 | } |
@@ -560,13 +657,13 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) | |||
560 | 657 | ||
561 | X509_OBJECT_up_ref_count(obj); | 658 | X509_OBJECT_up_ref_count(obj); |
562 | 659 | ||
563 | r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj); | 660 | r=(X509_OBJECT *)lh_insert(ctx->certs,obj); |
564 | if (r != NULL) | 661 | if (r != NULL) |
565 | { /* oops, put it back */ | 662 | { /* oops, put it back */ |
566 | lh_delete(ctx->certs,(char *)obj); | 663 | lh_delete(ctx->certs,obj); |
567 | X509_OBJECT_free_contents(obj); | 664 | X509_OBJECT_free_contents(obj); |
568 | Free(obj); | 665 | Free(obj); |
569 | lh_insert(ctx->certs,(char *)r); | 666 | lh_insert(ctx->certs,r); |
570 | X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE); | 667 | X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE); |
571 | ret=0; | 668 | ret=0; |
572 | } | 669 | } |
@@ -576,8 +673,8 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) | |||
576 | return(ret); | 673 | return(ret); |
577 | } | 674 | } |
578 | 675 | ||
579 | int X509_STORE_CTX_get_ex_new_index(long argl, char *argp, int (*new_func)(), | 676 | int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, |
580 | int (*dup_func)(), void (*free_func)()) | 677 | CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) |
581 | { | 678 | { |
582 | x509_store_ctx_num++; | 679 | x509_store_ctx_num++; |
583 | return(CRYPTO_get_ex_new_index(x509_store_ctx_num-1, | 680 | return(CRYPTO_get_ex_new_index(x509_store_ctx_num-1, |
@@ -620,6 +717,19 @@ STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) | |||
620 | return(ctx->chain); | 717 | return(ctx->chain); |
621 | } | 718 | } |
622 | 719 | ||
720 | STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) | ||
721 | { | ||
722 | int i; | ||
723 | X509 *x; | ||
724 | STACK_OF(X509) *chain; | ||
725 | if(!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) return NULL; | ||
726 | for(i = 0; i < sk_X509_num(chain); i++) { | ||
727 | x = sk_X509_value(chain, i); | ||
728 | CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | ||
729 | } | ||
730 | return(chain); | ||
731 | } | ||
732 | |||
623 | void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) | 733 | void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) |
624 | { | 734 | { |
625 | ctx->cert=x; | 735 | ctx->cert=x; |
@@ -630,6 +740,62 @@ void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) | |||
630 | ctx->untrusted=sk; | 740 | ctx->untrusted=sk; |
631 | } | 741 | } |
632 | 742 | ||
743 | int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) | ||
744 | { | ||
745 | return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); | ||
746 | } | ||
747 | |||
748 | int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) | ||
749 | { | ||
750 | return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); | ||
751 | } | ||
752 | |||
753 | /* This function is used to set the X509_STORE_CTX purpose and trust | ||
754 | * values. This is intended to be used when another structure has its | ||
755 | * own trust and purpose values which (if set) will be inherited by | ||
756 | * the ctx. If they aren't set then we will usually have a default | ||
757 | * purpose in mind which should then be used to set the trust value. | ||
758 | * An example of this is SSL use: an SSL structure will have its own | ||
759 | * purpose and trust settings which the application can set: if they | ||
760 | * aren't set then we use the default of SSL client/server. | ||
761 | */ | ||
762 | |||
763 | int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, | ||
764 | int purpose, int trust) | ||
765 | { | ||
766 | int idx; | ||
767 | /* If purpose not set use default */ | ||
768 | if(!purpose) purpose = def_purpose; | ||
769 | /* If we have a purpose then check it is valid */ | ||
770 | if(purpose) { | ||
771 | idx = X509_PURPOSE_get_by_id(purpose); | ||
772 | if(idx == -1) { | ||
773 | X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, | ||
774 | X509_R_UNKNOWN_PURPOSE_ID); | ||
775 | return 0; | ||
776 | } | ||
777 | /* If trust not set then get from purpose default */ | ||
778 | if(!trust) { | ||
779 | X509_PURPOSE *ptmp; | ||
780 | ptmp = X509_PURPOSE_get0(idx); | ||
781 | trust = ptmp->trust; | ||
782 | } | ||
783 | } | ||
784 | if(trust) { | ||
785 | idx = X509_TRUST_get_by_id(trust); | ||
786 | if(idx == -1) { | ||
787 | X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, | ||
788 | X509_R_UNKNOWN_TRUST_ID); | ||
789 | return 0; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | if(purpose) ctx->purpose = purpose; | ||
794 | if(trust) ctx->trust = trust; | ||
795 | return 1; | ||
796 | } | ||
797 | |||
798 | |||
633 | IMPLEMENT_STACK_OF(X509) | 799 | IMPLEMENT_STACK_OF(X509) |
634 | IMPLEMENT_ASN1_SET_OF(X509) | 800 | IMPLEMENT_ASN1_SET_OF(X509) |
635 | 801 | ||