Skip to content

Commit f7d8cbe

Browse files
committed
apr_crypto_openssl: Add provider support on OpenSSL3+.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1924449 13f79535-47bb-0310-9956-ffa450edef68
1 parent 5d93f08 commit f7d8cbe

File tree

4 files changed

+103
-14
lines changed

4 files changed

+103
-14
lines changed

CHANGES

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
-*- coding: utf-8 -*-
22
Changes for APR 2.0.0
33

4+
*) apr_crypto_openssl: Add provider support on OpenSSL3+.
5+
[Graham Leggett]
6+
47
*) apr_ldap: Add write capability to the LDAP API. Support for
58
add, modify, rename, delete, and extended operations.
69
[Graham Leggett]

crypto/apr_crypto_openssl.c

+87-11
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,30 @@
8787
#else
8888
#define APR_USE_OPENSSL_PRE_3_0_API 0
8989
#endif
90+
#if OPENSSL_VERSION_NUMBER < 0x30500000L
91+
#define APR_USE_OPENSSL_PRE_3_5_API 1
92+
#else
93+
#define APR_USE_OPENSSL_PRE_3_5_API 0
94+
#endif
9095

9196
#endif /* defined(LIBRESSL_VERSION_NUMBER) */
9297

9398
#if APR_USE_OPENSSL_PRE_3_0_API
9499
#define APR_USE_OPENSSL_ENGINE_API 1
100+
#define APR_USE_OPENSSL_PROVIDER_API 0
95101
#else
96102
#define APR_USE_OPENSSL_ENGINE_API 0
103+
#define APR_USE_OPENSSL_PROVIDER_API 1
97104
#endif
98105

99106
#if APR_USE_OPENSSL_ENGINE_API
100107
#include <openssl/engine.h>
101108
#endif
102109

110+
#if APR_USE_OPENSSL_PROVIDER_API
111+
#include <openssl/provider.h>
112+
#endif
113+
103114
#define LOG_PREFIX "apr_crypto_openssl: "
104115

105116
struct apr_crypto_t {
@@ -118,6 +129,9 @@ struct apr_crypto_config_t {
118129
#else
119130
void *engine;
120131
#endif
132+
#if APR_USE_OPENSSL_PROVIDER_API
133+
OSSL_LIB_CTX *libctx;
134+
#endif
121135
};
122136

123137
struct apr_crypto_key_t {
@@ -407,6 +421,11 @@ static apr_status_t crypto_cleanup(apr_crypto_t *f)
407421
ENGINE_free(f->config->engine);
408422
f->config->engine = NULL;
409423
}
424+
#endif
425+
#if APR_USE_OPENSSL_PROVIDER_API
426+
if (f->config->libctx) {
427+
OSSL_LIB_CTX_free(f->config->libctx);
428+
}
410429
#endif
411430
return APR_SUCCESS;
412431

@@ -418,6 +437,15 @@ static apr_status_t crypto_cleanup_helper(void *data)
418437
return crypto_cleanup(f);
419438
}
420439

440+
#if APR_USE_OPENSSL_PROVIDER_API
441+
static apr_status_t provider_cleanup(void *data)
442+
{
443+
OSSL_PROVIDER *prov = data;
444+
OSSL_PROVIDER_unload(prov);
445+
return APR_SUCCESS;
446+
}
447+
#endif
448+
421449
/**
422450
* @brief Create a context for supporting encryption. Keys, certificates,
423451
* algorithms and other parameters will be set per context. More than
@@ -452,8 +480,24 @@ static apr_status_t crypto_make(apr_crypto_t **ff,
452480
char *elt;
453481
int i = 0, j;
454482

483+
#if APR_USE_OPENSSL_PROVIDER_API
484+
OSSL_PROVIDER *prov = NULL;
485+
const char *path = NULL;
486+
#endif
487+
455488
*ff = NULL;
456489

490+
f = apr_pcalloc(pool, sizeof(apr_crypto_t));
491+
if (!f) {
492+
return APR_ENOMEM;
493+
}
494+
f->config = config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
495+
if (!config) {
496+
return APR_ENOMEM;
497+
}
498+
f->pool = pool;
499+
f->provider = provider;
500+
457501
if (params) {
458502
if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
459503
return status;
@@ -481,22 +525,54 @@ static apr_status_t crypto_make(apr_crypto_t **ff,
481525
}
482526
}
483527

528+
#if APR_USE_OPENSSL_PROVIDER_API
529+
if (!strcasecmp("provider-path", elt)) {
530+
path = ptr;
531+
}
532+
else if (!strcasecmp("provider", elt)) {
533+
534+
/* first provider, avoid loading the default by loading null */
535+
if (!config->libctx) {
536+
prov = OSSL_PROVIDER_load(NULL, "null");
537+
config->libctx = OSSL_LIB_CTX_new();
538+
if (!config->libctx) {
539+
return APR_ENOMEM;
540+
}
541+
542+
apr_pool_cleanup_register(pool, prov, provider_cleanup,
543+
apr_pool_cleanup_null);
544+
}
545+
546+
if (path) {
547+
OSSL_PROVIDER_set_default_search_path(config->libctx, path);
548+
path = NULL;
549+
}
550+
551+
prov = OSSL_PROVIDER_load(config->libctx, ptr);
552+
if (!prov) {
553+
return APR_ENOENGINE;
554+
}
555+
556+
apr_pool_cleanup_register(pool, prov, provider_cleanup,
557+
apr_pool_cleanup_null);
558+
}
559+
else if (prov) {
560+
/* options after a provider apply to the provider */
561+
#if !APR_USE_OPENSSL_PRE_3_5_API
562+
if (!OSSL_PROVIDER_add_conf_parameter(prov, elt, ptr)) {
563+
return PR_EINVAL;
564+
}
565+
#else
566+
return APR_ENOTIMPL;
567+
#endif
568+
}
569+
#endif
570+
484571
i++;
485572
}
486573
engine = fields[0].value;
487574
}
488575

489-
f = apr_pcalloc(pool, sizeof(apr_crypto_t));
490-
if (!f) {
491-
return APR_ENOMEM;
492-
}
493-
f->config = config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
494-
if (!config) {
495-
return APR_ENOMEM;
496-
}
497-
f->pool = pool;
498-
f->provider = provider;
499-
500576
/* The default/builtin "openssl" engine is the same as NULL though with
501577
* openssl-3+ it's called something else, keep NULL for that name.
502578
*/

include/apr_crypto.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -608,8 +608,11 @@ APR_DECLARE(apr_status_t) apr_crypto_error(const apu_err_t **result,
608608
* @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
609609
* if the engine cannot be initialised.
610610
* @remarks NSS: currently no params are supported.
611-
* @remarks OpenSSL: the params can have "engine" as a key, followed by an equal
612-
* sign and a value.
611+
* @remarks OpenSSL legacy: prior to v3, use "engine=[engine]" to set the engine.
612+
* @remarks OpenSSL3+: use "provider=[provider]" to set the provider to load, can
613+
* be specified more than once.
614+
* @remarks OpenSSL3.5+: "name=[value]" params specified after each "provider"
615+
* are applied to that provider.
613616
*/
614617
APR_DECLARE(apr_status_t) apr_crypto_make(apr_crypto_t **f,
615618
const apr_crypto_driver_t *driver, const char *params,

test/testcrypto.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,19 @@ static apr_crypto_t *make(abts_case *tc, apr_pool_t *pool,
107107

108108
apr_crypto_t *f = NULL;
109109

110+
apr_status_t status;
111+
110112
if (!driver) {
111113
return NULL;
112114
}
113115

114116
/* get the context */
115-
apr_crypto_make(&f, driver, "engine=openssl", pool);
117+
status = apr_crypto_make(&f, driver, "engine=openssl", pool);
118+
119+
if (APR_ENOTIMPL == status) {
120+
apr_crypto_make(&f, driver, "provider=default", pool);
121+
}
122+
116123
ABTS_ASSERT(tc, "apr_crypto_make returned NULL", f != NULL);
117124

118125
return f;

0 commit comments

Comments
 (0)