1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <string.h>
11e1051a39Sopenharmony_ci#include <limits.h>
12e1051a39Sopenharmony_ci#include <openssl/store.h>
13e1051a39Sopenharmony_ci#include <openssl/ui.h>
14e1051a39Sopenharmony_ci#include "testutil.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#ifndef PATH_MAX
17e1051a39Sopenharmony_ci# if defined(_WIN32) && defined(_MAX_PATH)
18e1051a39Sopenharmony_ci#  define PATH_MAX _MAX_PATH
19e1051a39Sopenharmony_ci# else
20e1051a39Sopenharmony_ci#  define PATH_MAX 4096
21e1051a39Sopenharmony_ci# endif
22e1051a39Sopenharmony_ci#endif
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_citypedef enum OPTION_choice {
25e1051a39Sopenharmony_ci    OPT_ERR = -1,
26e1051a39Sopenharmony_ci    OPT_EOF = 0,
27e1051a39Sopenharmony_ci    OPT_INPUTDIR,
28e1051a39Sopenharmony_ci    OPT_INFILE,
29e1051a39Sopenharmony_ci    OPT_SM2FILE,
30e1051a39Sopenharmony_ci    OPT_DATADIR,
31e1051a39Sopenharmony_ci    OPT_TEST_ENUM
32e1051a39Sopenharmony_ci} OPTION_CHOICE;
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_cistatic const char *inputdir = NULL;
35e1051a39Sopenharmony_cistatic const char *infile = NULL;
36e1051a39Sopenharmony_cistatic const char *sm2file = NULL;
37e1051a39Sopenharmony_cistatic const char *datadir = NULL;
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_cistatic int test_store_open(void)
40e1051a39Sopenharmony_ci{
41e1051a39Sopenharmony_ci    int ret = 0;
42e1051a39Sopenharmony_ci    OSSL_STORE_CTX *sctx = NULL;
43e1051a39Sopenharmony_ci    OSSL_STORE_SEARCH *search = NULL;
44e1051a39Sopenharmony_ci    UI_METHOD *ui_method = NULL;
45e1051a39Sopenharmony_ci    char *input = test_mk_file_path(inputdir, infile);
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_ci    ret = TEST_ptr(input)
48e1051a39Sopenharmony_ci          && TEST_ptr(search = OSSL_STORE_SEARCH_by_alias("nothing"))
49e1051a39Sopenharmony_ci          && TEST_ptr(ui_method= UI_create_method("DummyUI"))
50e1051a39Sopenharmony_ci          && TEST_ptr(sctx = OSSL_STORE_open_ex(input, NULL, NULL, ui_method,
51e1051a39Sopenharmony_ci                                                NULL, NULL, NULL, NULL))
52e1051a39Sopenharmony_ci          && TEST_false(OSSL_STORE_find(sctx, NULL))
53e1051a39Sopenharmony_ci          && TEST_true(OSSL_STORE_find(sctx, search));
54e1051a39Sopenharmony_ci    UI_destroy_method(ui_method);
55e1051a39Sopenharmony_ci    OSSL_STORE_SEARCH_free(search);
56e1051a39Sopenharmony_ci    OSSL_STORE_close(sctx);
57e1051a39Sopenharmony_ci    OPENSSL_free(input);
58e1051a39Sopenharmony_ci    return ret;
59e1051a39Sopenharmony_ci}
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_cistatic int test_store_search_by_key_fingerprint_fail(void)
62e1051a39Sopenharmony_ci{
63e1051a39Sopenharmony_ci    int ret;
64e1051a39Sopenharmony_ci    OSSL_STORE_SEARCH *search = NULL;
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci    ret = TEST_ptr_null(search = OSSL_STORE_SEARCH_by_key_fingerprint(
67e1051a39Sopenharmony_ci                                     EVP_sha256(), NULL, 0));
68e1051a39Sopenharmony_ci    OSSL_STORE_SEARCH_free(search);
69e1051a39Sopenharmony_ci    return ret;
70e1051a39Sopenharmony_ci}
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_cistatic int get_params(const char *uri, const char *type)
73e1051a39Sopenharmony_ci{
74e1051a39Sopenharmony_ci    EVP_PKEY *pkey = NULL;
75e1051a39Sopenharmony_ci    OSSL_STORE_CTX *ctx = NULL;
76e1051a39Sopenharmony_ci    OSSL_STORE_INFO *info;
77e1051a39Sopenharmony_ci    int ret = 0;
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci    ctx = OSSL_STORE_open_ex(uri, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
80e1051a39Sopenharmony_ci    if (!TEST_ptr(ctx))
81e1051a39Sopenharmony_ci        goto err;
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_ci    while (!OSSL_STORE_eof(ctx)
84e1051a39Sopenharmony_ci            && (info = OSSL_STORE_load(ctx)) != NULL
85e1051a39Sopenharmony_ci            && pkey == NULL) {
86e1051a39Sopenharmony_ci        if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PARAMS) {
87e1051a39Sopenharmony_ci            pkey = OSSL_STORE_INFO_get1_PARAMS(info);
88e1051a39Sopenharmony_ci        }
89e1051a39Sopenharmony_ci        OSSL_STORE_INFO_free(info);
90e1051a39Sopenharmony_ci        info = NULL;
91e1051a39Sopenharmony_ci    }
92e1051a39Sopenharmony_ci
93e1051a39Sopenharmony_ci    if (pkey != NULL)
94e1051a39Sopenharmony_ci        ret = EVP_PKEY_is_a(pkey, type);
95e1051a39Sopenharmony_ci    EVP_PKEY_free(pkey);
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_ci err:
98e1051a39Sopenharmony_ci    OSSL_STORE_close(ctx);
99e1051a39Sopenharmony_ci    return ret;
100e1051a39Sopenharmony_ci}
101e1051a39Sopenharmony_ci
102e1051a39Sopenharmony_cistatic int test_store_get_params(int idx)
103e1051a39Sopenharmony_ci{
104e1051a39Sopenharmony_ci    const char *type;
105e1051a39Sopenharmony_ci    const char *urifmt;
106e1051a39Sopenharmony_ci    char uri[PATH_MAX];
107e1051a39Sopenharmony_ci
108e1051a39Sopenharmony_ci    switch(idx) {
109e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
110e1051a39Sopenharmony_ci    case 0:
111e1051a39Sopenharmony_ci        type = "DH";
112e1051a39Sopenharmony_ci        break;
113e1051a39Sopenharmony_ci    case 1:
114e1051a39Sopenharmony_ci        type = "DHX";
115e1051a39Sopenharmony_ci        break;
116e1051a39Sopenharmony_ci#else
117e1051a39Sopenharmony_ci    case 0:
118e1051a39Sopenharmony_ci    case 1:
119e1051a39Sopenharmony_ci        return 1;
120e1051a39Sopenharmony_ci#endif
121e1051a39Sopenharmony_ci    case 2:
122e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA
123e1051a39Sopenharmony_ci        type = "DSA";
124e1051a39Sopenharmony_ci        break;
125e1051a39Sopenharmony_ci#else
126e1051a39Sopenharmony_ci        return 1;
127e1051a39Sopenharmony_ci#endif
128e1051a39Sopenharmony_ci    default:
129e1051a39Sopenharmony_ci        TEST_error("Invalid test index");
130e1051a39Sopenharmony_ci        return 0;
131e1051a39Sopenharmony_ci    }
132e1051a39Sopenharmony_ci
133e1051a39Sopenharmony_ci    urifmt = "%s/%s-params.pem";
134e1051a39Sopenharmony_ci#ifdef __VMS
135e1051a39Sopenharmony_ci    {
136e1051a39Sopenharmony_ci        char datadir_end = datadir[strlen(datadir) - 1];
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ci        if (datadir_end == ':' || datadir_end == ']' || datadir_end == '>')
139e1051a39Sopenharmony_ci            urifmt = "%s%s-params.pem";
140e1051a39Sopenharmony_ci    }
141e1051a39Sopenharmony_ci#endif
142e1051a39Sopenharmony_ci    if (!TEST_true(BIO_snprintf(uri, sizeof(uri), urifmt, datadir, type)))
143e1051a39Sopenharmony_ci        return 0;
144e1051a39Sopenharmony_ci
145e1051a39Sopenharmony_ci    TEST_info("Testing uri: %s", uri);
146e1051a39Sopenharmony_ci    if (!TEST_true(get_params(uri, type)))
147e1051a39Sopenharmony_ci        return 0;
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci    return 1;
150e1051a39Sopenharmony_ci}
151e1051a39Sopenharmony_ci
152e1051a39Sopenharmony_ci/*
153e1051a39Sopenharmony_ci * This test verifies that calling OSSL_STORE_ATTACH does not set an
154e1051a39Sopenharmony_ci * "unregistered scheme" error when called.
155e1051a39Sopenharmony_ci */
156e1051a39Sopenharmony_cistatic int test_store_attach_unregistered_scheme(void)
157e1051a39Sopenharmony_ci{
158e1051a39Sopenharmony_ci    int ret;
159e1051a39Sopenharmony_ci    OSSL_STORE_CTX *store_ctx = NULL;
160e1051a39Sopenharmony_ci    OSSL_PROVIDER *provider = NULL;
161e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = NULL;
162e1051a39Sopenharmony_ci    BIO *bio = NULL;
163e1051a39Sopenharmony_ci    char *input = test_mk_file_path(inputdir, sm2file);
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_ci    ret = TEST_ptr(input)
166e1051a39Sopenharmony_ci          && TEST_ptr(libctx = OSSL_LIB_CTX_new())
167e1051a39Sopenharmony_ci          && TEST_ptr(provider = OSSL_PROVIDER_load(libctx, "default"))
168e1051a39Sopenharmony_ci          && TEST_ptr(bio = BIO_new_file(input, "r"))
169e1051a39Sopenharmony_ci          && TEST_ptr(store_ctx = OSSL_STORE_attach(bio, "file", libctx, NULL,
170e1051a39Sopenharmony_ci                                                    NULL, NULL, NULL, NULL, NULL))
171e1051a39Sopenharmony_ci          && TEST_int_ne(ERR_GET_LIB(ERR_peek_error()), ERR_LIB_OSSL_STORE)
172e1051a39Sopenharmony_ci          && TEST_int_ne(ERR_GET_REASON(ERR_peek_error()),
173e1051a39Sopenharmony_ci                         OSSL_STORE_R_UNREGISTERED_SCHEME);
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ci    BIO_free(bio);
176e1051a39Sopenharmony_ci    OSSL_STORE_close(store_ctx);
177e1051a39Sopenharmony_ci    OSSL_PROVIDER_unload(provider);
178e1051a39Sopenharmony_ci    OSSL_LIB_CTX_free(libctx);
179e1051a39Sopenharmony_ci    OPENSSL_free(input);
180e1051a39Sopenharmony_ci    return ret;
181e1051a39Sopenharmony_ci}
182e1051a39Sopenharmony_ci
183e1051a39Sopenharmony_ciconst OPTIONS *test_get_options(void)
184e1051a39Sopenharmony_ci{
185e1051a39Sopenharmony_ci    static const OPTIONS test_options[] = {
186e1051a39Sopenharmony_ci        OPT_TEST_OPTIONS_DEFAULT_USAGE,
187e1051a39Sopenharmony_ci        { "dir", OPT_INPUTDIR, '/' },
188e1051a39Sopenharmony_ci        { "in", OPT_INFILE, '<' },
189e1051a39Sopenharmony_ci        { "sm2", OPT_SM2FILE, '<' },
190e1051a39Sopenharmony_ci        { "data", OPT_DATADIR, 's' },
191e1051a39Sopenharmony_ci        { NULL }
192e1051a39Sopenharmony_ci    };
193e1051a39Sopenharmony_ci    return test_options;
194e1051a39Sopenharmony_ci}
195e1051a39Sopenharmony_ci
196e1051a39Sopenharmony_ciint setup_tests(void)
197e1051a39Sopenharmony_ci{
198e1051a39Sopenharmony_ci    OPTION_CHOICE o;
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_ci    while ((o = opt_next()) != OPT_EOF) {
201e1051a39Sopenharmony_ci        switch (o) {
202e1051a39Sopenharmony_ci        case OPT_INPUTDIR:
203e1051a39Sopenharmony_ci            inputdir = opt_arg();
204e1051a39Sopenharmony_ci            break;
205e1051a39Sopenharmony_ci        case OPT_INFILE:
206e1051a39Sopenharmony_ci            infile = opt_arg();
207e1051a39Sopenharmony_ci            break;
208e1051a39Sopenharmony_ci        case OPT_SM2FILE:
209e1051a39Sopenharmony_ci            sm2file = opt_arg();
210e1051a39Sopenharmony_ci            break;
211e1051a39Sopenharmony_ci        case OPT_DATADIR:
212e1051a39Sopenharmony_ci            datadir = opt_arg();
213e1051a39Sopenharmony_ci            break;
214e1051a39Sopenharmony_ci        case OPT_TEST_CASES:
215e1051a39Sopenharmony_ci           break;
216e1051a39Sopenharmony_ci        default:
217e1051a39Sopenharmony_ci        case OPT_ERR:
218e1051a39Sopenharmony_ci            return 0;
219e1051a39Sopenharmony_ci        }
220e1051a39Sopenharmony_ci    }
221e1051a39Sopenharmony_ci
222e1051a39Sopenharmony_ci    if (datadir == NULL) {
223e1051a39Sopenharmony_ci        TEST_error("No data directory specified");
224e1051a39Sopenharmony_ci        return 0;
225e1051a39Sopenharmony_ci    }
226e1051a39Sopenharmony_ci    if (inputdir == NULL) {
227e1051a39Sopenharmony_ci        TEST_error("No input directory specified");
228e1051a39Sopenharmony_ci        return 0;
229e1051a39Sopenharmony_ci    }
230e1051a39Sopenharmony_ci
231e1051a39Sopenharmony_ci    if (infile != NULL)
232e1051a39Sopenharmony_ci        ADD_TEST(test_store_open);
233e1051a39Sopenharmony_ci    ADD_TEST(test_store_search_by_key_fingerprint_fail);
234e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_store_get_params, 3);
235e1051a39Sopenharmony_ci    if (sm2file != NULL)
236e1051a39Sopenharmony_ci        ADD_TEST(test_store_attach_unregistered_scheme);
237e1051a39Sopenharmony_ci    return 1;
238e1051a39Sopenharmony_ci}
239