[openssl-commits] [openssl] master update

Richard Levitte levitte at openssl.org
Fri Feb 23 06:43:17 UTC 2018


The branch master has been updated
       via  0764e4131243e72b54c86486462975d066cd9453 (commit)
       via  a75831f9cc608e4f4502f86f6ab35ef742762e85 (commit)
       via  6ab6deccd95c97a6235f345b371664afb65f77c7 (commit)
       via  511e4e0d6890d552eba77971bbcfb5df51e772e2 (commit)
       via  93d2f9fa4a5d03ac227a54f5c0f2f9b23f1121b6 (commit)
       via  fac8673b8aed77231e23d51d78cd8eb995d21f5c (commit)
       via  7622baf8a7c3e9084f97a4f41406a29ef5d04fc3 (commit)
       via  ce9586b98c792288a57620035b7f5824563389ce (commit)
       via  9511d973444d19e1d492762c5f28473cbd31a5a9 (commit)
       via  6541d9e2646d693b3879ce438a2e9b8d290907fc (commit)
       via  072bfcc90b6f7c206e39339da519567c4460250c (commit)
       via  4eefdbda815c2cd76d788049c839e90a5ac6b843 (commit)
      from  d5927344207e0d5d9ee5c862631fdc292e65e7e6 (commit)


- Log -----------------------------------------------------------------
commit 0764e4131243e72b54c86486462975d066cd9453
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Feb 22 05:45:18 2018 +0100

    Add a note in CHANGES
    
    [extended tests]
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit a75831f9cc608e4f4502f86f6ab35ef742762e85
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Feb 20 02:49:13 2017 +0100

    Test the storeutl searching options
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit 6ab6deccd95c97a6235f345b371664afb65f77c7
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 5 19:17:40 2017 +0200

    STORE: Add documentation on search criteria
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit 511e4e0d6890d552eba77971bbcfb5df51e772e2
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Feb 20 02:47:56 2017 +0100

    Adapt storeutl to allow search for specific objects
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit 93d2f9fa4a5d03ac227a54f5c0f2f9b23f1121b6
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Feb 20 02:39:52 2017 +0100

    STORE 'file' scheme loader: Add search capibility
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit fac8673b8aed77231e23d51d78cd8eb995d21f5c
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Feb 19 12:24:19 2017 +0100

    STORE: Add the possibility to search for specific information
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit 7622baf8a7c3e9084f97a4f41406a29ef5d04fc3
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Feb 11 04:02:32 2017 +0100

    Test the storeutl expectation options
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit ce9586b98c792288a57620035b7f5824563389ce
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 5 16:15:48 2017 +0200

    STORE: Add documentation on expecting specific infos
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit 9511d973444d19e1d492762c5f28473cbd31a5a9
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Feb 11 03:20:45 2017 +0100

    Adapt storeutl to allow looking for a specific info type
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit 6541d9e2646d693b3879ce438a2e9b8d290907fc
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Feb 11 02:27:31 2017 +0100

    STORE 'file' scheme loader: Add info type expectation
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit 072bfcc90b6f7c206e39339da519567c4460250c
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Feb 11 02:33:18 2017 +0100

    STORE: Add the possibility to specify an expected info type
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

commit 4eefdbda815c2cd76d788049c839e90a5ac6b843
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Feb 11 02:50:50 2017 +0100

    STORE: In preparation for coming work, mark when loading is started
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2688)

-----------------------------------------------------------------------

Summary of changes:
 CHANGES                        |   6 +
 apps/storeutl.c                | 246 +++++++++++++++++++++++++++++++++++++++--
 crypto/err/openssl.txt         |  16 +++
 crypto/store/loader_file.c     | 123 ++++++++++++++++++++-
 crypto/store/store_err.c       |  25 ++++-
 crypto/store/store_lib.c       | 188 ++++++++++++++++++++++++++++++-
 crypto/store/store_locl.h      |  32 +++++-
 crypto/store/store_register.c  |  14 +++
 doc/man1/storeutl.pod          |  50 ++++++++-
 doc/man3/OSSL_STORE_LOADER.pod |  45 +++++++-
 doc/man3/OSSL_STORE_SEARCH.pod | 193 ++++++++++++++++++++++++++++++++
 doc/man3/OSSL_STORE_expect.pod |  79 +++++++++++++
 doc/man7/ossl_store.pod        |   6 +-
 include/openssl/ossl_typ.h     |   1 +
 include/openssl/store.h        |  56 ++++++++++
 include/openssl/storeerr.h     |  12 ++
 test/recipes/90-test_store.t   |  72 ++++++++++--
 util/libcrypto.num             |  16 +++
 util/private.num               |   3 +
 19 files changed, 1157 insertions(+), 26 deletions(-)
 create mode 100644 doc/man3/OSSL_STORE_SEARCH.pod
 create mode 100644 doc/man3/OSSL_STORE_expect.pod

diff --git a/CHANGES b/CHANGES
index 5abfbad..e08644a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,12 @@
 
  Changes between 1.1.0g and 1.1.1 [xx XXX xxxx]
 
+  *) Extend OSSL_STORE with capabilities to search and to narrow the set of
+     objects loaded.  This adds the functions OSSL_STORE_expect() and
+     OSSL_STORE_find() as well as needed tools to construct searches and
+     get the search data out of them.
+     [Richard Levitte]
+
   *) Support for TLSv1.3 added. Note that users upgrading from an earlier
      version of OpenSSL should review their configuration settings to ensure
      that they are still appropriate for TLSv1.3. In particular if no TLSv1.3
diff --git a/apps/storeutl.c b/apps/storeutl.c
index 326c2af..d40d263 100644
--- a/apps/storeutl.c
+++ b/apps/storeutl.c
@@ -16,11 +16,17 @@
 #include <openssl/store.h>
 
 static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
-                   int text, int noout, int recursive, int indent, BIO *out);
+                   int expected, int criterion, OSSL_STORE_SEARCH *search,
+                   int text, int noout, int recursive, int indent, BIO *out,
+                   const char *prog);
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN,
-    OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE
+    OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE,
+    OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS,
+    OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL,
+    OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS,
+    OPT_MD
 } OPTION_CHOICE;
 
 const OPTIONS storeutl_options[] = {
@@ -30,6 +36,15 @@ const OPTIONS storeutl_options[] = {
     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
     {"text", OPT_TEXT, '-', "Print a text form of the objects"},
     {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
+    {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"},
+    {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"},
+    {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"},
+    {"subject", OPT_CRITERION_SUBJECT, 's', "Search by subject"},
+    {"issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name"},
+    {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"},
+    {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"},
+    {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"},
+    {"", OPT_MD, '-', "Any supported digest"},
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
@@ -46,6 +61,15 @@ int storeutl_main(int argc, char *argv[])
     OPTION_CHOICE o;
     char *prog = opt_init(argc, argv, storeutl_options);
     PW_CB_DATA pw_cb_data;
+    int expected = 0;
+    int criterion = 0;
+    X509_NAME *subject = NULL, *issuer = NULL;
+    ASN1_INTEGER *serial = NULL;
+    unsigned char *fingerprint = NULL;
+    size_t fingerprintlen = 0;
+    char *alias = NULL;
+    OSSL_STORE_SEARCH *search = NULL;
+    const EVP_MD *digest = NULL;
 
     while ((o = opt_next()) != OPT_EOF) {
         switch (o) {
@@ -73,9 +97,147 @@ int storeutl_main(int argc, char *argv[])
         case OPT_RECURSIVE:
             recursive = 1;
             break;
+        case OPT_SEARCHFOR_CERTS:
+        case OPT_SEARCHFOR_KEYS:
+        case OPT_SEARCHFOR_CRLS:
+            if (expected != 0) {
+                BIO_printf(bio_err, "%s: only one search type can be given.\n",
+                           prog);
+                goto end;
+            }
+            {
+                static const struct {
+                    enum OPTION_choice choice;
+                    int type;
+                } map[] = {
+                    {OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT},
+                    {OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY},
+                    {OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL},
+                };
+                size_t i;
+
+                for (i = 0; i < OSSL_NELEM(map); i++) {
+                    if (o == map[i].choice) {
+                        expected = map[i].type;
+                        break;
+                    }
+                }
+                /*
+                 * If expected wasn't set at this point, it means the map
+                 * isn't syncronised with the possible options leading here.
+                 */
+                OPENSSL_assert(expected != 0);
+            }
+            break;
+        case OPT_CRITERION_SUBJECT:
+            if (criterion != 0) {
+                BIO_printf(bio_err, "%s: criterion already given.\n",
+                           prog);
+                goto end;
+            }
+            criterion = OSSL_STORE_SEARCH_BY_NAME;
+            if (subject != NULL) {
+                BIO_printf(bio_err, "%s: subject already given.\n",
+                           prog);
+                goto end;
+            }
+            if ((subject = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) {
+                BIO_printf(bio_err, "%s: can't parse subject argument.\n",
+                           prog);
+                goto end;
+            }
+            break;
+        case OPT_CRITERION_ISSUER:
+            if (criterion != 0
+                || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
+                    && issuer != NULL)) {
+                BIO_printf(bio_err, "%s: criterion already given.\n",
+                           prog);
+                goto end;
+            }
+            criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
+            if (issuer != NULL) {
+                BIO_printf(bio_err, "%s: issuer already given.\n",
+                           prog);
+                goto end;
+            }
+            if ((issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) {
+                BIO_printf(bio_err, "%s: can't parse issuer argument.\n",
+                           prog);
+                goto end;
+            }
+            break;
+        case OPT_CRITERION_SERIAL:
+            if (criterion != 0
+                || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
+                    && serial != NULL)) {
+                BIO_printf(bio_err, "%s: criterion already given.\n",
+                           prog);
+                goto end;
+            }
+            criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
+            if (serial != NULL) {
+                BIO_printf(bio_err, "%s: serial number already given.\n",
+                           prog);
+                goto end;
+            }
+            if ((serial = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) {
+                BIO_printf(bio_err, "%s: can't parse serial number argument.\n",
+                           prog);
+                goto end;
+            }
+            break;
+        case OPT_CRITERION_FINGERPRINT:
+            if (criterion != 0
+                || (criterion == OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT
+                    && fingerprint != NULL)) {
+                BIO_printf(bio_err, "%s: criterion already given.\n",
+                           prog);
+                goto end;
+            }
+            criterion = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
+            if (fingerprint != NULL) {
+                BIO_printf(bio_err, "%s: fingerprint already given.\n",
+                           prog);
+                goto end;
+            }
+            {
+                long tmplen = 0;
+
+                if ((fingerprint = OPENSSL_hexstr2buf(opt_arg(), &tmplen))
+                    == NULL) {
+                    BIO_printf(bio_err,
+                               "%s: can't parse fingerprint argument.\n",
+                               prog);
+                    goto end;
+                }
+                fingerprintlen = (size_t)tmplen;
+            }
+            break;
+        case OPT_CRITERION_ALIAS:
+            if (criterion != 0) {
+                BIO_printf(bio_err, "%s: criterion already given.\n",
+                           prog);
+                goto end;
+            }
+            criterion = OSSL_STORE_SEARCH_BY_ALIAS;
+            if (alias != NULL) {
+                BIO_printf(bio_err, "%s: alias already given.\n",
+                           prog);
+                goto end;
+            }
+            if ((alias = OPENSSL_strdup(opt_arg())) == NULL) {
+                BIO_printf(bio_err, "%s: can't parse alias argument.\n",
+                           prog);
+                goto end;
+            }
+            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
+        case OPT_MD:
+            if (!opt_md(opt_unknown(), &digest))
+                goto opthelp;
         }
     }
     argc = opt_num_rest();
@@ -90,6 +252,45 @@ int storeutl_main(int argc, char *argv[])
         goto opthelp;
     }
 
+    if (criterion != 0) {
+        switch (criterion) {
+        case OSSL_STORE_SEARCH_BY_NAME:
+            if ((search = OSSL_STORE_SEARCH_by_name(subject)) == NULL) {
+                ERR_print_errors(bio_err);
+                goto end;
+            }
+            break;
+        case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
+            if (issuer == NULL || serial == NULL) {
+                BIO_printf(bio_err,
+                           "%s: both -issuer and -serial must be given.\n",
+                           prog);
+                goto end;
+            }
+            if ((search = OSSL_STORE_SEARCH_by_issuer_serial(issuer, serial))
+                == NULL) {
+                ERR_print_errors(bio_err);
+                goto end;
+            }
+            break;
+        case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
+            if ((search = OSSL_STORE_SEARCH_by_key_fingerprint(digest,
+                                                               fingerprint,
+                                                               fingerprintlen))
+                == NULL) {
+                ERR_print_errors(bio_err);
+                goto end;
+            }
+            break;
+        case OSSL_STORE_SEARCH_BY_ALIAS:
+            if ((search = OSSL_STORE_SEARCH_by_alias(alias)) == NULL) {
+                ERR_print_errors(bio_err);
+                goto end;
+            }
+            break;
+        }
+    }
+
     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
         BIO_printf(bio_err, "Error getting passwords\n");
         goto end;
@@ -101,10 +302,16 @@ int storeutl_main(int argc, char *argv[])
     if (out == NULL)
         goto end;
 
-    ret = process(argv[0], get_ui_method(), &pw_cb_data, text, noout, recursive,
-                  0, out);
+    ret = process(argv[0], get_ui_method(), &pw_cb_data,
+                  expected, criterion, search,
+                  text, noout, recursive, 0, out, prog);
 
  end:
+    OPENSSL_free(alias);
+    ASN1_INTEGER_free(serial);
+    X509_NAME_free(subject);
+    X509_NAME_free(issuer);
+    OSSL_STORE_SEARCH_free(search);
     BIO_free_all(out);
     OPENSSL_free(passin);
     release_engine(e);
@@ -125,7 +332,9 @@ static int indent_printf(int indent, BIO *bio, const char *format, ...)
 }
 
 static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
-                   int text, int noout, int recursive, int indent, BIO *out)
+                   int expected, int criterion, OSSL_STORE_SEARCH *search,
+                   int text, int noout, int recursive, int indent, BIO *out,
+                   const char *prog)
 {
     OSSL_STORE_CTX *store_ctx = NULL;
     int ret = 1, items = 0;
@@ -137,6 +346,27 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
         return ret;
     }
 
+    if (expected != 0) {
+        if (!OSSL_STORE_expect(store_ctx, expected)) {
+            ERR_print_errors(bio_err);
+            goto end2;
+        }
+    }
+
+    if (criterion != 0) {
+        if (!OSSL_STORE_supports_search(store_ctx, criterion)) {
+            BIO_printf(bio_err,
+                       "%s: the store scheme doesn't support the given search criteria.\n",
+                       prog);
+            goto end2;
+        }
+
+        if (!OSSL_STORE_find(store_ctx, search)) {
+            ERR_print_errors(bio_err);
+            goto end2;
+        }
+    }
+
     /* From here on, we count errors, and we'll return the count at the end */
     ret = 0;
 
@@ -188,8 +418,9 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
         case OSSL_STORE_INFO_NAME:
             if (recursive) {
                 const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
-                ret += process(suburi, uimeth, uidata, text, noout, recursive,
-                               indent + 2, out);
+                ret += process(suburi, uimeth, uidata,
+                               expected, criterion, search,
+                               text, noout, recursive, indent + 2, out, prog);
             }
             break;
         case OSSL_STORE_INFO_PARAMS:
@@ -230,6 +461,7 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
     }
     indent_printf(indent, out, "Total found: %d\n", items);
 
+ end2:
     if (!OSSL_STORE_close(store_ctx)) {
         ERR_print_errors(bio_err);
         ret++;
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 9b8a03a..e406bec 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -751,14 +751,17 @@ OCSP_F_OCSP_REQUEST_VERIFY:116:OCSP_request_verify
 OCSP_F_OCSP_RESPONSE_GET1_BASIC:111:OCSP_response_get1_basic
 OCSP_F_PARSE_HTTP_LINE1:118:parse_http_line1
 OSSL_STORE_F_FILE_CTRL:129:file_ctrl
+OSSL_STORE_F_FILE_FIND:138:file_find
 OSSL_STORE_F_FILE_GET_PASS:118:file_get_pass
 OSSL_STORE_F_FILE_LOAD:119:file_load
 OSSL_STORE_F_FILE_LOAD_TRY_DECODE:124:file_load_try_decode
 OSSL_STORE_F_FILE_NAME_TO_URI:126:file_name_to_uri
 OSSL_STORE_F_FILE_OPEN:120:file_open
 OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO:127:ossl_store_attach_pem_bio
+OSSL_STORE_F_OSSL_STORE_EXPECT:130:OSSL_STORE_expect
 OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT:128:\
 	ossl_store_file_attach_pem_bio_int
+OSSL_STORE_F_OSSL_STORE_FIND:131:OSSL_STORE_find
 OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT:100:ossl_store_get0_loader_int
 OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT:101:OSSL_STORE_INFO_get1_CERT
 OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL:102:OSSL_STORE_INFO_get1_CRL
@@ -780,6 +783,12 @@ OSSL_STORE_F_OSSL_STORE_LOADER_NEW:113:OSSL_STORE_LOADER_new
 OSSL_STORE_F_OSSL_STORE_OPEN:114:OSSL_STORE_open
 OSSL_STORE_F_OSSL_STORE_OPEN_INT:115:*
 OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT:117:ossl_store_register_loader_int
+OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS:132:OSSL_STORE_SEARCH_by_alias
+OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:133:\
+	OSSL_STORE_SEARCH_by_issuer_serial
+OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:136:\
+	OSSL_STORE_SEARCH_by_key_fingerprint
+OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME:137:OSSL_STORE_SEARCH_by_name
 OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT:116:\
 	ossl_store_unregister_loader_int
 OSSL_STORE_F_TRY_DECODE_PARAMS:121:try_decode_params
@@ -2146,9 +2155,12 @@ OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE:129:unsupported requestorname type
 OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type
 OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read
 OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac
+OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST:121:\
+	fingerprint size does not match digest
 OSSL_STORE_R_INVALID_SCHEME:106:invalid scheme
 OSSL_STORE_R_IS_NOT_A:112:is not a
 OSSL_STORE_R_LOADER_INCOMPLETE:116:loader incomplete
+OSSL_STORE_R_LOADING_STARTED:117:loading started
 OSSL_STORE_R_NOT_A_CERTIFICATE:100:not a certificate
 OSSL_STORE_R_NOT_A_CRL:101:not a crl
 OSSL_STORE_R_NOT_A_KEY:102:not a key
@@ -2156,10 +2168,14 @@ OSSL_STORE_R_NOT_A_NAME:103:not a name
 OSSL_STORE_R_NOT_PARAMETERS:104:not parameters
 OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error
 OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE:108:path must be absolute
+OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:119:\
+	search only supported for directories
 OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED:109:\
 	ui process interrupted or cancelled
 OSSL_STORE_R_UNREGISTERED_SCHEME:105:unregistered scheme
 OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE:110:unsupported content type
+OSSL_STORE_R_UNSUPPORTED_OPERATION:118:unsupported operation
+OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE:120:unsupported search type
 OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED:111:uri authority unsupported
 PEM_R_BAD_BASE64_DECODE:100:bad base64 decode
 PEM_R_BAD_DECRYPT:101:bad decrypt
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c
index 588a581..ea1b321 100644
--- a/crypto/store/loader_file.c
+++ b/crypto/store/loader_file.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -10,6 +10,7 @@
 #include "e_os.h"
 #include <string.h>
 #include <sys/stat.h>
+#include <ctype.h>
 #include <assert.h>
 
 #include <openssl/bio.h>
@@ -713,6 +714,13 @@ struct ossl_store_loader_ctx_st {
             char *uri;
 
             /*
+             * When a search expression is given, these are filled in.
+             * |search_name| contains the file basename to look for.
+             * The string is exactly 8 characters long.
+             */
+            char search_name[9];
+
+            /*
              * The directory reading utility we have combines opening with
              * reading the first name.  To make sure we can detect the end
              * at the right time, we read early and cache the name.
@@ -721,6 +729,9 @@ struct ossl_store_loader_ctx_st {
             int last_errno;
         } dir;
     } _;
+
+    /* Expected object type.  May be unspecified */
+    int expected_type;
 };
 
 static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
@@ -908,6 +919,43 @@ static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
     return ret;
 }
 
+static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
+{
+    ctx->expected_type = expected;
+    return 1;
+}
+
+static int file_find(OSSL_STORE_LOADER_CTX *ctx, OSSL_STORE_SEARCH *search)
+{
+    /*
+     * If ctx == NULL, the library is looking to know if this loader supports
+     * the given search type.
+     */
+
+    if (OSSL_STORE_SEARCH_get_type(search) == OSSL_STORE_SEARCH_BY_NAME) {
+        unsigned long hash = 0;
+
+        if (ctx == NULL)
+            return 1;
+
+        if (ctx->type != is_dir) {
+            OSSL_STOREerr(OSSL_STORE_F_FILE_FIND,
+                          OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
+            return 0;
+        }
+
+        hash = X509_NAME_hash(OSSL_STORE_SEARCH_get0_name(search));
+        BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name),
+                     "%08lx", hash);
+        return 1;
+    }
+
+    if (ctx != NULL)
+        OSSL_STOREerr(OSSL_STORE_F_FILE_FIND,
+                      OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE);
+    return 0;
+}
+
 /* Internal function to decode an already opened PEM file */
 OSSL_STORE_LOADER_CTX *ossl_store_file_attach_pem_bio_int(BIO *bp)
 {
@@ -1128,6 +1176,68 @@ static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name,
     return 1;
 }
 
+static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
+{
+    const char *p = NULL;
+
+    /* If there are no search criteria, all names are accepted */
+    if (ctx->_.dir.search_name[0] == '\0')
+        return 1;
+
+    /* If the expected type isn't supported, no name is accepted */
+    if (ctx->expected_type != 0
+        && ctx->expected_type != OSSL_STORE_INFO_CERT
+        && ctx->expected_type != OSSL_STORE_INFO_CRL)
+        return 0;
+
+    /*
+     * First, check the basename
+     */
+    if (strncasecmp(name, ctx->_.dir.search_name,
+                    sizeof(ctx->_.dir.search_name) - 1) != 0
+        || name[sizeof(ctx->_.dir.search_name) - 1] != '.')
+        return 0;
+    p = &name[sizeof(ctx->_.dir.search_name)];
+
+    /*
+     * Then, if the expected type is a CRL, check that the extension starts
+     * with 'r'
+     */
+    if (*p == 'r') {
+        p++;
+        if (ctx->expected_type != 0
+            && ctx->expected_type != OSSL_STORE_INFO_CRL)
+            return 0;
+    } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) {
+        return 0;
+    }
+
+    /*
+     * Last, check that the rest of the extension is a decimal number, at
+     * least one digit long.
+     */
+    if (!isdigit(*p))
+        return 0;
+    while (isdigit(*p))
+        p++;
+
+# ifdef __VMS
+    /*
+     * One extra step here, check for a possible generation number.
+     */
+    if (*p == ';')
+        for (p++; *p != '\0'; p++)
+            if (!isdigit(*p))
+                break;
+# endif
+
+    /*
+     * If we've reached the end of the string at this point, we've successfully
+     * found a fitting file name.
+     */
+    return *p == '\0';
+}
+
 static int file_eof(OSSL_STORE_LOADER_CTX *ctx);
 static int file_error(OSSL_STORE_LOADER_CTX *ctx);
 static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
@@ -1156,6 +1266,7 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
             }
 
             if (ctx->_.dir.last_entry[0] != '.'
+                && file_name_check(ctx, ctx->_.dir.last_entry)
                 && !file_name_to_uri(ctx, ctx->_.dir.last_entry, &newname))
                 return NULL;
 
@@ -1181,6 +1292,7 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
     } else {
         int matchcount = -1;
 
+     again:
         result = file_load_try_repeat(ctx, ui_method, ui_data);
         if (result != NULL)
             return result;
@@ -1251,6 +1363,13 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
         /* We bail out on ambiguity */
         if (matchcount > 1)
             return NULL;
+
+        if (result != NULL
+            && ctx->expected_type != 0
+            && ctx->expected_type != OSSL_STORE_INFO_get_type(result)) {
+            OSSL_STORE_INFO_free(result);
+            goto again;
+        }
     }
 
     return result;
@@ -1295,6 +1414,8 @@ static OSSL_STORE_LOADER file_loader =
         NULL,
         file_open,
         file_ctrl,
+        file_expect,
+        file_find,
         file_load,
         file_eof,
         file_error,
diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c
index c78b3899..5a8a840 100644
--- a/crypto/store/store_err.c
+++ b/crypto/store/store_err.c
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -15,6 +15,7 @@
 
 static const ERR_STRING_DATA OSSL_STORE_str_functs[] = {
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_CTRL, 0), "file_ctrl"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_FIND, 0), "file_find"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_GET_PASS, 0),
      "file_get_pass"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_LOAD, 0), "file_load"},
@@ -25,8 +26,12 @@ static const ERR_STRING_DATA OSSL_STORE_str_functs[] = {
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_OPEN, 0), "file_open"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO, 0),
      "ossl_store_attach_pem_bio"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_EXPECT, 0),
+     "OSSL_STORE_expect"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT, 0),
      "ossl_store_file_attach_pem_bio_int"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_FIND, 0),
+     "OSSL_STORE_find"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, 0),
      "ossl_store_get0_loader_int"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT, 0),
@@ -64,6 +69,14 @@ static const ERR_STRING_DATA OSSL_STORE_str_functs[] = {
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_OPEN_INT, 0), ""},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, 0),
      "ossl_store_register_loader_int"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS, 0),
+     "OSSL_STORE_SEARCH_by_alias"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL, 0),
+     "OSSL_STORE_SEARCH_by_issuer_serial"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT, 0),
+     "OSSL_STORE_SEARCH_by_key_fingerprint"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME, 0),
+     "OSSL_STORE_SEARCH_by_name"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, 0),
      "ossl_store_unregister_loader_int"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PARAMS, 0),
@@ -82,11 +95,15 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
     "bad password read"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC),
     "error verifying pkcs12 mac"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST),
+    "fingerprint size does not match digest"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_INVALID_SCHEME),
     "invalid scheme"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_IS_NOT_A), "is not a"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_LOADER_INCOMPLETE),
     "loader incomplete"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_LOADING_STARTED),
+    "loading started"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CERTIFICATE),
     "not a certificate"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CRL), "not a crl"},
@@ -98,12 +115,18 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
     "passphrase callback error"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE),
     "path must be absolute"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES),
+    "search only supported for directories"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED),
     "ui process interrupted or cancelled"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNREGISTERED_SCHEME),
     "unregistered scheme"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE),
     "unsupported content type"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNSUPPORTED_OPERATION),
+    "unsupported operation"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE),
+    "unsupported search type"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED),
     "uri authority unsupported"},
     {0, NULL}
diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c
index 24876a3..1c43547 100644
--- a/crypto/store/store_lib.c
+++ b/crypto/store/store_lib.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -10,6 +10,10 @@
 #include "e_os.h"
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
+
+#include "e_os.h"
+
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/store.h>
@@ -24,6 +28,10 @@ struct ossl_store_ctx_st {
     void *ui_data;
     OSSL_STORE_post_process_info_fn post_process;
     void *post_process_data;
+    int expected_type;
+
+    /* 0 before the first STORE_load(), 1 otherwise */
+    int loading;
 };
 
 OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
@@ -125,10 +133,41 @@ int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args)
     return 0;
 }
 
+int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type)
+{
+    if (ctx->loading) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_EXPECT,
+                      OSSL_STORE_R_LOADING_STARTED);
+        return 0;
+    }
+
+    ctx->expected_type = expected_type;
+    if (ctx->loader->expect != NULL)
+        return ctx->loader->expect(ctx->loader_ctx, expected_type);
+    return 1;
+}
+
+int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search)
+{
+    if (ctx->loading) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FIND,
+                      OSSL_STORE_R_LOADING_STARTED);
+        return 0;
+    }
+    if (ctx->loader->find == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FIND,
+                      OSSL_STORE_R_UNSUPPORTED_OPERATION);
+        return 0;
+    }
+
+    return ctx->loader->find(ctx->loader_ctx, search);
+}
+
 OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
 {
     OSSL_STORE_INFO *v = NULL;
 
+    ctx->loading = 1;
  again:
     if (OSSL_STORE_eof(ctx))
         return NULL;
@@ -146,6 +185,24 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
             goto again;
     }
 
+    if (v != NULL && ctx->expected_type != 0) {
+        int returned_type = OSSL_STORE_INFO_get_type(v);
+
+        if (returned_type != OSSL_STORE_INFO_NAME && returned_type != 0) {
+            /*
+             * Soft assert here so those who want to harsly weed out faulty
+             * loaders can do so using a debugging version of libcrypto.
+             */
+            if (ctx->loader->expect != NULL)
+                assert(ctx->expected_type == returned_type);
+
+            if (ctx->expected_type != returned_type) {
+                OSSL_STORE_INFO_free(v);
+                goto again;
+            }
+        }
+    }
+
     return v;
 }
 
@@ -411,6 +468,135 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
     }
 }
 
+int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type)
+{
+    OSSL_STORE_SEARCH tmp_search;
+
+    if (ctx->loader->find == NULL)
+        return 0;
+    tmp_search.search_type = search_type;
+    return ctx->loader->find(NULL, &tmp_search);
+}
+
+/* Search term constructors */
+OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name)
+{
+    OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
+
+    if (search == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME,
+                      ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    search->search_type = OSSL_STORE_SEARCH_BY_NAME;
+    search->name = name;
+    return search;
+}
+
+OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name,
+                                                    const ASN1_INTEGER *serial)
+{
+    OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
+
+    if (search == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL,
+                      ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    search->search_type = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
+    search->name = name;
+    search->serial = serial;
+    return search;
+}
+
+OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
+                                                        const unsigned char
+                                                        *bytes, size_t len)
+{
+    OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
+
+    if (search == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT,
+                      ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    if (digest != NULL && len != (size_t)EVP_MD_size(digest)) {
+        char buf1[20], buf2[20];
+
+        BIO_snprintf(buf1, sizeof(buf1), "%d", EVP_MD_size(digest));
+        BIO_snprintf(buf2, sizeof(buf2), "%zu", len);
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT,
+                      OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST);
+        ERR_add_error_data(5, EVP_MD_name(digest), " size is ", buf1,
+                           ", fingerprint size is ", buf2);
+    }
+
+    search->search_type = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
+    search->digest = digest;
+    search->string = bytes;
+    search->stringlength = len;
+    return search;
+}
+
+OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias)
+{
+    OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
+
+    if (search == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS,
+                      ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    search->search_type = OSSL_STORE_SEARCH_BY_ALIAS;
+    search->string = (const unsigned char *)alias;
+    search->stringlength = strlen(alias);
+    return search;
+}
+
+/* Search term destructor */
+void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search)
+{
+    OPENSSL_free(search);
+}
+
+/* Search term accessors */
+int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion)
+{
+    return criterion->search_type;
+}
+
+X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion)
+{
+    return criterion->name;
+}
+
+const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
+                                                 *criterion)
+{
+    return criterion->serial;
+}
+
+const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH
+                                                  *criterion, size_t *length)
+{
+    *length = criterion->stringlength;
+    return criterion->string;
+}
+
+const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion)
+{
+    return (const char *)criterion->string;
+}
+
+const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion)
+{
+    return criterion->digest;
+}
+
 /* Internal functions */
 OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name,
                                               BUF_MEM *embedded)
diff --git a/crypto/store/store_locl.h b/crypto/store/store_locl.h
index 789d332..369dcb3 100644
--- a/crypto/store/store_locl.h
+++ b/crypto/store/store_locl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -62,6 +62,34 @@ BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info);
 char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info);
 
 /*-
+ *  OSSL_STORE_SEARCH stuff
+ *  -----------------------
+ */
+
+struct ossl_store_search_st {
+    int search_type;
+
+    /*
+     * Used by OSSL_STORE_SEARCH_BY_NAME and
+     * OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
+     */
+    X509_NAME *name;
+
+    /* Used by OSSL_STORE_SEARCH_BY_ISSUER_SERIAL */
+    const ASN1_INTEGER *serial;
+
+    /* Used by OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT */
+    const EVP_MD *digest;
+
+    /*
+     * Used by OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT and
+     * OSSL_STORE_SEARCH_BY_ALIAS
+     */
+    const unsigned char *string;
+    size_t stringlength;
+};
+
+/*-
  *  OSSL_STORE_LOADER stuff
  *  -----------------------
  */
@@ -75,6 +103,8 @@ struct ossl_store_loader_st {
     ENGINE *engine;
     OSSL_STORE_open_fn open;
     OSSL_STORE_ctrl_fn ctrl;
+    OSSL_STORE_expect_fn expect;
+    OSSL_STORE_find_fn find;
     OSSL_STORE_load_fn load;
     OSSL_STORE_eof_fn eof;
     OSSL_STORE_error_fn error;
diff --git a/crypto/store/store_register.c b/crypto/store/store_register.c
index 855c28e..e68cb3c 100644
--- a/crypto/store/store_register.c
+++ b/crypto/store/store_register.c
@@ -78,6 +78,20 @@ int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader,
     return 1;
 }
 
+int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader,
+                                 OSSL_STORE_expect_fn expect_function)
+{
+    loader->expect = expect_function;
+    return 1;
+}
+
+int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader,
+                               OSSL_STORE_find_fn find_function)
+{
+    loader->find = find_function;
+    return 1;
+}
+
 int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader,
                                OSSL_STORE_load_fn load_function)
 {
diff --git a/doc/man1/storeutl.pod b/doc/man1/storeutl.pod
index 74361a7..3f26ab5 100644
--- a/doc/man1/storeutl.pod
+++ b/doc/man1/storeutl.pod
@@ -15,6 +15,15 @@ B<openssl> B<storeutl>
 [B<-text arg>]
 [B<-engine id>]
 [B<-r>]
+[B<-certs>]
+[B<-keys>]
+[B<-crls>]
+[B<-subject arg>]
+[B<-issuer arg>]
+[B<-serial arg>]
+[B<-alias arg>]
+[B<-fingerprint arg>]
+[B<-I<digest>>]
 B<uri> ...
 
 =head1 DESCRIPTION
@@ -60,6 +69,45 @@ The engine will then be set as the default for all available algorithms.
 
 Fetch objects recursively when possible.
 
+=item B<-certs>
+
+=item B<-keys>
+
+=item B<-crls>
+
+Only select the certificates, keys or CRLs from the given URI.
+However, if this URI would return a set of names (URIs), those are always
+returned.
+
+=item B<-subject arg>
+
+Search for an object having the subject name B<arg>.
+The arg must be formatted as I</type0=value0/type1=value1/type2=...>,
+characters may be escaped by \ (backslash), no spaces are skipped.
+
+=item B<-issuer arg>
+
+=item B<-serial arg>
+
+Search for an object having the given issuer name and serial number.
+These two options I<must> be used together.
+The issuer arg must be formatted as I</type0=value0/type1=value1/type2=...>,
+characters may be escaped by \ (backslash), no spaces are skipped.
+The serial arg may be specified as a decimal value or a hex value if preceded
+by B<0x>.
+
+=item B<-alias arg>
+
+Search for an object having the given alias.
+
+=item B<-fingerprint arg>
+
+Search for an object having the given fingerprint.
+
+=item B<-I<digest>>
+
+The digest that was used to compute the fingerprint given with B<-fingerprint>.
+
 =back
 
 =head1 SEE ALSO
@@ -72,7 +120,7 @@ B<openssl> B<storeutl> was added to OpenSSL 1.1.1.
 
 =head1 COPYRIGHT
 
-Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the OpenSSL license (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/doc/man3/OSSL_STORE_LOADER.pod b/doc/man3/OSSL_STORE_LOADER.pod
index 0bdd112..e827434 100644
--- a/doc/man3/OSSL_STORE_LOADER.pod
+++ b/doc/man3/OSSL_STORE_LOADER.pod
@@ -5,10 +5,12 @@
 OSSL_STORE_LOADER, OSSL_STORE_LOADER_CTX, OSSL_STORE_LOADER_new,
 OSSL_STORE_LOADER_get0_engine, OSSL_STORE_LOADER_get0_scheme,
 OSSL_STORE_LOADER_set_open, OSSL_STORE_LOADER_set_ctrl,
+OSSL_STORE_LOADER_set_expect, OSSL_STORE_LOADER_set_find,
 OSSL_STORE_LOADER_set_load, OSSL_STORE_LOADER_set_eof,
 OSSL_STORE_LOADER_set_error, OSSL_STORE_LOADER_set_close,
 OSSL_STORE_LOADER_free, OSSL_STORE_register_loader,
 OSSL_STORE_unregister_loader, OSSL_STORE_open_fn, OSSL_STORE_ctrl_fn,
+OSSL_STORE_expect_fn, OSSL_STORE_find_fn,
 OSSL_STORE_load_fn, OSSL_STORE_eof_fn, OSSL_STORE_error_fn,
 OSSL_STORE_close_fn - Types and functions to manipulate, register and
 unregister STORE loaders for different URI schemes
@@ -37,6 +39,13 @@ unregister STORE loaders for different URI schemes
                                    va_list args);
  int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *store_loader,
                                 OSSL_STORE_ctrl_fn store_ctrl_function);
+ typedef int (*OSSL_STORE_expect_fn)(OSSL_STORE_LOADER_CTX *ctx, int expected);
+ int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader,
+                                  OSSL_STORE_expect_fn expect_function);
+ typedef int (*OSSL_STORE_find_fn)(OSSL_STORE_LOADER_CTX *ctx,
+                                   OSSL_STORE_SEARCH *criteria);
+ int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader,
+                                OSSL_STORE_find_fn find_function);
  typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn)(OSSL_STORE_LOADER_CTX *ctx,
                                                 UI_METHOD *ui_method,
                                                 void *ui_data);
@@ -71,9 +80,10 @@ OSSL_STORE_close() for this scheme.
 B<OSSL_STORE_LOADER_CTX> is a type template, to be defined by each loader
 using B<struct ossl_store_loader_ctx_st { ... }>.
 
-B<OSSL_STORE_open_fn>, B<OSSL_STORE_ctrl_fn>, B<OSSL_STORE_load_fn>,
-B<OSSL_STORE_eof_fn> and B<OSSL_STORE_close_fn> are the function pointer
-types used within a STORE loader.
+B<OSSL_STORE_open_fn>, B<OSSL_STORE_ctrl_fn>, B<OSSL_STORE_expect_fn>,
+B<OSSL_STORE_find_fn>, B<OSSL_STORE_load_fn>, B<OSSL_STORE_eof_fn>,
+and B<OSSL_STORE_close_fn>
+are the function pointer types used within a STORE loader.
 The functions pointed at define the functionality of the given loader.
 
 =over 4
@@ -108,6 +118,27 @@ numbers.
 
 This function is expected to return 1 on success, 0 on error.
 
+=item B<OSSL_STORE_expect_fn>
+
+This function takes a B<OSSL_STORE_LOADER_CTX> pointer and a B<OSSL_STORE_INFO>
+identity B<expected>, and is used to tell the loader what object type is
+expected.
+B<expected> may be zero to signify that no specific object type is expected.
+
+This function is expected to return 1 on success, 0 on error.
+
+=item B<OSSL_STORE_find_fn>
+
+This function takes a B<OSSL_STORE_LOADER_CTX> pointer and a
+B<OSSL_STORE_SEARCH> search criterion, and is used to tell the loader what
+to search for.
+
+When called with the loader context being B<NULL>, this function is expected
+to return 1 if the loader supports the criterion, otherwise 0.
+
+When called with the loader context being something other than B<NULL>, this
+function is expected to return 1 on success, 0 on error.
+
 =item B<OSSL_STORE_load_fn>
 
 This function takes a B<OSSL_STORE_LOADER_CTX> pointer and a B<UI_METHOD>
@@ -161,6 +192,9 @@ B<store_loader>.
 OSSL_STORE_LOADER_set_ctrl() sets the control function for the
 B<store_loader>.
 
+OSSL_STORE_LOADER_set_expect() sets the expect function for the
+B<store_loader>.
+
 OSSL_STORE_LOADER_set_load() sets the loader function for the
 B<store_loader>.
 
@@ -186,9 +220,10 @@ The B<file:> scheme has built in support.
 =head1 RETURN VALUES
 
 The functions with the types B<OSSL_STORE_open_fn>, B<OSSL_STORE_ctrl_fn>,
+B<OSSL_STORE_expect_fn>,
 B<OSSL_STORE_load_fn>, B<OSSL_STORE_eof_fn> and B<OSSL_STORE_close_fn> have the
-same return values as OSSL_STORE_open(), OSSL_STORE_load(), OSSL_STORE_eof() and
-OSSL_STORE_close(), respectively.
+same return values as OSSL_STORE_open(), OSSL_STORE_ctrl(), OSSL_STORE_expect(),
+OSSL_STORE_load(), OSSL_STORE_eof() and OSSL_STORE_close(), respectively.
 
 OSSL_STORE_LOADER_new() returns a pointer to a B<OSSL_STORE_LOADER> on success,
 or B<NULL> on failure.
diff --git a/doc/man3/OSSL_STORE_SEARCH.pod b/doc/man3/OSSL_STORE_SEARCH.pod
new file mode 100644
index 0000000..411664d
--- /dev/null
+++ b/doc/man3/OSSL_STORE_SEARCH.pod
@@ -0,0 +1,193 @@
+=pod
+
+=head1 NAME
+
+OSSL_STORE_SEARCH,
+OSSL_STORE_SEARCH_by_name,
+OSSL_STORE_SEARCH_by_issuer_serial,
+OSSL_STORE_SEARCH_by_key_fingerprint,
+OSSL_STORE_SEARCH_by_alias,
+OSSL_STORE_SEARCH_free,
+OSSL_STORE_SEARCH_get_type,
+OSSL_STORE_SEARCH_get0_name,
+OSSL_STORE_SEARCH_get0_serial,
+OSSL_STORE_SEARCH_get0_bytes,
+OSSL_STORE_SEARCH_get0_string,
+OSSL_STORE_SEARCH_get0_digest
+- Type and functions to create OSSL_STORE search criteria
+
+=head1 SYNOPSIS
+
+ #include <openssl/store.h>
+
+ typedef struct ossl_store_search_st OSSL_STORE_SEARCH;
+
+ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name);
+ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name,
+                                                       const ASN1_INTEGER
+                                                       *serial);
+ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
+                                                         const unsigned char
+                                                         *bytes, int len);
+ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias);
+
+ void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search);
+
+ int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion);
+ X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion);
+ const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
+                                                   *criterion);
+ const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH
+                                                   *criterion, size_t *length);
+ const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion);
+ const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH
+                                             *criterion);
+
+=head1 DESCRIPTION
+
+These functions are use to specify search criteria to help search for specific
+objects through other names than just the URI that's given to OSSL_STORE_open().
+For example, this can be useful for an application that has received a URI
+and then wants to add on search criteria in a uniform and supported manner.
+
+=head2 Types
+
+B<OSSL_STORE_SEARCH> is an opaque type that holds the constructed search
+criterion, and that can be given to an OSSL_STORE context with
+OSSL_STORE_find().
+
+The calling application owns the allocation of an B<OSSL_STORE_SEARCH> at all
+times, and should therefore be careful not to deallocate it before
+OSSL_STORE_close() has been called for the OSSL_STORE context it was given
+to.
+
+=head2 Application Functions
+
+OSSL_STORE_SEARCH_by_name(),
+OSSL_STORE_SEARCH_by_issuer_serial(),
+OSSL_STORE_SEARCH_by_key_fingerprint(),
+and OSSL_STORE_SEARCH_by_alias()
+are used to create an B<OSSL_STORE_SEARCH> from a subject name, an issuer name
+and serial number pair, a key fingerprint, and an alias (for example a friendly
+name).
+The parameters that are provided are not copied, only referred to in a
+criterion, so they must have at least the same life time as the created
+B<OSSL_STORE_SEARCH>.
+
+OSSL_STORE_SEARCH_free() is used to free the B<OSSL_STORE_SEARCH>.
+
+=head2 Loader Functions
+
+OSSL_STORE_SEARCH_get_type() returns the criterion type for the given
+B<OSSL_STORE_SEARCH>.
+
+OSSL_STORE_SEARCH_get0_name(), OSSL_STORE_SEARCH_get0_serial(),
+OSSL_STORE_SEARCH_get0_bytes(), OSSL_STORE_SEARCH_get0_string(),
+and OSSL_STORE_SEARCH_get0_digest()
+are used to retrieve different data from a B<OSSL_STORE_SEARCH>, as
+available for each type.
+For more information, see L</SUPPORTED CRITERION TYPES> below.
+
+=head1 SUPPORTED CRITERION TYPES
+
+Currently supported criterion types are:
+
+=over 4
+
+=item OSSL_STORE_SEARCH_BY_NAME
+
+This criterion supports a search by exact match of subject name.
+The subject name itself is a B<X509_NAME> pointer.
+A criterion of this type is created with OSSL_STORE_SEARCH_by_name(),
+and the actual subject name is retrieved with OSSL_STORE_SEARCH_get0_name().
+
+=item OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
+
+This criterion supports a search by exact match of both issuer name and serial
+number.
+The issuer name itself is a B<X509_NAME> pointer, and the serial number is
+a B<ASN1_INTEGER> pointer.
+A criterion of this type is created with OSSL_STORE_SEARCH_by_issuer_serial()
+and the actual issuer name and serial number are retrieved with
+OSSL_STORE_SEARCH_get0_name() and OSSL_STORE_SEARCH_get0_serial().
+
+=item OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT
+
+This criterion supports a search by exact match of key fingerprint.
+The key fingerprint in itself is a string of bytes and its length, as
+well as the algorithm that was used to compute the fingerprint.
+The digest may be left unspecified (NULL), and in that case, the
+loader has to decide on a default digest and compare fingerprints
+accordingly.
+A criterion of this type is created with OSSL_STORE_SEARCH_by_key_fingerprint()
+and the actual fingerprint and its length can be retrieved with
+OSSL_STORE_SEARCH_get0_bytes().
+The digest can be retreived with OSSL_STORE_SEARCH_get0_digest().
+
+=item OSSL_STORE_SEARCH_BY_ALIAS
+
+This criterion supports a search by match of an alias of some kind.
+The alias in itself is a simple C string.
+A criterion of this type is created with OSSL_STORE_SEARCH_by_alias()
+and the actual alias is retrieved with OSSL_STORE_SEARCH_get0_string().
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_STORE_SEARCH_by_name(),
+OSSL_STORE_SEARCH_by_issuer_serial(),
+OSSL_STORE_SEARCH_by_key_fingerprint(),
+and OSSL_STORE_SEARCH_by_alias()
+return a B<OSSL_STORE_SEARCH> pointer on success, or B<NULL> on failure.
+
+OSSL_STORE_SEARCH_get_type() returns the criterion type of the given
+B<OSSL_STORE_SEARCH>.
+There is no error value.
+
+OSSL_STORE_SEARCH_get0_name() returns a B<X509_NAME> pointer on success,
+or B<NULL> when the given B<OSSL_STORE_SEARCH> was of a different type.
+
+OSSL_STORE_SEARCH_get0_serial() returns a B<ASN1_INTEGER> pointer on success,
+or B<NULL> when the given B<OSSL_STORE_SEARCH> was of a different type.
+
+OSSL_STORE_SEARCH_get0_bytes() returns a B<const unsigned char> pointer and
+sets B<*length> to the strings length on success, or B<NULL> when the given
+B<OSSL_STORE_SEARCH> was of a different type.
+
+OSSL_STORE_SEARCH_get0_string() returns a B<const char> pointer on success,
+or B<NULL> when the given B<OSSL_STORE_SEARCH> was of a different type.
+
+OSSL_STORE_SEARCH_get0_digest() returns a B<const EVP_MD> pointer.
+B<NULL> is a valid value and means that the store loader default will
+be used when applicable.
+
+=head1 SEE ALSO
+
+L<ossl_store(7)>, L<OSSL_STORE_supports_search(3)>, L<OSSL_STORE_find(3)>
+
+=head1 HISTORY
+
+B<OSSL_STORE_SEARCH>,
+OSSL_STORE_SEARCH_by_name(),
+OSSL_STORE_SEARCH_by_issuer_serial(),
+OSSL_STORE_SEARCH_by_key_fingerprint(),
+OSSL_STORE_SEARCH_by_alias(),
+OSSL_STORE_SEARCH_free(),
+OSSL_STORE_SEARCH_get_type(),
+OSSL_STORE_SEARCH_get0_name(),
+OSSL_STORE_SEARCH_get0_serial(),
+OSSL_STORE_SEARCH_get0_bytes(),
+and OSSL_STORE_SEARCH_get0_string()
+were added to OpenSSL 1.1.1.
+
+=head1 COPYRIGHT
+
+Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_STORE_expect.pod b/doc/man3/OSSL_STORE_expect.pod
new file mode 100644
index 0000000..ab0e878
--- /dev/null
+++ b/doc/man3/OSSL_STORE_expect.pod
@@ -0,0 +1,79 @@
+=pod
+
+=head1 NAME
+
+OSSL_STORE_expect,
+OSSL_STORE_supports_search,
+OSSL_STORE_find
+- Specify what object type is expected
+
+=head1 SYNOPSIS
+
+ #include <openssl/store.h>
+
+ int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type);
+
+ int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int criterion_type);
+ 
+ int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search);
+
+=head1 DESCRIPTION
+
+OSSL_STORE_expect() helps applications filter what OSSL_STORE_load() returns
+by specifying a B<OSSL_STORE_INFO> type.
+For example, if C<file:/foo/bar/store.pem> contains several different objects
+and only the certificates are interesting, the application can simply say
+that it expects the type B<OSSL_STORE_INFO_CERT>.
+All known object types (see L<OSSL_STORE_INFO(3)/SUPPORTED OBJECTS>)
+except for B<OSSL_STORE_INFO_NAME> are supported.
+
+OSSL_STORE_find() helps applications specify a criterion for a more fine
+grained search of objects.
+
+OSSL_STORE_supports_search() checks if the loader of the given OSSL_STORE
+context supports the given search type.
+See L<OSSL_STORE_SEARCH/SUPPORED CRITERION TYPES> for information on the
+supported search criterion types.
+
+OSSL_STORE_expect() and OSSL_STORE_find I<must> be called before the first
+OSSL_STORE_load() of a given session, or they will fail.
+
+=head1 NOTES
+
+If a more elaborate filter is required by the application, a better choice
+would be to use a post-processing function.
+See L<OSSL_STORE_open(3)> for more information.
+
+However, some loaders may take advantage of the knowledge of an expected type
+to make object retrieval more efficient, so if a single type is expected, this
+method is usually preferable.
+
+=head1 RETURN VALUES
+
+OSSL_STORE_expect() returns 1 on success, or 0 on failure.
+
+OSSL_STORE_supports_search() returns 1 if the criterion is supported, or 0
+otherwise.
+
+OSSL_STORE_find() returns 1 on success, or 0 on failure.
+
+=head1 SEE ALSO
+
+L<ossl_store(7)>, L<OSSL_STORE_INFO(3)>, L<OSSL_STORE_SEARCH(3)>,
+L<OSSL_STORE_load(3)>
+
+=head1 HISTORY
+
+OSSL_STORE_expect(), OSSL_STORE_supports_search() and OSSL_STORE_find()
+were added to OpenSSL 1.1.1.
+
+=head1 COPYRIGHT
+
+Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/ossl_store.pod b/doc/man7/ossl_store.pod
index 71cb27d..98cc04f 100644
--- a/doc/man7/ossl_store.pod
+++ b/doc/man7/ossl_store.pod
@@ -86,11 +86,13 @@ only).
 
 =head1 SEE ALSO
 
-L<OSSL_STORE_open(3)>, L<OSSL_STORE_INFO(3)>, L<OSSL_STORE_LOADER(3)>
+L<OSSL_STORE_INFO(3)>, L<OSSL_STORE_LOADER(3)>,
+L<OSSL_STORE_open(3)>, L<OSSL_STORE_expect(3)>,
+L<OSSL_STORE_SEARCH(3)>
 
 =head1 COPYRIGHT
 
-Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the OpenSSL license (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h
index f5214ab..2f242f1 100644
--- a/include/openssl/ossl_typ.h
+++ b/include/openssl/ossl_typ.h
@@ -174,6 +174,7 @@ typedef struct ctlog_store_st CTLOG_STORE;
 typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX;
 
 typedef struct ossl_store_info_st OSSL_STORE_INFO;
+typedef struct ossl_store_search_st OSSL_STORE_SEARCH;
 
 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
     defined(INTMAX_MAX) && defined(UINTMAX_MAX)
diff --git a/include/openssl/store.h b/include/openssl/store.h
index ff42953..7b43e8b 100644
--- a/include/openssl/store.h
+++ b/include/openssl/store.h
@@ -153,6 +153,55 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info);
 
 
 /*-
+ *  Functions to construct a search URI from a base URI and search criteria
+ *  -----------------------------------------------------------------------
+ */
+
+/* OSSL_STORE search types */
+# define OSSL_STORE_SEARCH_BY_NAME              1 /* subject in certs, issuer in CRLs */
+# define OSSL_STORE_SEARCH_BY_ISSUER_SERIAL     2
+# define OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT   3
+# define OSSL_STORE_SEARCH_BY_ALIAS             4
+
+/* To check what search types the scheme handler supports */
+int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type);
+
+/* Search term constructors */
+/*
+ * The input is considered to be owned by the caller, and must therefore
+ * remain present throughout the lifetime of the returned OSSL_STORE_SEARCH
+ */
+OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name);
+OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name,
+                                                      const ASN1_INTEGER
+                                                      *serial);
+OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
+                                                        const unsigned char
+                                                        *bytes, size_t len);
+OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias);
+
+/* Search term destructor */
+void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search);
+
+/* Search term accessors */
+int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion);
+X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion);
+const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
+                                                  *criterion);
+const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH
+                                                  *criterion, size_t *length);
+const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion);
+const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion);
+
+/*
+ * Add search criterion and expected return type (which can be unspecified)
+ * to the loading channel.  This MUST happen before the first OSSL_STORE_load().
+ */
+int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type);
+int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search);
+
+
+/*-
  *  Function to register a loader for the given URI scheme.
  *  -------------------------------------------------------
  *
@@ -177,6 +226,13 @@ typedef int (*OSSL_STORE_ctrl_fn)(OSSL_STORE_LOADER_CTX *ctx, int cmd,
                                   va_list args);
 int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader,
                                OSSL_STORE_ctrl_fn ctrl_function);
+typedef int (*OSSL_STORE_expect_fn)(OSSL_STORE_LOADER_CTX *ctx, int expected);
+int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader,
+                                 OSSL_STORE_expect_fn expect_function);
+typedef int (*OSSL_STORE_find_fn)(OSSL_STORE_LOADER_CTX *ctx,
+                                  OSSL_STORE_SEARCH *criteria);
+int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader,
+                               OSSL_STORE_find_fn find_function);
 typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn)(OSSL_STORE_LOADER_CTX *ctx,
                                                const UI_METHOD *ui_method,
                                                void *ui_data);
diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h
index 5476d00..33d0ab7 100644
--- a/include/openssl/storeerr.h
+++ b/include/openssl/storeerr.h
@@ -20,13 +20,16 @@ int ERR_load_OSSL_STORE_strings(void);
  * OSSL_STORE function codes.
  */
 # define OSSL_STORE_F_FILE_CTRL                           129
+# define OSSL_STORE_F_FILE_FIND                           138
 # define OSSL_STORE_F_FILE_GET_PASS                       118
 # define OSSL_STORE_F_FILE_LOAD                           119
 # define OSSL_STORE_F_FILE_LOAD_TRY_DECODE                124
 # define OSSL_STORE_F_FILE_NAME_TO_URI                    126
 # define OSSL_STORE_F_FILE_OPEN                           120
 # define OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO           127
+# define OSSL_STORE_F_OSSL_STORE_EXPECT                   130
 # define OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT  128
+# define OSSL_STORE_F_OSSL_STORE_FIND                     131
 # define OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT          100
 # define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT           101
 # define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL            102
@@ -46,6 +49,10 @@ int ERR_load_OSSL_STORE_strings(void);
 # define OSSL_STORE_F_OSSL_STORE_OPEN                     114
 # define OSSL_STORE_F_OSSL_STORE_OPEN_INT                 115
 # define OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT      117
+# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS          132
+# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL  133
+# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT 136
+# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME           137
 # define OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT    116
 # define OSSL_STORE_F_TRY_DECODE_PARAMS                   121
 # define OSSL_STORE_F_TRY_DECODE_PKCS12                   122
@@ -57,9 +64,11 @@ int ERR_load_OSSL_STORE_strings(void);
 # define OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE              107
 # define OSSL_STORE_R_BAD_PASSWORD_READ                   115
 # define OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC          113
+# define OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST 121
 # define OSSL_STORE_R_INVALID_SCHEME                      106
 # define OSSL_STORE_R_IS_NOT_A                            112
 # define OSSL_STORE_R_LOADER_INCOMPLETE                   116
+# define OSSL_STORE_R_LOADING_STARTED                     117
 # define OSSL_STORE_R_NOT_A_CERTIFICATE                   100
 # define OSSL_STORE_R_NOT_A_CRL                           101
 # define OSSL_STORE_R_NOT_A_KEY                           102
@@ -67,9 +76,12 @@ int ERR_load_OSSL_STORE_strings(void);
 # define OSSL_STORE_R_NOT_PARAMETERS                      104
 # define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR           114
 # define OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE               108
+# define OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 119
 # define OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED 109
 # define OSSL_STORE_R_UNREGISTERED_SCHEME                 105
 # define OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE            110
+# define OSSL_STORE_R_UNSUPPORTED_OPERATION               118
+# define OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE             120
 # define OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED           111
 
 #endif
diff --git a/test/recipes/90-test_store.t b/test/recipes/90-test_store.t
index 83ec012..2a6414b 100644
--- a/test/recipes/90-test_store.t
+++ b/test/recipes/90-test_store.t
@@ -1,12 +1,12 @@
 #! /usr/bin/env perl
-# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the OpenSSL license (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
 # in the file LICENSE in the source distribution or at
 # https://www.openssl.org/source/license.html
 
-use File::Spec;
+use File::Spec::Functions;
 use File::Copy;
 use MIME::Base64;
 use OpenSSL::Test qw(:DEFAULT srctop_file srctop_dir bldtop_file data_file);
@@ -69,13 +69,13 @@ my @noexist_file_files =
     ( "file:blahdiblah.pem",
       "file:test/blahdibleh.der" );
 
-
 my $n = (3 * scalar @noexist_files)
     + (6 * scalar @src_files)
     + (4 * scalar @generated_files)
     + (scalar keys %generated_file_files)
     + (scalar @noexist_file_files)
-    + 4;
+    + 3
+    + 11;
 
 plan tests => $n;
 
@@ -84,9 +84,7 @@ indir "store_$$" => sub {
     {
         skip "failed initialisation", $n unless init();
 
-        # test PEM_read_bio_PrivateKey
-        ok(run(app(["openssl", "rsa", "-in", "rsa-key-pkcs8-pbes2-sha256.pem",
-                    "-passin", "pass:password"])));
+        my $rehash = init_rehash();
 
         foreach (@noexist_files) {
             my $file = srctop_file($_);
@@ -152,6 +150,55 @@ indir "store_$$" => sub {
                 ok(run(app(["openssl", "storeutl", to_abs_file_uri($dir, 1)])));
             }
         }
+
+        ok(!run(app(['openssl', 'storeutl',
+                     '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert',
+                     srctop_file('test', 'testx509.pem')])),
+           "Checking that -subject can't be used with a single file");
+
+        ok(run(app(['openssl', 'storeutl', '-certs',
+                    srctop_file('test', 'testx509.pem')])),
+           "Checking that -certs returns 1 object on a certificate file");
+        ok(run(app(['openssl', 'storeutl', '-certs',
+                     srctop_file('test', 'testcrl.pem')])),
+           "Checking that -certs returns 0 objects on a CRL file");
+
+        ok(run(app(['openssl', 'storeutl', '-crls',
+                     srctop_file('test', 'testx509.pem')])),
+           "Checking that -crls returns 0 objects on a certificate file");
+        ok(run(app(['openssl', 'storeutl', '-crls',
+                    srctop_file('test', 'testcrl.pem')])),
+           "Checking that -crls returns 1 object on a CRL file");
+
+    SKIP: {
+            skip "failed rehash initialisation", 6 unless $rehash;
+
+            # subject from testx509.pem:
+            # '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert'
+            # issuer from testcrl.pem:
+            # '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority'
+            ok(run(app(['openssl', 'storeutl',
+                        '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert',
+                        catdir(curdir(), 'rehash')])));
+            ok(run(app(['openssl', 'storeutl',
+                        '-subject',
+                        '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority',
+                        catdir(curdir(), 'rehash')])));
+            ok(run(app(['openssl', 'storeutl', '-certs',
+                        '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert',
+                        catdir(curdir(), 'rehash')])));
+            ok(run(app(['openssl', 'storeutl', '-crls',
+                        '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert',
+                        catdir(curdir(), 'rehash')])));
+            ok(run(app(['openssl', 'storeutl', '-certs',
+                        '-subject',
+                        '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority',
+                        catdir(curdir(), 'rehash')])));
+            ok(run(app(['openssl', 'storeutl', '-crls',
+                        '-subject',
+                        '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority',
+                        catdir(curdir(), 'rehash')])));
+        }
     }
 }, create => 1, cleanup => 1;
 
@@ -350,6 +397,17 @@ sub init {
            );
 }
 
+sub init_rehash {
+    return (
+            mkdir(catdir(curdir(), 'rehash'))
+            && copy(srctop_file('test', 'testx509.pem'),
+                    catdir(curdir(), 'rehash'))
+            && copy(srctop_file('test', 'testcrl.pem'),
+                    catdir(curdir(), 'rehash'))
+            && run(app(['openssl', 'rehash', catdir(curdir(), 'rehash')]))
+           );
+}
+
 sub runall {
     my ($function, @items) = @_;
 
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 0049eab..bd94e27 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4505,3 +4505,19 @@ RAND_DRBG_secure_new                    4446	1_1_1	EXIST::FUNCTION:
 OSSL_STORE_vctrl                        4447	1_1_1	EXIST::FUNCTION:
 X509_get0_authority_key_id              4448	1_1_0h	EXIST::FUNCTION:
 BIO_bind                                4449	1_1_1	EXIST::FUNCTION:SOCK
+OSSL_STORE_LOADER_set_expect            4450	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_expect                       4451	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_by_key_fingerprint    4452	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_get0_serial           4453	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_by_name               4454	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_supports_search              4455	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_find                         4456	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_get_type              4457	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_get0_bytes            4458	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_get0_string           4459	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_by_issuer_serial      4460	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_get0_name             4461	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_by_alias              4462	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_LOADER_set_find              4463	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_free                  4464	1_1_1	EXIST::FUNCTION:
+OSSL_STORE_SEARCH_get0_digest           4465	1_1_1	EXIST::FUNCTION:
diff --git a/util/private.num b/util/private.num
index 099a4f7..c106e60 100644
--- a/util/private.num
+++ b/util/private.num
@@ -31,8 +31,11 @@ OSSL_STORE_CTX                          datatype
 OSSL_STORE_INFO                         datatype
 OSSL_STORE_LOADER                       datatype
 OSSL_STORE_LOADER_CTX                   datatype
+OSSL_STORE_SEARCH                       datatype
 OSSL_STORE_close_fn                     datatype
 OSSL_STORE_ctrl_fn                      datatype
+OSSL_STORE_expect_fn                    datatype
+OSSL_STORE_find_fn                      datatype
 OSSL_STORE_eof_fn                       datatype
 OSSL_STORE_error_fn                     datatype
 OSSL_STORE_load_fn                      datatype


More information about the openssl-commits mailing list