Add the STORE module
authorRichard Levitte <levitte@openssl.org>
Thu, 8 Dec 2016 14:51:31 +0000 (15:51 +0100)
committerRichard Levitte <levitte@openssl.org>
Thu, 29 Jun 2017 09:55:31 +0000 (11:55 +0200)
This STORE module adds the following functionality:

- A function OSSL_STORE_open(), OSSL_STORE_load() and OSSL_STORE_close()
  that accesses a URI and helps loading the supported objects (PKEYs,
  CERTs and CRLs for the moment) from it.
- An opaque type OSSL_STORE_INFO that holds information on each loaded
  object.
- A few functions to retrieve desired data from a OSSL_STORE_INFO
  reference.
- Functions to register and unregister loaders for different URI
  schemes.  This enables dynamic addition of loaders from applications
  or from engines.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3542)

20 files changed:
Configure
crypto/err/err.c
crypto/err/err_all.c
crypto/err/openssl.ec
crypto/err/openssl.txt
crypto/include/internal/store.h [new file with mode: 0644]
crypto/init.c
crypto/store/build.info [new file with mode: 0644]
crypto/store/store_err.c [new file with mode: 0644]
crypto/store/store_init.c [new file with mode: 0644]
crypto/store/store_lib.c [new file with mode: 0644]
crypto/store/store_locl.h [new file with mode: 0644]
crypto/store/store_register.c [new file with mode: 0644]
crypto/store/store_strings.c [new file with mode: 0644]
include/openssl/err.h
include/openssl/ossl_typ.h
include/openssl/store.h [new file with mode: 0644]
include/openssl/storeerr.h [new file with mode: 0644]
util/libcrypto.num
util/private.num

index 2eacb23..e302a58 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -310,7 +310,7 @@ $config{sdirs} = [
     "bn", "ec", "rsa", "dsa", "dh", "dso", "engine",
     "buffer", "bio", "stack", "lhash", "rand", "err",
     "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
-    "cms", "ts", "srp", "cmac", "ct", "async", "kdf"
+    "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
     ];
 # test/ subdirectories to build
 $config{tdirs} = [ "ossl_shim" ];
index 4d83024..17a9fe1 100644 (file)
@@ -60,6 +60,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
     {ERR_PACK(ERR_LIB_CT, 0, 0), "CT routines"},
     {ERR_PACK(ERR_LIB_ASYNC, 0, 0), "ASYNC routines"},
     {ERR_PACK(ERR_LIB_KDF, 0, 0), "KDF routines"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, 0), "STORE routines"},
     {0, NULL},
 };
 
@@ -108,6 +109,7 @@ static ERR_STRING_DATA ERR_str_reasons[] = {
     {ERR_R_X509V3_LIB, "X509V3 lib"},
     {ERR_R_ENGINE_LIB, "ENGINE lib"},
     {ERR_R_UI_LIB, "UI lib"},
+    {ERR_R_OSSL_STORE_LIB, "STORE lib"},
     {ERR_R_ECDSA_LIB, "ECDSA lib"},
 
     {ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"},
index 6cc8c8f..3fff594 100644 (file)
@@ -36,6 +36,7 @@
 #include <openssl/ct.h>
 #include <openssl/async.h>
 #include <openssl/kdf.h>
+#include <openssl/store.h>
 
 int err_load_crypto_strings_int(void)
 {
@@ -93,7 +94,8 @@ int err_load_crypto_strings_int(void)
 # endif
         ERR_load_ASYNC_strings() == 0 ||
 #endif
-        ERR_load_KDF_strings() == 0)
+        ERR_load_KDF_strings() == 0 ||
+        ERR_load_OSSL_STORE_strings() == 0)
         return 0;
 
     return 1;
index 20b6b4a..be84c7c 100644 (file)
@@ -32,6 +32,7 @@ L CMS           include/openssl/cms.h           crypto/cms/cms_err.c
 L CT            include/openssl/ct.h            crypto/ct/ct_err.c
 L ASYNC         include/openssl/async.h         crypto/async/async_err.c
 L KDF           include/openssl/kdf.h           crypto/kdf/kdf_err.c
+L OSSL_STORE    include/openssl/store.h         crypto/store/store_err.c
 
 # additional header files to be scanned for function names
 L NONE          include/openssl/x509_vfy.h      NONE
index d9fa3d3..14987b1 100644 (file)
@@ -724,6 +724,28 @@ OCSP_F_OCSP_REQUEST_SIGN:110:OCSP_request_sign
 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_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
+OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME:103:OSSL_STORE_INFO_get1_NAME
+OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION:135:\
+       OSSL_STORE_INFO_get1_NAME_description
+OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS:104:OSSL_STORE_INFO_get1_PARAMS
+OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY:105:OSSL_STORE_INFO_get1_PKEY
+OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT:106:OSSL_STORE_INFO_new_CERT
+OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL:107:OSSL_STORE_INFO_new_CRL
+OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME:109:OSSL_STORE_INFO_new_NAME
+OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS:110:OSSL_STORE_INFO_new_PARAMS
+OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY:111:OSSL_STORE_INFO_new_PKEY
+OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION:134:\
+       OSSL_STORE_INFO_set0_NAME_description
+OSSL_STORE_F_OSSL_STORE_INIT_ONCE:112:ossl_store_init_once
+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_UNREGISTER_LOADER_INT:116:\
+       ossl_store_unregister_loader_int
 PEM_F_B2I_DSS:127:b2i_dss
 PEM_F_B2I_PVK_BIO:128:b2i_PVK_bio
 PEM_F_B2I_RSA:129:b2i_rsa
@@ -1950,6 +1972,13 @@ OCSP_R_STATUS_TOO_OLD:127:status too old
 OCSP_R_UNKNOWN_MESSAGE_DIGEST:119:unknown message digest
 OCSP_R_UNKNOWN_NID:120:unknown nid
 OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE:129:unsupported requestorname type
+OSSL_STORE_R_INVALID_SCHEME:106:invalid scheme
+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
+OSSL_STORE_R_NOT_A_NAME:103:not a name
+OSSL_STORE_R_NOT_PARAMETERS:104:not parameters
+OSSL_STORE_R_UNREGISTERED_SCHEME:105:unregistered scheme
 PEM_R_BAD_BASE64_DECODE:100:bad base64 decode
 PEM_R_BAD_DECRYPT:101:bad decrypt
 PEM_R_BAD_END_LINE:102:bad end line
diff --git a/crypto/include/internal/store.h b/crypto/include/internal/store.h
new file mode 100644 (file)
index 0000000..f5013dc
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2016 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
+ */
+
+void ossl_store_cleanup_int(void);
index 2d2b07d..e159a3d 100644 (file)
@@ -24,6 +24,7 @@
 #include <assert.h>
 #include <internal/thread_once.h>
 #include <internal/dso.h>
+#include <internal/store.h>
 
 static int stopped = 0;
 
@@ -491,6 +492,7 @@ void OPENSSL_cleanup(void)
 #ifndef OPENSSL_NO_ENGINE
     engine_cleanup_int();
 #endif
+    ossl_store_cleanup_int();
     crypto_cleanup_all_ex_data_int();
     bio_cleanup();
     evp_cleanup_int();
diff --git a/crypto/store/build.info b/crypto/store/build.info
new file mode 100644 (file)
index 0000000..4b6af29
--- /dev/null
@@ -0,0 +1,3 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=\
+        store_err.c store_init.c store_lib.c store_register.c store_strings.c
diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c
new file mode 100644 (file)
index 0000000..3f5069a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2017 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
+ */
+
+#include <openssl/err.h>
+#include <openssl/storeerr.h>
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA OSSL_STORE_str_functs[] = {
+    {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),
+     "OSSL_STORE_INFO_get1_CERT"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL, 0),
+     "OSSL_STORE_INFO_get1_CRL"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME, 0),
+     "OSSL_STORE_INFO_get1_NAME"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION, 0),
+     "OSSL_STORE_INFO_get1_NAME_description"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS, 0),
+     "OSSL_STORE_INFO_get1_PARAMS"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY, 0),
+     "OSSL_STORE_INFO_get1_PKEY"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT, 0),
+     "OSSL_STORE_INFO_new_CERT"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL, 0),
+     "OSSL_STORE_INFO_new_CRL"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME, 0),
+     "OSSL_STORE_INFO_new_NAME"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS, 0),
+     "OSSL_STORE_INFO_new_PARAMS"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY, 0),
+     "OSSL_STORE_INFO_new_PKEY"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION, 0),
+     "OSSL_STORE_INFO_set0_NAME_description"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INIT_ONCE, 0),
+     "ossl_store_init_once"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_LOADER_NEW, 0),
+     "OSSL_STORE_LOADER_new"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_OPEN, 0),
+     "OSSL_STORE_open"},
+    {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_UNREGISTER_LOADER_INT, 0),
+     "ossl_store_unregister_loader_int"},
+    {0, NULL}
+};
+
+static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_INVALID_SCHEME),
+    "invalid scheme"},
+    {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"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_KEY), "not a key"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_NAME), "not a name"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_PARAMETERS),
+    "not parameters"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNREGISTERED_SCHEME),
+    "unregistered scheme"},
+    {0, NULL}
+};
+
+#endif
+
+int ERR_load_OSSL_STORE_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+    if (ERR_func_error_string(OSSL_STORE_str_functs[0].error) == NULL) {
+        ERR_load_strings_const(OSSL_STORE_str_functs);
+        ERR_load_strings_const(OSSL_STORE_str_reasons);
+    }
+#endif
+    return 1;
+}
diff --git a/crypto/store/store_init.c b/crypto/store/store_init.c
new file mode 100644 (file)
index 0000000..90d5436
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016-2017 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
+ */
+
+#include <openssl/err.h>
+#include "internal/store.h"
+#include "store_locl.h"
+
+static CRYPTO_ONCE store_init = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(do_store_init)
+{
+    return OPENSSL_init_crypto(0, NULL);
+}
+
+int ossl_store_init_once()
+{
+    if (!RUN_ONCE(&store_init, do_store_init)) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INIT_ONCE, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    return 1;
+}
+
+void ossl_store_cleanup_int(void)
+{
+    ossl_store_destroy_loaders_int();
+}
diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c
new file mode 100644 (file)
index 0000000..5f07f8c
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2016-2017 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
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/store.h>
+#include "internal/thread_once.h"
+#include "store_locl.h"
+
+struct ossl_store_ctx_st {
+    const OSSL_STORE_LOADER *loader;
+    OSSL_STORE_LOADER_CTX *loader_ctx;
+    const UI_METHOD *ui_method;
+    void *ui_data;
+    OSSL_STORE_post_process_info_fn post_process;
+    void *post_process_data;
+};
+
+OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
+                                void *ui_data,
+                                OSSL_STORE_post_process_info_fn post_process,
+                                void *post_process_data)
+{
+    const OSSL_STORE_LOADER *loader;
+    OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
+    OSSL_STORE_CTX *ctx = NULL;
+    char scheme_copy[256], *p;
+
+    OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
+    if ((p = strchr(scheme_copy, ':')) != NULL) {
+        *p = '\0';
+        p = scheme_copy;
+    } else {
+        p = "file";
+    }
+
+    if ((loader = ossl_store_get0_loader_int(p)) == NULL
+        || (loader_ctx = loader->open(loader, uri, ui_method, ui_data)) == NULL)
+        goto done;
+    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_OPEN, ERR_R_MALLOC_FAILURE);
+        goto done;
+    }
+
+    ctx->loader = loader;
+    ctx->loader_ctx = loader_ctx;
+    loader_ctx = NULL;
+    ctx->ui_method = ui_method;
+    ctx->ui_data = ui_data;
+    ctx->post_process = post_process;
+    ctx->post_process_data = post_process_data;
+
+ done:
+    if (loader_ctx != NULL) {
+        /*
+         * We ignore a returned error because we will return NULL anyway in
+         * this case, so if something goes wrong when closing, that'll simply
+         * just add another entry on the error stack.
+         */
+        (void)loader->close(loader_ctx);
+    }
+    return ctx;
+}
+
+int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
+{
+    va_list args;
+    int ret = 0;
+
+    va_start(args, cmd);
+    if (ctx->loader->ctrl != NULL)
+        ret = ctx->loader->ctrl(ctx->loader_ctx, cmd, args);
+    va_end(args);
+
+    return ret;
+}
+
+OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
+{
+    OSSL_STORE_INFO *v = NULL;
+
+ again:
+    v = ctx->loader->load(ctx->loader_ctx, ctx->ui_method, ctx->ui_data);
+
+    if (ctx->post_process != NULL && v != NULL) {
+        v = ctx->post_process(v, ctx->post_process_data);
+
+        /*
+         * By returning NULL, the callback decides that this object should
+         * be ignored.
+         */
+        if (v == NULL)
+            goto again;
+    }
+
+    return v;
+}
+
+int OSSL_STORE_error(OSSL_STORE_CTX *ctx)
+{
+    return ctx->loader->error(ctx->loader_ctx);
+}
+
+int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
+{
+    return ctx->loader->eof(ctx->loader_ctx);
+}
+
+int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
+{
+    int loader_ret = ctx->loader->close(ctx->loader_ctx);
+
+    OPENSSL_free(ctx);
+    return loader_ret;
+}
+
+/*
+ * Functions to generate OSSL_STORE_INFOs, one function for each type we
+ * support having in them.  Along with each of them, one macro that
+ * can be used to determine what types are supported.
+ *
+ * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO
+ * and will therefore be freed when the OSSL_STORE_INFO is freed.
+ */
+static OSSL_STORE_INFO *store_info_new(int type, void *data)
+{
+    OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info));
+
+    if (info == NULL)
+        return NULL;
+
+    info->type = type;
+    info->_.data = data;
+    return info;
+}
+
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
+{
+    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_NAME, NULL);
+
+    if (info == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME,
+                      ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    info->_.name.name = name;
+    info->_.name.desc = NULL;
+
+    return info;
+}
+
+int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc)
+{
+    if (info->type != OSSL_STORE_INFO_NAME) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION,
+                      ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+
+    info->_.name.desc = desc;
+
+    return 1;
+}
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
+{
+    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PARAMS, params);
+
+    if (info == NULL)
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS,
+                      ERR_R_MALLOC_FAILURE);
+    return info;
+}
+
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
+{
+    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PKEY, pkey);
+
+    if (info == NULL)
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY,
+                      ERR_R_MALLOC_FAILURE);
+    return info;
+}
+
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
+{
+    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CERT, x509);
+
+    if (info == NULL)
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT,
+                      ERR_R_MALLOC_FAILURE);
+    return info;
+}
+
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
+{
+    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CRL, crl);
+
+    if (info == NULL)
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL,
+                      ERR_R_MALLOC_FAILURE);
+    return info;
+}
+
+/*
+ * Functions to try to extract data from a OSSL_STORE_INFO.
+ */
+int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info)
+{
+    return info->type;
+}
+
+const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_NAME)
+        return info->_.name.name;
+    return NULL;
+}
+
+char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_NAME) {
+        char *ret = OPENSSL_strdup(info->_.name.name);
+
+        if (ret == NULL)
+            OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME,
+                          ERR_R_MALLOC_FAILURE);
+        return ret;
+    }
+    OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME,
+                  OSSL_STORE_R_NOT_A_NAME);
+    return NULL;
+}
+
+const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_NAME)
+        return info->_.name.desc;
+    return NULL;
+}
+
+char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_NAME) {
+        char *ret = OPENSSL_strdup(info->_.name.desc
+                                   ? info->_.name.desc : "");
+
+        if (ret == NULL)
+            OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION,
+                     ERR_R_MALLOC_FAILURE);
+        return ret;
+    }
+    OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION,
+                  OSSL_STORE_R_NOT_A_NAME);
+    return NULL;
+}
+
+EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_PARAMS)
+        return info->_.params;
+    return NULL;
+}
+
+EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_PARAMS) {
+        EVP_PKEY_up_ref(info->_.params);
+        return info->_.params;
+    }
+    OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS,
+                  OSSL_STORE_R_NOT_PARAMETERS);
+    return NULL;
+}
+
+EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_PKEY)
+        return info->_.pkey;
+    return NULL;
+}
+
+EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_PKEY) {
+        EVP_PKEY_up_ref(info->_.pkey);
+        return info->_.pkey;
+    }
+    OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY,
+                  OSSL_STORE_R_NOT_A_KEY);
+    return NULL;
+}
+
+X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_CERT)
+        return info->_.x509;
+    return NULL;
+}
+
+X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_CERT) {
+        X509_up_ref(info->_.x509);
+        return info->_.x509;
+    }
+    OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT,
+                  OSSL_STORE_R_NOT_A_CERTIFICATE);
+    return NULL;
+}
+
+X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_CRL)
+        return info->_.crl;
+    return NULL;
+}
+
+X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_CRL) {
+        X509_CRL_up_ref(info->_.crl);
+        return info->_.crl;
+    }
+    OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL,
+                  OSSL_STORE_R_NOT_A_CRL);
+    return NULL;
+}
+
+/*
+ * Free the OSSL_STORE_INFO
+ */
+void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
+{
+    if (info != NULL) {
+        switch (info->type) {
+        case OSSL_STORE_INFO_NAME:
+            OPENSSL_free(info->_.name.name);
+            OPENSSL_free(info->_.name.desc);
+            break;
+        case OSSL_STORE_INFO_PARAMS:
+            EVP_PKEY_free(info->_.params);
+            break;
+        case OSSL_STORE_INFO_PKEY:
+            EVP_PKEY_free(info->_.pkey);
+            break;
+        case OSSL_STORE_INFO_CERT:
+            X509_free(info->_.x509);
+            break;
+        case OSSL_STORE_INFO_CRL:
+            X509_CRL_free(info->_.crl);
+            break;
+        }
+        OPENSSL_free(info);
+    }
+}
+
diff --git a/crypto/store/store_locl.h b/crypto/store/store_locl.h
new file mode 100644 (file)
index 0000000..c8c409d
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016-2017 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
+ */
+
+#include "internal/thread_once.h"
+#include <openssl/dsa.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include <openssl/x509.h>
+#include <openssl/store.h>
+
+/*-
+ *  OSSL_STORE_INFO stuff
+ *  ---------------------
+ */
+
+struct ossl_store_info_st {
+    int type;
+    union {
+        struct {
+            char *name;
+            char *desc;
+        } name;                  /* when type == OSSL_STORE_INFO_NAME */
+
+        EVP_PKEY *params;        /* when type == OSSL_STORE_INFO_PARAMS */
+        EVP_PKEY *pkey;          /* when type == OSSL_STORE_INFO_PKEY */
+        X509 *x509;              /* when type == OSSL_STORE_INFO_CERT */
+        X509_CRL *crl;           /* when type == OSSL_STORE_INFO_CRL */
+        void *data;              /* used internally */
+    } _;
+};
+
+DEFINE_STACK_OF(OSSL_STORE_INFO)
+
+/*-
+ *  OSSL_STORE_LOADER stuff
+ *  -----------------------
+ */
+
+int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader);
+OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme);
+
+/* loader stuff */
+struct ossl_store_loader_st {
+    const char *scheme;
+    OSSL_STORE_open_fn open;
+    OSSL_STORE_ctrl_fn ctrl;
+    OSSL_STORE_load_fn load;
+    OSSL_STORE_eof_fn eof;
+    OSSL_STORE_error_fn error;
+    OSSL_STORE_close_fn close;
+};
+DEFINE_LHASH_OF(OSSL_STORE_LOADER);
+
+const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme);
+void ossl_store_destroy_loaders_int(void);
+
+/*-
+ *  OSSL_STORE init stuff
+ *  ---------------------
+ */
+
+int ossl_store_init_once(void);
diff --git a/crypto/store/store_register.c b/crypto/store/store_register.c
new file mode 100644 (file)
index 0000000..a138edc
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2016-2017 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
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include "store_locl.h"
+
+static CRYPTO_RWLOCK *registry_lock;
+static CRYPTO_ONCE registry_init = CRYPTO_ONCE_STATIC_INIT;
+
+DEFINE_RUN_ONCE_STATIC(do_registry_init)
+{
+    registry_lock = CRYPTO_THREAD_lock_new();
+    return registry_lock != NULL;
+}
+
+/*
+ *  Functions for manipulating OSSL_STORE_LOADERs
+ */
+
+OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(const char *scheme)
+{
+    OSSL_STORE_LOADER *res = OPENSSL_zalloc(sizeof(*res));
+
+    if (res == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_LOADER_NEW, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    /*
+     * We usually don't check NULL arguments.  For loaders, though, the
+     * scheme is crucial and must never be NULL, or the user will get
+     * mysterious errors when trying to register the created loader
+     * later on.
+     */
+    if (scheme == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_LOADER_NEW,
+                      OSSL_STORE_R_INVALID_SCHEME);
+        return NULL;
+    }
+
+    res->scheme = scheme;
+    return res;
+}
+
+const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader)
+{
+    return loader->scheme;
+}
+
+int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader,
+                               OSSL_STORE_open_fn open_function)
+{
+    loader->open = open_function;
+    return 1;
+}
+
+int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader,
+                               OSSL_STORE_ctrl_fn ctrl_function)
+{
+    loader->ctrl = ctrl_function;
+    return 1;
+}
+
+int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader,
+                               OSSL_STORE_load_fn load_function)
+{
+    loader->load = load_function;
+    return 1;
+}
+
+int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader,
+                              OSSL_STORE_eof_fn eof_function)
+{
+    loader->eof = eof_function;
+    return 1;
+}
+
+int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader,
+                                OSSL_STORE_error_fn error_function)
+{
+    loader->error = error_function;
+    return 1;
+}
+
+int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader,
+                                OSSL_STORE_close_fn close_function)
+{
+    loader->close = close_function;
+    return 1;
+}
+
+void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader)
+{
+    OPENSSL_free(loader);
+}
+
+/*
+ *  Functions for registering OSSL_STORE_LOADERs
+ */
+
+static unsigned long store_loader_hash(const OSSL_STORE_LOADER *v)
+{
+    return OPENSSL_LH_strhash(v->scheme);
+}
+
+static int store_loader_cmp(const OSSL_STORE_LOADER *a,
+                            const OSSL_STORE_LOADER *b)
+{
+    if (a->scheme != NULL && b->scheme != NULL)
+        return strcmp(a->scheme, b->scheme);
+    else if (a->scheme == b->scheme)
+        return 0;
+    return a->scheme == NULL ? -1 : 1;
+}
+
+static LHASH_OF(OSSL_STORE_LOADER) *loader_register = NULL;
+
+int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader)
+{
+    const char *scheme = loader->scheme;
+    int ok = 0;
+
+    /*
+     * Check that the given scheme conforms to correct scheme syntax as per
+     * RFC 3986:
+     *
+     * scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+     */
+    if (isalpha(*scheme))
+        while (*scheme != '\0'
+               && (isalpha(*scheme)
+                   || isdigit(*scheme)
+                   || strchr("+-.", *scheme) != NULL))
+            scheme++;
+    if (*scheme != '\0') {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT,
+                      OSSL_STORE_R_INVALID_SCHEME);
+        ERR_add_error_data(4, "scheme=", loader->scheme);
+        return 0;
+    }
+
+    if (!RUN_ONCE(&registry_init, do_registry_init)) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT,
+                      ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    CRYPTO_THREAD_write_lock(registry_lock);
+
+    if (loader_register == NULL) {
+        loader_register = lh_OSSL_STORE_LOADER_new(store_loader_hash,
+                                                   store_loader_cmp);
+    }
+
+    if (loader_register != NULL
+        && (lh_OSSL_STORE_LOADER_insert(loader_register, loader) != NULL
+            || lh_OSSL_STORE_LOADER_error(loader_register) == 0))
+        ok = 1;
+
+    CRYPTO_THREAD_unlock(registry_lock);
+
+    return ok;
+}
+int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader)
+{
+    if (!ossl_store_init_once())
+        return 0;
+    return ossl_store_register_loader_int(loader);
+}
+
+const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme)
+{
+    OSSL_STORE_LOADER template;
+    OSSL_STORE_LOADER *loader = NULL;
+
+    template.scheme = scheme;
+    template.open = NULL;
+    template.load = NULL;
+    template.eof = NULL;
+    template.close = NULL;
+
+    if (!ossl_store_init_once())
+        return NULL;
+
+    if (!RUN_ONCE(&registry_init, do_registry_init)) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT,
+                      ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    CRYPTO_THREAD_write_lock(registry_lock);
+
+    loader = lh_OSSL_STORE_LOADER_retrieve(loader_register, &template);
+
+    if (loader == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT,
+                      OSSL_STORE_R_UNREGISTERED_SCHEME);
+        ERR_add_error_data(2, "scheme=", scheme);
+    }
+
+    CRYPTO_THREAD_unlock(registry_lock);
+
+    return loader;
+}
+
+OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme)
+{
+    OSSL_STORE_LOADER template;
+    OSSL_STORE_LOADER *loader = NULL;
+
+    template.scheme = scheme;
+    template.open = NULL;
+    template.load = NULL;
+    template.eof = NULL;
+    template.close = NULL;
+
+    if (!RUN_ONCE(&registry_init, do_registry_init)) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT,
+                      ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    CRYPTO_THREAD_write_lock(registry_lock);
+
+    loader = lh_OSSL_STORE_LOADER_delete(loader_register, &template);
+
+    if (loader == NULL) {
+        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT,
+                      OSSL_STORE_R_UNREGISTERED_SCHEME);
+        ERR_add_error_data(2, "scheme=", scheme);
+    }
+
+    CRYPTO_THREAD_unlock(registry_lock);
+
+    return loader;
+}
+OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme)
+{
+    if (!ossl_store_init_once())
+        return 0;
+    return ossl_store_unregister_loader_int(scheme);
+}
+
+void ossl_store_destroy_loaders_int(void)
+{
+    assert(lh_OSSL_STORE_LOADER_num_items(loader_register) == 0);
+    lh_OSSL_STORE_LOADER_free(loader_register);
+    loader_register = NULL;
+    CRYPTO_THREAD_lock_free(registry_lock);
+    registry_lock = NULL;
+}
diff --git a/crypto/store/store_strings.c b/crypto/store/store_strings.c
new file mode 100644 (file)
index 0000000..76cf316
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016-2017 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
+ */
+
+#include <openssl/store.h>
+
+static char *type_strings[] = {
+    "Name",                      /* OSSL_STORE_INFO_NAME */
+    "Parameters",                /* OSSL_STORE_INFO_PARAMS */
+    "Pkey",                      /* OSSL_STORE_INFO_PKEY */
+    "Certificate",               /* OSSL_STORE_INFO_CERT */
+    "CRL"                        /* OSSL_STORE_INFO_CRL */
+};
+
+const char *OSSL_STORE_INFO_type_string(int type)
+{
+    int types = sizeof(type_strings) / sizeof(type_strings[0]);
+
+    if (type < 1 || type > types)
+        return NULL;
+
+    return type_strings[type - 1];
+}
index 4020f42..9b807b4 100644 (file)
@@ -84,7 +84,7 @@ typedef struct err_state_st {
 # define ERR_LIB_COMP            41
 # define ERR_LIB_ECDSA           42
 # define ERR_LIB_ECDH            43
-# define ERR_LIB_STORE           44
+# define ERR_LIB_OSSL_STORE      44
 # define ERR_LIB_FIPS            45
 # define ERR_LIB_CMS             46
 # define ERR_LIB_TS              47
@@ -123,7 +123,7 @@ typedef struct err_state_st {
 # define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define ECDSAerr(f,r)  ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define ECDHerr(f,r)  ERR_PUT_error(ERR_LIB_ECDH,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
-# define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
+# define OSSL_STOREerr(f,r) ERR_PUT_error(ERR_LIB_OSSL_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
@@ -131,6 +131,7 @@ typedef struct err_state_st {
 # define CTerr(f,r) ERR_PUT_error(ERR_LIB_CT,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define ASYNCerr(f,r) ERR_PUT_error(ERR_LIB_ASYNC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define KDFerr(f,r) ERR_PUT_error(ERR_LIB_KDF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
+# define OSSL_STOREerr(f,r) ERR_PUT_error(ERR_LIB_OSSL_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 
 # define ERR_PACK(l,f,r) ( \
         (((unsigned int)(l) & 0x0FF) << 24L) | \
@@ -183,6 +184,7 @@ typedef struct err_state_st {
 # define ERR_R_ENGINE_LIB ERR_LIB_ENGINE/* 38 */
 # define ERR_R_UI_LIB    ERR_LIB_UI/* 40 */
 # define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */
+# define ERR_R_OSSL_STORE_LIB ERR_LIB_OSSL_STORE/* 44 */
 
 # define ERR_R_NESTED_ASN1_ERROR                 58
 # define ERR_R_MISSING_ASN1_EOS                  63
index deea038..173a42d 100644 (file)
@@ -171,6 +171,8 @@ typedef struct ctlog_st CTLOG;
 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;
+
 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
     defined(INTMAX_MAX) && defined(UINTMAX_MAX)
 typedef intmax_t ossl_intmax_t;
diff --git a/include/openssl/store.h b/include/openssl/store.h
new file mode 100644 (file)
index 0000000..35f62ec
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2016-2017 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
+ */
+
+#ifndef HEADER_OSSL_STORE_H
+# define HEADER_OSSL_STORE_H
+
+# include <stdarg.h>
+# include <openssl/ossl_typ.h>
+# include <openssl/pem.h>
+# include <openssl/storeerr.h>
+
+# ifdef  __cplusplus
+extern "C" {
+# endif
+
+/*-
+ *  The main OSSL_STORE functions.
+ *  ------------------------------
+ *
+ *  These allow applications to open a channel to a resource with supported
+ *  data (keys, certs, crls, ...), read the data a piece at a time and decide
+ *  what to do with it, and finally close.
+ */
+
+typedef struct ossl_store_ctx_st OSSL_STORE_CTX;
+
+/*
+ * Typedef for the OSSL_STORE_INFO post processing callback.  This can be used
+ * to massage the given OSSL_STORE_INFO, or to drop it entirely (by returning
+ * NULL).
+ */
+typedef OSSL_STORE_INFO *(*OSSL_STORE_post_process_info_fn)(OSSL_STORE_INFO *,
+                                                            void *);
+
+/*
+ * Open a channel given a URI.  The given UI method will be used any time the
+ * loader needs extra input, for example when a password or pin is needed, and
+ * will be passed the same user data every time it's needed in this context.
+ *
+ * Returns a context reference which represents the channel to communicate
+ * through.
+ */
+OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
+                                void *ui_data,
+                                OSSL_STORE_post_process_info_fn post_process,
+                                void *post_process_data);
+
+/*
+ * Control / fine tune the OSSL_STORE channel.  |cmd| determines what is to be
+ * done, and depends on the underlying loader (use OSSL_STORE_get0_scheme to
+ * determine which loader is used), except for common commands (see below).
+ * Each command takes different arguments.
+ */
+int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ... /* args */);
+
+/*
+ * Common ctrl commands that different loaders may choose to support.
+ */
+/* Where custom commands start */
+# define OSSL_STORE_C_CUSTOM_START    100
+
+/*
+ * Read one data item (a key, a cert, a CRL) that is supported by the OSSL_STORE
+ * functionality, given a context.
+ * Returns a OSSL_STORE_INFO pointer, from which OpenSSL typed data can be
+ * extracted with OSSL_STORE_INFO_get0_PKEY(), OSSL_STORE_INFO_get0_CERT(), ...
+ * NULL is returned on error, which may include that the data found at the URI
+ * can't be figured out for certain or is ambiguous.
+ */
+OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx);
+
+/*
+ * Check if end of data (end of file) is reached
+ * Returns 1 on end, 0 otherwise.
+ */
+int OSSL_STORE_eof(OSSL_STORE_CTX *ctx);
+
+/*
+ * Check if an error occured
+ * Returns 1 if it did, 0 otherwise.
+ */
+int OSSL_STORE_error(OSSL_STORE_CTX *ctx);
+
+/*
+ * Close the channel
+ * Returns 1 on success, 0 on error.
+ */
+int OSSL_STORE_close(OSSL_STORE_CTX *ctx);
+
+
+/*-
+ *  Extracting OpenSSL types from and creating new OSSL_STORE_INFOs
+ *  ---------------------------------------------------------------
+ */
+
+/*
+ * Types of data that can be ossl_stored in a OSSL_STORE_INFO.
+ * OSSL_STORE_INFO_NAME is typically found when getting a listing of
+ * available "files" / "tokens" / what have you.
+ */
+# define OSSL_STORE_INFO_NAME           1   /* char * */
+# define OSSL_STORE_INFO_PARAMS         2   /* EVP_PKEY * */
+# define OSSL_STORE_INFO_PKEY           3   /* EVP_PKEY * */
+# define OSSL_STORE_INFO_CERT           4   /* X509 * */
+# define OSSL_STORE_INFO_CRL            5   /* X509_CRL * */
+
+/*
+ * Functions to generate OSSL_STORE_INFOs, one function for each type we
+ * support having in them.  Along with each of them, one macro that
+ * can be used to determine what types are supported.
+ *
+ * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO
+ * and will therefore be freed when the OSSL_STORE_INFO is freed.
+ */
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name);
+int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc);
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params);
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey);
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509);
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
+
+/*
+ * Functions to try to extract data from a OSSL_STORE_INFO.
+ */
+int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info);
+const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info);
+char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info);
+const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info);
+char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info);
+EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info);
+EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info);
+EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info);
+EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info);
+X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info);
+X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info);
+X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info);
+X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info);
+
+const char *OSSL_STORE_INFO_type_string(int type);
+
+/*
+ * Free the OSSL_STORE_INFO
+ */
+void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info);
+
+
+/*-
+ *  Function to register a loader for the given URI scheme.
+ *  -------------------------------------------------------
+ *
+ *  The loader receives all the main components of an URI except for the
+ *  scheme.
+ */
+
+typedef struct ossl_store_loader_st OSSL_STORE_LOADER;
+OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(const char *scheme);
+const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader);
+/* struct ossl_store_loader_ctx_st is defined differently by each loader */
+typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX;
+typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(const OSSL_STORE_LOADER
+                                                     *loader,
+                                                     const char *uri,
+                                                     const UI_METHOD *ui_method,
+                                                     void *ui_data);
+int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader,
+                               OSSL_STORE_open_fn open_function);
+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 OSSL_STORE_INFO *(*OSSL_STORE_load_fn)(OSSL_STORE_LOADER_CTX *ctx,
+                                               const UI_METHOD *ui_method,
+                                               void *ui_data);
+int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader,
+                               OSSL_STORE_load_fn load_function);
+typedef int (*OSSL_STORE_eof_fn)(OSSL_STORE_LOADER_CTX *ctx);
+int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader,
+                              OSSL_STORE_eof_fn eof_function);
+typedef int (*OSSL_STORE_error_fn)(OSSL_STORE_LOADER_CTX *ctx);
+int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader,
+                                OSSL_STORE_error_fn error_function);
+typedef int (*OSSL_STORE_close_fn)(OSSL_STORE_LOADER_CTX *ctx);
+int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader,
+                                OSSL_STORE_close_fn close_function);
+void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader);
+
+int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader);
+OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme);
+
+
+/*
+ * Error strings
+ */
+int ERR_load_OSSL_STORE_strings(void);
+
+# ifdef  __cplusplus
+}
+# endif
+#endif
diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h
new file mode 100644 (file)
index 0000000..1fca2db
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2017 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
+ */
+
+#ifndef HEADER_OSSL_STOREERR_H
+# define HEADER_OSSL_STOREERR_H
+
+# ifdef  __cplusplus
+extern "C" {
+# endif
+int ERR_load_OSSL_STORE_strings(void);
+# ifdef  __cplusplus
+}
+# endif
+
+/*
+ * OSSL_STORE function codes.
+ */
+# 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
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME           103
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION 135
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS         104
+# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY           105
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT            106
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL             107
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME            109
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS          110
+# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY            111
+# define OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION 134
+# define OSSL_STORE_F_OSSL_STORE_INIT_ONCE                112
+# define OSSL_STORE_F_OSSL_STORE_LOADER_NEW               113
+# 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_UNREGISTER_LOADER_INT    116
+
+/*
+ * OSSL_STORE reason codes.
+ */
+# define OSSL_STORE_R_INVALID_SCHEME                      106
+# define OSSL_STORE_R_NOT_A_CERTIFICATE                   100
+# define OSSL_STORE_R_NOT_A_CRL                           101
+# define OSSL_STORE_R_NOT_A_KEY                           102
+# define OSSL_STORE_R_NOT_A_NAME                          103
+# define OSSL_STORE_R_NOT_PARAMETERS                      104
+# define OSSL_STORE_R_UNREGISTERED_SCHEME                 105
+
+#endif
index 523a281..3c651ed 100644 (file)
@@ -4300,3 +4300,43 @@ ERR_load_strings_const                  4242     1_1_1   EXIST::FUNCTION:
 ASN1_TIME_to_tm                         4243   1_1_1   EXIST::FUNCTION:
 ASN1_TIME_set_string_X509               4244   1_1_1   EXIST::FUNCTION:
 OCSP_resp_get1_id                       4245   1_1_1   EXIST::FUNCTION:OCSP
+OSSL_STORE_register_loader              4246   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_LOADER_set_error             4247   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_PKEY               4248   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get_type                4249   1_1_1   EXIST::FUNCTION:
+ERR_load_OSSL_STORE_strings             4250   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_LOADER_free                  4251   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get1_PKEY               4252   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_free                    4253   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_open_file                    4254   1_1_1   NOEXIST::FUNCTION:
+OSSL_STORE_LOADER_set_eof               4255   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_LOADER_new                   4256   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_CERT               4257   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_LOADER_set_close             4258   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_new_PARAMS              4259   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_new_PKEY                4260   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get1_PARAMS             4261   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get1_CRL                4262   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_error                        4263   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get1_CERT               4264   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_PARAMS             4265   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_type_string             4266   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get1_NAME               4267   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_LOADER_set_load              4268   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_LOADER_get0_scheme           4269   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_open                         4270   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_close                        4271   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_new_CERT                4272   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_CRL                4273   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_load                         4274   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_NAME               4275   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_unregister_loader            4276   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_new_CRL                 4277   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_new_NAME                4278   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_eof                          4279   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_LOADER_set_open              4280   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_LOADER_set_ctrl              4281   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_ctrl                         4282   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_NAME_description   4283   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_set0_NAME_description   4284   1_1_1   EXIST::FUNCTION:
+OSSL_STORE_INFO_get1_NAME_description   4285   1_1_1   EXIST::FUNCTION:
index 2ad754f..203b531 100644 (file)
@@ -20,6 +20,17 @@ CRYPTO_EX_new                           datatype
 EVP_PKEY_gen_cb                         datatype
 GEN_SESSION_CB                          datatype
 OPENSSL_Applink                         external
+OSSL_STORE_CTX                          datatype
+OSSL_STORE_INFO                         datatype
+OSSL_STORE_LOADER                       datatype
+OSSL_STORE_LOADER_CTX                   datatype
+OSSL_STORE_close_fn                     datatype
+OSSL_STORE_ctrl_fn                      datatype
+OSSL_STORE_eof_fn                       datatype
+OSSL_STORE_error_fn                     datatype
+OSSL_STORE_load_fn                      datatype
+OSSL_STORE_open_fn                      datatype
+OSSL_STORE_post_process_info_fn         datatype
 SSL_CTX_keylog_cb_func                  datatype
 SSL_early_cb_fn                         datatype
 SSL_psk_client_cb_func                  datatype