Add a STORE loader for the "file" scheme
authorRichard Levitte <levitte@openssl.org>
Mon, 28 Nov 2016 16:30:21 +0000 (17:30 +0100)
committerRichard Levitte <levitte@openssl.org>
Thu, 29 Jun 2017 09:55:31 +0000 (11:55 +0200)
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3542)

crypto/err/openssl.txt
crypto/store/build.info
crypto/store/loader_file.c [new file with mode: 0644]
crypto/store/store_err.c
crypto/store/store_init.c
crypto/store/store_locl.h
include/openssl/storeerr.h

index 14987b10b0def6d935efaf0245692e939d77e6b3..79f08f46570fe08035ccb53744e8ed11e680bfc6 100644 (file)
@@ -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
index 4b6af298176e4c50d5437eff49a5ed67f28bc270..7d882f313ea50eface16423d003c2af90b35283e 100644 (file)
@@ -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 (file)
index 0000000..f8fc3ba
--- /dev/null
@@ -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;
+}
index 3f5069abf53ef0926f8764f4aa497c486acf6fbb..20f19fcd2600affdad952c19b8974a46ac468d13 100644 (file)
 #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}
 };
 
index 90d5436634220df8b0fd73059d6a9104a5a5b2de..4b53108684611032abd9ca51aefe8936672ab92b 100644 (file)
@@ -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()
index c8c409d767fb573230ccfd4a9edb2a5196f36770..cf14e53e4d1b8b79ae5e9dc8153d48d67ca9555c 100644 (file)
@@ -67,3 +67,4 @@ void ossl_store_destroy_loaders_int(void);
  */
 
 int ossl_store_init_once(void);
+int ossl_store_file_loader_init(void);
index 1fca2db1ef74053021e31c090676613d31287012..28d11a274c6b99c630f9b6ce24f063e8c2eafec2 100644 (file)
@@ -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