summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2025-02-08 10:12:00 +0000
committertb <>2025-02-08 10:12:00 +0000
commit6c52bae3df522ccb0c1f2d5138b4c0c6bad8152c (patch)
treea2c0f3c491127e4eb760af97a3fc828a3b541fe1
parente5c3598995f7ea0447aa4041ff08a6e099042a22 (diff)
downloadopenbsd-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.c3
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c52
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() */
534static int 535static int
535x509_verify_parent_signature(X509 *parent, X509 *child, int *error) 536x509_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() */
1556static int
1557x509_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 */
1555static int 1587static int
1556x509_vfy_check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) 1588x509_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
1652err: 1671 err:
1653 EVP_PKEY_free(ikey);
1654 return ok; 1672 return ok;
1655} 1673}
1656 1674