diff options
author | tb <> | 2025-02-08 10:12:00 +0000 |
---|---|---|
committer | tb <> | 2025-02-08 10:12:00 +0000 |
commit | 6c52bae3df522ccb0c1f2d5138b4c0c6bad8152c (patch) | |
tree | a2c0f3c491127e4eb760af97a3fc828a3b541fe1 | |
parent | e5c3598995f7ea0447aa4041ff08a6e099042a22 (diff) | |
download | openbsd-6c52bae3df522ccb0c1f2d5138b4c0c6bad8152c.tar.gz openbsd-6c52bae3df522ccb0c1f2d5138b4c0c6bad8152c.tar.bz2 openbsd-6c52bae3df522ccb0c1f2d5138b4c0c6bad8152c.zip |
Cache CRLs in issuer cache
The issuer cache holds a pair of SHA-512 of parent and child cert plus
the result of the signature verification. Since CRLs also have a cached
hash of their DER, we can easily add them to the same cache. This way we
also avoid the cost of repeated signature verification for CRLs.
For ordinary workloads the cache is larger than necessary and it won't
currently take up more space than ~8M anyway, so the cost of doing this
is negligible.
For applications like rpki-client where the same (CA, CRL) pair is used
to verify multiple EE certs, the gain is significant. In fact, the current
worst case is a single pair being used for > 50k EE certs, responsible for
about 20-25% of the total runtime of an ordinary rpki-client run if a
hw-accelerated version of SHA-2 is available and even more if it isn't.
In both cases the cost of processing of this pair is reduced by more than
an order of magnitude.
The implementation is a translation of x509_verify_parent_signature() to
the case of CRLs and is entirely trivial thanks to the cache's design.
Found while investigating a performance bottleneck found by job
tested by job
ok beck
-rw-r--r-- | src/lib/libcrypto/x509/x509_verify.c | 3 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 52 |
2 files changed, 37 insertions, 18 deletions
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c index 235f488fc7..f25e2b3f15 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.72 2025/02/08 01:04:56 tb Exp $ */ | 1 | /* $OpenBSD: x509_verify.c,v 1.73 2025/02/08 10:12:00 tb 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 | * |
@@ -531,6 +531,7 @@ x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent, | |||
531 | return X509_check_issued(parent, child) == X509_V_OK; | 531 | return X509_check_issued(parent, child) == X509_V_OK; |
532 | } | 532 | } |
533 | 533 | ||
534 | /* Matches x509_crl_verify_parent_signature() */ | ||
534 | static int | 535 | static int |
535 | x509_verify_parent_signature(X509 *parent, X509 *child, int *error) | 536 | x509_verify_parent_signature(X509 *parent, X509 *child, int *error) |
536 | { | 537 | { |
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index 78ec8a4e81..5384686251 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.145 2024/08/28 07:37:50 tb Exp $ */ | 1 | /* $OpenBSD: x509_vfy.c,v 1.146 2025/02/08 10:12:00 tb 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 | * |
@@ -76,6 +76,7 @@ | |||
76 | 76 | ||
77 | #include "asn1_local.h" | 77 | #include "asn1_local.h" |
78 | #include "x509_internal.h" | 78 | #include "x509_internal.h" |
79 | #include "x509_issuer_cache.h" | ||
79 | #include "x509_local.h" | 80 | #include "x509_local.h" |
80 | 81 | ||
81 | /* CRL score values */ | 82 | /* CRL score values */ |
@@ -1551,12 +1552,42 @@ done: | |||
1551 | return 0; | 1552 | return 0; |
1552 | } | 1553 | } |
1553 | 1554 | ||
1555 | /* Matches x509_verify_parent_signature() */ | ||
1556 | static int | ||
1557 | x509_crl_verify_parent_signature(X509 *parent, X509_CRL *crl, int *error) | ||
1558 | { | ||
1559 | EVP_PKEY *pkey; | ||
1560 | int cached; | ||
1561 | int ret = 0; | ||
1562 | |||
1563 | /* Use cached value if we have it */ | ||
1564 | if ((cached = x509_issuer_cache_find(parent->hash, crl->hash)) >= 0) { | ||
1565 | if (cached == 0) | ||
1566 | *error = X509_V_ERR_CRL_SIGNATURE_FAILURE; | ||
1567 | return cached; | ||
1568 | } | ||
1569 | |||
1570 | /* Check signature. Did parent sign crl? */ | ||
1571 | if ((pkey = X509_get0_pubkey(parent)) == NULL) { | ||
1572 | *error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; | ||
1573 | return 0; | ||
1574 | } | ||
1575 | if (X509_CRL_verify(crl, pkey) <= 0) | ||
1576 | *error = X509_V_ERR_CRL_SIGNATURE_FAILURE; | ||
1577 | else | ||
1578 | ret = 1; | ||
1579 | |||
1580 | /* Add result to cache */ | ||
1581 | x509_issuer_cache_add(parent->hash, crl->hash, ret); | ||
1582 | |||
1583 | return ret; | ||
1584 | } | ||
1585 | |||
1554 | /* Check CRL validity */ | 1586 | /* Check CRL validity */ |
1555 | static int | 1587 | static int |
1556 | x509_vfy_check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) | 1588 | x509_vfy_check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) |
1557 | { | 1589 | { |
1558 | X509 *issuer = NULL; | 1590 | X509 *issuer = NULL; |
1559 | EVP_PKEY *ikey = NULL; | ||
1560 | int ok = 0, chnum, cnum; | 1591 | int ok = 0, chnum, cnum; |
1561 | 1592 | ||
1562 | cnum = ctx->error_depth; | 1593 | cnum = ctx->error_depth; |
@@ -1628,29 +1659,16 @@ x509_vfy_check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) | |||
1628 | goto err; | 1659 | goto err; |
1629 | } | 1660 | } |
1630 | 1661 | ||
1631 | /* Attempt to get issuer certificate public key */ | 1662 | if (!x509_crl_verify_parent_signature(issuer, crl, &ctx->error)) { |
1632 | ikey = X509_get_pubkey(issuer); | ||
1633 | |||
1634 | if (!ikey) { | ||
1635 | ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; | ||
1636 | ok = ctx->verify_cb(0, ctx); | 1663 | ok = ctx->verify_cb(0, ctx); |
1637 | if (!ok) | 1664 | if (!ok) |
1638 | goto err; | 1665 | goto err; |
1639 | } else { | ||
1640 | /* Verify CRL signature */ | ||
1641 | if (X509_CRL_verify(crl, ikey) <= 0) { | ||
1642 | ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE; | ||
1643 | ok = ctx->verify_cb(0, ctx); | ||
1644 | if (!ok) | ||
1645 | goto err; | ||
1646 | } | ||
1647 | } | 1666 | } |
1648 | } | 1667 | } |
1649 | 1668 | ||
1650 | ok = 1; | 1669 | ok = 1; |
1651 | 1670 | ||
1652 | err: | 1671 | err: |
1653 | EVP_PKEY_free(ikey); | ||
1654 | return ok; | 1672 | return ok; |
1655 | } | 1673 | } |
1656 | 1674 | ||