1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <openssl/opensslconf.h> 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include "apps.h" 13e1051a39Sopenharmony_ci#include "progs.h" 14e1051a39Sopenharmony_ci#include <openssl/err.h> 15e1051a39Sopenharmony_ci#include <openssl/pem.h> 16e1051a39Sopenharmony_ci#include <openssl/store.h> 17e1051a39Sopenharmony_ci#include <openssl/x509v3.h> /* s2i_ASN1_INTEGER */ 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_cistatic int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, 20e1051a39Sopenharmony_ci int expected, int criterion, OSSL_STORE_SEARCH *search, 21e1051a39Sopenharmony_ci int text, int noout, int recursive, int indent, BIO *out, 22e1051a39Sopenharmony_ci const char *prog, OSSL_LIB_CTX *libctx); 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_citypedef enum OPTION_choice { 25e1051a39Sopenharmony_ci OPT_COMMON, 26e1051a39Sopenharmony_ci OPT_ENGINE, OPT_OUT, OPT_PASSIN, 27e1051a39Sopenharmony_ci OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE, 28e1051a39Sopenharmony_ci OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS, 29e1051a39Sopenharmony_ci OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL, 30e1051a39Sopenharmony_ci OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS, 31e1051a39Sopenharmony_ci OPT_MD, OPT_PROV_ENUM 32e1051a39Sopenharmony_ci} OPTION_CHOICE; 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ciconst OPTIONS storeutl_options[] = { 35e1051a39Sopenharmony_ci {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\n"}, 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci OPT_SECTION("General"), 38e1051a39Sopenharmony_ci {"help", OPT_HELP, '-', "Display this summary"}, 39e1051a39Sopenharmony_ci {"", OPT_MD, '-', "Any supported digest"}, 40e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE 41e1051a39Sopenharmony_ci {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 42e1051a39Sopenharmony_ci#endif 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ci OPT_SECTION("Search"), 45e1051a39Sopenharmony_ci {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"}, 46e1051a39Sopenharmony_ci {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"}, 47e1051a39Sopenharmony_ci {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"}, 48e1051a39Sopenharmony_ci {"subject", OPT_CRITERION_SUBJECT, 's', "Search by subject"}, 49e1051a39Sopenharmony_ci {"issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name"}, 50e1051a39Sopenharmony_ci {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"}, 51e1051a39Sopenharmony_ci {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"}, 52e1051a39Sopenharmony_ci {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"}, 53e1051a39Sopenharmony_ci {"r", OPT_RECURSIVE, '-', "Recurse through names"}, 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci OPT_SECTION("Input"), 56e1051a39Sopenharmony_ci {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci OPT_SECTION("Output"), 59e1051a39Sopenharmony_ci {"out", OPT_OUT, '>', "Output file - default stdout"}, 60e1051a39Sopenharmony_ci {"text", OPT_TEXT, '-', "Print a text form of the objects"}, 61e1051a39Sopenharmony_ci {"noout", OPT_NOOUT, '-', "No PEM output, just status"}, 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ci OPT_PROV_OPTIONS, 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ci OPT_PARAMETERS(), 66e1051a39Sopenharmony_ci {"uri", 0, 0, "URI of the store object"}, 67e1051a39Sopenharmony_ci {NULL} 68e1051a39Sopenharmony_ci}; 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ciint storeutl_main(int argc, char *argv[]) 71e1051a39Sopenharmony_ci{ 72e1051a39Sopenharmony_ci int ret = 1, noout = 0, text = 0, recursive = 0; 73e1051a39Sopenharmony_ci char *outfile = NULL, *passin = NULL, *passinarg = NULL; 74e1051a39Sopenharmony_ci BIO *out = NULL; 75e1051a39Sopenharmony_ci ENGINE *e = NULL; 76e1051a39Sopenharmony_ci OPTION_CHOICE o; 77e1051a39Sopenharmony_ci char *prog = opt_init(argc, argv, storeutl_options); 78e1051a39Sopenharmony_ci PW_CB_DATA pw_cb_data; 79e1051a39Sopenharmony_ci int expected = 0; 80e1051a39Sopenharmony_ci int criterion = 0; 81e1051a39Sopenharmony_ci X509_NAME *subject = NULL, *issuer = NULL; 82e1051a39Sopenharmony_ci ASN1_INTEGER *serial = NULL; 83e1051a39Sopenharmony_ci unsigned char *fingerprint = NULL; 84e1051a39Sopenharmony_ci size_t fingerprintlen = 0; 85e1051a39Sopenharmony_ci char *alias = NULL, *digestname = NULL; 86e1051a39Sopenharmony_ci OSSL_STORE_SEARCH *search = NULL; 87e1051a39Sopenharmony_ci EVP_MD *digest = NULL; 88e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx = app_get0_libctx(); 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci while ((o = opt_next()) != OPT_EOF) { 91e1051a39Sopenharmony_ci switch (o) { 92e1051a39Sopenharmony_ci case OPT_EOF: 93e1051a39Sopenharmony_ci case OPT_ERR: 94e1051a39Sopenharmony_ci opthelp: 95e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 96e1051a39Sopenharmony_ci goto end; 97e1051a39Sopenharmony_ci case OPT_HELP: 98e1051a39Sopenharmony_ci opt_help(storeutl_options); 99e1051a39Sopenharmony_ci ret = 0; 100e1051a39Sopenharmony_ci goto end; 101e1051a39Sopenharmony_ci case OPT_OUT: 102e1051a39Sopenharmony_ci outfile = opt_arg(); 103e1051a39Sopenharmony_ci break; 104e1051a39Sopenharmony_ci case OPT_PASSIN: 105e1051a39Sopenharmony_ci passinarg = opt_arg(); 106e1051a39Sopenharmony_ci break; 107e1051a39Sopenharmony_ci case OPT_NOOUT: 108e1051a39Sopenharmony_ci noout = 1; 109e1051a39Sopenharmony_ci break; 110e1051a39Sopenharmony_ci case OPT_TEXT: 111e1051a39Sopenharmony_ci text = 1; 112e1051a39Sopenharmony_ci break; 113e1051a39Sopenharmony_ci case OPT_RECURSIVE: 114e1051a39Sopenharmony_ci recursive = 1; 115e1051a39Sopenharmony_ci break; 116e1051a39Sopenharmony_ci case OPT_SEARCHFOR_CERTS: 117e1051a39Sopenharmony_ci case OPT_SEARCHFOR_KEYS: 118e1051a39Sopenharmony_ci case OPT_SEARCHFOR_CRLS: 119e1051a39Sopenharmony_ci if (expected != 0) { 120e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: only one search type can be given.\n", 121e1051a39Sopenharmony_ci prog); 122e1051a39Sopenharmony_ci goto end; 123e1051a39Sopenharmony_ci } 124e1051a39Sopenharmony_ci { 125e1051a39Sopenharmony_ci static const struct { 126e1051a39Sopenharmony_ci enum OPTION_choice choice; 127e1051a39Sopenharmony_ci int type; 128e1051a39Sopenharmony_ci } map[] = { 129e1051a39Sopenharmony_ci {OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT}, 130e1051a39Sopenharmony_ci {OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY}, 131e1051a39Sopenharmony_ci {OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL}, 132e1051a39Sopenharmony_ci }; 133e1051a39Sopenharmony_ci size_t i; 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci for (i = 0; i < OSSL_NELEM(map); i++) { 136e1051a39Sopenharmony_ci if (o == map[i].choice) { 137e1051a39Sopenharmony_ci expected = map[i].type; 138e1051a39Sopenharmony_ci break; 139e1051a39Sopenharmony_ci } 140e1051a39Sopenharmony_ci } 141e1051a39Sopenharmony_ci /* 142e1051a39Sopenharmony_ci * If expected wasn't set at this point, it means the map 143e1051a39Sopenharmony_ci * isn't synchronised with the possible options leading here. 144e1051a39Sopenharmony_ci */ 145e1051a39Sopenharmony_ci OPENSSL_assert(expected != 0); 146e1051a39Sopenharmony_ci } 147e1051a39Sopenharmony_ci break; 148e1051a39Sopenharmony_ci case OPT_CRITERION_SUBJECT: 149e1051a39Sopenharmony_ci if (criterion != 0) { 150e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: criterion already given.\n", 151e1051a39Sopenharmony_ci prog); 152e1051a39Sopenharmony_ci goto end; 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci criterion = OSSL_STORE_SEARCH_BY_NAME; 155e1051a39Sopenharmony_ci if (subject != NULL) { 156e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: subject already given.\n", 157e1051a39Sopenharmony_ci prog); 158e1051a39Sopenharmony_ci goto end; 159e1051a39Sopenharmony_ci } 160e1051a39Sopenharmony_ci subject = parse_name(opt_arg(), MBSTRING_UTF8, 1, "subject"); 161e1051a39Sopenharmony_ci if (subject == NULL) 162e1051a39Sopenharmony_ci goto end; 163e1051a39Sopenharmony_ci break; 164e1051a39Sopenharmony_ci case OPT_CRITERION_ISSUER: 165e1051a39Sopenharmony_ci if (criterion != 0 166e1051a39Sopenharmony_ci && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) { 167e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: criterion already given.\n", 168e1051a39Sopenharmony_ci prog); 169e1051a39Sopenharmony_ci goto end; 170e1051a39Sopenharmony_ci } 171e1051a39Sopenharmony_ci criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; 172e1051a39Sopenharmony_ci if (issuer != NULL) { 173e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: issuer already given.\n", 174e1051a39Sopenharmony_ci prog); 175e1051a39Sopenharmony_ci goto end; 176e1051a39Sopenharmony_ci } 177e1051a39Sopenharmony_ci issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1, "issuer"); 178e1051a39Sopenharmony_ci if (issuer == NULL) 179e1051a39Sopenharmony_ci goto end; 180e1051a39Sopenharmony_ci break; 181e1051a39Sopenharmony_ci case OPT_CRITERION_SERIAL: 182e1051a39Sopenharmony_ci if (criterion != 0 183e1051a39Sopenharmony_ci && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) { 184e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: criterion already given.\n", 185e1051a39Sopenharmony_ci prog); 186e1051a39Sopenharmony_ci goto end; 187e1051a39Sopenharmony_ci } 188e1051a39Sopenharmony_ci criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; 189e1051a39Sopenharmony_ci if (serial != NULL) { 190e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: serial number already given.\n", 191e1051a39Sopenharmony_ci prog); 192e1051a39Sopenharmony_ci goto end; 193e1051a39Sopenharmony_ci } 194e1051a39Sopenharmony_ci if ((serial = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) { 195e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: can't parse serial number argument.\n", 196e1051a39Sopenharmony_ci prog); 197e1051a39Sopenharmony_ci goto end; 198e1051a39Sopenharmony_ci } 199e1051a39Sopenharmony_ci break; 200e1051a39Sopenharmony_ci case OPT_CRITERION_FINGERPRINT: 201e1051a39Sopenharmony_ci if (criterion != 0 202e1051a39Sopenharmony_ci || (criterion == OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT 203e1051a39Sopenharmony_ci && fingerprint != NULL)) { 204e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: criterion already given.\n", 205e1051a39Sopenharmony_ci prog); 206e1051a39Sopenharmony_ci goto end; 207e1051a39Sopenharmony_ci } 208e1051a39Sopenharmony_ci criterion = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT; 209e1051a39Sopenharmony_ci if (fingerprint != NULL) { 210e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: fingerprint already given.\n", 211e1051a39Sopenharmony_ci prog); 212e1051a39Sopenharmony_ci goto end; 213e1051a39Sopenharmony_ci } 214e1051a39Sopenharmony_ci { 215e1051a39Sopenharmony_ci long tmplen = 0; 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci if ((fingerprint = OPENSSL_hexstr2buf(opt_arg(), &tmplen)) 218e1051a39Sopenharmony_ci == NULL) { 219e1051a39Sopenharmony_ci BIO_printf(bio_err, 220e1051a39Sopenharmony_ci "%s: can't parse fingerprint argument.\n", 221e1051a39Sopenharmony_ci prog); 222e1051a39Sopenharmony_ci goto end; 223e1051a39Sopenharmony_ci } 224e1051a39Sopenharmony_ci fingerprintlen = (size_t)tmplen; 225e1051a39Sopenharmony_ci } 226e1051a39Sopenharmony_ci break; 227e1051a39Sopenharmony_ci case OPT_CRITERION_ALIAS: 228e1051a39Sopenharmony_ci if (criterion != 0) { 229e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: criterion already given.\n", 230e1051a39Sopenharmony_ci prog); 231e1051a39Sopenharmony_ci goto end; 232e1051a39Sopenharmony_ci } 233e1051a39Sopenharmony_ci criterion = OSSL_STORE_SEARCH_BY_ALIAS; 234e1051a39Sopenharmony_ci if (alias != NULL) { 235e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: alias already given.\n", 236e1051a39Sopenharmony_ci prog); 237e1051a39Sopenharmony_ci goto end; 238e1051a39Sopenharmony_ci } 239e1051a39Sopenharmony_ci if ((alias = OPENSSL_strdup(opt_arg())) == NULL) { 240e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: can't parse alias argument.\n", 241e1051a39Sopenharmony_ci prog); 242e1051a39Sopenharmony_ci goto end; 243e1051a39Sopenharmony_ci } 244e1051a39Sopenharmony_ci break; 245e1051a39Sopenharmony_ci case OPT_ENGINE: 246e1051a39Sopenharmony_ci e = setup_engine(opt_arg(), 0); 247e1051a39Sopenharmony_ci break; 248e1051a39Sopenharmony_ci case OPT_MD: 249e1051a39Sopenharmony_ci digestname = opt_unknown(); 250e1051a39Sopenharmony_ci break; 251e1051a39Sopenharmony_ci case OPT_PROV_CASES: 252e1051a39Sopenharmony_ci if (!opt_provider(o)) 253e1051a39Sopenharmony_ci goto end; 254e1051a39Sopenharmony_ci break; 255e1051a39Sopenharmony_ci } 256e1051a39Sopenharmony_ci } 257e1051a39Sopenharmony_ci 258e1051a39Sopenharmony_ci /* One argument, the URI */ 259e1051a39Sopenharmony_ci argc = opt_num_rest(); 260e1051a39Sopenharmony_ci argv = opt_rest(); 261e1051a39Sopenharmony_ci if (argc != 1) 262e1051a39Sopenharmony_ci goto opthelp; 263e1051a39Sopenharmony_ci 264e1051a39Sopenharmony_ci if (digestname != NULL) { 265e1051a39Sopenharmony_ci if (!opt_md(digestname, &digest)) 266e1051a39Sopenharmony_ci goto opthelp; 267e1051a39Sopenharmony_ci } 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci if (criterion != 0) { 270e1051a39Sopenharmony_ci switch (criterion) { 271e1051a39Sopenharmony_ci case OSSL_STORE_SEARCH_BY_NAME: 272e1051a39Sopenharmony_ci if ((search = OSSL_STORE_SEARCH_by_name(subject)) == NULL) { 273e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 274e1051a39Sopenharmony_ci goto end; 275e1051a39Sopenharmony_ci } 276e1051a39Sopenharmony_ci break; 277e1051a39Sopenharmony_ci case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL: 278e1051a39Sopenharmony_ci if (issuer == NULL || serial == NULL) { 279e1051a39Sopenharmony_ci BIO_printf(bio_err, 280e1051a39Sopenharmony_ci "%s: both -issuer and -serial must be given.\n", 281e1051a39Sopenharmony_ci prog); 282e1051a39Sopenharmony_ci goto end; 283e1051a39Sopenharmony_ci } 284e1051a39Sopenharmony_ci if ((search = OSSL_STORE_SEARCH_by_issuer_serial(issuer, serial)) 285e1051a39Sopenharmony_ci == NULL) { 286e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 287e1051a39Sopenharmony_ci goto end; 288e1051a39Sopenharmony_ci } 289e1051a39Sopenharmony_ci break; 290e1051a39Sopenharmony_ci case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT: 291e1051a39Sopenharmony_ci if ((search = OSSL_STORE_SEARCH_by_key_fingerprint(digest, 292e1051a39Sopenharmony_ci fingerprint, 293e1051a39Sopenharmony_ci fingerprintlen)) 294e1051a39Sopenharmony_ci == NULL) { 295e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 296e1051a39Sopenharmony_ci goto end; 297e1051a39Sopenharmony_ci } 298e1051a39Sopenharmony_ci break; 299e1051a39Sopenharmony_ci case OSSL_STORE_SEARCH_BY_ALIAS: 300e1051a39Sopenharmony_ci if ((search = OSSL_STORE_SEARCH_by_alias(alias)) == NULL) { 301e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 302e1051a39Sopenharmony_ci goto end; 303e1051a39Sopenharmony_ci } 304e1051a39Sopenharmony_ci break; 305e1051a39Sopenharmony_ci } 306e1051a39Sopenharmony_ci } 307e1051a39Sopenharmony_ci 308e1051a39Sopenharmony_ci if (!app_passwd(passinarg, NULL, &passin, NULL)) { 309e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error getting passwords\n"); 310e1051a39Sopenharmony_ci goto end; 311e1051a39Sopenharmony_ci } 312e1051a39Sopenharmony_ci pw_cb_data.password = passin; 313e1051a39Sopenharmony_ci pw_cb_data.prompt_info = argv[0]; 314e1051a39Sopenharmony_ci 315e1051a39Sopenharmony_ci out = bio_open_default(outfile, 'w', FORMAT_TEXT); 316e1051a39Sopenharmony_ci if (out == NULL) 317e1051a39Sopenharmony_ci goto end; 318e1051a39Sopenharmony_ci 319e1051a39Sopenharmony_ci ret = process(argv[0], get_ui_method(), &pw_cb_data, 320e1051a39Sopenharmony_ci expected, criterion, search, 321e1051a39Sopenharmony_ci text, noout, recursive, 0, out, prog, libctx); 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ci end: 324e1051a39Sopenharmony_ci EVP_MD_free(digest); 325e1051a39Sopenharmony_ci OPENSSL_free(fingerprint); 326e1051a39Sopenharmony_ci OPENSSL_free(alias); 327e1051a39Sopenharmony_ci ASN1_INTEGER_free(serial); 328e1051a39Sopenharmony_ci X509_NAME_free(subject); 329e1051a39Sopenharmony_ci X509_NAME_free(issuer); 330e1051a39Sopenharmony_ci OSSL_STORE_SEARCH_free(search); 331e1051a39Sopenharmony_ci BIO_free_all(out); 332e1051a39Sopenharmony_ci OPENSSL_free(passin); 333e1051a39Sopenharmony_ci release_engine(e); 334e1051a39Sopenharmony_ci return ret; 335e1051a39Sopenharmony_ci} 336e1051a39Sopenharmony_ci 337e1051a39Sopenharmony_cistatic int indent_printf(int indent, BIO *bio, const char *format, ...) 338e1051a39Sopenharmony_ci{ 339e1051a39Sopenharmony_ci va_list args; 340e1051a39Sopenharmony_ci int ret; 341e1051a39Sopenharmony_ci 342e1051a39Sopenharmony_ci va_start(args, format); 343e1051a39Sopenharmony_ci 344e1051a39Sopenharmony_ci ret = BIO_printf(bio, "%*s", indent, "") + BIO_vprintf(bio, format, args); 345e1051a39Sopenharmony_ci 346e1051a39Sopenharmony_ci va_end(args); 347e1051a39Sopenharmony_ci return ret; 348e1051a39Sopenharmony_ci} 349e1051a39Sopenharmony_ci 350e1051a39Sopenharmony_cistatic int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, 351e1051a39Sopenharmony_ci int expected, int criterion, OSSL_STORE_SEARCH *search, 352e1051a39Sopenharmony_ci int text, int noout, int recursive, int indent, BIO *out, 353e1051a39Sopenharmony_ci const char *prog, OSSL_LIB_CTX *libctx) 354e1051a39Sopenharmony_ci{ 355e1051a39Sopenharmony_ci OSSL_STORE_CTX *store_ctx = NULL; 356e1051a39Sopenharmony_ci int ret = 1, items = 0; 357e1051a39Sopenharmony_ci 358e1051a39Sopenharmony_ci if ((store_ctx = OSSL_STORE_open_ex(uri, libctx, app_get0_propq(), uimeth, uidata, 359e1051a39Sopenharmony_ci NULL, NULL, NULL)) 360e1051a39Sopenharmony_ci == NULL) { 361e1051a39Sopenharmony_ci BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri); 362e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 363e1051a39Sopenharmony_ci return ret; 364e1051a39Sopenharmony_ci } 365e1051a39Sopenharmony_ci 366e1051a39Sopenharmony_ci if (expected != 0) { 367e1051a39Sopenharmony_ci if (!OSSL_STORE_expect(store_ctx, expected)) { 368e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 369e1051a39Sopenharmony_ci goto end2; 370e1051a39Sopenharmony_ci } 371e1051a39Sopenharmony_ci } 372e1051a39Sopenharmony_ci 373e1051a39Sopenharmony_ci if (criterion != 0) { 374e1051a39Sopenharmony_ci if (!OSSL_STORE_supports_search(store_ctx, criterion)) { 375e1051a39Sopenharmony_ci BIO_printf(bio_err, 376e1051a39Sopenharmony_ci "%s: the store scheme doesn't support the given search criteria.\n", 377e1051a39Sopenharmony_ci prog); 378e1051a39Sopenharmony_ci goto end2; 379e1051a39Sopenharmony_ci } 380e1051a39Sopenharmony_ci 381e1051a39Sopenharmony_ci if (!OSSL_STORE_find(store_ctx, search)) { 382e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 383e1051a39Sopenharmony_ci goto end2; 384e1051a39Sopenharmony_ci } 385e1051a39Sopenharmony_ci } 386e1051a39Sopenharmony_ci 387e1051a39Sopenharmony_ci /* From here on, we count errors, and we'll return the count at the end */ 388e1051a39Sopenharmony_ci ret = 0; 389e1051a39Sopenharmony_ci 390e1051a39Sopenharmony_ci for (;;) { 391e1051a39Sopenharmony_ci OSSL_STORE_INFO *info = OSSL_STORE_load(store_ctx); 392e1051a39Sopenharmony_ci int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info); 393e1051a39Sopenharmony_ci const char *infostr = 394e1051a39Sopenharmony_ci info == NULL ? NULL : OSSL_STORE_INFO_type_string(type); 395e1051a39Sopenharmony_ci 396e1051a39Sopenharmony_ci if (info == NULL) { 397e1051a39Sopenharmony_ci if (OSSL_STORE_error(store_ctx)) { 398e1051a39Sopenharmony_ci if (recursive) 399e1051a39Sopenharmony_ci ERR_clear_error(); 400e1051a39Sopenharmony_ci else 401e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 402e1051a39Sopenharmony_ci if (OSSL_STORE_eof(store_ctx)) 403e1051a39Sopenharmony_ci break; 404e1051a39Sopenharmony_ci ret++; 405e1051a39Sopenharmony_ci continue; 406e1051a39Sopenharmony_ci } 407e1051a39Sopenharmony_ci 408e1051a39Sopenharmony_ci if (OSSL_STORE_eof(store_ctx)) 409e1051a39Sopenharmony_ci break; 410e1051a39Sopenharmony_ci 411e1051a39Sopenharmony_ci BIO_printf(bio_err, 412e1051a39Sopenharmony_ci "ERROR: OSSL_STORE_load() returned NULL without " 413e1051a39Sopenharmony_ci "eof or error indications\n"); 414e1051a39Sopenharmony_ci BIO_printf(bio_err, " This is an error in the loader\n"); 415e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 416e1051a39Sopenharmony_ci ret++; 417e1051a39Sopenharmony_ci break; 418e1051a39Sopenharmony_ci } 419e1051a39Sopenharmony_ci 420e1051a39Sopenharmony_ci if (type == OSSL_STORE_INFO_NAME) { 421e1051a39Sopenharmony_ci const char *name = OSSL_STORE_INFO_get0_NAME(info); 422e1051a39Sopenharmony_ci const char *desc = OSSL_STORE_INFO_get0_NAME_description(info); 423e1051a39Sopenharmony_ci indent_printf(indent, bio_out, "%d: %s: %s\n", items, infostr, 424e1051a39Sopenharmony_ci name); 425e1051a39Sopenharmony_ci if (desc != NULL) 426e1051a39Sopenharmony_ci indent_printf(indent, bio_out, "%s\n", desc); 427e1051a39Sopenharmony_ci } else { 428e1051a39Sopenharmony_ci indent_printf(indent, bio_out, "%d: %s\n", items, infostr); 429e1051a39Sopenharmony_ci } 430e1051a39Sopenharmony_ci 431e1051a39Sopenharmony_ci /* 432e1051a39Sopenharmony_ci * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in 433e1051a39Sopenharmony_ci * functionality, so we must figure out how exactly to write things 434e1051a39Sopenharmony_ci * ourselves... 435e1051a39Sopenharmony_ci */ 436e1051a39Sopenharmony_ci switch (type) { 437e1051a39Sopenharmony_ci case OSSL_STORE_INFO_NAME: 438e1051a39Sopenharmony_ci if (recursive) { 439e1051a39Sopenharmony_ci const char *suburi = OSSL_STORE_INFO_get0_NAME(info); 440e1051a39Sopenharmony_ci ret += process(suburi, uimeth, uidata, 441e1051a39Sopenharmony_ci expected, criterion, search, 442e1051a39Sopenharmony_ci text, noout, recursive, indent + 2, out, prog, 443e1051a39Sopenharmony_ci libctx); 444e1051a39Sopenharmony_ci } 445e1051a39Sopenharmony_ci break; 446e1051a39Sopenharmony_ci case OSSL_STORE_INFO_PARAMS: 447e1051a39Sopenharmony_ci if (text) 448e1051a39Sopenharmony_ci EVP_PKEY_print_params(out, OSSL_STORE_INFO_get0_PARAMS(info), 449e1051a39Sopenharmony_ci 0, NULL); 450e1051a39Sopenharmony_ci if (!noout) 451e1051a39Sopenharmony_ci PEM_write_bio_Parameters(out, 452e1051a39Sopenharmony_ci OSSL_STORE_INFO_get0_PARAMS(info)); 453e1051a39Sopenharmony_ci break; 454e1051a39Sopenharmony_ci case OSSL_STORE_INFO_PUBKEY: 455e1051a39Sopenharmony_ci if (text) 456e1051a39Sopenharmony_ci EVP_PKEY_print_public(out, OSSL_STORE_INFO_get0_PUBKEY(info), 457e1051a39Sopenharmony_ci 0, NULL); 458e1051a39Sopenharmony_ci if (!noout) 459e1051a39Sopenharmony_ci PEM_write_bio_PUBKEY(out, OSSL_STORE_INFO_get0_PUBKEY(info)); 460e1051a39Sopenharmony_ci break; 461e1051a39Sopenharmony_ci case OSSL_STORE_INFO_PKEY: 462e1051a39Sopenharmony_ci if (text) 463e1051a39Sopenharmony_ci EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info), 464e1051a39Sopenharmony_ci 0, NULL); 465e1051a39Sopenharmony_ci if (!noout) 466e1051a39Sopenharmony_ci PEM_write_bio_PrivateKey(out, OSSL_STORE_INFO_get0_PKEY(info), 467e1051a39Sopenharmony_ci NULL, NULL, 0, NULL, NULL); 468e1051a39Sopenharmony_ci break; 469e1051a39Sopenharmony_ci case OSSL_STORE_INFO_CERT: 470e1051a39Sopenharmony_ci if (text) 471e1051a39Sopenharmony_ci X509_print(out, OSSL_STORE_INFO_get0_CERT(info)); 472e1051a39Sopenharmony_ci if (!noout) 473e1051a39Sopenharmony_ci PEM_write_bio_X509(out, OSSL_STORE_INFO_get0_CERT(info)); 474e1051a39Sopenharmony_ci break; 475e1051a39Sopenharmony_ci case OSSL_STORE_INFO_CRL: 476e1051a39Sopenharmony_ci if (text) 477e1051a39Sopenharmony_ci X509_CRL_print(out, OSSL_STORE_INFO_get0_CRL(info)); 478e1051a39Sopenharmony_ci if (!noout) 479e1051a39Sopenharmony_ci PEM_write_bio_X509_CRL(out, OSSL_STORE_INFO_get0_CRL(info)); 480e1051a39Sopenharmony_ci break; 481e1051a39Sopenharmony_ci default: 482e1051a39Sopenharmony_ci BIO_printf(bio_err, "!!! Unknown code\n"); 483e1051a39Sopenharmony_ci ret++; 484e1051a39Sopenharmony_ci break; 485e1051a39Sopenharmony_ci } 486e1051a39Sopenharmony_ci items++; 487e1051a39Sopenharmony_ci OSSL_STORE_INFO_free(info); 488e1051a39Sopenharmony_ci } 489e1051a39Sopenharmony_ci indent_printf(indent, out, "Total found: %d\n", items); 490e1051a39Sopenharmony_ci 491e1051a39Sopenharmony_ci end2: 492e1051a39Sopenharmony_ci if (!OSSL_STORE_close(store_ctx)) { 493e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 494e1051a39Sopenharmony_ci ret++; 495e1051a39Sopenharmony_ci } 496e1051a39Sopenharmony_ci 497e1051a39Sopenharmony_ci return ret; 498e1051a39Sopenharmony_ci} 499