STORE: Add a OSSL_STORE_INFO type to help support file handler restarts
[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 <stdlib.h>
11 #include <string.h>
12
13 #include <openssl/crypto.h>
14 #include <openssl/err.h>
15 #include <openssl/store.h>
16 #include "internal/thread_once.h"
17 #include "store_locl.h"
18
19 struct ossl_store_ctx_st {
20     const OSSL_STORE_LOADER *loader;
21     OSSL_STORE_LOADER_CTX *loader_ctx;
22     const UI_METHOD *ui_method;
23     void *ui_data;
24     OSSL_STORE_post_process_info_fn post_process;
25     void *post_process_data;
26 };
27
28 OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
29                                 void *ui_data,
30                                 OSSL_STORE_post_process_info_fn post_process,
31                                 void *post_process_data)
32 {
33     const OSSL_STORE_LOADER *loader;
34     OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
35     OSSL_STORE_CTX *ctx = NULL;
36     char scheme_copy[256], *p;
37
38     OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
39     if ((p = strchr(scheme_copy, ':')) != NULL) {
40         *p = '\0';
41         p = scheme_copy;
42     } else {
43         p = "file";
44     }
45
46     if ((loader = ossl_store_get0_loader_int(p)) == NULL
47         || (loader_ctx = loader->open(loader, uri, ui_method, ui_data)) == NULL)
48         goto done;
49     if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
50         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_OPEN, ERR_R_MALLOC_FAILURE);
51         goto done;
52     }
53
54     ctx->loader = loader;
55     ctx->loader_ctx = loader_ctx;
56     loader_ctx = NULL;
57     ctx->ui_method = ui_method;
58     ctx->ui_data = ui_data;
59     ctx->post_process = post_process;
60     ctx->post_process_data = post_process_data;
61
62  done:
63     if (loader_ctx != NULL) {
64         /*
65          * We ignore a returned error because we will return NULL anyway in
66          * this case, so if something goes wrong when closing, that'll simply
67          * just add another entry on the error stack.
68          */
69         (void)loader->close(loader_ctx);
70     }
71     return ctx;
72 }
73
74 int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
75 {
76     va_list args;
77     int ret = 0;
78
79     va_start(args, cmd);
80     if (ctx->loader->ctrl != NULL)
81         ret = ctx->loader->ctrl(ctx->loader_ctx, cmd, args);
82     va_end(args);
83
84     return ret;
85 }
86
87 OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
88 {
89     OSSL_STORE_INFO *v = NULL;
90
91  again:
92     v = ctx->loader->load(ctx->loader_ctx, ctx->ui_method, ctx->ui_data);
93
94     if (ctx->post_process != NULL && v != NULL) {
95         v = ctx->post_process(v, ctx->post_process_data);
96
97         /*
98          * By returning NULL, the callback decides that this object should
99          * be ignored.
100          */
101         if (v == NULL)
102             goto again;
103     }
104
105     return v;
106 }
107
108 int OSSL_STORE_error(OSSL_STORE_CTX *ctx)
109 {
110     return ctx->loader->error(ctx->loader_ctx);
111 }
112
113 int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
114 {
115     return ctx->loader->eof(ctx->loader_ctx);
116 }
117
118 int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
119 {
120     int loader_ret = ctx->loader->close(ctx->loader_ctx);
121
122     OPENSSL_free(ctx);
123     return loader_ret;
124 }
125
126 /*
127  * Functions to generate OSSL_STORE_INFOs, one function for each type we
128  * support having in them.  Along with each of them, one macro that
129  * can be used to determine what types are supported.
130  *
131  * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO
132  * and will therefore be freed when the OSSL_STORE_INFO is freed.
133  */
134 static OSSL_STORE_INFO *store_info_new(int type, void *data)
135 {
136     OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info));
137
138     if (info == NULL)
139         return NULL;
140
141     info->type = type;
142     info->_.data = data;
143     return info;
144 }
145
146 OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
147 {
148     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_NAME, NULL);
149
150     if (info == NULL) {
151         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME,
152                       ERR_R_MALLOC_FAILURE);
153         return NULL;
154     }
155
156     info->_.name.name = name;
157     info->_.name.desc = NULL;
158
159     return info;
160 }
161
162 int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc)
163 {
164     if (info->type != OSSL_STORE_INFO_NAME) {
165         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION,
166                       ERR_R_PASSED_INVALID_ARGUMENT);
167         return 0;
168     }
169
170     info->_.name.desc = desc;
171
172     return 1;
173 }
174 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
175 {
176     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PARAMS, params);
177
178     if (info == NULL)
179         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS,
180                       ERR_R_MALLOC_FAILURE);
181     return info;
182 }
183
184 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
185 {
186     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PKEY, pkey);
187
188     if (info == NULL)
189         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY,
190                       ERR_R_MALLOC_FAILURE);
191     return info;
192 }
193
194 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
195 {
196     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CERT, x509);
197
198     if (info == NULL)
199         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT,
200                       ERR_R_MALLOC_FAILURE);
201     return info;
202 }
203
204 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
205 {
206     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CRL, crl);
207
208     if (info == NULL)
209         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL,
210                       ERR_R_MALLOC_FAILURE);
211     return info;
212 }
213
214 /*
215  * Functions to try to extract data from a OSSL_STORE_INFO.
216  */
217 int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info)
218 {
219     return info->type;
220 }
221
222 const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info)
223 {
224     if (info->type == OSSL_STORE_INFO_NAME)
225         return info->_.name.name;
226     return NULL;
227 }
228
229 char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info)
230 {
231     if (info->type == OSSL_STORE_INFO_NAME) {
232         char *ret = OPENSSL_strdup(info->_.name.name);
233
234         if (ret == NULL)
235             OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME,
236                           ERR_R_MALLOC_FAILURE);
237         return ret;
238     }
239     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME,
240                   OSSL_STORE_R_NOT_A_NAME);
241     return NULL;
242 }
243
244 const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info)
245 {
246     if (info->type == OSSL_STORE_INFO_NAME)
247         return info->_.name.desc;
248     return NULL;
249 }
250
251 char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info)
252 {
253     if (info->type == OSSL_STORE_INFO_NAME) {
254         char *ret = OPENSSL_strdup(info->_.name.desc
255                                    ? info->_.name.desc : "");
256
257         if (ret == NULL)
258             OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION,
259                      ERR_R_MALLOC_FAILURE);
260         return ret;
261     }
262     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION,
263                   OSSL_STORE_R_NOT_A_NAME);
264     return NULL;
265 }
266
267 EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info)
268 {
269     if (info->type == OSSL_STORE_INFO_PARAMS)
270         return info->_.params;
271     return NULL;
272 }
273
274 EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info)
275 {
276     if (info->type == OSSL_STORE_INFO_PARAMS) {
277         EVP_PKEY_up_ref(info->_.params);
278         return info->_.params;
279     }
280     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS,
281                   OSSL_STORE_R_NOT_PARAMETERS);
282     return NULL;
283 }
284
285 EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info)
286 {
287     if (info->type == OSSL_STORE_INFO_PKEY)
288         return info->_.pkey;
289     return NULL;
290 }
291
292 EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info)
293 {
294     if (info->type == OSSL_STORE_INFO_PKEY) {
295         EVP_PKEY_up_ref(info->_.pkey);
296         return info->_.pkey;
297     }
298     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY,
299                   OSSL_STORE_R_NOT_A_KEY);
300     return NULL;
301 }
302
303 X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info)
304 {
305     if (info->type == OSSL_STORE_INFO_CERT)
306         return info->_.x509;
307     return NULL;
308 }
309
310 X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info)
311 {
312     if (info->type == OSSL_STORE_INFO_CERT) {
313         X509_up_ref(info->_.x509);
314         return info->_.x509;
315     }
316     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT,
317                   OSSL_STORE_R_NOT_A_CERTIFICATE);
318     return NULL;
319 }
320
321 X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info)
322 {
323     if (info->type == OSSL_STORE_INFO_CRL)
324         return info->_.crl;
325     return NULL;
326 }
327
328 X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info)
329 {
330     if (info->type == OSSL_STORE_INFO_CRL) {
331         X509_CRL_up_ref(info->_.crl);
332         return info->_.crl;
333     }
334     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL,
335                   OSSL_STORE_R_NOT_A_CRL);
336     return NULL;
337 }
338
339 /*
340  * Free the OSSL_STORE_INFO
341  */
342 void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
343 {
344     if (info != NULL) {
345         switch (info->type) {
346         case OSSL_STORE_INFO_EMBEDDED:
347             BUF_MEM_free(info->_.embedded.blob);
348             OPENSSL_free(info->_.embedded.pem_name);
349             break;
350         case OSSL_STORE_INFO_NAME:
351             OPENSSL_free(info->_.name.name);
352             OPENSSL_free(info->_.name.desc);
353             break;
354         case OSSL_STORE_INFO_PARAMS:
355             EVP_PKEY_free(info->_.params);
356             break;
357         case OSSL_STORE_INFO_PKEY:
358             EVP_PKEY_free(info->_.pkey);
359             break;
360         case OSSL_STORE_INFO_CERT:
361             X509_free(info->_.x509);
362             break;
363         case OSSL_STORE_INFO_CRL:
364             X509_CRL_free(info->_.crl);
365             break;
366         }
367         OPENSSL_free(info);
368     }
369 }
370
371 /* Internal functions */
372 OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name,
373                                               BUF_MEM *embedded)
374 {
375     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_EMBEDDED, NULL);
376
377     if (info == NULL) {
378         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED,
379                       ERR_R_MALLOC_FAILURE);
380         return NULL;
381     }
382
383     info->_.embedded.blob = embedded;
384     info->_.embedded.pem_name =
385         new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
386
387     if (new_pem_name != NULL && info->_.embedded.pem_name == NULL) {
388         OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED,
389                       ERR_R_MALLOC_FAILURE);
390         OSSL_STORE_INFO_free(info);
391         info = NULL;
392     }
393
394     return info;
395 }
396
397 BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info)
398 {
399     if (info->type == OSSL_STORE_INFO_EMBEDDED)
400         return info->_.embedded.blob;
401     return NULL;
402 }
403
404 char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info)
405 {
406     if (info->type == OSSL_STORE_INFO_EMBEDDED)
407         return info->_.embedded.pem_name;
408     return NULL;
409 }