summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2016-11-28 17:30:21 +0100
committerRichard Levitte <levitte@openssl.org>2017-06-29 11:55:31 +0200
commit9c6da42d0c61fafcf860c8a6c03efd3c33826f99 (patch)
tree1ca8bb803c62ec502ffbf0312f76ca2c5997b610
parentdc10560eba147b1b6484153b424d8f715c055e2f (diff)
Add a STORE loader for the "file" scheme
Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/3542)
-rw-r--r--crypto/err/openssl.txt10
-rw-r--r--crypto/store/build.info3
-rw-r--r--crypto/store/loader_file.c583
-rw-r--r--crypto/store/store_err.c16
-rw-r--r--crypto/store/store_init.c3
-rw-r--r--crypto/store/store_locl.h1
-rw-r--r--include/openssl/storeerr.h9
7 files changed, 623 insertions, 2 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 14987b10b0..79f08f4657 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -724,6 +724,9 @@ 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_FILE_GET_PASS:118:file_get_pass
+OSSL_STORE_F_FILE_LOAD:119:file_load
+OSSL_STORE_F_FILE_OPEN:120:file_open
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
@@ -746,6 +749,7 @@ 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
+OSSL_STORE_F_TRY_DECODE_PARAMS:121:try_decode_params
PEM_F_B2I_DSS:127:b2i_dss
PEM_F_B2I_PVK_BIO:128:b2i_PVK_bio
PEM_F_B2I_RSA:129:b2i_rsa
@@ -1972,13 +1976,19 @@ 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_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content 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_PATH_MUST_BE_ABSOLUTE:108:path must be absolute
+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_URI_AUTHORITY_UNSUPPORED:111:uri authority unsuppored
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/store/build.info b/crypto/store/build.info
index 4b6af29817..7d882f313e 100644
--- a/crypto/store/build.info
+++ b/crypto/store/build.info
@@ -1,3 +1,4 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
- store_err.c store_init.c store_lib.c store_register.c store_strings.c
+ store_err.c store_init.c store_lib.c store_register.c store_strings.c \
+ loader_file.c
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c
new file mode 100644
index 0000000000..f8fc3ba4e4
--- /dev/null
+++ b/crypto/store/loader_file.c
@@ -0,0 +1,583 @@
+/*
+ * 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 <openssl/bio.h>
+#include <openssl/dsa.h> /* For d2i_DSAPrivateKey */
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h> /* For the PKCS8 stuff o.O */
+#include <openssl/rsa.h> /* For d2i_RSAPrivateKey */
+#include <openssl/safestack.h>
+#include <openssl/store.h>
+#include <openssl/ui.h>
+#include <openssl/x509.h> /* For the PKCS8 stuff o.O */
+#include "internal/asn1_int.h"
+#include "store_locl.h"
+
+#include "e_os.h"
+
+/*
+ * Password prompting
+ */
+
+static char *file_get_pass(const UI_METHOD *ui_method, char *pass,
+ size_t maxsize, const char *prompt_info, void *data)
+{
+ UI *ui = UI_new();
+ char *prompt = NULL;
+
+ if (ui == NULL) {
+ OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (ui_method != NULL)
+ UI_set_method(ui, ui_method);
+ UI_add_user_data(ui, data);
+
+ if ((prompt = UI_construct_prompt(ui, "pass phrase",
+ prompt_info)) == NULL) {
+ OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_MALLOC_FAILURE);
+ pass = NULL;
+ } else if (!UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD,
+ pass, 0, maxsize - 1)) {
+ OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_UI_LIB);
+ pass = NULL;
+ } else {
+ switch (UI_process(ui)) {
+ case -2:
+ OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS,
+ OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED);
+ pass = NULL;
+ break;
+ case -1:
+ OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_UI_LIB);
+ pass = NULL;
+ break;
+ default:
+ break;
+ }
+ }
+
+ OPENSSL_free(prompt);
+ UI_free(ui);
+ return pass;
+}
+
+struct pem_pass_data {
+ const UI_METHOD *ui_method;
+ void *data;
+ const char *prompt_info;
+};
+static int file_fill_pem_pass_data(struct pem_pass_data *pass_data,
+ const char *prompt_info,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ if (pass_data == NULL)
+ return 0;
+ pass_data->ui_method = ui_method;
+ pass_data->data = ui_data;
+ pass_data->prompt_info = prompt_info;
+ return 1;
+}
+static int file_get_pem_pass(char *buf, int num, int w, void *data)
+{
+ struct pem_pass_data *pass_data = data;
+ char *pass = file_get_pass(pass_data->ui_method, buf, num,
+ pass_data->prompt_info, pass_data->data);
+
+ return pass == NULL ? 0 : strlen(pass);
+}
+
+/*
+ * The file scheme handlers
+ */
+
+/*-
+ * The try_decode function is called to check if the blob of data can
+ * be used by this handler, and if it can, decodes it into a supported
+ * OpenSSL type and returns a OSSL_STORE_INFO with the decoded data.
+ * Input:
+ * pem_name: If this blob comes from a PEM file, this holds
+ * the PEM name. If it comes from another type of
+ * file, this is NULL.
+ * pem_header: If this blob comes from a PEM file, this holds
+ * the PEM headers. If it comes from another type of
+ * file, this is NULL.
+ * blob: The blob of data to match with what this handler
+ * can use.
+ * len: The length of the blob.
+ * ui_method: Application UI method for getting a password, pin
+ * or any other interactive data.
+ * ui_data: Application data to be passed to ui_method when
+ * it's called.
+ * Output:
+ * a OSSL_STORE_INFO
+ */
+typedef OSSL_STORE_INFO *(*file_try_decode_fn)(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len,
+ const UI_METHOD *ui_method,
+ void *ui_data);
+
+typedef struct file_handler_st {
+ const char *name;
+ file_try_decode_fn try_decode;
+} FILE_HANDLER;
+
+int pem_check_suffix(const char *pem_str, const char *suffix);
+static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ EVP_PKEY *pkey = NULL;
+ const EVP_PKEY_ASN1_METHOD *ameth = NULL;
+
+ if (pem_name != NULL) {
+ int slen;
+
+ if ((slen = pem_check_suffix(pem_name, "PRIVATE KEY")) > 0
+ && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, slen)) != NULL)
+ pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &blob, len);
+ } else {
+ int i;
+
+ for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+ ameth = EVP_PKEY_asn1_get0(i);
+ if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
+ continue;
+ pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &blob, len);
+ if (pkey != NULL)
+ break;
+ }
+ }
+ if (pkey == NULL)
+ /* No match */
+ return NULL;
+
+ store_info = OSSL_STORE_INFO_new_PKEY(pkey);
+ if (store_info == NULL)
+ EVP_PKEY_free(pkey);
+
+ return store_info;
+}
+static FILE_HANDLER PrivateKey_handler = {
+ "PrivateKey",
+ try_decode_PrivateKey
+};
+
+static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ if (pem_name != NULL && strcmp(pem_name, PEM_STRING_PUBLIC) != 0)
+ /* No match */
+ return NULL;
+
+ if ((pkey = d2i_PUBKEY(NULL, &blob, len)) != NULL)
+ store_info = OSSL_STORE_INFO_new_PKEY(pkey);
+
+ return store_info;
+}
+static FILE_HANDLER PUBKEY_handler = {
+ "PUBKEY",
+ try_decode_PUBKEY
+};
+
+static OSSL_STORE_INFO *try_decode_params(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ EVP_PKEY *pkey = EVP_PKEY_new();
+ const EVP_PKEY_ASN1_METHOD *ameth = NULL;
+ int ok = 0;
+
+ if (pkey == NULL) {
+ OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB);
+ return NULL;
+ }
+
+ if (pem_name != NULL) {
+ int slen;
+
+ if ((slen = pem_check_suffix(pem_name, "PARAMETERS")) > 0
+ && EVP_PKEY_set_type_str(pkey, pem_name, slen)
+ && (ameth = EVP_PKEY_get0_asn1(pkey)) != NULL
+ && ameth->param_decode != NULL
+ && ameth->param_decode(pkey, &blob, len))
+ ok = 1;
+ } else {
+ int i;
+
+ for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+ ameth = EVP_PKEY_asn1_get0(i);
+ if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
+ continue;
+ if (EVP_PKEY_set_type(pkey, ameth->pkey_id)
+ && (ameth = EVP_PKEY_get0_asn1(pkey)) != NULL
+ && ameth->param_decode != NULL
+ && ameth->param_decode(pkey, &blob, len)) {
+ ok = 1;
+ break;
+ }
+ }
+ }
+
+ if (ok)
+ store_info = OSSL_STORE_INFO_new_PARAMS(pkey);
+ if (store_info == NULL)
+ EVP_PKEY_free(pkey);
+
+ return store_info;
+}
+static FILE_HANDLER params_handler = {
+ "params",
+ try_decode_params
+};
+
+static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ X509 *cert = NULL;
+
+ /*
+ * In most cases, we can try to interpret the serialized data as a trusted
+ * cert (X509 + X509_AUX) and fall back to reading it as a normal cert
+ * (just X509), but if the PEM name specifically declares it as a trusted
+ * cert, then no fallback should be engaged. |ignore_trusted| tells if
+ * the fallback can be used (1) or not (0).
+ */
+ int ignore_trusted = 1;
+
+ if (pem_name != NULL) {
+ if (strcmp(pem_name, PEM_STRING_X509_TRUSTED) == 0)
+ ignore_trusted = 0;
+ else if (strcmp(pem_name, PEM_STRING_X509_OLD) != 0
+ && strcmp(pem_name, PEM_STRING_X509) != 0)
+ /* No match */
+ return NULL;
+ }
+
+ if ((cert = d2i_X509_AUX(NULL, &blob, len)) != NULL
+ || (ignore_trusted && (cert = d2i_X509(NULL, &blob, len)) != NULL))
+ store_info = OSSL_STORE_INFO_new_CERT(cert);
+
+ if (store_info == NULL)
+ X509_free(cert);
+
+ return store_info;
+}
+static FILE_HANDLER X509Certificate_handler = {
+ "X509Certificate",
+ try_decode_X509Certificate
+};
+
+static OSSL_STORE_INFO *try_decode_X509CRL(const char *pem_name,
+ const char *pem_header,
+ const unsigned char *blob,
+ size_t len,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ OSSL_STORE_INFO *store_info = NULL;
+ X509_CRL *crl = NULL;
+
+ if (pem_name != NULL
+ && strcmp(pem_name, PEM_STRING_X509_CRL) != 0)
+ /* No match */
+ return NULL;
+
+ if ((crl = d2i_X509_CRL(NULL, &blob, len)) != NULL)
+ store_info = OSSL_STORE_INFO_new_CRL(crl);
+
+ if (store_info == NULL)
+ X509_CRL_free(crl);
+
+ return store_info;
+}
+static FILE_HANDLER X509CRL_handler = {
+ "X509CRL",
+ try_decode_X509CRL
+};
+
+static const FILE_HANDLER *file_handlers[] = {
+ &X509Certificate_handler,
+ &X509CRL_handler,
+ &params_handler,
+ &PUBKEY_handler,
+ &PrivateKey_handler,
+};
+
+
+/*
+ * The loader itself
+ */
+
+struct ossl_store_loader_ctx_st {
+ BIO *file;
+ int is_pem;
+ int errcnt;
+};
+
+static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
+ const char *uri,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ BIO *buff = NULL;
+ char peekbuf[4096];
+ OSSL_STORE_LOADER_CTX *ctx = NULL;
+ const char *path = NULL;
+
+ if (strncasecmp(uri, "file:", 5) == 0) {
+ if (strncmp(&uri[5], "//localhost/", 12) == 0) {
+ path = &uri[16];
+ } else if (strncmp(&uri[5], "///", 3) == 0) {
+ path = &uri[7];
+ } else if (strncmp(&uri[5], "//", 2) != 0) {
+ path = &uri[5];
+ } else {
+ OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
+ OSSL_STORE_R_URI_AUTHORITY_UNSUPPORED);
+ return NULL;
+ }
+
+ /*
+ * If the scheme "file" was an explicit part of the URI, the path must
+ * be absolute. So says RFC 8089
+ */
+ if (path[0] != '/') {
+ OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
+ OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE);
+ return NULL;
+ }
+
+#ifdef _WIN32
+ /* Windows file: URIs with a drive letter start with a / */
+ if (path[0] == '/' && path[2] == ':' && path[3] == '/')
+ path++;
+#endif
+ } else {
+ path = uri;
+ }
+
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if ((buff = BIO_new(BIO_f_buffer())) == NULL)
+ goto err;
+ if ((ctx->file = BIO_new_file(path, "rb")) == NULL) {
+ goto err;
+ }
+ ctx->file = BIO_push(buff, ctx->file);
+ if (BIO_buffer_peek(ctx->file, peekbuf, sizeof(peekbuf)-1) > 0) {
+ peekbuf[sizeof(peekbuf)-1] = '\0';
+ if (strstr(peekbuf, "-----BEGIN ") != NULL)
+ ctx->is_pem = 1;
+ }
+
+ return ctx;
+ err:
+ if (buff != NULL)
+ BIO_free(buff);
+ OPENSSL_free(ctx);
+ return NULL;
+}
+
+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,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ OSSL_STORE_INFO *result = NULL;
+ int matchcount = -1;
+
+ if (file_error(ctx))
+ return NULL;
+
+ do {
+ char *pem_name = NULL; /* PEM record name */
+ char *pem_header = NULL; /* PEM record header */
+ unsigned char *data = NULL; /* DER encoded data */
+ BUF_MEM *mem = NULL;
+ long len = 0; /* DER encoded data length */
+ int r = 0;
+ size_t i = 0;
+ file_try_decode_fn *matching_functions = NULL;
+
+ matchcount = -1;
+ if (ctx->is_pem) {
+ r = PEM_read_bio(ctx->file, &pem_name, &pem_header, &data, &len);
+ if (r <= 0) {
+ if (!file_eof(ctx))
+ ctx->errcnt++;
+ goto end;
+ }
+
+ /*
+ * 10 is the number of characters in "Proc-Type:", which
+ * PEM_get_EVP_CIPHER_INFO() requires to be present.
+ * If the PEM header has less characters than that, it's
+ * not worth spending cycles on it.
+ */
+ if (strlen(pem_header) > 10) {
+ EVP_CIPHER_INFO cipher;
+ struct pem_pass_data pass_data;
+
+ if (!PEM_get_EVP_CIPHER_INFO(pem_header, &cipher)
+ || !file_fill_pem_pass_data(&pass_data, "PEM", ui_method,
+ ui_data)
+ || !PEM_do_header(&cipher, data, &len, file_get_pem_pass,
+ &pass_data)) {
+ ctx->errcnt++;
+ goto err;
+ }
+ }
+ } else {
+#if 0 /* PKCS12 not yet ready */
+ PKCS12 *pkcs12 =NULL;
+#endif
+
+ if ((len = asn1_d2i_read_bio(ctx->file, &mem)) < 0) {
+ if (!file_eof(ctx))
+ ctx->errcnt++;
+ goto err;
+ }
+
+ data = (unsigned char *)mem->data;
+ len = (long)mem->length;
+
+#if 0 /* PKCS12 not yet ready */
+ /* Try and see if we loaded a PKCS12 */
+ pkcs12 = d2i_PKCS12(NULL, &data, len);
+#endif
+ }
+
+ result = NULL;
+ matchcount = 0;
+ matching_functions = OPENSSL_zalloc(sizeof(*matching_functions)
+ * OSSL_NELEM(file_handlers));
+
+ for (i = 0; i < OSSL_NELEM(file_handlers); i++) {
+ const FILE_HANDLER *handler = file_handlers[i];
+ OSSL_STORE_INFO *tmp_result =
+ handler->try_decode(pem_name, pem_header, data, len, ui_method,
+ ui_data);
+
+ if (tmp_result != NULL) {
+ if (matching_functions)
+ matching_functions[matchcount] = handler->try_decode;
+
+ if (++matchcount == 1) {
+ result = tmp_result;
+ tmp_result = NULL;
+ } else {
+ /* more than one match => ambiguous, kill any result */
+ OSSL_STORE_INFO_free(result);
+ OSSL_STORE_INFO_free(tmp_result);
+ result = NULL;
+ }
+ }
+ }
+
+ if (matchcount > 1)
+ OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD,
+ OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE);
+ if (matchcount == 0)
+ OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD,
+ OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE);
+
+ if (result)
+ ERR_clear_error();
+
+ err:
+ OPENSSL_free(matching_functions);
+ OPENSSL_free(pem_name);
+ OPENSSL_free(pem_header);
+ if (mem == NULL)
+ OPENSSL_free(data);
+ else
+ BUF_MEM_free(mem);
+ } while (matchcount == 0 && !file_eof(ctx) && !file_error(ctx));
+
+ /* We bail out on ambiguity */
+ if (matchcount > 1)
+ return NULL;
+
+ end:
+ return result;
+}
+
+static int file_error(OSSL_STORE_LOADER_CTX *ctx)
+{
+ return ctx->errcnt > 0;
+}
+
+static int file_eof(OSSL_STORE_LOADER_CTX *ctx)
+{
+ return BIO_eof(ctx->file);
+}
+
+static int file_close(OSSL_STORE_LOADER_CTX *ctx)
+{
+ BIO_free_all(ctx->file);
+ OPENSSL_free(ctx);
+ return 1;
+}
+
+static OSSL_STORE_LOADER file_loader =
+ {
+ "file",
+ file_open,
+ NULL,
+ file_load,
+ file_eof,
+ file_error,
+ file_close
+ };
+
+static void store_file_loader_deinit(void)
+{
+ ossl_store_unregister_loader_int(file_loader.scheme);
+}
+
+int ossl_store_file_loader_init(void)
+{
+ int ret = ossl_store_register_loader_int(&file_loader);
+
+ OPENSSL_atexit(store_file_loader_deinit);
+ return ret;
+}
diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c
index 3f5069abf5..20f19fcd26 100644
--- a/crypto/store/store_err.c
+++ b/crypto/store/store_err.c
@@ -14,6 +14,10 @@
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA OSSL_STORE_str_functs[] = {
+ {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"},
+ {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_GET0_LOADER_INT, 0),
"ossl_store_get0_loader_int"},
{ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT, 0),
@@ -51,10 +55,14 @@ static const ERR_STRING_DATA OSSL_STORE_str_functs[] = {
"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"},
+ {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PARAMS, 0),
+ "try_decode_params"},
{0, NULL}
};
static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE),
+ "ambiguous content type"},
{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),
@@ -64,8 +72,16 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
{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_PATH_MUST_BE_ABSOLUTE),
+ "path must be absolute"},
+ {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_URI_AUTHORITY_UNSUPPORED),
+ "uri authority unsuppored"},
{0, NULL}
};
diff --git a/crypto/store/store_init.c b/crypto/store/store_init.c
index 90d5436634..4b53108684 100644
--- a/crypto/store/store_init.c
+++ b/crypto/store/store_init.c
@@ -14,7 +14,8 @@
static CRYPTO_ONCE store_init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_store_init)
{
- return OPENSSL_init_crypto(0, NULL);
+ return OPENSSL_init_crypto(0, NULL)
+ && ossl_store_file_loader_init();
}
int ossl_store_init_once()
diff --git a/crypto/store/store_locl.h b/crypto/store/store_locl.h
index c8c409d767..cf14e53e4d 100644
--- a/crypto/store/store_locl.h
+++ b/crypto/store/store_locl.h
@@ -67,3 +67,4 @@ void ossl_store_destroy_loaders_int(void);
*/
int ossl_store_init_once(void);
+int ossl_store_file_loader_init(void);
diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h
index 1fca2db1ef..28d11a274c 100644
--- a/include/openssl/storeerr.h
+++ b/include/openssl/storeerr.h
@@ -22,6 +22,9 @@ int ERR_load_OSSL_STORE_strings(void);
/*
* OSSL_STORE function codes.
*/
+# define OSSL_STORE_F_FILE_GET_PASS 118
+# define OSSL_STORE_F_FILE_LOAD 119
+# define OSSL_STORE_F_FILE_OPEN 120
# 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
@@ -41,16 +44,22 @@ int ERR_load_OSSL_STORE_strings(void);
# 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
+# define OSSL_STORE_F_TRY_DECODE_PARAMS 121
/*
* OSSL_STORE reason codes.
*/
+# define OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE 107
# 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_PATH_MUST_BE_ABSOLUTE 108
+# 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_URI_AUTHORITY_UNSUPPORED 111
#endif