2 * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * A filtering provider for test purposes. We pass all calls through to the
12 * default provider except where we want other behaviour for a test.
16 #include <openssl/core.h>
17 #include <openssl/provider.h>
18 #include <openssl/crypto.h>
20 #include "filterprov.h"
22 #define MAX_FILTERS 10
23 #define MAX_ALG_FILTERS 5
25 struct filter_prov_globals_st
{
30 OSSL_ALGORITHM alg
[MAX_ALG_FILTERS
+ 1];
31 } dispatch
[MAX_FILTERS
];
34 unsigned long int query_count
;
38 static struct filter_prov_globals_st ourglobals
;
40 static struct filter_prov_globals_st
*get_globals(void)
43 * Ideally we'd like to store this in the OSSL_LIB_CTX so that we can have
44 * more than one instance of the filter provider at a time. But for now we
45 * just make it simple.
50 static OSSL_FUNC_provider_gettable_params_fn filter_gettable_params
;
51 static OSSL_FUNC_provider_get_params_fn filter_get_params
;
52 static OSSL_FUNC_provider_query_operation_fn filter_query
;
53 static OSSL_FUNC_provider_unquery_operation_fn filter_unquery
;
54 static OSSL_FUNC_provider_teardown_fn filter_teardown
;
56 static const OSSL_PARAM
*filter_gettable_params(void *provctx
)
58 struct filter_prov_globals_st
*globs
= get_globals();
60 return OSSL_PROVIDER_gettable_params(globs
->deflt
);
63 static int filter_get_params(void *provctx
, OSSL_PARAM params
[])
65 struct filter_prov_globals_st
*globs
= get_globals();
67 return OSSL_PROVIDER_get_params(globs
->deflt
, params
);
70 static int filter_get_capabilities(void *provctx
, const char *capability
,
71 OSSL_CALLBACK
*cb
, void *arg
)
73 struct filter_prov_globals_st
*globs
= get_globals();
75 return OSSL_PROVIDER_get_capabilities(globs
->deflt
, capability
, cb
, arg
);
78 static const OSSL_ALGORITHM
*filter_query(void *provctx
,
82 struct filter_prov_globals_st
*globs
= get_globals();
86 for (i
= 0; i
< globs
->num_dispatch
; i
++) {
87 if (globs
->dispatch
[i
].operation
== operation_id
) {
88 *no_cache
= globs
->no_cache
;
89 return globs
->dispatch
[i
].alg
;
93 /* No filter set, so pass it down to the chained provider */
94 return OSSL_PROVIDER_query_operation(globs
->deflt
, operation_id
, no_cache
);
97 static void filter_unquery(void *provctx
, int operation_id
,
98 const OSSL_ALGORITHM
*algs
)
100 struct filter_prov_globals_st
*globs
= get_globals();
103 if (!TEST_ulong_gt(globs
->query_count
, 0))
106 globs
->query_count
--;
108 for (i
= 0; i
< globs
->num_dispatch
; i
++)
109 if (globs
->dispatch
[i
].alg
== algs
)
111 OSSL_PROVIDER_unquery_operation(globs
->deflt
, operation_id
, algs
);
114 static void filter_teardown(void *provctx
)
116 struct filter_prov_globals_st
*globs
= get_globals();
118 OSSL_PROVIDER_unload(globs
->deflt
);
119 OSSL_LIB_CTX_free(globs
->libctx
);
120 memset(globs
, 0, sizeof(*globs
));
123 /* Functions we provide to the core */
124 static const OSSL_DISPATCH filter_dispatch_table
[] = {
125 { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS
, (void (*)(void))filter_gettable_params
},
126 { OSSL_FUNC_PROVIDER_GET_PARAMS
, (void (*)(void))filter_get_params
},
127 { OSSL_FUNC_PROVIDER_QUERY_OPERATION
, (void (*)(void))filter_query
},
128 { OSSL_FUNC_PROVIDER_UNQUERY_OPERATION
, (void (*)(void))filter_unquery
},
129 { OSSL_FUNC_PROVIDER_GET_CAPABILITIES
, (void (*)(void))filter_get_capabilities
},
130 { OSSL_FUNC_PROVIDER_TEARDOWN
, (void (*)(void))filter_teardown
},
134 int filter_provider_init(const OSSL_CORE_HANDLE
*handle
,
135 const OSSL_DISPATCH
*in
,
136 const OSSL_DISPATCH
**out
,
139 memset(&ourglobals
, 0, sizeof(ourglobals
));
140 ourglobals
.libctx
= OSSL_LIB_CTX_new();
141 if (ourglobals
.libctx
== NULL
)
144 ourglobals
.deflt
= OSSL_PROVIDER_load(ourglobals
.libctx
, "default");
145 if (ourglobals
.deflt
== NULL
)
148 *provctx
= OSSL_PROVIDER_get0_provider_ctx(ourglobals
.deflt
);
149 *out
= filter_dispatch_table
;
153 OSSL_PROVIDER_unload(ourglobals
.deflt
);
154 OSSL_LIB_CTX_free(ourglobals
.libctx
);
159 * Set a filter for the given operation id. The filter string is a colon
160 * separated list of algorithms that will be made available by this provider.
161 * Anything not in the filter will be suppressed. If a filter is not set for
162 * a given operation id then all algorithms are made available.
164 int filter_provider_set_filter(int operation
, const char *filterstr
)
167 int algnum
= 0, last
= 0, ret
= 0;
168 struct filter_prov_globals_st
*globs
= get_globals();
170 char *filterstrtmp
= OPENSSL_strdup(filterstr
);
172 const OSSL_ALGORITHM
*provalgs
= OSSL_PROVIDER_query_operation(globs
->deflt
,
175 const OSSL_ALGORITHM
*algs
;
177 if (filterstrtmp
== NULL
)
180 /* Nothing to filter */
181 if (provalgs
== NULL
)
184 if (globs
->num_dispatch
>= MAX_FILTERS
)
187 for (name
= filterstrtmp
; !last
; name
= (sep
== NULL
? NULL
: sep
+ 1)) {
188 sep
= strstr(name
, ":");
193 namelen
= strlen(name
);
195 for (algs
= provalgs
; algs
->algorithm_names
!= NULL
; algs
++) {
196 const char *found
= strstr(algs
->algorithm_names
, name
);
200 if (found
[namelen
] != '\0' && found
[namelen
] != ':')
202 if (found
!= algs
->algorithm_names
&& found
[-1] != ':')
205 /* We found a match */
206 if (algnum
>= MAX_ALG_FILTERS
)
209 globs
->dispatch
[globs
->num_dispatch
].alg
[algnum
++] = *algs
;
212 if (algs
->algorithm_names
== NULL
) {
218 globs
->dispatch
[globs
->num_dispatch
].operation
= operation
;
219 globs
->no_cache
= no_cache
;
220 globs
->num_dispatch
++;
224 OSSL_PROVIDER_unquery_operation(globs
->deflt
, operation
, provalgs
);
225 OPENSSL_free(filterstrtmp
);
230 * Test if a filter provider is in a clean finishing state.
231 * If it is return 1, otherwise return 0.
233 int filter_provider_check_clean_finish(void)
235 struct filter_prov_globals_st
*globs
= get_globals();
237 return TEST_ulong_eq(globs
->query_count
, 0) && !globs
->error
;