From: William Lallemand Date: Fri, 31 Jul 2026 15:26:21 +0000 (+0000) Subject: MINOR: ech: introduce an ech_store type and helpers in load_echkeys() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=744a7751452d9dc387254a879203a3a36e895b6d;p=thirdparty%2Fhaproxy.git MINOR: ech: introduce an ech_store type and helpers in load_echkeys() Alias OSSL_ECHSTORE as ech_store, and wrap OSSL_ECHSTORE_new(), OSSL_ECHSTORE_free(), SSL_CTX_set1_echstore() and the per-file PEM loading loop behind ech_store_new(), ech_store_free(), ech_store_set_ctx() and ech_store_load_file(). Use them in load_echkeys() instead of the OpenSSL calls directly. ech_store_load_file() no longer reads strerror(errno) to explain a BIO_new_file() failure: that function records the fopen() failure reason in the crypto library's error queue, not in errno. load_echkeys() already drains that queue into *err on any failure, so just keeping the message filename-only here is enough to get the real reason appended. This is pure preparation with no functional change otherwise: a following commit will give ech_store and these four helpers an AWS-LC-specific body, so that load_echkeys() can be shared between the two SSL libraries. --- diff --git a/src/ech.c b/src/ech.c index 71adf9256..439358b6d 100644 --- a/src/ech.c +++ b/src/ech.c @@ -30,6 +30,57 @@ struct show_ech_ctx { } state; /* phase of the current dump */ }; +typedef OSSL_ECHSTORE ech_store; + +/* load one ECH key file into . + * Returns 1 on success, 0 on error, with a reason appended to *err. + */ +static int ech_store_load_file(ech_store *store, const char *filename, char **err) +{ + BIO *in; + int rv; + + in = BIO_new_file(filename, "r"); + if (!in) { + /* BIO_new_file() records the fopen() failure reason in the + * crypto library's error queue rather than leaving it in + * errno; load_echkeys() drains that queue into *err. + */ + memprintf(err, "%sunable to open ECH key file '%s'", + err && *err ? *err : "", filename); + return 0; + } + rv = (OSSL_ECHSTORE_read_pem(store, in, OSSL_ECH_FOR_RETRY) == 1); + if (!rv) + memprintf(err, "%sunable to load ECH key file '%s'", + err && *err ? *err : "", filename); + BIO_free_all(in); + return rv; +} + +/* allocate a new, empty ech_store. + * Returns the new store, or NULL on error. + */ +static ech_store *ech_store_new(void) +{ + return OSSL_ECHSTORE_new(NULL, NULL); +} + +/* release . may be NULL. + */ +static void ech_store_free(ech_store *store) +{ + OSSL_ECHSTORE_free(store); +} + +/* install as the active ECH configuration on . + * Returns 1 on success, 0 on error. + */ +static int ech_store_set_ctx(SSL_CTX *ctx, ech_store *store) +{ + return SSL_CTX_set1_echstore(ctx, store) == 1; +} + /* * load any key files called .ech we find in the named * directory @@ -41,11 +92,11 @@ int load_echkeys(SSL_CTX *ctx, char *dirname, int *loaded, char **err) int rv = 0, i, nrv = 0, somekeyworked = 0; char *den = NULL, *last4 = NULL, privname[PATH_MAX]; size_t elen = 0, nlen = 0; - OSSL_ECHSTORE *es; + ech_store *es; ERR_clear_error(); - es = OSSL_ECHSTORE_new(NULL, NULL); + es = ech_store_new(); if (es == NULL) goto end; nrv = scandir(dirname, &de_list, 0, alphasort); @@ -60,10 +111,6 @@ int load_echkeys(SSL_CTX *ctx, char *dirname, int *loaded, char **err) den = de->d_name; nlen = strlen(den); if (nlen > 4) { - BIO *in = NULL; - int load_failed = 1; - const int is_retry_config = OSSL_ECH_FOR_RETRY; - last4 = den + nlen - 4; if (strncmp(last4, ".ech", 4)) goto ignore_entry; @@ -73,25 +120,12 @@ int load_echkeys(SSL_CTX *ctx, char *dirname, int *loaded, char **err) if (stat(privname, &thestat) != 0) { memprintf(err, "%sunable to stat ECH key file '%s': %s", err && *err ? *err : "", privname, strerror(errno)); - goto failed; - } - if ((in = BIO_new_file(privname, "r")) == NULL) { - memprintf(err, "%sunable to open ECH key file '%s': %s", - err && *err ? *err : "", privname, strerror(errno)); - goto failed; - } - if (OSSL_ECHSTORE_read_pem(es, in, is_retry_config) != 1) { - memprintf(err, "%sunable to load ECH key file '%s'", - err && *err ? *err : "", privname); - goto failed; + goto end; } - load_failed = 0; - somekeyworked++; -failed: - BIO_free_all(in); /* a ".ech" file is expected to be valid; fail immediately */ - if (load_failed) + if (!ech_store_load_file(es, privname, err)) goto end; + somekeyworked++; } ignore_entry: ; @@ -102,21 +136,21 @@ ignore_entry: err && *err ? *err : "", dirname); goto end; } - if (OSSL_ECHSTORE_num_keys(es, loaded) != 1) + if (!OSSL_ECHSTORE_num_keys(es, loaded)) goto end; if (*loaded == 0) { memprintf(err, "%sno ECH key file in '%s' contains a usable private key", err && *err ? *err : "", dirname); goto end; } - if (1 != SSL_CTX_set1_echstore(ctx, es)) + if (!ech_store_set_ctx(ctx, es)) goto end; rv = 1; end: for (i = 0; i < nrv; i++) free(de_list[i]); free(de_list); - OSSL_ECHSTORE_free(es); + ech_store_free(es); if (!rv) { unsigned long ret;