2 * Copyright 2020 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/core_dispatch.h>
18 #include <openssl/provider.h>
19 #include <openssl/crypto.h>
21 OSSL_provider_init_fn filter_provider_init
;
23 int filter_provider_set_filter(int operation
, const char *name
);
25 #define MAX_FILTERS 10
26 #define MAX_ALG_FILTERS 5
28 struct filter_prov_globals_st
{
33 OSSL_ALGORITHM alg
[MAX_ALG_FILTERS
+ 1];
34 } dispatch
[MAX_FILTERS
];
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_teardown_fn filter_teardown
;
55 static const OSSL_PARAM
*filter_gettable_params(void *provctx
)
57 struct filter_prov_globals_st
*globs
= get_globals();
59 return OSSL_PROVIDER_gettable_params(globs
->deflt
);
62 static int filter_get_params(void *provctx
, OSSL_PARAM params
[])
64 struct filter_prov_globals_st
*globs
= get_globals();
66 return OSSL_PROVIDER_get_params(globs
->deflt
, params
);
69 static int filter_get_capabilities(void *provctx
, const char *capability
,
70 OSSL_CALLBACK
*cb
, void *arg
)
72 struct filter_prov_globals_st
*globs
= get_globals();
74 return OSSL_PROVIDER_get_capabilities(globs
->deflt
, capability
, cb
, arg
);
77 static const OSSL_ALGORITHM
*filter_query(void *provctx
,
81 struct filter_prov_globals_st
*globs
= get_globals();
84 for (i
= 0; i
< globs
->num_dispatch
; i
++) {
85 if (globs
->dispatch
[i
].operation
== operation_id
) {
87 return globs
->dispatch
[i
].alg
;
91 /* No filter set, so pass it down to the chained provider */
92 return OSSL_PROVIDER_query_operation(globs
->deflt
, operation_id
, no_cache
);
95 static void filter_teardown(void *provctx
)
97 struct filter_prov_globals_st
*globs
= get_globals();
99 OSSL_PROVIDER_unload(globs
->deflt
);
100 OSSL_LIB_CTX_free(globs
->libctx
);
103 /* Functions we provide to the core */
104 static const OSSL_DISPATCH filter_dispatch_table
[] = {
105 { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS
, (void (*)(void))filter_gettable_params
},
106 { OSSL_FUNC_PROVIDER_GET_PARAMS
, (void (*)(void))filter_get_params
},
107 { OSSL_FUNC_PROVIDER_QUERY_OPERATION
, (void (*)(void))filter_query
},
108 { OSSL_FUNC_PROVIDER_GET_CAPABILITIES
, (void (*)(void))filter_get_capabilities
},
109 { OSSL_FUNC_PROVIDER_TEARDOWN
, (void (*)(void))filter_teardown
},
113 int filter_provider_init(const OSSL_CORE_HANDLE
*handle
,
114 const OSSL_DISPATCH
*in
,
115 const OSSL_DISPATCH
**out
,
118 memset(&ourglobals
, 0, sizeof(ourglobals
));
119 ourglobals
.libctx
= OSSL_LIB_CTX_new();
120 if (ourglobals
.libctx
== NULL
)
123 ourglobals
.deflt
= OSSL_PROVIDER_load(ourglobals
.libctx
, "default");
124 if (ourglobals
.deflt
== NULL
)
127 *provctx
= OSSL_PROVIDER_get0_provider_ctx(ourglobals
.deflt
);
128 *out
= filter_dispatch_table
;
132 OSSL_PROVIDER_unload(ourglobals
.deflt
);
133 OSSL_LIB_CTX_free(ourglobals
.libctx
);
138 * Set a filter for the given operation id. The filter string is a colon
139 * separated list of algorithms that will be made available by this provider.
140 * Anything not in the filter will be suppressed. If a filter is not set for
141 * a given operation id then all algorithms are made available.
143 int filter_provider_set_filter(int operation
, const char *filterstr
)
146 int algnum
= 0, last
= 0, ret
= 0;
147 struct filter_prov_globals_st
*globs
= get_globals();
149 char *filterstrtmp
= OPENSSL_strdup(filterstr
);
151 const OSSL_ALGORITHM
*provalgs
= OSSL_PROVIDER_query_operation(globs
->deflt
,
154 const OSSL_ALGORITHM
*algs
;
156 if (filterstrtmp
== NULL
)
159 /* We don't support no_cache */
163 /* Nothing to filter */
164 if (provalgs
== NULL
)
167 if (globs
->num_dispatch
>= MAX_FILTERS
)
170 for (name
= filterstrtmp
; !last
; name
= sep
+ 1) {
171 sep
= strstr(name
, ":");
176 namelen
= strlen(name
);
178 for (algs
= provalgs
; algs
->algorithm_names
!= NULL
; algs
++) {
179 const char *found
= strstr(algs
->algorithm_names
, name
);
183 if (found
[namelen
] != '\0' && found
[namelen
] != ':')
185 if (found
!= algs
->algorithm_names
&& found
[-1] != ':')
188 /* We found a match */
189 if (algnum
>= MAX_ALG_FILTERS
)
192 globs
->dispatch
[globs
->num_dispatch
].alg
[algnum
++] = *algs
;
195 if (algs
->algorithm_names
== NULL
) {
201 globs
->dispatch
[globs
->num_dispatch
].operation
= operation
;
202 globs
->num_dispatch
++;
206 OPENSSL_free(filterstrtmp
);