OSSL_STORE: Add OSSL_STORE_vctrl()
[oweals/openssl.git] / crypto / store / store_lib.c
1 /*
2  * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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
10 #include "e_os.h"
11 #include <stdlib.h>
12 #include <string.h>
13 #include <openssl/crypto.h>
14 #include <openssl/err.h>
15 #include <openssl/store.h>
16 #include "internal/thread_once.h"
17 #include "internal/store_int.h"
18 #include "store_locl.h"
19
20 struct ossl_store_ctx_st {
21     const OSSL_STORE_LOADER *loader;
22     OSSL_STORE_LOADER_CTX *loader_ctx;
23     const UI_METHOD *ui_method;
24     void *ui_data;
25     OSSL_STORE_post_process_info_fn post_process;
26     void *post_process_data;
27 };
28
29 OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
30                                 void *ui_data,
31                                 OSSL_STORE_post_process_info_fn post_process,
32                                 void *post_process_data)
33 {
34     const OSSL_STORE_LOADER *loader = NULL;
35     OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
36     OSSL_STORE_CTX *ctx = NULL;
37     char scheme_copy[256], *p, *schemes[2];
38     size_t schemes_n = 0;
39     size_t i;
40
41     /*
42      * Put the file scheme first.  If the uri does represent an existing file,
43      * possible device name and all, then it should be loaded.  Only a failed
44      * attempt at loading a local file should have us try something else.
45      */
46     schemes[schemes_n++] = "file";
47
48     /*
49      * Now, check if we have something that looks like a scheme, and add it
50      * as a second scheme.  However, also check if there's an authority start
51      * (://), because that will invalidate the previous file scheme.  Also,
52      * check that this isn't actually the file scheme, as there's no point
53      * going through that one twice!
54      */
55     OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
56     if ((p = strchr(scheme_copy, ':')) != NULL) {
57         *p++ = '\0';
58         if (strcasecmp(scheme_copy, "file") != 0) {
59             if (strncmp(p, "//", 2) == 0)
60                 schemes_n--;         /* Invalidate the file scheme */
61             schemes[schemes_n++] = scheme_copy;
62         }
63     }
64
65     ERR_set_mark();
66
67     /* Try each scheme until we find one that could open the URI */
68     for (i = 0; loader_ctx == NULL && i < schemes_n; i++) {
69         if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL)
70             loader_ctx = loader->open(loader, uri, ui_method, ui_data);
71     }
72     if (loader_ctx == NULL)
73         goto err;
74
75     if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
76         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_OPEN, ERR_R_MALLOC_FAILURE);
77         goto err;
78     }
79
80     ctx->loader = loader;
81     ctx->loader_ctx = loader_ctx;
82     ctx->ui_method = ui_method;
83     ctx->ui_data = ui_data;
84     ctx->post_process = post_process;
85     ctx->post_process_data = post_process_data;
86
87     /*
88      * If the attempt to open with the 'file' scheme loader failed and the
89      * other scheme loader succeeded, the failure to open with the 'file'
90      * scheme loader leaves an error on the error stack.  Let's remove it.
91      */
92     ERR_pop_to_mark();
93
94     return ctx;
95
96  err:
97     ERR_clear_last_mark();
98     if (loader_ctx != NULL) {
99         /*
100          * We ignore a returned error because we will return NULL anyway in
101          * this case, so if something goes wrong when closing, that'll simply
102          * just add another entry on the error stack.
103          */
104         (void)loader->close(loader_ctx);
105     }
106     return NULL;
107 }
108
109 int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
110 {
111     va_list args;
112     int ret;
113
114     va_start(args, cmd);
115     ret = OSSL_STORE_vctrl(ctx, cmd, args);
116     va_end(args);
117
118     return ret;
119 }
120
121 int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args)
122 {
123     if (ctx->loader->ctrl != NULL)
124         return ctx->loader->ctrl(ctx->loader_ctx, cmd, args);
125     return 0;
126 }
127
128 OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
129 {
130     OSSL_STORE_INFO *v = NULL;
131
132  again:
133     if (OSSL_STORE_eof(ctx))
134         return NULL;
135
136     v = ctx->loader->load(ctx->loader_ctx, ctx->ui_method, ctx->ui_data);
137
138     if (ctx->post_process != NULL && v != NULL) {
139         v = ctx->post_process(v, ctx->post_process_data);
140
141         /*
142          * By returning NULL, the callback decides that this object should
143          * be ignored.
144          */
145         if (v == NULL)
146             goto again;
147     }
148
149     return v;
150 }
151
152 int OSSL_STORE_error(OSSL_STORE_CTX *ctx)
153 {
154     return ctx->loader->error(ctx->loader_ctx);
155 }
156
157 int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
158 {
159     return ctx->loader->eof(ctx->loader_ctx);
160 }
161
162 int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
163 {
164     int loader_ret = ctx->loader->close(ctx->loader_ctx);
165
166     OPENSSL_free(ctx);
167     return loader_ret;
168 }
169
170 /*
171  * Functions to generate OSSL_STORE_INFOs, one function for each type we
172  * support having in them as well as a generic constructor.
173  *
174  * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO
175  * and will therefore be freed when the OSSL_STORE_INFO is freed.
176  */
177 static OSSL_STORE_INFO *store_info_new(int type, void *data)
178 {
179     OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info));
180
181     if (info == NULL)
182         return NULL;
183
184     info->type = type;
185     info->_.data = data;
186     return info;
187 }
188
189 OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
190 {
191     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_NAME, NULL);
192
193     if (info == NULL) {
194         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME,
195                       ERR_R_MALLOC_FAILURE);
196         return NULL;
197     }
198
199     info->_.name.name = name;
200     info->_.name.desc = NULL;
201
202     return info;
203 }
204
205 int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc)
206 {
207     if (info->type != OSSL_STORE_INFO_NAME) {
208         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION,
209                       ERR_R_PASSED_INVALID_ARGUMENT);
210         return 0;
211     }
212
213     info->_.name.desc = desc;
214
215     return 1;
216 }
217 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
218 {
219     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PARAMS, params);
220
221     if (info == NULL)
222         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS,
223                       ERR_R_MALLOC_FAILURE);
224     return info;
225 }
226
227 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
228 {
229     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PKEY, pkey);
230
231     if (info == NULL)
232         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY,
233                       ERR_R_MALLOC_FAILURE);
234     return info;
235 }
236
237 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
238 {
239     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CERT, x509);
240
241     if (info == NULL)
242         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT,
243                       ERR_R_MALLOC_FAILURE);
244     return info;
245 }
246
247 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
248 {
249     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CRL, crl);
250
251     if (info == NULL)
252         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL,
253                       ERR_R_MALLOC_FAILURE);
254     return info;
255 }
256
257 /*
258  * Functions to try to extract data from a OSSL_STORE_INFO.
259  */
260 int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info)
261 {
262     return info->type;
263 }
264
265 const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info)
266 {
267     if (info->type == OSSL_STORE_INFO_NAME)
268         return info->_.name.name;
269     return NULL;
270 }
271
272 char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info)
273 {
274     if (info->type == OSSL_STORE_INFO_NAME) {
275         char *ret = OPENSSL_strdup(info->_.name.name);
276
277         if (ret == NULL)
278             OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME,
279                           ERR_R_MALLOC_FAILURE);
280         return ret;
281     }
282     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME,
283                   OSSL_STORE_R_NOT_A_NAME);
284     return NULL;
285 }
286
287 const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info)
288 {
289     if (info->type == OSSL_STORE_INFO_NAME)
290         return info->_.name.desc;
291     return NULL;
292 }
293
294 char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info)
295 {
296     if (info->type == OSSL_STORE_INFO_NAME) {
297         char *ret = OPENSSL_strdup(info->_.name.desc
298                                    ? info->_.name.desc : "");
299
300         if (ret == NULL)
301             OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION,
302                      ERR_R_MALLOC_FAILURE);
303         return ret;
304     }
305     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION,
306                   OSSL_STORE_R_NOT_A_NAME);
307     return NULL;
308 }
309
310 EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info)
311 {
312     if (info->type == OSSL_STORE_INFO_PARAMS)
313         return info->_.params;
314     return NULL;
315 }
316
317 EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info)
318 {
319     if (info->type == OSSL_STORE_INFO_PARAMS) {
320         EVP_PKEY_up_ref(info->_.params);
321         return info->_.params;
322     }
323     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS,
324                   OSSL_STORE_R_NOT_PARAMETERS);
325     return NULL;
326 }
327
328 EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info)
329 {
330     if (info->type == OSSL_STORE_INFO_PKEY)
331         return info->_.pkey;
332     return NULL;
333 }
334
335 EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info)
336 {
337     if (info->type == OSSL_STORE_INFO_PKEY) {
338         EVP_PKEY_up_ref(info->_.pkey);
339         return info->_.pkey;
340     }
341     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY,
342                   OSSL_STORE_R_NOT_A_KEY);
343     return NULL;
344 }
345
346 X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info)
347 {
348     if (info->type == OSSL_STORE_INFO_CERT)
349         return info->_.x509;
350     return NULL;
351 }
352
353 X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info)
354 {
355     if (info->type == OSSL_STORE_INFO_CERT) {
356         X509_up_ref(info->_.x509);
357         return info->_.x509;
358     }
359     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT,
360                   OSSL_STORE_R_NOT_A_CERTIFICATE);
361     return NULL;
362 }
363
364 X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info)
365 {
366     if (info->type == OSSL_STORE_INFO_CRL)
367         return info->_.crl;
368     return NULL;
369 }
370
371 X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info)
372 {
373     if (info->type == OSSL_STORE_INFO_CRL) {
374         X509_CRL_up_ref(info->_.crl);
375         return info->_.crl;
376     }
377     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL,
378                   OSSL_STORE_R_NOT_A_CRL);
379     return NULL;
380 }
381
382 /*
383  * Free the OSSL_STORE_INFO
384  */
385 void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
386 {
387     if (info != NULL) {
388         switch (info->type) {
389         case OSSL_STORE_INFO_EMBEDDED:
390             BUF_MEM_free(info->_.embedded.blob);
391             OPENSSL_free(info->_.embedded.pem_name);
392             break;
393         case OSSL_STORE_INFO_NAME:
394             OPENSSL_free(info->_.name.name);
395             OPENSSL_free(info->_.name.desc);
396             break;
397         case OSSL_STORE_INFO_PARAMS:
398             EVP_PKEY_free(info->_.params);
399             break;
400         case OSSL_STORE_INFO_PKEY:
401             EVP_PKEY_free(info->_.pkey);
402             break;
403         case OSSL_STORE_INFO_CERT:
404             X509_free(info->_.x509);
405             break;
406         case OSSL_STORE_INFO_CRL:
407             X509_CRL_free(info->_.crl);
408             break;
409         }
410         OPENSSL_free(info);
411     }
412 }
413
414 /* Internal functions */
415 OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name,
416                                               BUF_MEM *embedded)
417 {
418     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_EMBEDDED, NULL);
419
420     if (info == NULL) {
421         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED,
422                       ERR_R_MALLOC_FAILURE);
423         return NULL;
424     }
425
426     info->_.embedded.blob = embedded;
427     info->_.embedded.pem_name =
428         new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
429
430     if (new_pem_name != NULL && info->_.embedded.pem_name == NULL) {
431         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED,
432                       ERR_R_MALLOC_FAILURE);
433         OSSL_STORE_INFO_free(info);
434         info = NULL;
435     }
436
437     return info;
438 }
439
440 BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info)
441 {
442     if (info->type == OSSL_STORE_INFO_EMBEDDED)
443         return info->_.embedded.blob;
444     return NULL;
445 }
446
447 char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info)
448 {
449     if (info->type == OSSL_STORE_INFO_EMBEDDED)
450         return info->_.embedded.pem_name;
451     return NULL;
452 }
453
454 OSSL_STORE_CTX *ossl_store_attach_pem_bio(BIO *bp, const UI_METHOD *ui_method,
455                                           void *ui_data)
456 {
457     OSSL_STORE_CTX *ctx = NULL;
458     const OSSL_STORE_LOADER *loader = NULL;
459     OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
460
461     if ((loader = ossl_store_get0_loader_int("file")) == NULL
462         || ((loader_ctx = ossl_store_file_attach_pem_bio_int(bp)) == NULL))
463         goto done;
464     if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
465         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO,
466                      ERR_R_MALLOC_FAILURE);
467         goto done;
468     }
469
470     ctx->loader = loader;
471     ctx->loader_ctx = loader_ctx;
472     loader_ctx = NULL;
473     ctx->ui_method = ui_method;
474     ctx->ui_data = ui_data;
475     ctx->post_process = NULL;
476     ctx->post_process_data = NULL;
477
478  done:
479     if (loader_ctx != NULL)
480         /*
481          * We ignore a returned error because we will return NULL anyway in
482          * this case, so if something goes wrong when closing, that'll simply
483          * just add another entry on the error stack.
484          */
485         (void)loader->close(loader_ctx);
486     return ctx;
487 }
488
489 int ossl_store_detach_pem_bio(OSSL_STORE_CTX *ctx)
490 {
491     int loader_ret = ossl_store_file_detach_pem_bio_int(ctx->loader_ctx);
492
493     OPENSSL_free(ctx);
494     return loader_ret;
495 }