]> git.ipfire.org Git - thirdparty/openssl.git/blob - apps/provider.c
Security hardening: Expose Build flags for Position Independed Execution (PIE)
[thirdparty/openssl.git] / apps / provider.c
1 /*
2 * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
3 *
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
8 */
9
10 #include <openssl/opensslconf.h>
11
12 #include "apps.h"
13 #include "app_params.h"
14 #include "progs.h"
15 #include "names.h"
16 #include <openssl/err.h>
17 #include <openssl/evp.h>
18 #include <openssl/safestack.h>
19 #include <openssl/provider.h>
20 #include <openssl/core.h>
21 #include <openssl/core_numbers.h>
22
23 DEFINE_STACK_OF_CSTRING()
24
25 typedef enum OPTION_choice {
26 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
27 OPT_V = 100, OPT_VV, OPT_VVV
28 } OPTION_CHOICE;
29
30 const OPTIONS provider_options[] = {
31 {OPT_HELP_STR, 1, '-', "Usage: %s [options] [provider...]\n"},
32
33 OPT_SECTION("General"),
34 {"help", OPT_HELP, '-', "Display this summary"},
35
36 OPT_SECTION("Output"),
37 {"v", OPT_V, '-', "List the algorithm names of specified provider"},
38 {"vv", OPT_VV, '-', "List the algorithm names of specified providers,"},
39 {OPT_MORE_STR, 0, '-', "categorised by operation type"},
40 {"vvv", OPT_VVV, '-', "List the algorithm names of specified provider"},
41 {OPT_MORE_STR, 0, '-', "one at a time, and list all known parameters"},
42
43 OPT_PARAMETERS(),
44 {"provider", 0, 0, "Provider(s) to load"},
45 {NULL}
46 };
47
48 typedef struct info_st INFO;
49 typedef struct meta_st META;
50
51 struct info_st {
52 void (*collect_names_fn)(void *method, STACK_OF(OPENSSL_CSTRING) *names);
53 void *method;
54 const OSSL_PARAM *gettable_params;
55 const OSSL_PARAM *gettable_ctx_params;
56 const OSSL_PARAM *settable_ctx_params;
57 };
58
59 struct meta_st {
60 int first; /* For prints */
61 int total;
62 int indent;
63 int subindent;
64 int verbose;
65 const char *label;
66 OSSL_PROVIDER *prov;
67 void (*fn)(META *meta, INFO *info);
68 };
69
70 static void collect_cipher_names(void *method,
71 STACK_OF(OPENSSL_CSTRING) *names)
72 {
73 EVP_CIPHER_names_do_all(method, collect_names, names);
74 }
75
76 static void collect_digest_names(void *method,
77 STACK_OF(OPENSSL_CSTRING) *names)
78 {
79 EVP_MD_names_do_all(method, collect_names, names);
80 }
81
82 static void collect_mac_names(void *method,
83 STACK_OF(OPENSSL_CSTRING) *names)
84 {
85 EVP_MAC_names_do_all(method, collect_names, names);
86 }
87
88 static void collect_keymgmt_names(void *method,
89 STACK_OF(OPENSSL_CSTRING) *names)
90 {
91 EVP_KEYMGMT_names_do_all(method, collect_names, names);
92 }
93
94 static void collect_keyexch_names(void *method,
95 STACK_OF(OPENSSL_CSTRING) *names)
96 {
97 EVP_KEYEXCH_names_do_all(method, collect_names, names);
98 }
99
100 static void collect_signature_names(void *method,
101 STACK_OF(OPENSSL_CSTRING) *names)
102 {
103 EVP_SIGNATURE_names_do_all(method, collect_names, names);
104 }
105
106 static void print_method_names(BIO *out, INFO *info)
107 {
108 STACK_OF(OPENSSL_CSTRING) *names = sk_OPENSSL_CSTRING_new(name_cmp);
109
110 info->collect_names_fn(info->method, names);
111 print_names(out, names);
112 sk_OPENSSL_CSTRING_free(names);
113 }
114
115 static void print_caps(META *meta, INFO *info)
116 {
117 switch (meta->verbose) {
118 case 1:
119 if (!meta->first)
120 BIO_printf(bio_out, "; ");
121 print_method_names(bio_out, info);
122 break;
123 case 2:
124 if (meta->first) {
125 if (meta->total > 0)
126 BIO_printf(bio_out, "\n");
127 BIO_printf(bio_out, "%*s%ss:", meta->indent, "", meta->label);
128 }
129 BIO_printf(bio_out, " ");
130 print_method_names(bio_out, info);
131 break;
132 case 3:
133 default:
134 BIO_printf(bio_out, "%*s%s ", meta->indent, "", meta->label);
135 print_method_names(bio_out, info);
136 BIO_printf(bio_out, "\n");
137 print_param_types("retrievable algorithm parameters",
138 info->gettable_params, meta->subindent);
139 print_param_types("retrievable operation parameters",
140 info->gettable_ctx_params, meta->subindent);
141 print_param_types("settable operation parameters",
142 info->settable_ctx_params, meta->subindent);
143 break;
144 }
145 meta->first = 0;
146 }
147
148 static void do_method(void *method,
149 void (*collect_names_fn)(void *method,
150 STACK_OF(OPENSSL_CSTRING) *names),
151 const OSSL_PARAM *gettable_params,
152 const OSSL_PARAM *gettable_ctx_params,
153 const OSSL_PARAM *settable_ctx_params,
154 META *meta)
155 {
156 INFO info;
157
158 info.collect_names_fn = collect_names_fn;
159 info.method = method;
160 info.gettable_params = gettable_params;
161 info.gettable_ctx_params = gettable_ctx_params;
162 info.settable_ctx_params = settable_ctx_params;
163 meta->fn(meta, &info);
164 meta->total++;
165 }
166
167 static void do_cipher(EVP_CIPHER *cipher, void *meta)
168 {
169 do_method(cipher, collect_cipher_names,
170 EVP_CIPHER_gettable_params(cipher),
171 EVP_CIPHER_gettable_ctx_params(cipher),
172 EVP_CIPHER_settable_ctx_params(cipher),
173 meta);
174 }
175
176 static void do_digest(EVP_MD *digest, void *meta)
177 {
178 do_method(digest, collect_digest_names,
179 EVP_MD_gettable_params(digest),
180 EVP_MD_gettable_ctx_params(digest),
181 EVP_MD_settable_ctx_params(digest),
182 meta);
183 }
184
185 static void do_mac(EVP_MAC *mac, void *meta)
186 {
187 do_method(mac, collect_mac_names,
188 EVP_MAC_gettable_params(mac),
189 EVP_MAC_gettable_ctx_params(mac),
190 EVP_MAC_settable_ctx_params(mac),
191 meta);
192 }
193
194 static void do_keymgmt(EVP_KEYMGMT *keymgmt, void *meta)
195 {
196 do_method(keymgmt, collect_keymgmt_names,
197 /*
198 * TODO(3.0) Enable when KEYMGMT and KEYEXCH have gettables and settables
199 */
200 #if 0
201 EVP_KEYMGMT_gettable_params(keymgmt),
202 EVP_KEYMGMT_gettable_ctx_params(keymgmt),
203 EVP_KEYMGMT_settable_ctx_params(keymgmt),
204 #else
205 NULL, NULL, NULL,
206 #endif
207 meta);
208 }
209
210 static void do_keyexch(EVP_KEYEXCH *keyexch, void *meta)
211 {
212 do_method(keyexch, collect_keyexch_names,
213 /*
214 * TODO(3.0) Enable when KEYMGMT and KEYEXCH have gettables and settables
215 */
216 #if 0
217 EVP_KEYEXCH_gettable_params(keyexch),
218 EVP_KEYEXCH_gettable_ctx_params(keyexch),
219 EVP_KEYEXCH_settable_ctx_params(keyexch),
220 #else
221 NULL, NULL, NULL,
222 #endif
223 meta);
224 }
225
226 static void do_signature(EVP_SIGNATURE *signature, void *meta)
227 {
228 do_method(signature, collect_signature_names,
229 /*
230 * TODO(3.0) Enable when KEYMGMT and SIGNATURE have gettables and settables
231 */
232 #if 0
233 EVP_SIGNATURE_gettable_params(signature),
234 EVP_SIGNATURE_gettable_ctx_params(signature),
235 EVP_SIGNATURE_settable_ctx_params(signature),
236 #else
237 NULL, NULL, NULL,
238 #endif
239 meta);
240 }
241
242 int provider_main(int argc, char **argv)
243 {
244 int ret = 1, i;
245 int verbose = 0;
246 STACK_OF(OPENSSL_CSTRING) *providers = sk_OPENSSL_CSTRING_new_null();
247 OPTION_CHOICE o;
248 char *prog;
249
250 prog = opt_init(argc, argv, provider_options);
251 while ((o = opt_next()) != OPT_EOF) {
252 switch (o) {
253 default: /* Catching OPT_ERR & covering OPT_EOF which isn't possible */
254 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
255 goto end;
256 case OPT_HELP:
257 opt_help(provider_options);
258 ret = 0;
259 goto end;
260 case OPT_VVV:
261 case OPT_VV:
262 case OPT_V:
263 /* Convert to an integer from one to four. */
264 i = (int)(o - OPT_V) + 1;
265 if (verbose < i)
266 verbose = i;
267 break;
268 }
269 }
270
271 /* Allow any trailing parameters as provider names. */
272 argc = opt_num_rest();
273 argv = opt_rest();
274 for ( ; *argv; argv++) {
275 /* This isn't necessary since -- is supported. */
276 if (**argv == '-') {
277 BIO_printf(bio_err, "%s: Cannot mix flags and provider names.\n",
278 prog);
279 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
280 goto end;
281 }
282 sk_OPENSSL_CSTRING_push(providers, *argv);
283 }
284
285 ret = 0;
286 for (i = 0; i < sk_OPENSSL_CSTRING_num(providers); i++) {
287 const char *name = sk_OPENSSL_CSTRING_value(providers, i);
288 OSSL_PROVIDER *prov = OSSL_PROVIDER_load(NULL, name);
289
290 if (prov != NULL) {
291 BIO_printf(bio_out, verbose == 0 ? "%s\n" : "[ %s ]\n", name);
292
293 if (verbose > 0) {
294 META data;
295
296 data.total = 0;
297 data.first = 1;
298 data.verbose = verbose;
299 data.prov = prov;
300 data.fn = print_caps;
301
302 switch (verbose) {
303 case 1:
304 BIO_printf(bio_out, " ");
305 break;
306 case 2:
307 data.indent = 4;
308 break;
309 case 3:
310 default:
311 data.indent = 4;
312 data.subindent = 10;
313 break;
314 }
315
316 if (verbose > 1) {
317 data.first = 1;
318 data.label = "Cipher";
319 }
320 EVP_CIPHER_do_all_provided(NULL, do_cipher, &data);
321 if (verbose > 1) {
322 data.first = 1;
323 data.label = "Digest";
324 }
325 EVP_MD_do_all_provided(NULL, do_digest, &data);
326 if (verbose > 1) {
327 data.first = 1;
328 data.label = "MAC";
329 }
330 EVP_MAC_do_all_provided(NULL, do_mac, &data);
331
332 if (verbose > 1) {
333 data.first = 1;
334 data.label = "Key manager";
335 }
336 EVP_KEYMGMT_do_all_provided(NULL, do_keymgmt, &data);
337 if (verbose > 1) {
338 data.first = 1;
339 data.label = "Key exchange";
340 }
341 EVP_KEYEXCH_do_all_provided(NULL, do_keyexch, &data);
342 if (verbose > 1) {
343 data.first = 1;
344 data.label = "Signature";
345 }
346 EVP_SIGNATURE_do_all_provided(NULL, do_signature, &data);
347
348 switch (verbose) {
349 default:
350 break;
351 case 2:
352 case 1:
353 BIO_printf(bio_out, "\n");
354 break;
355 }
356 }
357 OSSL_PROVIDER_unload(prov);
358 } else {
359 ERR_print_errors(bio_err);
360 ret = 1;
361 /*
362 * Just because one provider module failed, there's no reason to
363 * stop, if there are more to try.
364 */
365 }
366 }
367
368 end:
369
370 ERR_print_errors(bio_err);
371 sk_OPENSSL_CSTRING_free(providers);
372 return ret;
373 }