X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=crypto%2Fstore%2Fstore_lib.c;h=15c0862019e3b3af4ae436b70272b972283069ce;hb=6ab6ecfd6d2d659326f427dceb1b65ae1b4b012b;hp=2cc247d12ed1eac10a21a11c6baea536ec34727b;hpb=07016a8a3174db5caf07182930533cf88ad9b0ad;p=openssl.git diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c index 2cc247d12e..15c0862019 100644 --- a/crypto/store/store_lib.c +++ b/crypto/store/store_lib.c @@ -1,7 +1,7 @@ /* - * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -10,12 +10,17 @@ #include "e_os.h" #include #include +#include + +#include "e_os.h" + #include #include +#include #include #include "internal/thread_once.h" -#include "internal/store_int.h" -#include "store_locl.h" +#include "crypto/store.h" +#include "store_local.h" struct ossl_store_ctx_st { const OSSL_STORE_LOADER *loader; @@ -24,6 +29,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, @@ -66,9 +75,14 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, /* Try each scheme until we find one that could open the URI */ for (i = 0; loader_ctx == NULL && i < schemes_n; i++) { - if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL) + OSSL_TRACE1(STORE, "Looking up scheme %s\n", schemes[i]); + if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL) { + OSSL_TRACE1(STORE, "Found loader for scheme %s\n", schemes[i]); loader_ctx = loader->open(loader, uri, ui_method, ui_data); + OSSL_TRACE2(STORE, "Opened %s => %p\n", uri, (void *)loader_ctx); + } } + if (loader_ctx == NULL) goto err; @@ -109,24 +123,62 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...) { va_list args; - int ret = 0; + int ret; va_start(args, cmd); - if (ctx->loader->ctrl != NULL) - ret = ctx->loader->ctrl(ctx->loader_ctx, cmd, args); + ret = OSSL_STORE_vctrl(ctx, cmd, args); va_end(args); return ret; } +int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args) +{ + if (ctx->loader->ctrl != NULL) + return ctx->loader->ctrl(ctx->loader_ctx, cmd, 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, const 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; + OSSL_TRACE(STORE, "Loading next object\n"); v = ctx->loader->load(ctx->loader_ctx, ctx->ui_method, ctx->ui_data); if (ctx->post_process != NULL && v != NULL) { @@ -140,6 +192,28 @@ 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; + } + } + } + + if (v != NULL) + OSSL_TRACE1(STORE, "Got a %s\n", + OSSL_STORE_INFO_type_string(OSSL_STORE_INFO_get_type(v))); + return v; } @@ -155,7 +229,10 @@ int OSSL_STORE_eof(OSSL_STORE_CTX *ctx) int OSSL_STORE_close(OSSL_STORE_CTX *ctx) { - int loader_ret = ctx->loader->close(ctx->loader_ctx); + int loader_ret; + + OSSL_TRACE1(STORE, "Closing %p\n", (void *)ctx->loader_ctx); + loader_ret = ctx->loader->close(ctx->loader_ctx); OPENSSL_free(ctx); return loader_ret; @@ -165,7 +242,7 @@ int OSSL_STORE_close(OSSL_STORE_CTX *ctx) * Functions to generate OSSL_STORE_INFOs, one function for each type we * support having in them as well as a generic constructor. * - * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO + * In all cases, ownership of the object is transferred 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) @@ -405,6 +482,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(const 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) @@ -445,45 +651,33 @@ char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info) return NULL; } -OSSL_STORE_CTX *ossl_store_attach_pem_bio(BIO *bp, const UI_METHOD *ui_method, - void *ui_data) +OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, OPENSSL_CTX *libctx, + const char *scheme, const char *propq, + const UI_METHOD *ui_method, void *ui_data, + OSSL_STORE_post_process_info_fn post_process, + void *post_process_data) { OSSL_STORE_CTX *ctx = NULL; const OSSL_STORE_LOADER *loader = NULL; OSSL_STORE_LOADER_CTX *loader_ctx = NULL; - if ((loader = ossl_store_get0_loader_int("file")) == NULL - || ((loader_ctx = ossl_store_file_attach_pem_bio_int(bp)) == NULL)) - goto done; + if ((loader = + ossl_store_get0_loader_int(scheme != NULL ? scheme : "file")) == NULL + || (loader_ctx = loader->attach(loader, bp, libctx, propq, + ui_method, ui_data)) == NULL) + return NULL; + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { - OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO, - ERR_R_MALLOC_FAILURE); - goto done; + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_ATTACH, ERR_R_MALLOC_FAILURE); + return NULL; } ctx->loader = loader; ctx->loader_ctx = loader_ctx; - loader_ctx = NULL; ctx->ui_method = ui_method; ctx->ui_data = ui_data; - ctx->post_process = NULL; - ctx->post_process_data = NULL; + 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_detach_pem_bio(OSSL_STORE_CTX *ctx) -{ - int loader_ret = ossl_store_file_detach_pem_bio_int(ctx->loader_ctx); - - OPENSSL_free(ctx); - return loader_ret; -}