1 | #include <machine/rtems-bsd-user-space.h> |
---|
2 | #ifdef __rtems__ |
---|
3 | #include <machine/rtems-bsd-program.h> |
---|
4 | #include "rtems-bsd-openssl-namespace.h" |
---|
5 | #endif /* __rtems__ */ |
---|
6 | |
---|
7 | /* |
---|
8 | * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. |
---|
9 | * |
---|
10 | * Licensed under the OpenSSL license (the "License"). You may not use |
---|
11 | * this file except in compliance with the License. You can obtain a copy |
---|
12 | * in the file LICENSE in the source distribution or at |
---|
13 | * https://www.openssl.org/source/license.html |
---|
14 | */ |
---|
15 | |
---|
16 | #include <openssl/opensslconf.h> |
---|
17 | #ifdef OPENSSL_NO_ENGINE |
---|
18 | NON_EMPTY_TRANSLATION_UNIT |
---|
19 | #else |
---|
20 | |
---|
21 | # include "apps.h" |
---|
22 | # include "progs.h" |
---|
23 | # include <stdio.h> |
---|
24 | # include <stdlib.h> |
---|
25 | # include <string.h> |
---|
26 | # include <openssl/err.h> |
---|
27 | # include <openssl/engine.h> |
---|
28 | # include <openssl/ssl.h> |
---|
29 | # include <openssl/store.h> |
---|
30 | |
---|
31 | typedef enum OPTION_choice { |
---|
32 | OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, |
---|
33 | OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST, |
---|
34 | OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV |
---|
35 | } OPTION_CHOICE; |
---|
36 | |
---|
37 | const OPTIONS engine_options[] = { |
---|
38 | {OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"}, |
---|
39 | {OPT_HELP_STR, 1, '-', |
---|
40 | " engine... Engines to load\n"}, |
---|
41 | {"help", OPT_HELP, '-', "Display this summary"}, |
---|
42 | {"v", OPT_V, '-', "List 'control commands' For each specified engine"}, |
---|
43 | {"vv", OPT_VV, '-', "Also display each command's description"}, |
---|
44 | {"vvv", OPT_VVV, '-', "Also add the input flags for each command"}, |
---|
45 | {"vvvv", OPT_VVVV, '-', "Also show internal input flags"}, |
---|
46 | {"c", OPT_C, '-', "List the capabilities of specified engine"}, |
---|
47 | {"t", OPT_T, '-', "Check that specified engine is available"}, |
---|
48 | {"tt", OPT_TT, '-', "Display error trace for unavailable engines"}, |
---|
49 | {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"}, |
---|
50 | {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"}, |
---|
51 | {OPT_MORE_STR, OPT_EOF, 1, |
---|
52 | "Commands are like \"SO_PATH:/lib/libdriver.so\""}, |
---|
53 | {NULL} |
---|
54 | }; |
---|
55 | |
---|
56 | static int append_buf(char **buf, int *size, const char *s) |
---|
57 | { |
---|
58 | const int expand = 256; |
---|
59 | int len = strlen(s) + 1; |
---|
60 | char *p = *buf; |
---|
61 | |
---|
62 | if (p == NULL) { |
---|
63 | *size = ((len + expand - 1) / expand) * expand; |
---|
64 | p = *buf = app_malloc(*size, "engine buffer"); |
---|
65 | } else { |
---|
66 | const int blen = strlen(p); |
---|
67 | |
---|
68 | if (blen > 0) |
---|
69 | len += 2 + blen; |
---|
70 | |
---|
71 | if (len > *size) { |
---|
72 | *size = ((len + expand - 1) / expand) * expand; |
---|
73 | p = OPENSSL_realloc(p, *size); |
---|
74 | if (p == NULL) { |
---|
75 | OPENSSL_free(*buf); |
---|
76 | *buf = NULL; |
---|
77 | return 0; |
---|
78 | } |
---|
79 | *buf = p; |
---|
80 | } |
---|
81 | |
---|
82 | if (blen > 0) { |
---|
83 | p += blen; |
---|
84 | *p++ = ','; |
---|
85 | *p++ = ' '; |
---|
86 | } |
---|
87 | } |
---|
88 | |
---|
89 | strcpy(p, s); |
---|
90 | return 1; |
---|
91 | } |
---|
92 | |
---|
93 | static int util_flags(BIO *out, unsigned int flags, const char *indent) |
---|
94 | { |
---|
95 | int started = 0, err = 0; |
---|
96 | /* Indent before displaying input flags */ |
---|
97 | BIO_printf(out, "%s%s(input flags): ", indent, indent); |
---|
98 | if (flags == 0) { |
---|
99 | BIO_printf(out, "<no flags>\n"); |
---|
100 | return 1; |
---|
101 | } |
---|
102 | /* |
---|
103 | * If the object is internal, mark it in a way that shows instead of |
---|
104 | * having it part of all the other flags, even if it really is. |
---|
105 | */ |
---|
106 | if (flags & ENGINE_CMD_FLAG_INTERNAL) { |
---|
107 | BIO_printf(out, "[Internal] "); |
---|
108 | } |
---|
109 | |
---|
110 | if (flags & ENGINE_CMD_FLAG_NUMERIC) { |
---|
111 | BIO_printf(out, "NUMERIC"); |
---|
112 | started = 1; |
---|
113 | } |
---|
114 | /* |
---|
115 | * Now we check that no combinations of the mutually exclusive NUMERIC, |
---|
116 | * STRING, and NO_INPUT flags have been used. Future flags that can be |
---|
117 | * OR'd together with these would need to added after these to preserve |
---|
118 | * the testing logic. |
---|
119 | */ |
---|
120 | if (flags & ENGINE_CMD_FLAG_STRING) { |
---|
121 | if (started) { |
---|
122 | BIO_printf(out, "|"); |
---|
123 | err = 1; |
---|
124 | } |
---|
125 | BIO_printf(out, "STRING"); |
---|
126 | started = 1; |
---|
127 | } |
---|
128 | if (flags & ENGINE_CMD_FLAG_NO_INPUT) { |
---|
129 | if (started) { |
---|
130 | BIO_printf(out, "|"); |
---|
131 | err = 1; |
---|
132 | } |
---|
133 | BIO_printf(out, "NO_INPUT"); |
---|
134 | started = 1; |
---|
135 | } |
---|
136 | /* Check for unknown flags */ |
---|
137 | flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & |
---|
138 | ~ENGINE_CMD_FLAG_STRING & |
---|
139 | ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL; |
---|
140 | if (flags) { |
---|
141 | if (started) |
---|
142 | BIO_printf(out, "|"); |
---|
143 | BIO_printf(out, "<0x%04X>", flags); |
---|
144 | } |
---|
145 | if (err) |
---|
146 | BIO_printf(out, " <illegal flags!>"); |
---|
147 | BIO_printf(out, "\n"); |
---|
148 | return 1; |
---|
149 | } |
---|
150 | |
---|
151 | static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent) |
---|
152 | { |
---|
153 | static const int line_wrap = 78; |
---|
154 | int num; |
---|
155 | int ret = 0; |
---|
156 | char *name = NULL; |
---|
157 | char *desc = NULL; |
---|
158 | int flags; |
---|
159 | int xpos = 0; |
---|
160 | STACK_OF(OPENSSL_STRING) *cmds = NULL; |
---|
161 | if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || |
---|
162 | ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, |
---|
163 | 0, NULL, NULL)) <= 0)) { |
---|
164 | return 1; |
---|
165 | } |
---|
166 | |
---|
167 | cmds = sk_OPENSSL_STRING_new_null(); |
---|
168 | if (cmds == NULL) |
---|
169 | goto err; |
---|
170 | |
---|
171 | do { |
---|
172 | int len; |
---|
173 | /* Get the command input flags */ |
---|
174 | if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, |
---|
175 | NULL, NULL)) < 0) |
---|
176 | goto err; |
---|
177 | if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) { |
---|
178 | /* Get the command name */ |
---|
179 | if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, |
---|
180 | NULL, NULL)) <= 0) |
---|
181 | goto err; |
---|
182 | name = app_malloc(len + 1, "name buffer"); |
---|
183 | if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, |
---|
184 | NULL) <= 0) |
---|
185 | goto err; |
---|
186 | /* Get the command description */ |
---|
187 | if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, |
---|
188 | NULL, NULL)) < 0) |
---|
189 | goto err; |
---|
190 | if (len > 0) { |
---|
191 | desc = app_malloc(len + 1, "description buffer"); |
---|
192 | if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, |
---|
193 | NULL) <= 0) |
---|
194 | goto err; |
---|
195 | } |
---|
196 | /* Now decide on the output */ |
---|
197 | if (xpos == 0) |
---|
198 | /* Do an indent */ |
---|
199 | xpos = BIO_puts(out, indent); |
---|
200 | else |
---|
201 | /* Otherwise prepend a ", " */ |
---|
202 | xpos += BIO_printf(out, ", "); |
---|
203 | if (verbose == 1) { |
---|
204 | /* |
---|
205 | * We're just listing names, comma-delimited |
---|
206 | */ |
---|
207 | if ((xpos > (int)strlen(indent)) && |
---|
208 | (xpos + (int)strlen(name) > line_wrap)) { |
---|
209 | BIO_printf(out, "\n"); |
---|
210 | xpos = BIO_puts(out, indent); |
---|
211 | } |
---|
212 | xpos += BIO_printf(out, "%s", name); |
---|
213 | } else { |
---|
214 | /* We're listing names plus descriptions */ |
---|
215 | BIO_printf(out, "%s: %s\n", name, |
---|
216 | (desc == NULL) ? "<no description>" : desc); |
---|
217 | /* ... and sometimes input flags */ |
---|
218 | if ((verbose >= 3) && !util_flags(out, flags, indent)) |
---|
219 | goto err; |
---|
220 | xpos = 0; |
---|
221 | } |
---|
222 | } |
---|
223 | OPENSSL_free(name); |
---|
224 | name = NULL; |
---|
225 | OPENSSL_free(desc); |
---|
226 | desc = NULL; |
---|
227 | /* Move to the next command */ |
---|
228 | num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL); |
---|
229 | } while (num > 0); |
---|
230 | if (xpos > 0) |
---|
231 | BIO_printf(out, "\n"); |
---|
232 | ret = 1; |
---|
233 | err: |
---|
234 | sk_OPENSSL_STRING_free(cmds); |
---|
235 | OPENSSL_free(name); |
---|
236 | OPENSSL_free(desc); |
---|
237 | return ret; |
---|
238 | } |
---|
239 | |
---|
240 | static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, |
---|
241 | BIO *out, const char *indent) |
---|
242 | { |
---|
243 | int loop, res, num = sk_OPENSSL_STRING_num(cmds); |
---|
244 | |
---|
245 | if (num < 0) { |
---|
246 | BIO_printf(out, "[Error]: internal stack error\n"); |
---|
247 | return; |
---|
248 | } |
---|
249 | for (loop = 0; loop < num; loop++) { |
---|
250 | char buf[256]; |
---|
251 | const char *cmd, *arg; |
---|
252 | cmd = sk_OPENSSL_STRING_value(cmds, loop); |
---|
253 | res = 1; /* assume success */ |
---|
254 | /* Check if this command has no ":arg" */ |
---|
255 | if ((arg = strstr(cmd, ":")) == NULL) { |
---|
256 | if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) |
---|
257 | res = 0; |
---|
258 | } else { |
---|
259 | if ((int)(arg - cmd) > 254) { |
---|
260 | BIO_printf(out, "[Error]: command name too long\n"); |
---|
261 | return; |
---|
262 | } |
---|
263 | memcpy(buf, cmd, (int)(arg - cmd)); |
---|
264 | buf[arg - cmd] = '\0'; |
---|
265 | arg++; /* Move past the ":" */ |
---|
266 | /* Call the command with the argument */ |
---|
267 | if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) |
---|
268 | res = 0; |
---|
269 | } |
---|
270 | if (res) { |
---|
271 | BIO_printf(out, "[Success]: %s\n", cmd); |
---|
272 | } else { |
---|
273 | BIO_printf(out, "[Failure]: %s\n", cmd); |
---|
274 | ERR_print_errors(out); |
---|
275 | } |
---|
276 | } |
---|
277 | } |
---|
278 | |
---|
279 | struct util_store_cap_data { |
---|
280 | ENGINE *engine; |
---|
281 | char **cap_buf; |
---|
282 | int *cap_size; |
---|
283 | int ok; |
---|
284 | }; |
---|
285 | static void util_store_cap(const OSSL_STORE_LOADER *loader, void *arg) |
---|
286 | { |
---|
287 | struct util_store_cap_data *ctx = arg; |
---|
288 | |
---|
289 | if (OSSL_STORE_LOADER_get0_engine(loader) == ctx->engine) { |
---|
290 | char buf[256]; |
---|
291 | BIO_snprintf(buf, sizeof(buf), "STORE(%s)", |
---|
292 | OSSL_STORE_LOADER_get0_scheme(loader)); |
---|
293 | if (!append_buf(ctx->cap_buf, ctx->cap_size, buf)) |
---|
294 | ctx->ok = 0; |
---|
295 | } |
---|
296 | } |
---|
297 | |
---|
298 | int engine_main(int argc, char **argv) |
---|
299 | { |
---|
300 | int ret = 1, i; |
---|
301 | int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0; |
---|
302 | ENGINE *e; |
---|
303 | STACK_OF(OPENSSL_CSTRING) *engines = sk_OPENSSL_CSTRING_new_null(); |
---|
304 | STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null(); |
---|
305 | STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null(); |
---|
306 | BIO *out; |
---|
307 | const char *indent = " "; |
---|
308 | OPTION_CHOICE o; |
---|
309 | char *prog; |
---|
310 | char *argv1; |
---|
311 | |
---|
312 | out = dup_bio_out(FORMAT_TEXT); |
---|
313 | if (engines == NULL || pre_cmds == NULL || post_cmds == NULL) |
---|
314 | goto end; |
---|
315 | |
---|
316 | /* Remember the original command name, parse/skip any leading engine |
---|
317 | * names, and then setup to parse the rest of the line as flags. */ |
---|
318 | prog = argv[0]; |
---|
319 | while ((argv1 = argv[1]) != NULL && *argv1 != '-') { |
---|
320 | sk_OPENSSL_CSTRING_push(engines, argv1); |
---|
321 | argc--; |
---|
322 | argv++; |
---|
323 | } |
---|
324 | argv[0] = prog; |
---|
325 | opt_init(argc, argv, engine_options); |
---|
326 | |
---|
327 | while ((o = opt_next()) != OPT_EOF) { |
---|
328 | switch (o) { |
---|
329 | case OPT_EOF: |
---|
330 | case OPT_ERR: |
---|
331 | BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); |
---|
332 | goto end; |
---|
333 | case OPT_HELP: |
---|
334 | opt_help(engine_options); |
---|
335 | ret = 0; |
---|
336 | goto end; |
---|
337 | case OPT_VVVV: |
---|
338 | case OPT_VVV: |
---|
339 | case OPT_VV: |
---|
340 | case OPT_V: |
---|
341 | /* Convert to an integer from one to four. */ |
---|
342 | i = (int)(o - OPT_V) + 1; |
---|
343 | if (verbose < i) |
---|
344 | verbose = i; |
---|
345 | break; |
---|
346 | case OPT_C: |
---|
347 | list_cap = 1; |
---|
348 | break; |
---|
349 | case OPT_TT: |
---|
350 | test_avail_noise++; |
---|
351 | /* fall thru */ |
---|
352 | case OPT_T: |
---|
353 | test_avail++; |
---|
354 | break; |
---|
355 | case OPT_PRE: |
---|
356 | sk_OPENSSL_STRING_push(pre_cmds, opt_arg()); |
---|
357 | break; |
---|
358 | case OPT_POST: |
---|
359 | sk_OPENSSL_STRING_push(post_cmds, opt_arg()); |
---|
360 | break; |
---|
361 | } |
---|
362 | } |
---|
363 | |
---|
364 | /* Allow any trailing parameters as engine names. */ |
---|
365 | argc = opt_num_rest(); |
---|
366 | argv = opt_rest(); |
---|
367 | for ( ; *argv; argv++) { |
---|
368 | if (**argv == '-') { |
---|
369 | BIO_printf(bio_err, "%s: Cannot mix flags and engine names.\n", |
---|
370 | prog); |
---|
371 | BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); |
---|
372 | goto end; |
---|
373 | } |
---|
374 | sk_OPENSSL_CSTRING_push(engines, *argv); |
---|
375 | } |
---|
376 | |
---|
377 | if (sk_OPENSSL_CSTRING_num(engines) == 0) { |
---|
378 | for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { |
---|
379 | sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e)); |
---|
380 | } |
---|
381 | } |
---|
382 | |
---|
383 | ret = 0; |
---|
384 | for (i = 0; i < sk_OPENSSL_CSTRING_num(engines); i++) { |
---|
385 | const char *id = sk_OPENSSL_CSTRING_value(engines, i); |
---|
386 | if ((e = ENGINE_by_id(id)) != NULL) { |
---|
387 | const char *name = ENGINE_get_name(e); |
---|
388 | /* |
---|
389 | * Do "id" first, then "name". Easier to auto-parse. |
---|
390 | */ |
---|
391 | BIO_printf(out, "(%s) %s\n", id, name); |
---|
392 | util_do_cmds(e, pre_cmds, out, indent); |
---|
393 | if (strcmp(ENGINE_get_id(e), id) != 0) { |
---|
394 | BIO_printf(out, "Loaded: (%s) %s\n", |
---|
395 | ENGINE_get_id(e), ENGINE_get_name(e)); |
---|
396 | } |
---|
397 | if (list_cap) { |
---|
398 | int cap_size = 256; |
---|
399 | char *cap_buf = NULL; |
---|
400 | int k, n; |
---|
401 | const int *nids; |
---|
402 | ENGINE_CIPHERS_PTR fn_c; |
---|
403 | ENGINE_DIGESTS_PTR fn_d; |
---|
404 | ENGINE_PKEY_METHS_PTR fn_pk; |
---|
405 | |
---|
406 | if (ENGINE_get_RSA(e) != NULL |
---|
407 | && !append_buf(&cap_buf, &cap_size, "RSA")) |
---|
408 | goto end; |
---|
409 | if (ENGINE_get_DSA(e) != NULL |
---|
410 | && !append_buf(&cap_buf, &cap_size, "DSA")) |
---|
411 | goto end; |
---|
412 | if (ENGINE_get_DH(e) != NULL |
---|
413 | && !append_buf(&cap_buf, &cap_size, "DH")) |
---|
414 | goto end; |
---|
415 | if (ENGINE_get_RAND(e) != NULL |
---|
416 | && !append_buf(&cap_buf, &cap_size, "RAND")) |
---|
417 | goto end; |
---|
418 | |
---|
419 | fn_c = ENGINE_get_ciphers(e); |
---|
420 | if (fn_c == NULL) |
---|
421 | goto skip_ciphers; |
---|
422 | n = fn_c(e, NULL, &nids, 0); |
---|
423 | for (k = 0; k < n; ++k) |
---|
424 | if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) |
---|
425 | goto end; |
---|
426 | |
---|
427 | skip_ciphers: |
---|
428 | fn_d = ENGINE_get_digests(e); |
---|
429 | if (fn_d == NULL) |
---|
430 | goto skip_digests; |
---|
431 | n = fn_d(e, NULL, &nids, 0); |
---|
432 | for (k = 0; k < n; ++k) |
---|
433 | if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) |
---|
434 | goto end; |
---|
435 | |
---|
436 | skip_digests: |
---|
437 | fn_pk = ENGINE_get_pkey_meths(e); |
---|
438 | if (fn_pk == NULL) |
---|
439 | goto skip_pmeths; |
---|
440 | n = fn_pk(e, NULL, &nids, 0); |
---|
441 | for (k = 0; k < n; ++k) |
---|
442 | if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) |
---|
443 | goto end; |
---|
444 | skip_pmeths: |
---|
445 | { |
---|
446 | struct util_store_cap_data store_ctx; |
---|
447 | |
---|
448 | store_ctx.engine = e; |
---|
449 | store_ctx.cap_buf = &cap_buf; |
---|
450 | store_ctx.cap_size = &cap_size; |
---|
451 | store_ctx.ok = 1; |
---|
452 | |
---|
453 | OSSL_STORE_do_all_loaders(util_store_cap, &store_ctx); |
---|
454 | if (!store_ctx.ok) |
---|
455 | goto end; |
---|
456 | } |
---|
457 | if (cap_buf != NULL && (*cap_buf != '\0')) |
---|
458 | BIO_printf(out, " [%s]\n", cap_buf); |
---|
459 | |
---|
460 | OPENSSL_free(cap_buf); |
---|
461 | } |
---|
462 | if (test_avail) { |
---|
463 | BIO_printf(out, "%s", indent); |
---|
464 | if (ENGINE_init(e)) { |
---|
465 | BIO_printf(out, "[ available ]\n"); |
---|
466 | util_do_cmds(e, post_cmds, out, indent); |
---|
467 | ENGINE_finish(e); |
---|
468 | } else { |
---|
469 | BIO_printf(out, "[ unavailable ]\n"); |
---|
470 | if (test_avail_noise) |
---|
471 | ERR_print_errors_fp(stdout); |
---|
472 | ERR_clear_error(); |
---|
473 | } |
---|
474 | } |
---|
475 | if ((verbose > 0) && !util_verbose(e, verbose, out, indent)) |
---|
476 | goto end; |
---|
477 | ENGINE_free(e); |
---|
478 | } else { |
---|
479 | ERR_print_errors(bio_err); |
---|
480 | /* because exit codes above 127 have special meaning on Unix */ |
---|
481 | if (++ret > 127) |
---|
482 | ret = 127; |
---|
483 | } |
---|
484 | } |
---|
485 | |
---|
486 | end: |
---|
487 | |
---|
488 | ERR_print_errors(bio_err); |
---|
489 | sk_OPENSSL_CSTRING_free(engines); |
---|
490 | sk_OPENSSL_STRING_free(pre_cmds); |
---|
491 | sk_OPENSSL_STRING_free(post_cmds); |
---|
492 | BIO_free_all(out); |
---|
493 | return ret; |
---|
494 | } |
---|
495 | #endif |
---|
496 | #ifdef __rtems__ |
---|
497 | #include "rtems-bsd-openssl-engine-data.h" |
---|
498 | #endif /* __rtems__ */ |
---|