1 /*
2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9 #include <openssl/store.h>
10 #include <openssl/core_dispatch.h>
11 #include <openssl/core_names.h>
12 #include <openssl/core_object.h>
13 #include <openssl/bio.h>
14 #include <openssl/err.h>
15 #include <openssl/params.h>
16 #include <openssl/decoder.h>
17 #include <openssl/proverr.h>
18 #include <openssl/store.h> /* The OSSL_STORE_INFO type numbers */
19 #include "internal/cryptlib.h"
20 #include "internal/o_dir.h"
21 #include "crypto/decoder.h"
22 #include "crypto/ctype.h" /* ossl_isdigit() */
23 #include "prov/implementations.h"
24 #include "prov/providercommon.h"
25 #include "prov/bio.h"
26 #include "file_store_local.h"
27 #ifdef __CYGWIN__
28 # include <windows.h>
29 #endif
30 #include <wincrypt.h>
31
32 enum {
33 STATE_IDLE,
34 STATE_READ,
35 STATE_EOF,
36 };
37
38 struct winstore_ctx_st {
39 void *provctx;
40 char *propq;
41 unsigned char *subject;
42 size_t subject_len;
43
44 HCERTSTORE win_store;
45 const CERT_CONTEXT *win_ctx;
46 int state;
47
48 OSSL_DECODER_CTX *dctx;
49 };
50
winstore_win_reset(struct winstore_ctx_st * ctx)51 static void winstore_win_reset(struct winstore_ctx_st *ctx)
52 {
53 if (ctx->win_ctx != NULL) {
54 CertFreeCertificateContext(ctx->win_ctx);
55 ctx->win_ctx = NULL;
56 }
57
58 ctx->state = STATE_IDLE;
59 }
60
winstore_win_advance(struct winstore_ctx_st * ctx)61 static void winstore_win_advance(struct winstore_ctx_st *ctx)
62 {
63 CERT_NAME_BLOB name = {0};
64
65 if (ctx->state == STATE_EOF)
66 return;
67
68 name.cbData = ctx->subject_len;
69 name.pbData = ctx->subject;
70
71 ctx->win_ctx = (name.cbData == 0 ? NULL :
72 CertFindCertificateInStore(ctx->win_store,
73 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
74 0, CERT_FIND_SUBJECT_NAME,
75 &name, ctx->win_ctx));
76
77 ctx->state = (ctx->win_ctx == NULL) ? STATE_EOF : STATE_READ;
78 }
79
winstore_open(void * provctx,const char * uri)80 static void *winstore_open(void *provctx, const char *uri)
81 {
82 struct winstore_ctx_st *ctx = NULL;
83
84 if (!HAS_CASE_PREFIX(uri, "org.openssl.winstore:"))
85 return NULL;
86
87 ctx = OPENSSL_zalloc(sizeof(*ctx));
88 if (ctx == NULL)
89 return NULL;
90
91 ctx->provctx = provctx;
92 ctx->win_store = CertOpenSystemStoreW(0, L"ROOT");
93 if (ctx->win_store == NULL) {
94 OPENSSL_free(ctx);
95 return NULL;
96 }
97
98 winstore_win_reset(ctx);
99 return ctx;
100 }
101
winstore_attach(void * provctx,OSSL_CORE_BIO * cin)102 static void *winstore_attach(void *provctx, OSSL_CORE_BIO *cin)
103 {
104 return NULL; /* not supported */
105 }
106
winstore_settable_ctx_params(void * loaderctx,const OSSL_PARAM params[])107 static const OSSL_PARAM *winstore_settable_ctx_params(void *loaderctx, const OSSL_PARAM params[])
108 {
109 static const OSSL_PARAM known_settable_ctx_params[] = {
110 OSSL_PARAM_octet_string(OSSL_STORE_PARAM_SUBJECT, NULL, 0),
111 OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_PROPERTIES, NULL, 0),
112 OSSL_PARAM_END
113 };
114 return known_settable_ctx_params;
115 }
116
winstore_set_ctx_params(void * loaderctx,const OSSL_PARAM params[])117 static int winstore_set_ctx_params(void *loaderctx, const OSSL_PARAM params[])
118 {
119 struct winstore_ctx_st *ctx = loaderctx;
120 const OSSL_PARAM *p;
121 int do_reset = 0;
122
123 if (ossl_param_is_empty(params))
124 return 1;
125
126 p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_PROPERTIES);
127 if (p != NULL) {
128 do_reset = 1;
129 OPENSSL_free(ctx->propq);
130 ctx->propq = NULL;
131 if (!OSSL_PARAM_get_utf8_string(p, &ctx->propq, 0))
132 return 0;
133 }
134
135 p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT);
136 if (p != NULL) {
137 const unsigned char *der = NULL;
138 size_t der_len = 0;
139
140 if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&der, &der_len))
141 return 0;
142
143 do_reset = 1;
144
145 OPENSSL_free(ctx->subject);
146
147 ctx->subject = OPENSSL_malloc(der_len);
148 if (ctx->subject == NULL) {
149 ctx->subject_len = 0;
150 return 0;
151 }
152
153 ctx->subject_len = der_len;
154 memcpy(ctx->subject, der, der_len);
155 }
156
157 if (do_reset) {
158 winstore_win_reset(ctx);
159 winstore_win_advance(ctx);
160 }
161
162 return 1;
163 }
164
165 struct load_data_st {
166 OSSL_CALLBACK *object_cb;
167 void *object_cbarg;
168 };
169
load_construct(OSSL_DECODER_INSTANCE * decoder_inst,const OSSL_PARAM * params,void * construct_data)170 static int load_construct(OSSL_DECODER_INSTANCE *decoder_inst,
171 const OSSL_PARAM *params, void *construct_data)
172 {
173 struct load_data_st *data = construct_data;
174 return data->object_cb(params, data->object_cbarg);
175 }
176
load_cleanup(void * construct_data)177 static void load_cleanup(void *construct_data)
178 {
179 /* No-op. */
180 }
181
setup_decoder(struct winstore_ctx_st * ctx)182 static int setup_decoder(struct winstore_ctx_st *ctx)
183 {
184 OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(ctx->provctx);
185 const OSSL_ALGORITHM *to_algo = NULL;
186
187 if (ctx->dctx != NULL)
188 return 1;
189
190 ctx->dctx = OSSL_DECODER_CTX_new();
191 if (ctx->dctx == NULL) {
192 ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
193 return 0;
194 }
195
196 if (!OSSL_DECODER_CTX_set_input_type(ctx->dctx, "DER")) {
197 ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
198 goto err;
199 }
200
201 if (!OSSL_DECODER_CTX_set_input_structure(ctx->dctx, "Certificate")) {
202 ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
203 goto err;
204 }
205
206 for (to_algo = ossl_any_to_obj_algorithm;
207 to_algo->algorithm_names != NULL;
208 to_algo++) {
209 OSSL_DECODER *to_obj = NULL;
210 OSSL_DECODER_INSTANCE *to_obj_inst = NULL;
211
212 /*
213 * Create the internal last resort decoder implementation
214 * together with a "decoder instance".
215 * The decoder doesn't need any identification or to be
216 * attached to any provider, since it's only used locally.
217 */
218 to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL);
219 if (to_obj != NULL)
220 to_obj_inst = ossl_decoder_instance_new(to_obj, ctx->provctx);
221
222 OSSL_DECODER_free(to_obj);
223 if (to_obj_inst == NULL)
224 goto err;
225
226 if (!ossl_decoder_ctx_add_decoder_inst(ctx->dctx,
227 to_obj_inst)) {
228 ossl_decoder_instance_free(to_obj_inst);
229 ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
230 goto err;
231 }
232 }
233
234 if (!OSSL_DECODER_CTX_add_extra(ctx->dctx, libctx, ctx->propq)) {
235 ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
236 goto err;
237 }
238
239 if (!OSSL_DECODER_CTX_set_construct(ctx->dctx, load_construct)) {
240 ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
241 goto err;
242 }
243
244 if (!OSSL_DECODER_CTX_set_cleanup(ctx->dctx, load_cleanup)) {
245 ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB);
246 goto err;
247 }
248
249 return 1;
250
251 err:
252 OSSL_DECODER_CTX_free(ctx->dctx);
253 ctx->dctx = NULL;
254 return 0;
255 }
256
winstore_load_using(struct winstore_ctx_st * ctx,OSSL_CALLBACK * object_cb,void * object_cbarg,OSSL_PASSPHRASE_CALLBACK * pw_cb,void * pw_cbarg,const void * der,size_t der_len)257 static int winstore_load_using(struct winstore_ctx_st *ctx,
258 OSSL_CALLBACK *object_cb, void *object_cbarg,
259 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg,
260 const void *der, size_t der_len)
261 {
262 struct load_data_st data;
263 const unsigned char *der_ = der;
264 size_t der_len_ = der_len;
265
266 if (setup_decoder(ctx) == 0)
267 return 0;
268
269 data.object_cb = object_cb;
270 data.object_cbarg = object_cbarg;
271
272 OSSL_DECODER_CTX_set_construct_data(ctx->dctx, &data);
273 OSSL_DECODER_CTX_set_passphrase_cb(ctx->dctx, pw_cb, pw_cbarg);
274
275 if (OSSL_DECODER_from_data(ctx->dctx, &der_, &der_len_) == 0)
276 return 0;
277
278 return 1;
279 }
280
winstore_load(void * loaderctx,OSSL_CALLBACK * object_cb,void * object_cbarg,OSSL_PASSPHRASE_CALLBACK * pw_cb,void * pw_cbarg)281 static int winstore_load(void *loaderctx,
282 OSSL_CALLBACK *object_cb, void *object_cbarg,
283 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
284 {
285 int ret = 0;
286 struct winstore_ctx_st *ctx = loaderctx;
287
288 if (ctx->state != STATE_READ)
289 return 0;
290
291 ret = winstore_load_using(ctx, object_cb, object_cbarg, pw_cb, pw_cbarg,
292 ctx->win_ctx->pbCertEncoded,
293 ctx->win_ctx->cbCertEncoded);
294
295 if (ret == 1)
296 winstore_win_advance(ctx);
297
298 return ret;
299 }
300
winstore_eof(void * loaderctx)301 static int winstore_eof(void *loaderctx)
302 {
303 struct winstore_ctx_st *ctx = loaderctx;
304
305 return ctx->state != STATE_READ;
306 }
307
winstore_close(void * loaderctx)308 static int winstore_close(void *loaderctx)
309 {
310 struct winstore_ctx_st *ctx = loaderctx;
311
312 winstore_win_reset(ctx);
313 CertCloseStore(ctx->win_store, 0);
314 OSSL_DECODER_CTX_free(ctx->dctx);
315 OPENSSL_free(ctx->propq);
316 OPENSSL_free(ctx->subject);
317 OPENSSL_free(ctx);
318 return 1;
319 }
320
321 const OSSL_DISPATCH ossl_winstore_store_functions[] = {
322 { OSSL_FUNC_STORE_OPEN, (void (*)(void))winstore_open },
323 { OSSL_FUNC_STORE_ATTACH, (void (*)(void))winstore_attach },
324 { OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS, (void (*)(void))winstore_settable_ctx_params },
325 { OSSL_FUNC_STORE_SET_CTX_PARAMS, (void (*)(void))winstore_set_ctx_params },
326 { OSSL_FUNC_STORE_LOAD, (void (*)(void))winstore_load },
327 { OSSL_FUNC_STORE_EOF, (void (*)(void))winstore_eof },
328 { OSSL_FUNC_STORE_CLOSE, (void (*)(void))winstore_close },
329 OSSL_DISPATCH_END,
330 };
331