diff options
author | beck <> | 2021-11-04 23:52:34 +0000 |
---|---|---|
committer | beck <> | 2021-11-04 23:52:34 +0000 |
commit | 244374d8dda906a87c40f39a8ed949cf07a1c8f3 (patch) | |
tree | 3ca9bd91a3930e5f3e28873aa362dffdb8cf6227 | |
parent | b866948734d2d995d78efdc04fb93574782722fa (diff) | |
download | openbsd-244374d8dda906a87c40f39a8ed949cf07a1c8f3.tar.gz openbsd-244374d8dda906a87c40f39a8ed949cf07a1c8f3.tar.bz2 openbsd-244374d8dda906a87c40f39a8ed949cf07a1c8f3.zip |
Cache sha512 hash and parsed not_before and not_after with X509 cert.
Replace sha1 hash use with sha512 for certificate comparisons internal
to the library. use the cached sha512 for the validator's verification
cache.
Reduces our recomputation of hashes, and heavy use of time1 time
conversion functions noticed bu claudio@ in rpki client.
ok jsing@ tb@
-rw-r--r-- | src/lib/libcrypto/ts/ts_rsp_sign.c | 10 | ||||
-rw-r--r-- | src/lib/libcrypto/ts/ts_rsp_verify.c | 11 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_cmp.c | 4 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_internal.h | 6 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_lcl.h | 12 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_purp.c | 10 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_verify.c | 172 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_verify.h | 3 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 56 |
9 files changed, 149 insertions, 135 deletions
diff --git a/src/lib/libcrypto/ts/ts_rsp_sign.c b/src/lib/libcrypto/ts/ts_rsp_sign.c index 828407aa4b..cbd7039abe 100644 --- a/src/lib/libcrypto/ts/ts_rsp_sign.c +++ b/src/lib/libcrypto/ts/ts_rsp_sign.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ts_rsp_sign.c,v 1.24 2021/11/01 20:53:08 tb Exp $ */ | 1 | /* $OpenBSD: ts_rsp_sign.c,v 1.25 2021/11/04 23:52:34 beck Exp $ */ |
2 | /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL | 2 | /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL |
3 | * project 2002. | 3 | * project 2002. |
4 | */ | 4 | */ |
@@ -849,14 +849,18 @@ ESS_CERT_ID_new_init(X509 *cert, int issuer_needed) | |||
849 | { | 849 | { |
850 | ESS_CERT_ID *cid = NULL; | 850 | ESS_CERT_ID *cid = NULL; |
851 | GENERAL_NAME *name = NULL; | 851 | GENERAL_NAME *name = NULL; |
852 | unsigned char cert_hash[TS_HASH_LEN]; | ||
852 | 853 | ||
853 | /* Recompute SHA1 hash of certificate if necessary (side effect). */ | 854 | /* Recompute SHA1 hash of certificate if necessary (side effect). */ |
854 | X509_check_purpose(cert, -1, 0); | 855 | X509_check_purpose(cert, -1, 0); |
855 | 856 | ||
856 | if (!(cid = ESS_CERT_ID_new())) | 857 | if (!(cid = ESS_CERT_ID_new())) |
857 | goto err; | 858 | goto err; |
858 | if (!ASN1_OCTET_STRING_set(cid->hash, cert->sha1_hash, | 859 | |
859 | sizeof(cert->sha1_hash))) | 860 | if (!X509_digest(cert, TS_HASH_EVP, cert_hash, NULL)) |
861 | goto err; | ||
862 | |||
863 | if (!ASN1_OCTET_STRING_set(cid->hash, cert_hash, sizeof(cert_hash))) | ||
860 | goto err; | 864 | goto err; |
861 | 865 | ||
862 | /* Setting the issuer/serial if requested. */ | 866 | /* Setting the issuer/serial if requested. */ |
diff --git a/src/lib/libcrypto/ts/ts_rsp_verify.c b/src/lib/libcrypto/ts/ts_rsp_verify.c index 2e72ff47ae..07578945cb 100644 --- a/src/lib/libcrypto/ts/ts_rsp_verify.c +++ b/src/lib/libcrypto/ts/ts_rsp_verify.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ts_rsp_verify.c,v 1.22 2021/11/01 20:53:08 tb Exp $ */ | 1 | /* $OpenBSD: ts_rsp_verify.c,v 1.23 2021/11/04 23:52:34 beck Exp $ */ |
2 | /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL | 2 | /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL |
3 | * project 2002. | 3 | * project 2002. |
4 | */ | 4 | */ |
@@ -325,10 +325,14 @@ static int | |||
325 | TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) | 325 | TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) |
326 | { | 326 | { |
327 | int i; | 327 | int i; |
328 | unsigned char cert_hash[TS_HASH_LEN]; | ||
328 | 329 | ||
329 | if (!cert_ids || !cert) | 330 | if (!cert_ids || !cert) |
330 | return -1; | 331 | return -1; |
331 | 332 | ||
333 | if (!X509_digest(cert, TS_HASH_EVP, cert_hash, NULL)) | ||
334 | return -1; | ||
335 | |||
332 | /* Recompute SHA1 hash of certificate if necessary (side effect). */ | 336 | /* Recompute SHA1 hash of certificate if necessary (side effect). */ |
333 | X509_check_purpose(cert, -1, 0); | 337 | X509_check_purpose(cert, -1, 0); |
334 | 338 | ||
@@ -337,9 +341,8 @@ TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) | |||
337 | ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i); | 341 | ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i); |
338 | 342 | ||
339 | /* Check the SHA-1 hash first. */ | 343 | /* Check the SHA-1 hash first. */ |
340 | if (cid->hash->length == sizeof(cert->sha1_hash) && | 344 | if (cid->hash->length == TS_HASH_LEN && !memcmp(cid->hash->data, |
341 | !memcmp(cid->hash->data, cert->sha1_hash, | 345 | cert_hash, TS_HASH_LEN)) { |
342 | sizeof(cert->sha1_hash))) { | ||
343 | /* Check the issuer/serial as well if specified. */ | 346 | /* Check the issuer/serial as well if specified. */ |
344 | ESS_ISSUER_SERIAL *is = cid->issuer_serial; | 347 | ESS_ISSUER_SERIAL *is = cid->issuer_serial; |
345 | if (!is || !TS_issuer_serial_cmp(is, cert->cert_info)) | 348 | if (!is || !TS_issuer_serial_cmp(is, cert->cert_info)) |
diff --git a/src/lib/libcrypto/x509/x509_cmp.c b/src/lib/libcrypto/x509/x509_cmp.c index 134a082730..bc944b71d7 100644 --- a/src/lib/libcrypto/x509/x509_cmp.c +++ b/src/lib/libcrypto/x509/x509_cmp.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_cmp.c,v 1.36 2021/11/01 20:53:08 tb Exp $ */ | 1 | /* $OpenBSD: x509_cmp.c,v 1.37 2021/11/04 23:52:34 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 | * |
@@ -215,7 +215,7 @@ X509_cmp(const X509 *a, const X509 *b) | |||
215 | X509_check_purpose((X509 *)a, -1, 0); | 215 | X509_check_purpose((X509 *)a, -1, 0); |
216 | X509_check_purpose((X509 *)b, -1, 0); | 216 | X509_check_purpose((X509 *)b, -1, 0); |
217 | 217 | ||
218 | return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); | 218 | return memcmp(a->hash, b->hash, X509_CERT_HASH_LEN); |
219 | } | 219 | } |
220 | #endif | 220 | #endif |
221 | 221 | ||
diff --git a/src/lib/libcrypto/x509/x509_internal.h b/src/lib/libcrypto/x509/x509_internal.h index 7ca67a853b..a9b584b13e 100644 --- a/src/lib/libcrypto/x509/x509_internal.h +++ b/src/lib/libcrypto/x509/x509_internal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_internal.h,v 1.14 2021/11/01 20:53:08 tb Exp $ */ | 1 | /* $OpenBSD: x509_internal.h,v 1.15 2021/11/04 23:52:34 beck Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> |
4 | * | 4 | * |
@@ -96,8 +96,7 @@ int x509_vfy_callback_indicate_success(X509_STORE_CTX *ctx); | |||
96 | void x509v3_cache_extensions(X509 *x); | 96 | void x509v3_cache_extensions(X509 *x); |
97 | X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x); | 97 | X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x); |
98 | 98 | ||
99 | int x509_verify_asn1_time_to_tm(const ASN1_TIME *atime, struct tm *tm, | 99 | time_t x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notafter); |
100 | int notafter); | ||
101 | 100 | ||
102 | struct x509_verify_ctx *x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc); | 101 | struct x509_verify_ctx *x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc); |
103 | 102 | ||
@@ -132,6 +131,7 @@ int x509_constraints_check(struct x509_constraints_names *names, | |||
132 | struct x509_constraints_names *excluded, int *error); | 131 | struct x509_constraints_names *excluded, int *error); |
133 | int x509_constraints_chain(STACK_OF(X509) *chain, int *error, | 132 | int x509_constraints_chain(STACK_OF(X509) *chain, int *error, |
134 | int *depth); | 133 | int *depth); |
134 | void x509_verify_cert_info_populate(X509 *cert); | ||
135 | 135 | ||
136 | __END_HIDDEN_DECLS | 136 | __END_HIDDEN_DECLS |
137 | 137 | ||
diff --git a/src/lib/libcrypto/x509/x509_lcl.h b/src/lib/libcrypto/x509/x509_lcl.h index 1b352aee78..804fff48fc 100644 --- a/src/lib/libcrypto/x509/x509_lcl.h +++ b/src/lib/libcrypto/x509/x509_lcl.h | |||
@@ -61,6 +61,12 @@ | |||
61 | 61 | ||
62 | __BEGIN_HIDDEN_DECLS | 62 | __BEGIN_HIDDEN_DECLS |
63 | 63 | ||
64 | #define TS_HASH_EVP EVP_sha1() | ||
65 | #define TS_HASH_LEN SHA_DIGEST_LENGTH | ||
66 | |||
67 | #define X509_CERT_HASH_EVP EVP_sha512() | ||
68 | #define X509_CERT_HASH_LEN SHA512_DIGEST_LENGTH | ||
69 | |||
64 | struct X509_pubkey_st { | 70 | struct X509_pubkey_st { |
65 | X509_ALGOR *algor; | 71 | X509_ALGOR *algor; |
66 | ASN1_BIT_STRING *public_key; | 72 | ASN1_BIT_STRING *public_key; |
@@ -177,9 +183,9 @@ struct x509_st { | |||
177 | STACK_OF(IPAddressFamily) *rfc3779_addr; | 183 | STACK_OF(IPAddressFamily) *rfc3779_addr; |
178 | struct ASIdentifiers_st *rfc3779_asid; | 184 | struct ASIdentifiers_st *rfc3779_asid; |
179 | #endif | 185 | #endif |
180 | #ifndef OPENSSL_NO_SHA | 186 | unsigned char hash[X509_CERT_HASH_LEN]; |
181 | unsigned char sha1_hash[SHA_DIGEST_LENGTH]; | 187 | time_t not_before; |
182 | #endif | 188 | time_t not_after; |
183 | X509_CERT_AUX *aux; | 189 | X509_CERT_AUX *aux; |
184 | } /* X509 */; | 190 | } /* X509 */; |
185 | 191 | ||
diff --git a/src/lib/libcrypto/x509/x509_purp.c b/src/lib/libcrypto/x509/x509_purp.c index 67a7b51fb1..a05c0388ac 100644 --- a/src/lib/libcrypto/x509/x509_purp.c +++ b/src/lib/libcrypto/x509/x509_purp.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_purp.c,v 1.12 2021/11/01 20:53:08 tb Exp $ */ | 1 | /* $OpenBSD: x509_purp.c,v 1.13 2021/11/04 23:52:34 beck Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2001. | 3 | * project 2001. |
4 | */ | 4 | */ |
@@ -65,6 +65,7 @@ | |||
65 | #include <openssl/x509v3.h> | 65 | #include <openssl/x509v3.h> |
66 | #include <openssl/x509_vfy.h> | 66 | #include <openssl/x509_vfy.h> |
67 | 67 | ||
68 | #include "x509_internal.h" | ||
68 | #include "x509_lcl.h" | 69 | #include "x509_lcl.h" |
69 | 70 | ||
70 | #define V1_ROOT (EXFLAG_V1|EXFLAG_SS) | 71 | #define V1_ROOT (EXFLAG_V1|EXFLAG_SS) |
@@ -449,9 +450,7 @@ x509v3_cache_extensions(X509 *x) | |||
449 | if (x->ex_flags & EXFLAG_SET) | 450 | if (x->ex_flags & EXFLAG_SET) |
450 | return; | 451 | return; |
451 | 452 | ||
452 | #ifndef OPENSSL_NO_SHA | 453 | X509_digest(x, X509_CERT_HASH_EVP, x->hash, NULL); |
453 | X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); | ||
454 | #endif | ||
455 | 454 | ||
456 | /* V1 should mean no extensions ... */ | 455 | /* V1 should mean no extensions ... */ |
457 | if (!X509_get_version(x)) | 456 | if (!X509_get_version(x)) |
@@ -618,6 +617,9 @@ x509v3_cache_extensions(X509 *x) | |||
618 | break; | 617 | break; |
619 | } | 618 | } |
620 | } | 619 | } |
620 | |||
621 | x509_verify_cert_info_populate(x); | ||
622 | |||
621 | x->ex_flags |= EXFLAG_SET; | 623 | x->ex_flags |= EXFLAG_SET; |
622 | } | 624 | } |
623 | 625 | ||
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c index 8bcc647149..b9ba2bee3c 100644 --- a/src/lib/libcrypto/x509/x509_verify.c +++ b/src/lib/libcrypto/x509/x509_verify.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_verify.c,v 1.50 2021/10/26 15:14:18 job Exp $ */ | 1 | /* $OpenBSD: x509_verify.c,v 1.51 2021/11/04 23:52:34 beck Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org> |
4 | * | 4 | * |
@@ -38,7 +38,58 @@ static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, | |||
38 | size_t depth, int error, int ok); | 38 | size_t depth, int error, int ok); |
39 | static void x509_verify_chain_free(struct x509_verify_chain *chain); | 39 | static void x509_verify_chain_free(struct x509_verify_chain *chain); |
40 | 40 | ||
41 | #define X509_VERIFY_CERT_HASH (EVP_sha512()) | 41 | /* |
42 | * Parse an asn1 to a representable time_t as per RFC 5280 rules. | ||
43 | * Returns -1 if that can't be done for any reason. | ||
44 | */ | ||
45 | time_t | ||
46 | x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notAfter) | ||
47 | { | ||
48 | struct tm tm = { 0 }; | ||
49 | int type; | ||
50 | |||
51 | type = ASN1_time_parse(atime->data, atime->length, &tm, atime->type); | ||
52 | if (type == -1) | ||
53 | return -1; | ||
54 | |||
55 | /* RFC 5280 section 4.1.2.5 */ | ||
56 | if (tm.tm_year < 150 && type != V_ASN1_UTCTIME) | ||
57 | return -1; | ||
58 | if (tm.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME) | ||
59 | return -1; | ||
60 | |||
61 | if (notAfter) { | ||
62 | /* | ||
63 | * If we are a completely broken operating system with a | ||
64 | * 32 bit time_t, and we have been told this is a notAfter | ||
65 | * date, limit the date to a 32 bit representable value. | ||
66 | */ | ||
67 | if (!ASN1_time_tm_clamp_notafter(&tm)) | ||
68 | return -1; | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * Defensively fail if the time string is not representable as | ||
73 | * a time_t. A time_t must be sane if you care about times after | ||
74 | * Jan 19 2038. | ||
75 | */ | ||
76 | return timegm(&tm); | ||
77 | } | ||
78 | |||
79 | /* | ||
80 | * Cache certificate hash, and values parsed out of an X509. | ||
81 | * called from cache_extensions() | ||
82 | */ | ||
83 | void | ||
84 | x509_verify_cert_info_populate(X509 *cert) | ||
85 | { | ||
86 | /* | ||
87 | * Parse and save the cert times, or remember that they | ||
88 | * are unacceptable/unparsable. | ||
89 | */ | ||
90 | cert->not_before = x509_verify_asn1_time_to_time_t(X509_get_notBefore(cert), 0); | ||
91 | cert->not_after = x509_verify_asn1_time_to_time_t(X509_get_notAfter(cert), 1); | ||
92 | } | ||
42 | 93 | ||
43 | struct x509_verify_chain * | 94 | struct x509_verify_chain * |
44 | x509_verify_chain_new(void) | 95 | x509_verify_chain_new(void) |
@@ -194,6 +245,7 @@ x509_verify_cert_cache_extensions(X509 *cert) { | |||
194 | } | 245 | } |
195 | if (cert->ex_flags & EXFLAG_INVALID) | 246 | if (cert->ex_flags & EXFLAG_INVALID) |
196 | return 0; | 247 | return 0; |
248 | |||
197 | return (cert->ex_flags & EXFLAG_SET); | 249 | return (cert->ex_flags & EXFLAG_SET); |
198 | } | 250 | } |
199 | 251 | ||
@@ -455,22 +507,15 @@ x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent, | |||
455 | } | 507 | } |
456 | 508 | ||
457 | static int | 509 | static int |
458 | x509_verify_parent_signature(X509 *parent, X509 *child, | 510 | x509_verify_parent_signature(X509 *parent, X509 *child, int *error) |
459 | unsigned char *child_md, int *error) | ||
460 | { | 511 | { |
461 | unsigned char parent_md[EVP_MAX_MD_SIZE] = { 0 }; | ||
462 | EVP_PKEY *pkey; | 512 | EVP_PKEY *pkey; |
463 | int cached; | 513 | int cached; |
464 | int ret = 0; | 514 | int ret = 0; |
465 | 515 | ||
466 | /* Use cached value if we have it */ | 516 | /* Use cached value if we have it */ |
467 | if (child_md != NULL) { | 517 | if ((cached = x509_issuer_cache_find(parent->hash, child->hash)) >= 0) |
468 | if (!X509_digest(parent, X509_VERIFY_CERT_HASH, parent_md, | 518 | return cached; |
469 | NULL)) | ||
470 | return 0; | ||
471 | if ((cached = x509_issuer_cache_find(parent_md, child_md)) >= 0) | ||
472 | return cached; | ||
473 | } | ||
474 | 519 | ||
475 | /* Check signature. Did parent sign child? */ | 520 | /* Check signature. Did parent sign child? */ |
476 | if ((pkey = X509_get_pubkey(parent)) == NULL) { | 521 | if ((pkey = X509_get_pubkey(parent)) == NULL) { |
@@ -483,8 +528,7 @@ x509_verify_parent_signature(X509 *parent, X509 *child, | |||
483 | ret = 1; | 528 | ret = 1; |
484 | 529 | ||
485 | /* Add result to cache */ | 530 | /* Add result to cache */ |
486 | if (child_md != NULL) | 531 | x509_issuer_cache_add(parent->hash, child->hash, ret); |
487 | x509_issuer_cache_add(parent_md, child_md, ret); | ||
488 | 532 | ||
489 | EVP_PKEY_free(pkey); | 533 | EVP_PKEY_free(pkey); |
490 | 534 | ||
@@ -493,8 +537,8 @@ x509_verify_parent_signature(X509 *parent, X509 *child, | |||
493 | 537 | ||
494 | static int | 538 | static int |
495 | x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, | 539 | x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, |
496 | unsigned char *cert_md, int is_root_cert, X509 *candidate, | 540 | int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain, |
497 | struct x509_verify_chain *current_chain, int full_chain) | 541 | int full_chain) |
498 | { | 542 | { |
499 | int depth = sk_X509_num(current_chain->certs); | 543 | int depth = sk_X509_num(current_chain->certs); |
500 | struct x509_verify_chain *new_chain; | 544 | struct x509_verify_chain *new_chain; |
@@ -514,8 +558,7 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, | |||
514 | return 0; | 558 | return 0; |
515 | } | 559 | } |
516 | 560 | ||
517 | if (!x509_verify_parent_signature(candidate, cert, cert_md, | 561 | if (!x509_verify_parent_signature(candidate, cert, &ctx->error)) { |
518 | &ctx->error)) { | ||
519 | if (!x509_verify_cert_error(ctx, candidate, depth, | 562 | if (!x509_verify_cert_error(ctx, candidate, depth, |
520 | ctx->error, 0)) | 563 | ctx->error, 0)) |
521 | return 0; | 564 | return 0; |
@@ -579,7 +622,6 @@ static void | |||
579 | x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | 622 | x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, |
580 | struct x509_verify_chain *current_chain, int full_chain) | 623 | struct x509_verify_chain *current_chain, int full_chain) |
581 | { | 624 | { |
582 | unsigned char cert_md[EVP_MAX_MD_SIZE] = { 0 }; | ||
583 | X509 *candidate; | 625 | X509 *candidate; |
584 | int i, depth, count, ret, is_root; | 626 | int i, depth, count, ret, is_root; |
585 | 627 | ||
@@ -600,11 +642,6 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | |||
600 | X509_V_ERR_CERT_CHAIN_TOO_LONG, 0)) | 642 | X509_V_ERR_CERT_CHAIN_TOO_LONG, 0)) |
601 | return; | 643 | return; |
602 | 644 | ||
603 | if (!X509_digest(cert, X509_VERIFY_CERT_HASH, cert_md, NULL) && | ||
604 | !x509_verify_cert_error(ctx, cert, depth, | ||
605 | X509_V_ERR_UNSPECIFIED, 0)) | ||
606 | return; | ||
607 | |||
608 | count = ctx->chains_count; | 645 | count = ctx->chains_count; |
609 | 646 | ||
610 | ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; | 647 | ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; |
@@ -640,7 +677,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | |||
640 | is_root = !full_chain || | 677 | is_root = !full_chain || |
641 | x509_verify_cert_self_signed(candidate); | 678 | x509_verify_cert_self_signed(candidate); |
642 | x509_verify_consider_candidate(ctx, cert, | 679 | x509_verify_consider_candidate(ctx, cert, |
643 | cert_md, is_root, candidate, current_chain, | 680 | is_root, candidate, current_chain, |
644 | full_chain); | 681 | full_chain); |
645 | } | 682 | } |
646 | X509_free(candidate); | 683 | X509_free(candidate); |
@@ -653,7 +690,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | |||
653 | is_root = !full_chain || | 690 | is_root = !full_chain || |
654 | x509_verify_cert_self_signed(candidate); | 691 | x509_verify_cert_self_signed(candidate); |
655 | x509_verify_consider_candidate(ctx, cert, | 692 | x509_verify_consider_candidate(ctx, cert, |
656 | cert_md, is_root, candidate, current_chain, | 693 | is_root, candidate, current_chain, |
657 | full_chain); | 694 | full_chain); |
658 | } | 695 | } |
659 | } | 696 | } |
@@ -665,7 +702,7 @@ x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, | |||
665 | candidate = sk_X509_value(ctx->intermediates, i); | 702 | candidate = sk_X509_value(ctx->intermediates, i); |
666 | if (x509_verify_potential_parent(ctx, candidate, cert)) { | 703 | if (x509_verify_potential_parent(ctx, candidate, cert)) { |
667 | x509_verify_consider_candidate(ctx, cert, | 704 | x509_verify_consider_candidate(ctx, cert, |
668 | cert_md, 0, candidate, current_chain, | 705 | 0, candidate, current_chain, |
669 | full_chain); | 706 | full_chain); |
670 | } | 707 | } |
671 | } | 708 | } |
@@ -748,47 +785,9 @@ x509_verify_set_check_time(struct x509_verify_ctx *ctx) { | |||
748 | return 1; | 785 | return 1; |
749 | } | 786 | } |
750 | 787 | ||
751 | int | ||
752 | x509_verify_asn1_time_to_tm(const ASN1_TIME *atime, struct tm *tm, int notafter) | ||
753 | { | ||
754 | int type; | ||
755 | |||
756 | type = ASN1_time_parse(atime->data, atime->length, tm, atime->type); | ||
757 | if (type == -1) | ||
758 | return 0; | ||
759 | |||
760 | /* RFC 5280 section 4.1.2.5 */ | ||
761 | if (tm->tm_year < 150 && type != V_ASN1_UTCTIME) | ||
762 | return 0; | ||
763 | if (tm->tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME) | ||
764 | return 0; | ||
765 | |||
766 | if (notafter) { | ||
767 | /* | ||
768 | * If we are a completely broken operating system with a | ||
769 | * 32 bit time_t, and we have been told this is a notafter | ||
770 | * date, limit the date to a 32 bit representable value. | ||
771 | */ | ||
772 | if (!ASN1_time_tm_clamp_notafter(tm)) | ||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | /* | ||
777 | * Defensively fail if the time string is not representable as | ||
778 | * a time_t. A time_t must be sane if you care about times after | ||
779 | * Jan 19 2038. | ||
780 | */ | ||
781 | if (timegm(tm) == -1) | ||
782 | return 0; | ||
783 | |||
784 | return 1; | ||
785 | } | ||
786 | |||
787 | static int | 788 | static int |
788 | x509_verify_cert_time(int is_notafter, const ASN1_TIME *cert_asn1, | 789 | x509_verify_cert_times(X509 *cert, time_t *cmp_time, int *error) |
789 | time_t *cmp_time, int *error) | ||
790 | { | 790 | { |
791 | struct tm cert_tm, when_tm; | ||
792 | time_t when; | 791 | time_t when; |
793 | 792 | ||
794 | if (cmp_time == NULL) | 793 | if (cmp_time == NULL) |
@@ -796,29 +795,21 @@ x509_verify_cert_time(int is_notafter, const ASN1_TIME *cert_asn1, | |||
796 | else | 795 | else |
797 | when = *cmp_time; | 796 | when = *cmp_time; |
798 | 797 | ||
799 | if (!x509_verify_asn1_time_to_tm(cert_asn1, &cert_tm, | 798 | if (cert->not_before == -1) { |
800 | is_notafter)) { | 799 | *error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; |
801 | *error = is_notafter ? | ||
802 | X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD : | ||
803 | X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; | ||
804 | return 0; | 800 | return 0; |
805 | } | 801 | } |
806 | 802 | if (when < cert->not_before) { | |
807 | if (gmtime_r(&when, &when_tm) == NULL) { | 803 | *error = X509_V_ERR_CERT_NOT_YET_VALID; |
808 | *error = X509_V_ERR_UNSPECIFIED; | ||
809 | return 0; | 804 | return 0; |
810 | } | 805 | } |
811 | 806 | if (cert->not_after == -1) { | |
812 | if (is_notafter) { | 807 | *error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; |
813 | if (ASN1_time_tm_cmp(&cert_tm, &when_tm) == -1) { | 808 | return 0; |
814 | *error = X509_V_ERR_CERT_HAS_EXPIRED; | 809 | } |
815 | return 0; | 810 | if (when > cert->not_after) { |
816 | } | 811 | *error = X509_V_ERR_CERT_HAS_EXPIRED; |
817 | } else { | 812 | return 0; |
818 | if (ASN1_time_tm_cmp(&cert_tm, &when_tm) == 1) { | ||
819 | *error = X509_V_ERR_CERT_NOT_YET_VALID; | ||
820 | return 0; | ||
821 | } | ||
822 | } | 813 | } |
823 | 814 | ||
824 | return 1; | 815 | return 1; |
@@ -924,15 +915,8 @@ x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, | |||
924 | } | 915 | } |
925 | 916 | ||
926 | if (x509_verify_set_check_time(ctx)) { | 917 | if (x509_verify_set_check_time(ctx)) { |
927 | if (!x509_verify_cert_time(0, X509_get_notBefore(cert), | 918 | if (!x509_verify_cert_times(cert, ctx->check_time, |
928 | ctx->check_time, &ctx->error)) { | 919 | &ctx->error)) { |
929 | if (!x509_verify_cert_error(ctx, cert, depth, | ||
930 | ctx->error, 0)) | ||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | if (!x509_verify_cert_time(1, X509_get_notAfter(cert), | ||
935 | ctx->check_time, &ctx->error)) { | ||
936 | if (!x509_verify_cert_error(ctx, cert, depth, | 920 | if (!x509_verify_cert_error(ctx, cert, depth, |
937 | ctx->error, 0)) | 921 | ctx->error, 0)) |
938 | return 0; | 922 | return 0; |
diff --git a/src/lib/libcrypto/x509/x509_verify.h b/src/lib/libcrypto/x509/x509_verify.h index a097404f2e..d8d2cb0b5f 100644 --- a/src/lib/libcrypto/x509/x509_verify.h +++ b/src/lib/libcrypto/x509/x509_verify.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_verify.h,v 1.1 2020/09/13 15:06:17 beck Exp $ */ | 1 | /* $OpenBSD: x509_verify.h,v 1.2 2021/11/04 23:52:34 beck Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> |
4 | * | 4 | * |
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #ifdef LIBRESSL_INTERNAL | 20 | #ifdef LIBRESSL_INTERNAL |
21 | struct x509_verify_ctx; | 21 | struct x509_verify_ctx; |
22 | struct x509_verify_cert_info; | ||
22 | typedef struct x509_verify_ctx X509_VERIFY_CTX; | 23 | typedef struct x509_verify_ctx X509_VERIFY_CTX; |
23 | 24 | ||
24 | X509_VERIFY_CTX *x509_verify_ctx_new(STACK_OF(X509) *roots); | 25 | X509_VERIFY_CTX *x509_verify_ctx_new(STACK_OF(X509) *roots); |
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index 664474139c..3b0d6dfa35 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.93 2021/11/01 20:53:08 tb Exp $ */ | 1 | /* $OpenBSD: x509_vfy.c,v 1.94 2021/11/04 23:52:34 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 | * |
@@ -1843,6 +1843,18 @@ verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err) | |||
1843 | return ctx->verify_cb(0, ctx); | 1843 | return ctx->verify_cb(0, ctx); |
1844 | } | 1844 | } |
1845 | 1845 | ||
1846 | |||
1847 | /* Mimic OpenSSL '0 for failure' ick */ | ||
1848 | static int | ||
1849 | time_t_bogocmp(time_t a, time_t b) | ||
1850 | { | ||
1851 | if (a == -1 || b == -1) | ||
1852 | return 0; | ||
1853 | if (a <= b) | ||
1854 | return -1; | ||
1855 | return 1; | ||
1856 | } | ||
1857 | |||
1846 | /* | 1858 | /* |
1847 | * Check certificate validity times. | 1859 | * Check certificate validity times. |
1848 | * | 1860 | * |
@@ -1854,17 +1866,21 @@ verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err) | |||
1854 | int | 1866 | int |
1855 | x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) | 1867 | x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) |
1856 | { | 1868 | { |
1857 | time_t *ptime; | 1869 | time_t ptime; |
1858 | int i; | 1870 | int i; |
1859 | 1871 | ||
1860 | if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) | 1872 | if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) |
1861 | ptime = &ctx->param->check_time; | 1873 | ptime = ctx->param->check_time; |
1862 | else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) | 1874 | else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) |
1863 | return 1; | 1875 | return 1; |
1864 | else | 1876 | else |
1865 | ptime = NULL; | 1877 | ptime = time(NULL); |
1878 | |||
1879 | if (x->ex_flags & EXFLAG_SET) | ||
1880 | i = time_t_bogocmp(x->not_before, ptime); | ||
1881 | else | ||
1882 | i = X509_cmp_time(X509_get_notBefore(x), &ptime); | ||
1866 | 1883 | ||
1867 | i = X509_cmp_time(X509_get_notBefore(x), ptime); | ||
1868 | if (i >= 0 && depth < 0) | 1884 | if (i >= 0 && depth < 0) |
1869 | return 0; | 1885 | return 0; |
1870 | if (i == 0 && !verify_cb_cert(ctx, x, depth, | 1886 | if (i == 0 && !verify_cb_cert(ctx, x, depth, |
@@ -1874,7 +1890,11 @@ x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) | |||
1874 | X509_V_ERR_CERT_NOT_YET_VALID)) | 1890 | X509_V_ERR_CERT_NOT_YET_VALID)) |
1875 | return 0; | 1891 | return 0; |
1876 | 1892 | ||
1877 | i = X509_cmp_time_internal(X509_get_notAfter(x), ptime, 1); | 1893 | if (x->ex_flags & EXFLAG_SET) |
1894 | i = time_t_bogocmp(x->not_after, ptime); | ||
1895 | else | ||
1896 | i = X509_cmp_time_internal(X509_get_notAfter(x), &ptime, 1); | ||
1897 | |||
1878 | if (i <= 0 && depth < 0) | 1898 | if (i <= 0 && depth < 0) |
1879 | return 0; | 1899 | return 0; |
1880 | if (i == 0 && !verify_cb_cert(ctx, x, depth, | 1900 | if (i == 0 && !verify_cb_cert(ctx, x, depth, |
@@ -1883,6 +1903,7 @@ x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) | |||
1883 | if (i < 0 && !verify_cb_cert(ctx, x, depth, | 1903 | if (i < 0 && !verify_cb_cert(ctx, x, depth, |
1884 | X509_V_ERR_CERT_HAS_EXPIRED)) | 1904 | X509_V_ERR_CERT_HAS_EXPIRED)) |
1885 | return 0; | 1905 | return 0; |
1906 | |||
1886 | return 1; | 1907 | return 1; |
1887 | } | 1908 | } |
1888 | 1909 | ||
@@ -1994,30 +2015,23 @@ X509_cmp_current_time(const ASN1_TIME *ctm) | |||
1994 | * 0 on error. | 2015 | * 0 on error. |
1995 | */ | 2016 | */ |
1996 | static int | 2017 | static int |
1997 | X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time, int clamp_notafter) | 2018 | X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time, int is_notafter) |
1998 | { | 2019 | { |
1999 | time_t compare; | 2020 | time_t compare, cert_time; |
2000 | struct tm tm1, tm2; | ||
2001 | int ret = 0; | ||
2002 | 2021 | ||
2003 | if (cmp_time == NULL) | 2022 | if (cmp_time == NULL) |
2004 | compare = time(NULL); | 2023 | compare = time(NULL); |
2005 | else | 2024 | else |
2006 | compare = *cmp_time; | 2025 | compare = *cmp_time; |
2007 | 2026 | ||
2008 | memset(&tm1, 0, sizeof(tm1)); | 2027 | if ((cert_time = x509_verify_asn1_time_to_time_t(ctm, is_notafter)) == |
2028 | -1) | ||
2029 | return 0; /* invalid time */ | ||
2009 | 2030 | ||
2010 | if (!x509_verify_asn1_time_to_tm(ctm, &tm1, clamp_notafter)) | 2031 | if (cert_time <= compare) |
2011 | goto out; /* invalid time */ | 2032 | return -1; /* 0 is used for error, so map same to less than */ |
2012 | 2033 | ||
2013 | if (gmtime_r(&compare, &tm2) == NULL) | 2034 | return 1; |
2014 | goto out; | ||
2015 | |||
2016 | ret = ASN1_time_tm_cmp(&tm1, &tm2); | ||
2017 | if (ret == 0) | ||
2018 | ret = -1; /* 0 is used for error, so map same to less than */ | ||
2019 | out: | ||
2020 | return (ret); | ||
2021 | } | 2035 | } |
2022 | 2036 | ||
2023 | int | 2037 | int |