xref: /netbsd-src/crypto/external/bsd/openssl/dist/apps/storeutl.c (revision b0d1725196a7921d003d2c66a14f186abda4176b)
113d40330Schristos /*
2*b0d17251Schristos  * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
313d40330Schristos  *
4*b0d17251Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
513d40330Schristos  * this file except in compliance with the License.  You can obtain a copy
613d40330Schristos  * in the file LICENSE in the source distribution or at
713d40330Schristos  * https://www.openssl.org/source/license.html
813d40330Schristos  */
913d40330Schristos 
1013d40330Schristos #include <openssl/opensslconf.h>
1113d40330Schristos 
1213d40330Schristos #include "apps.h"
1313d40330Schristos #include "progs.h"
1413d40330Schristos #include <openssl/err.h>
1513d40330Schristos #include <openssl/pem.h>
1613d40330Schristos #include <openssl/store.h>
1713d40330Schristos #include <openssl/x509v3.h>      /* s2i_ASN1_INTEGER */
1813d40330Schristos 
1913d40330Schristos static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
2013d40330Schristos                    int expected, int criterion, OSSL_STORE_SEARCH *search,
2113d40330Schristos                    int text, int noout, int recursive, int indent, BIO *out,
22*b0d17251Schristos                    const char *prog, OSSL_LIB_CTX *libctx);
2313d40330Schristos 
2413d40330Schristos typedef enum OPTION_choice {
25*b0d17251Schristos     OPT_COMMON,
26*b0d17251Schristos     OPT_ENGINE, OPT_OUT, OPT_PASSIN,
2713d40330Schristos     OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE,
2813d40330Schristos     OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS,
2913d40330Schristos     OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL,
3013d40330Schristos     OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS,
31*b0d17251Schristos     OPT_MD, OPT_PROV_ENUM
3213d40330Schristos } OPTION_CHOICE;
3313d40330Schristos 
3413d40330Schristos const OPTIONS storeutl_options[] = {
35*b0d17251Schristos     {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\n"},
36*b0d17251Schristos 
37*b0d17251Schristos     OPT_SECTION("General"),
3813d40330Schristos     {"help", OPT_HELP, '-', "Display this summary"},
39*b0d17251Schristos     {"", OPT_MD, '-', "Any supported digest"},
40*b0d17251Schristos #ifndef OPENSSL_NO_ENGINE
41*b0d17251Schristos     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
42*b0d17251Schristos #endif
43*b0d17251Schristos 
44*b0d17251Schristos     OPT_SECTION("Search"),
4513d40330Schristos     {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"},
4613d40330Schristos     {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"},
4713d40330Schristos     {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"},
4813d40330Schristos     {"subject", OPT_CRITERION_SUBJECT, 's', "Search by subject"},
4913d40330Schristos     {"issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name"},
5013d40330Schristos     {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"},
5113d40330Schristos     {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"},
5213d40330Schristos     {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"},
5313d40330Schristos     {"r", OPT_RECURSIVE, '-', "Recurse through names"},
54*b0d17251Schristos 
55*b0d17251Schristos     OPT_SECTION("Input"),
56*b0d17251Schristos     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
57*b0d17251Schristos 
58*b0d17251Schristos     OPT_SECTION("Output"),
59*b0d17251Schristos     {"out", OPT_OUT, '>', "Output file - default stdout"},
60*b0d17251Schristos     {"text", OPT_TEXT, '-', "Print a text form of the objects"},
61*b0d17251Schristos     {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
62*b0d17251Schristos 
63*b0d17251Schristos     OPT_PROV_OPTIONS,
64*b0d17251Schristos 
65*b0d17251Schristos     OPT_PARAMETERS(),
66*b0d17251Schristos     {"uri", 0, 0, "URI of the store object"},
6713d40330Schristos     {NULL}
6813d40330Schristos };
6913d40330Schristos 
storeutl_main(int argc,char * argv[])7013d40330Schristos int storeutl_main(int argc, char *argv[])
7113d40330Schristos {
7213d40330Schristos     int ret = 1, noout = 0, text = 0, recursive = 0;
7313d40330Schristos     char *outfile = NULL, *passin = NULL, *passinarg = NULL;
7413d40330Schristos     BIO *out = NULL;
7513d40330Schristos     ENGINE *e = NULL;
7613d40330Schristos     OPTION_CHOICE o;
7713d40330Schristos     char *prog = opt_init(argc, argv, storeutl_options);
7813d40330Schristos     PW_CB_DATA pw_cb_data;
7913d40330Schristos     int expected = 0;
8013d40330Schristos     int criterion = 0;
8113d40330Schristos     X509_NAME *subject = NULL, *issuer = NULL;
8213d40330Schristos     ASN1_INTEGER *serial = NULL;
8313d40330Schristos     unsigned char *fingerprint = NULL;
8413d40330Schristos     size_t fingerprintlen = 0;
85*b0d17251Schristos     char *alias = NULL, *digestname = NULL;
8613d40330Schristos     OSSL_STORE_SEARCH *search = NULL;
87*b0d17251Schristos     EVP_MD *digest = NULL;
88*b0d17251Schristos     OSSL_LIB_CTX *libctx = app_get0_libctx();
8913d40330Schristos 
9013d40330Schristos     while ((o = opt_next()) != OPT_EOF) {
9113d40330Schristos         switch (o) {
9213d40330Schristos         case OPT_EOF:
9313d40330Schristos         case OPT_ERR:
9413d40330Schristos  opthelp:
9513d40330Schristos             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
9613d40330Schristos             goto end;
9713d40330Schristos         case OPT_HELP:
9813d40330Schristos             opt_help(storeutl_options);
9913d40330Schristos             ret = 0;
10013d40330Schristos             goto end;
10113d40330Schristos         case OPT_OUT:
10213d40330Schristos             outfile = opt_arg();
10313d40330Schristos             break;
10413d40330Schristos         case OPT_PASSIN:
10513d40330Schristos             passinarg = opt_arg();
10613d40330Schristos             break;
10713d40330Schristos         case OPT_NOOUT:
10813d40330Schristos             noout = 1;
10913d40330Schristos             break;
11013d40330Schristos         case OPT_TEXT:
11113d40330Schristos             text = 1;
11213d40330Schristos             break;
11313d40330Schristos         case OPT_RECURSIVE:
11413d40330Schristos             recursive = 1;
11513d40330Schristos             break;
11613d40330Schristos         case OPT_SEARCHFOR_CERTS:
11713d40330Schristos         case OPT_SEARCHFOR_KEYS:
11813d40330Schristos         case OPT_SEARCHFOR_CRLS:
11913d40330Schristos             if (expected != 0) {
12013d40330Schristos                 BIO_printf(bio_err, "%s: only one search type can be given.\n",
12113d40330Schristos                            prog);
12213d40330Schristos                 goto end;
12313d40330Schristos             }
12413d40330Schristos             {
12513d40330Schristos                 static const struct {
12613d40330Schristos                     enum OPTION_choice choice;
12713d40330Schristos                     int type;
12813d40330Schristos                 } map[] = {
12913d40330Schristos                     {OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT},
13013d40330Schristos                     {OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY},
13113d40330Schristos                     {OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL},
13213d40330Schristos                 };
13313d40330Schristos                 size_t i;
13413d40330Schristos 
13513d40330Schristos                 for (i = 0; i < OSSL_NELEM(map); i++) {
13613d40330Schristos                     if (o == map[i].choice) {
13713d40330Schristos                         expected = map[i].type;
13813d40330Schristos                         break;
13913d40330Schristos                     }
14013d40330Schristos                 }
14113d40330Schristos                 /*
14213d40330Schristos                  * If expected wasn't set at this point, it means the map
1434ce06407Schristos                  * isn't synchronised with the possible options leading here.
14413d40330Schristos                  */
14513d40330Schristos                 OPENSSL_assert(expected != 0);
14613d40330Schristos             }
14713d40330Schristos             break;
14813d40330Schristos         case OPT_CRITERION_SUBJECT:
14913d40330Schristos             if (criterion != 0) {
15013d40330Schristos                 BIO_printf(bio_err, "%s: criterion already given.\n",
15113d40330Schristos                            prog);
15213d40330Schristos                 goto end;
15313d40330Schristos             }
15413d40330Schristos             criterion = OSSL_STORE_SEARCH_BY_NAME;
15513d40330Schristos             if (subject != NULL) {
15613d40330Schristos                 BIO_printf(bio_err, "%s: subject already given.\n",
15713d40330Schristos                            prog);
15813d40330Schristos                 goto end;
15913d40330Schristos             }
160*b0d17251Schristos             subject = parse_name(opt_arg(), MBSTRING_UTF8, 1, "subject");
161*b0d17251Schristos             if (subject == NULL)
16213d40330Schristos                 goto end;
16313d40330Schristos             break;
16413d40330Schristos         case OPT_CRITERION_ISSUER:
16513d40330Schristos             if (criterion != 0
166*b0d17251Schristos                 && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) {
16713d40330Schristos                 BIO_printf(bio_err, "%s: criterion already given.\n",
16813d40330Schristos                            prog);
16913d40330Schristos                 goto end;
17013d40330Schristos             }
17113d40330Schristos             criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
17213d40330Schristos             if (issuer != NULL) {
17313d40330Schristos                 BIO_printf(bio_err, "%s: issuer already given.\n",
17413d40330Schristos                            prog);
17513d40330Schristos                 goto end;
17613d40330Schristos             }
177*b0d17251Schristos             issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1, "issuer");
178*b0d17251Schristos             if (issuer == NULL)
17913d40330Schristos                 goto end;
18013d40330Schristos             break;
18113d40330Schristos         case OPT_CRITERION_SERIAL:
18213d40330Schristos             if (criterion != 0
183*b0d17251Schristos                 && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) {
18413d40330Schristos                 BIO_printf(bio_err, "%s: criterion already given.\n",
18513d40330Schristos                            prog);
18613d40330Schristos                 goto end;
18713d40330Schristos             }
18813d40330Schristos             criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
18913d40330Schristos             if (serial != NULL) {
19013d40330Schristos                 BIO_printf(bio_err, "%s: serial number already given.\n",
19113d40330Schristos                            prog);
19213d40330Schristos                 goto end;
19313d40330Schristos             }
19413d40330Schristos             if ((serial = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) {
19513d40330Schristos                 BIO_printf(bio_err, "%s: can't parse serial number argument.\n",
19613d40330Schristos                            prog);
19713d40330Schristos                 goto end;
19813d40330Schristos             }
19913d40330Schristos             break;
20013d40330Schristos         case OPT_CRITERION_FINGERPRINT:
20113d40330Schristos             if (criterion != 0
20213d40330Schristos                 || (criterion == OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT
20313d40330Schristos                     && fingerprint != NULL)) {
20413d40330Schristos                 BIO_printf(bio_err, "%s: criterion already given.\n",
20513d40330Schristos                            prog);
20613d40330Schristos                 goto end;
20713d40330Schristos             }
20813d40330Schristos             criterion = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
20913d40330Schristos             if (fingerprint != NULL) {
21013d40330Schristos                 BIO_printf(bio_err, "%s: fingerprint already given.\n",
21113d40330Schristos                            prog);
21213d40330Schristos                 goto end;
21313d40330Schristos             }
21413d40330Schristos             {
21513d40330Schristos                 long tmplen = 0;
21613d40330Schristos 
21713d40330Schristos                 if ((fingerprint = OPENSSL_hexstr2buf(opt_arg(), &tmplen))
21813d40330Schristos                     == NULL) {
21913d40330Schristos                     BIO_printf(bio_err,
22013d40330Schristos                                "%s: can't parse fingerprint argument.\n",
22113d40330Schristos                                prog);
22213d40330Schristos                     goto end;
22313d40330Schristos                 }
22413d40330Schristos                 fingerprintlen = (size_t)tmplen;
22513d40330Schristos             }
22613d40330Schristos             break;
22713d40330Schristos         case OPT_CRITERION_ALIAS:
22813d40330Schristos             if (criterion != 0) {
22913d40330Schristos                 BIO_printf(bio_err, "%s: criterion already given.\n",
23013d40330Schristos                            prog);
23113d40330Schristos                 goto end;
23213d40330Schristos             }
23313d40330Schristos             criterion = OSSL_STORE_SEARCH_BY_ALIAS;
23413d40330Schristos             if (alias != NULL) {
23513d40330Schristos                 BIO_printf(bio_err, "%s: alias already given.\n",
23613d40330Schristos                            prog);
23713d40330Schristos                 goto end;
23813d40330Schristos             }
23913d40330Schristos             if ((alias = OPENSSL_strdup(opt_arg())) == NULL) {
24013d40330Schristos                 BIO_printf(bio_err, "%s: can't parse alias argument.\n",
24113d40330Schristos                            prog);
24213d40330Schristos                 goto end;
24313d40330Schristos             }
24413d40330Schristos             break;
24513d40330Schristos         case OPT_ENGINE:
24613d40330Schristos             e = setup_engine(opt_arg(), 0);
24713d40330Schristos             break;
24813d40330Schristos         case OPT_MD:
249*b0d17251Schristos             digestname = opt_unknown();
250*b0d17251Schristos             break;
251*b0d17251Schristos         case OPT_PROV_CASES:
252*b0d17251Schristos             if (!opt_provider(o))
253*b0d17251Schristos                 goto end;
254*b0d17251Schristos             break;
25513d40330Schristos         }
25613d40330Schristos     }
257*b0d17251Schristos 
258*b0d17251Schristos     /* One argument, the URI */
25913d40330Schristos     argc = opt_num_rest();
26013d40330Schristos     argv = opt_rest();
261*b0d17251Schristos     if (argc != 1)
26213d40330Schristos         goto opthelp;
263*b0d17251Schristos 
264*b0d17251Schristos     if (digestname != NULL) {
265*b0d17251Schristos         if (!opt_md(digestname, &digest))
26613d40330Schristos             goto opthelp;
26713d40330Schristos     }
26813d40330Schristos 
26913d40330Schristos     if (criterion != 0) {
27013d40330Schristos         switch (criterion) {
27113d40330Schristos         case OSSL_STORE_SEARCH_BY_NAME:
27213d40330Schristos             if ((search = OSSL_STORE_SEARCH_by_name(subject)) == NULL) {
27313d40330Schristos                 ERR_print_errors(bio_err);
27413d40330Schristos                 goto end;
27513d40330Schristos             }
27613d40330Schristos             break;
27713d40330Schristos         case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
27813d40330Schristos             if (issuer == NULL || serial == NULL) {
27913d40330Schristos                 BIO_printf(bio_err,
28013d40330Schristos                            "%s: both -issuer and -serial must be given.\n",
28113d40330Schristos                            prog);
28213d40330Schristos                 goto end;
28313d40330Schristos             }
28413d40330Schristos             if ((search = OSSL_STORE_SEARCH_by_issuer_serial(issuer, serial))
28513d40330Schristos                 == NULL) {
28613d40330Schristos                 ERR_print_errors(bio_err);
28713d40330Schristos                 goto end;
28813d40330Schristos             }
28913d40330Schristos             break;
29013d40330Schristos         case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
29113d40330Schristos             if ((search = OSSL_STORE_SEARCH_by_key_fingerprint(digest,
29213d40330Schristos                                                                fingerprint,
29313d40330Schristos                                                                fingerprintlen))
29413d40330Schristos                 == NULL) {
29513d40330Schristos                 ERR_print_errors(bio_err);
29613d40330Schristos                 goto end;
29713d40330Schristos             }
29813d40330Schristos             break;
29913d40330Schristos         case OSSL_STORE_SEARCH_BY_ALIAS:
30013d40330Schristos             if ((search = OSSL_STORE_SEARCH_by_alias(alias)) == NULL) {
30113d40330Schristos                 ERR_print_errors(bio_err);
30213d40330Schristos                 goto end;
30313d40330Schristos             }
30413d40330Schristos             break;
30513d40330Schristos         }
30613d40330Schristos     }
30713d40330Schristos 
30813d40330Schristos     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
30913d40330Schristos         BIO_printf(bio_err, "Error getting passwords\n");
31013d40330Schristos         goto end;
31113d40330Schristos     }
31213d40330Schristos     pw_cb_data.password = passin;
31313d40330Schristos     pw_cb_data.prompt_info = argv[0];
31413d40330Schristos 
31513d40330Schristos     out = bio_open_default(outfile, 'w', FORMAT_TEXT);
31613d40330Schristos     if (out == NULL)
31713d40330Schristos         goto end;
31813d40330Schristos 
31913d40330Schristos     ret = process(argv[0], get_ui_method(), &pw_cb_data,
32013d40330Schristos                   expected, criterion, search,
321*b0d17251Schristos                   text, noout, recursive, 0, out, prog, libctx);
32213d40330Schristos 
32313d40330Schristos  end:
324*b0d17251Schristos     EVP_MD_free(digest);
32513d40330Schristos     OPENSSL_free(fingerprint);
32613d40330Schristos     OPENSSL_free(alias);
32713d40330Schristos     ASN1_INTEGER_free(serial);
32813d40330Schristos     X509_NAME_free(subject);
32913d40330Schristos     X509_NAME_free(issuer);
33013d40330Schristos     OSSL_STORE_SEARCH_free(search);
33113d40330Schristos     BIO_free_all(out);
33213d40330Schristos     OPENSSL_free(passin);
33313d40330Schristos     release_engine(e);
33413d40330Schristos     return ret;
33513d40330Schristos }
33613d40330Schristos 
indent_printf(int indent,BIO * bio,const char * format,...)33713d40330Schristos static int indent_printf(int indent, BIO *bio, const char *format, ...)
33813d40330Schristos {
33913d40330Schristos     va_list args;
34013d40330Schristos     int ret;
34113d40330Schristos 
34213d40330Schristos     va_start(args, format);
34313d40330Schristos 
34413d40330Schristos     ret = BIO_printf(bio, "%*s", indent, "") + BIO_vprintf(bio, format, args);
34513d40330Schristos 
34613d40330Schristos     va_end(args);
34713d40330Schristos     return ret;
34813d40330Schristos }
34913d40330Schristos 
process(const char * uri,const UI_METHOD * uimeth,PW_CB_DATA * uidata,int expected,int criterion,OSSL_STORE_SEARCH * search,int text,int noout,int recursive,int indent,BIO * out,const char * prog,OSSL_LIB_CTX * libctx)35013d40330Schristos static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
35113d40330Schristos                    int expected, int criterion, OSSL_STORE_SEARCH *search,
35213d40330Schristos                    int text, int noout, int recursive, int indent, BIO *out,
353*b0d17251Schristos                    const char *prog, OSSL_LIB_CTX *libctx)
35413d40330Schristos {
35513d40330Schristos     OSSL_STORE_CTX *store_ctx = NULL;
35613d40330Schristos     int ret = 1, items = 0;
35713d40330Schristos 
358*b0d17251Schristos     if ((store_ctx = OSSL_STORE_open_ex(uri, libctx, app_get0_propq(), uimeth, uidata,
359*b0d17251Schristos                                         NULL, NULL, NULL))
36013d40330Schristos         == NULL) {
36113d40330Schristos         BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri);
36213d40330Schristos         ERR_print_errors(bio_err);
36313d40330Schristos         return ret;
36413d40330Schristos     }
36513d40330Schristos 
36613d40330Schristos     if (expected != 0) {
36713d40330Schristos         if (!OSSL_STORE_expect(store_ctx, expected)) {
36813d40330Schristos             ERR_print_errors(bio_err);
36913d40330Schristos             goto end2;
37013d40330Schristos         }
37113d40330Schristos     }
37213d40330Schristos 
37313d40330Schristos     if (criterion != 0) {
37413d40330Schristos         if (!OSSL_STORE_supports_search(store_ctx, criterion)) {
37513d40330Schristos             BIO_printf(bio_err,
37613d40330Schristos                        "%s: the store scheme doesn't support the given search criteria.\n",
37713d40330Schristos                        prog);
37813d40330Schristos             goto end2;
37913d40330Schristos         }
38013d40330Schristos 
38113d40330Schristos         if (!OSSL_STORE_find(store_ctx, search)) {
38213d40330Schristos             ERR_print_errors(bio_err);
38313d40330Schristos             goto end2;
38413d40330Schristos         }
38513d40330Schristos     }
38613d40330Schristos 
38713d40330Schristos     /* From here on, we count errors, and we'll return the count at the end */
38813d40330Schristos     ret = 0;
38913d40330Schristos 
39013d40330Schristos     for (;;) {
39113d40330Schristos         OSSL_STORE_INFO *info = OSSL_STORE_load(store_ctx);
39213d40330Schristos         int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info);
39313d40330Schristos         const char *infostr =
39413d40330Schristos             info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
39513d40330Schristos 
39613d40330Schristos         if (info == NULL) {
39713d40330Schristos             if (OSSL_STORE_error(store_ctx)) {
39813d40330Schristos                 if (recursive)
39913d40330Schristos                     ERR_clear_error();
40013d40330Schristos                 else
40113d40330Schristos                     ERR_print_errors(bio_err);
402*b0d17251Schristos                 if (OSSL_STORE_eof(store_ctx))
403*b0d17251Schristos                     break;
40413d40330Schristos                 ret++;
40513d40330Schristos                 continue;
40613d40330Schristos             }
40713d40330Schristos 
408*b0d17251Schristos             if (OSSL_STORE_eof(store_ctx))
409*b0d17251Schristos                 break;
410*b0d17251Schristos 
41113d40330Schristos             BIO_printf(bio_err,
41213d40330Schristos                        "ERROR: OSSL_STORE_load() returned NULL without "
41313d40330Schristos                        "eof or error indications\n");
41413d40330Schristos             BIO_printf(bio_err, "       This is an error in the loader\n");
41513d40330Schristos             ERR_print_errors(bio_err);
41613d40330Schristos             ret++;
41713d40330Schristos             break;
41813d40330Schristos         }
41913d40330Schristos 
42013d40330Schristos         if (type == OSSL_STORE_INFO_NAME) {
42113d40330Schristos             const char *name = OSSL_STORE_INFO_get0_NAME(info);
42213d40330Schristos             const char *desc = OSSL_STORE_INFO_get0_NAME_description(info);
42313d40330Schristos             indent_printf(indent, bio_out, "%d: %s: %s\n", items, infostr,
42413d40330Schristos                           name);
42513d40330Schristos             if (desc != NULL)
42613d40330Schristos                 indent_printf(indent, bio_out, "%s\n", desc);
42713d40330Schristos         } else {
42813d40330Schristos             indent_printf(indent, bio_out, "%d: %s\n", items, infostr);
42913d40330Schristos         }
43013d40330Schristos 
43113d40330Schristos         /*
43213d40330Schristos          * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in
43313d40330Schristos          * functionality, so we must figure out how exactly to write things
43413d40330Schristos          * ourselves...
43513d40330Schristos          */
43613d40330Schristos         switch (type) {
43713d40330Schristos         case OSSL_STORE_INFO_NAME:
43813d40330Schristos             if (recursive) {
43913d40330Schristos                 const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
44013d40330Schristos                 ret += process(suburi, uimeth, uidata,
44113d40330Schristos                                expected, criterion, search,
442*b0d17251Schristos                                text, noout, recursive, indent + 2, out, prog,
443*b0d17251Schristos                                libctx);
44413d40330Schristos             }
44513d40330Schristos             break;
44613d40330Schristos         case OSSL_STORE_INFO_PARAMS:
44713d40330Schristos             if (text)
44813d40330Schristos                 EVP_PKEY_print_params(out, OSSL_STORE_INFO_get0_PARAMS(info),
44913d40330Schristos                                       0, NULL);
45013d40330Schristos             if (!noout)
45113d40330Schristos                 PEM_write_bio_Parameters(out,
45213d40330Schristos                                          OSSL_STORE_INFO_get0_PARAMS(info));
45313d40330Schristos             break;
454*b0d17251Schristos         case OSSL_STORE_INFO_PUBKEY:
455*b0d17251Schristos             if (text)
456*b0d17251Schristos                 EVP_PKEY_print_public(out, OSSL_STORE_INFO_get0_PUBKEY(info),
457*b0d17251Schristos                                       0, NULL);
458*b0d17251Schristos             if (!noout)
459*b0d17251Schristos                 PEM_write_bio_PUBKEY(out, OSSL_STORE_INFO_get0_PUBKEY(info));
460*b0d17251Schristos             break;
46113d40330Schristos         case OSSL_STORE_INFO_PKEY:
46213d40330Schristos             if (text)
46313d40330Schristos                 EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info),
46413d40330Schristos                                        0, NULL);
46513d40330Schristos             if (!noout)
46613d40330Schristos                 PEM_write_bio_PrivateKey(out, OSSL_STORE_INFO_get0_PKEY(info),
46713d40330Schristos                                          NULL, NULL, 0, NULL, NULL);
46813d40330Schristos             break;
46913d40330Schristos         case OSSL_STORE_INFO_CERT:
47013d40330Schristos             if (text)
47113d40330Schristos                 X509_print(out, OSSL_STORE_INFO_get0_CERT(info));
47213d40330Schristos             if (!noout)
47313d40330Schristos                 PEM_write_bio_X509(out, OSSL_STORE_INFO_get0_CERT(info));
47413d40330Schristos             break;
47513d40330Schristos         case OSSL_STORE_INFO_CRL:
47613d40330Schristos             if (text)
47713d40330Schristos                 X509_CRL_print(out, OSSL_STORE_INFO_get0_CRL(info));
47813d40330Schristos             if (!noout)
47913d40330Schristos                 PEM_write_bio_X509_CRL(out, OSSL_STORE_INFO_get0_CRL(info));
48013d40330Schristos             break;
48113d40330Schristos         default:
48213d40330Schristos             BIO_printf(bio_err, "!!! Unknown code\n");
48313d40330Schristos             ret++;
48413d40330Schristos             break;
48513d40330Schristos         }
48613d40330Schristos         items++;
48713d40330Schristos         OSSL_STORE_INFO_free(info);
48813d40330Schristos     }
48913d40330Schristos     indent_printf(indent, out, "Total found: %d\n", items);
49013d40330Schristos 
49113d40330Schristos  end2:
49213d40330Schristos     if (!OSSL_STORE_close(store_ctx)) {
49313d40330Schristos         ERR_print_errors(bio_err);
49413d40330Schristos         ret++;
49513d40330Schristos     }
49613d40330Schristos 
49713d40330Schristos     return ret;
49813d40330Schristos }
499