diff options
-rwxr-xr-x | Configure | 2 | ||||
-rw-r--r-- | crypto/err/err.c | 2 | ||||
-rw-r--r-- | crypto/err/err_all.c | 4 | ||||
-rw-r--r-- | crypto/err/openssl.ec | 1 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 29 | ||||
-rw-r--r-- | crypto/include/internal/store.h | 10 | ||||
-rw-r--r-- | crypto/init.c | 2 | ||||
-rw-r--r-- | crypto/store/build.info | 3 | ||||
-rw-r--r-- | crypto/store/store_err.c | 83 | ||||
-rw-r--r-- | crypto/store/store_init.c | 32 | ||||
-rw-r--r-- | crypto/store/store_lib.c | 366 | ||||
-rw-r--r-- | crypto/store/store_locl.h | 69 | ||||
-rw-r--r-- | crypto/store/store_register.c | 259 | ||||
-rw-r--r-- | crypto/store/store_strings.c | 28 | ||||
-rw-r--r-- | include/openssl/err.h | 6 | ||||
-rw-r--r-- | include/openssl/ossl_typ.h | 2 | ||||
-rw-r--r-- | include/openssl/store.h | 205 | ||||
-rw-r--r-- | include/openssl/storeerr.h | 56 | ||||
-rw-r--r-- | util/libcrypto.num | 40 | ||||
-rw-r--r-- | util/private.num | 11 |
20 files changed, 1206 insertions, 4 deletions
@@ -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" ]; diff --git a/crypto/err/err.c b/crypto/err/err.c index 4d83024877..17a9fe1351 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -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"}, diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c index 6cc8c8f20b..3fff594747 100644 --- a/crypto/err/err_all.c +++ b/crypto/err/err_all.c @@ -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; diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec index 20b6b4a2a8..be84c7cb23 100644 --- a/crypto/err/openssl.ec +++ b/crypto/err/openssl.ec @@ -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 diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index d9fa3d3309..14987b10b0 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -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 index 0000000000..f5013dc367 --- /dev/null +++ b/crypto/include/internal/store.h @@ -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); diff --git a/crypto/init.c b/crypto/init.c index 2d2b07dd75..e159a3dd0c 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -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 index 0000000000..4b6af29817 --- /dev/null +++ b/crypto/store/build.info @@ -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 index 0000000000..3f5069abf5 --- /dev/null +++ b/crypto/store/store_err.c @@ -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 index 0000000000..90d5436634 --- /dev/null +++ b/crypto/store/store_init.c @@ -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 index 0000000000..5f07f8ce5f --- /dev/null +++ b/crypto/store/store_lib.c @@ -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 index 0000000000..c8c409d767 --- /dev/null +++ b/crypto/store/store_locl.h @@ -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 index 0000000000..a138edc636 --- /dev/null +++ b/crypto/store/store_register.c @@ -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(®istry_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; + + |