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