]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/encode_decode/decoder_meth.c
Rename OSSL_SERIALIZER / OSSL_DESERIALIZER to OSSL_ENCODE / OSSL_DECODE
[thirdparty/openssl.git] / crypto / encode_decode / decoder_meth.c
CommitLineData
ece9304c
RL
1/*
2 * Copyright 2020 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
10#include <openssl/core.h>
11#include <openssl/core_dispatch.h>
12#include <openssl/decoder.h>
13#include <openssl/ui.h>
14#include "internal/core.h"
15#include "internal/namemap.h"
16#include "internal/property.h"
17#include "internal/provider.h"
18#include "crypto/encoder.h"
19#include "encoder_local.h"
20
21static void OSSL_DECODER_INSTANCE_free(OSSL_DECODER_INSTANCE *instance);
22
23/*
24 * Decoder can have multiple names, separated with colons in a name string
25 */
26#define NAME_SEPARATOR ':'
27
28/* Simple method structure constructor and destructor */
29static OSSL_DECODER *ossl_decoder_new(void)
30{
31 OSSL_DECODER *decoder = NULL;
32
33 if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL
34 || (decoder->base.lock = CRYPTO_THREAD_lock_new()) == NULL) {
35 OSSL_DECODER_free(decoder);
36 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
37 return NULL;
38 }
39
40 decoder->base.refcnt = 1;
41
42 return decoder;
43}
44
45int OSSL_DECODER_up_ref(OSSL_DECODER *decoder)
46{
47 int ref = 0;
48
49 CRYPTO_UP_REF(&decoder->base.refcnt, &ref, decoder->base.lock);
50 return 1;
51}
52
53void OSSL_DECODER_free(OSSL_DECODER *decoder)
54{
55 int ref = 0;
56
57 if (decoder == NULL)
58 return;
59
60 CRYPTO_DOWN_REF(&decoder->base.refcnt, &ref, decoder->base.lock);
61 if (ref > 0)
62 return;
63 ossl_provider_free(decoder->base.prov);
64 CRYPTO_THREAD_lock_free(decoder->base.lock);
65 OPENSSL_free(decoder);
66}
67
68/* Permanent decoder method store, constructor and destructor */
69static void decoder_store_free(void *vstore)
70{
71 ossl_method_store_free(vstore);
72}
73
74static void *decoder_store_new(OPENSSL_CTX *ctx)
75{
76 return ossl_method_store_new(ctx);
77}
78
79
80static const OPENSSL_CTX_METHOD decoder_store_method = {
81 decoder_store_new,
82 decoder_store_free,
83};
84
85/* Data to be passed through ossl_method_construct() */
86struct decoder_data_st {
87 OPENSSL_CTX *libctx;
88 OSSL_METHOD_CONSTRUCT_METHOD *mcm;
89 int id; /* For get_decoder_from_store() */
90 const char *names; /* For get_decoder_from_store() */
91 const char *propquery; /* For get_decoder_from_store() */
92};
93
94/*
95 * Generic routines to fetch / create DECODER methods with
96 * ossl_method_construct()
97 */
98
99/* Temporary decoder method store, constructor and destructor */
100static void *alloc_tmp_decoder_store(OPENSSL_CTX *ctx)
101{
102 return ossl_method_store_new(ctx);
103}
104
105static void dealloc_tmp_decoder_store(void *store)
106{
107 if (store != NULL)
108 ossl_method_store_free(store);
109}
110
111/* Get the permanent decoder store */
112static OSSL_METHOD_STORE *get_decoder_store(OPENSSL_CTX *libctx)
113{
114 return openssl_ctx_get_data(libctx, OPENSSL_CTX_DECODER_STORE_INDEX,
115 &decoder_store_method);
116}
117
118/* Get decoder methods from a store, or put one in */
119static void *get_decoder_from_store(OPENSSL_CTX *libctx, void *store,
120 void *data)
121{
122 struct decoder_data_st *methdata = data;
123 void *method = NULL;
124 int id;
125
126 if ((id = methdata->id) == 0) {
127 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
128
129 id = ossl_namemap_name2num(namemap, methdata->names);
130 }
131
132 if (store == NULL
133 && (store = get_decoder_store(libctx)) == NULL)
134 return NULL;
135
136 if (!ossl_method_store_fetch(store, id, methdata->propquery, &method))
137 return NULL;
138 return method;
139}
140
141static int put_decoder_in_store(OPENSSL_CTX *libctx, void *store,
142 void *method, const OSSL_PROVIDER *prov,
143 int operation_id, const char *names,
144 const char *propdef, void *unused)
145{
146 OSSL_NAMEMAP *namemap;
147 int id;
148
149 if ((namemap = ossl_namemap_stored(libctx)) == NULL
150 || (id = ossl_namemap_name2num(namemap, names)) == 0)
151 return 0;
152
153 if (store == NULL && (store = get_decoder_store(libctx)) == NULL)
154 return 0;
155
156 return ossl_method_store_add(store, prov, id, propdef, method,
157 (int (*)(void *))OSSL_DECODER_up_ref,
158 (void (*)(void *))OSSL_DECODER_free);
159}
160
161/* Create and populate a decoder method */
162static void *decoder_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
163 OSSL_PROVIDER *prov)
164{
165 OSSL_DECODER *decoder = NULL;
166 const OSSL_DISPATCH *fns = algodef->implementation;
167
168 if ((decoder = ossl_decoder_new()) == NULL)
169 return NULL;
170 decoder->base.id = id;
171 decoder->base.propdef = algodef->property_definition;
172
173 for (; fns->function_id != 0; fns++) {
174 switch (fns->function_id) {
175 case OSSL_FUNC_DECODER_NEWCTX:
176 if (decoder->newctx == NULL)
177 decoder->newctx = OSSL_FUNC_decoder_newctx(fns);
178 break;
179 case OSSL_FUNC_DECODER_FREECTX:
180 if (decoder->freectx == NULL)
181 decoder->freectx = OSSL_FUNC_decoder_freectx(fns);
182 break;
183 case OSSL_FUNC_DECODER_GET_PARAMS:
184 if (decoder->get_params == NULL)
185 decoder->get_params =
186 OSSL_FUNC_decoder_get_params(fns);
187 break;
188 case OSSL_FUNC_DECODER_GETTABLE_PARAMS:
189 if (decoder->gettable_params == NULL)
190 decoder->gettable_params =
191 OSSL_FUNC_decoder_gettable_params(fns);
192 break;
193 case OSSL_FUNC_DECODER_SET_CTX_PARAMS:
194 if (decoder->set_ctx_params == NULL)
195 decoder->set_ctx_params =
196 OSSL_FUNC_decoder_set_ctx_params(fns);
197 break;
198 case OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS:
199 if (decoder->settable_ctx_params == NULL)
200 decoder->settable_ctx_params =
201 OSSL_FUNC_decoder_settable_ctx_params(fns);
202 break;
203 case OSSL_FUNC_DECODER_DECODE:
204 if (decoder->decode == NULL)
205 decoder->decode = OSSL_FUNC_decoder_decode(fns);
206 break;
207 case OSSL_FUNC_DECODER_EXPORT_OBJECT:
208 if (decoder->export_object == NULL)
209 decoder->export_object = OSSL_FUNC_decoder_export_object(fns);
210 break;
211 }
212 }
213 /*
214 * Try to check that the method is sensible.
215 * If you have a constructor, you must have a destructor and vice versa.
216 * You must have at least one of the encoding driver functions.
217 */
218 if (!((decoder->newctx == NULL && decoder->freectx == NULL)
219 || (decoder->newctx != NULL && decoder->freectx != NULL))
220 || (decoder->decode == NULL && decoder->export_object == NULL)) {
221 OSSL_DECODER_free(decoder);
222 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
223 return NULL;
224 }
225
226 if (prov != NULL && !ossl_provider_up_ref(prov)) {
227 OSSL_DECODER_free(decoder);
228 return NULL;
229 }
230
231 decoder->base.prov = prov;
232 return decoder;
233}
234
235
236/*
237 * The core fetching functionality passes the names of the implementation.
238 * This function is responsible to getting an identity number for them,
239 * then call decoder_from_dispatch() with that identity number.
240 */
241static void *construct_decoder(const OSSL_ALGORITHM *algodef,
242 OSSL_PROVIDER *prov, void *unused)
243{
244 /*
245 * This function is only called if get_decoder_from_store() returned
246 * NULL, so it's safe to say that of all the spots to create a new
247 * namemap entry, this is it. Should the name already exist there, we
248 * know that ossl_namemap_add() will return its corresponding number.
249 */
250 OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
251 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
252 const char *names = algodef->algorithm_names;
253 int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
254 void *method = NULL;
255
256 if (id != 0)
257 method = decoder_from_dispatch(id, algodef, prov);
258
259 return method;
260}
261
262/* Intermediary function to avoid ugly casts, used below */
263static void destruct_decoder(void *method, void *data)
264{
265 OSSL_DECODER_free(method);
266}
267
268static int up_ref_decoder(void *method)
269{
270 return OSSL_DECODER_up_ref(method);
271}
272
273static void free_decoder(void *method)
274{
275 OSSL_DECODER_free(method);
276}
277
278/* Fetching support. Can fetch by numeric identity or by name */
279static OSSL_DECODER *inner_ossl_decoder_fetch(OPENSSL_CTX *libctx, int id,
280 const char *name,
281 const char *properties)
282{
283 OSSL_METHOD_STORE *store = get_decoder_store(libctx);
284 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
285 void *method = NULL;
286
287 if (store == NULL || namemap == NULL)
288 return NULL;
289
290 /*
291 * If we have been passed neither a name_id or a name, we have an
292 * internal programming error.
293 */
294 if (!ossl_assert(id != 0 || name != NULL))
295 return NULL;
296
297 if (id == 0)
298 id = ossl_namemap_name2num(namemap, name);
299
300 if (id == 0
301 || !ossl_method_store_cache_get(store, id, properties, &method)) {
302 OSSL_METHOD_CONSTRUCT_METHOD mcm = {
303 alloc_tmp_decoder_store,
304 dealloc_tmp_decoder_store,
305 get_decoder_from_store,
306 put_decoder_in_store,
307 construct_decoder,
308 destruct_decoder
309 };
310 struct decoder_data_st mcmdata;
311
312 mcmdata.libctx = libctx;
313 mcmdata.mcm = &mcm;
314 mcmdata.id = id;
315 mcmdata.names = name;
316 mcmdata.propquery = properties;
317 if ((method = ossl_method_construct(libctx, OSSL_OP_DECODER,
318 0 /* !force_cache */,
319 &mcm, &mcmdata)) != NULL) {
320 /*
321 * If construction did create a method for us, we know that
322 * there is a correct name_id and meth_id, since those have
323 * already been calculated in get_decoder_from_store() and
324 * put_decoder_in_store() above.
325 */
326 if (id == 0)
327 id = ossl_namemap_name2num(namemap, name);
328 ossl_method_store_cache_set(store, id, properties, method,
329 up_ref_decoder, free_decoder);
330 }
331 }
332
333 return method;
334}
335
336OSSL_DECODER *OSSL_DECODER_fetch(OPENSSL_CTX *libctx, const char *name,
337 const char *properties)
338{
339 return inner_ossl_decoder_fetch(libctx, 0, name, properties);
340}
341
342OSSL_DECODER *ossl_decoder_fetch_by_number(OPENSSL_CTX *libctx, int id,
343 const char *properties)
344{
345 return inner_ossl_decoder_fetch(libctx, id, NULL, properties);
346}
347
348/*
349 * Library of basic method functions
350 */
351
352const OSSL_PROVIDER *OSSL_DECODER_provider(const OSSL_DECODER *decoder)
353{
354 if (!ossl_assert(decoder != NULL)) {
355 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
356 return 0;
357 }
358
359 return decoder->base.prov;
360}
361
362const char *OSSL_DECODER_properties(const OSSL_DECODER *decoder)
363{
364 if (!ossl_assert(decoder != NULL)) {
365 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
366 return 0;
367 }
368
369 return decoder->base.propdef;
370}
371
372int OSSL_DECODER_number(const OSSL_DECODER *decoder)
373{
374 if (!ossl_assert(decoder != NULL)) {
375 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
376 return 0;
377 }
378
379 return decoder->base.id;
380}
381
382int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name)
383{
384 if (decoder->base.prov != NULL) {
385 OPENSSL_CTX *libctx = ossl_provider_library_context(decoder->base.prov);
386 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
387
388 return ossl_namemap_name2num(namemap, name) == decoder->base.id;
389 }
390 return 0;
391}
392
393struct decoder_do_all_data_st {
394 void (*user_fn)(void *method, void *arg);
395 void *user_arg;
396};
397
398static void decoder_do_one(OSSL_PROVIDER *provider,
399 const OSSL_ALGORITHM *algodef,
400 int no_store, void *vdata)
401{
402 struct decoder_do_all_data_st *data = vdata;
403 OPENSSL_CTX *libctx = ossl_provider_library_context(provider);
404 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
405 const char *names = algodef->algorithm_names;
406 int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
407 void *method = NULL;
408
409 if (id != 0)
410 method =
411 decoder_from_dispatch(id, algodef, provider);
412
413 if (method != NULL) {
414 data->user_fn(method, data->user_arg);
415 OSSL_DECODER_free(method);
416 }
417}
418
419void OSSL_DECODER_do_all_provided(OPENSSL_CTX *libctx,
420 void (*fn)(OSSL_DECODER *decoder, void *arg),
421 void *arg)
422{
423 struct decoder_do_all_data_st data;
424
425 data.user_fn = (void (*)(void *, void *))fn;
426 data.user_arg = arg;
427 ossl_algorithm_do_all(libctx, OSSL_OP_DECODER, NULL,
428 NULL, decoder_do_one, NULL,
429 &data);
430}
431
432void OSSL_DECODER_names_do_all(const OSSL_DECODER *decoder,
433 void (*fn)(const char *name, void *data),
434 void *data)
435{
436 if (decoder == NULL)
437 return;
438
439 if (decoder->base.prov != NULL) {
440 OPENSSL_CTX *libctx = ossl_provider_library_context(decoder->base.prov);
441 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
442
443 ossl_namemap_doall_names(namemap, decoder->base.id, fn, data);
444 }
445}
446
447const OSSL_PARAM *
448OSSL_DECODER_gettable_params(OSSL_DECODER *decoder)
449{
450 if (decoder != NULL && decoder->gettable_params != NULL) {
451 void *provctx = ossl_provider_ctx(OSSL_DECODER_provider(decoder));
452
453 return decoder->gettable_params(provctx);
454 }
455 return NULL;
456}
457
458int OSSL_DECODER_get_params(OSSL_DECODER *decoder, OSSL_PARAM params[])
459{
460 if (decoder != NULL && decoder->get_params != NULL)
461 return decoder->get_params(params);
462 return 0;
463}
464
465const OSSL_PARAM *
466OSSL_DECODER_settable_ctx_params(OSSL_DECODER *decoder)
467{
468 if (decoder != NULL && decoder->settable_ctx_params != NULL) {
469 void *provctx = ossl_provider_ctx(OSSL_DECODER_provider(decoder));
470
471 return decoder->settable_ctx_params(provctx);
472 }
473 return NULL;
474}
475
476/*
477 * Decoder context support
478 */
479
480/*
481 * |encoder| value NULL is valid, and signifies that there is no decoder.
482 * This is useful to provide fallback mechanisms.
483 * Functions that want to verify if there is a decoder can do so with
484 * OSSL_DECODER_CTX_get_decoder()
485 */
486OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void)
487{
488 OSSL_DECODER_CTX *ctx;
489
490 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
491 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
492 return NULL;
493 }
494
495 ctx->passphrase_cb = ossl_decoder_passphrase_in_cb;
496 return ctx;
497}
498
499int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx,
500 const OSSL_PARAM params[])
501{
502 size_t i;
503 size_t l;
504
505 if (!ossl_assert(ctx != NULL)) {
506 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
507 return 0;
508 }
509
510 if (ctx->decoder_insts == NULL)
511 return 1;
512
513 l = (size_t)sk_OSSL_DECODER_INSTANCE_num(ctx->decoder_insts);
514 for (i = 0; i < l; i++) {
515 OSSL_DECODER_INSTANCE *decoder_inst =
516 sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i);
517
518 if (decoder_inst->deserctx == NULL
519 || decoder_inst->decoder->set_ctx_params == NULL)
520 continue;
521 if (!decoder_inst->decoder->set_ctx_params(decoder_inst->deserctx, params))
522 return 0;
523 }
524 return 1;
525}
526
527static void
528OSSL_DECODER_INSTANCE_free(OSSL_DECODER_INSTANCE *decoder_inst)
529{
530 if (decoder_inst != NULL) {
531 if (decoder_inst->decoder->freectx != NULL)
532 decoder_inst->decoder->freectx(decoder_inst->deserctx);
533 decoder_inst->deserctx = NULL;
534 OSSL_DECODER_free(decoder_inst->decoder);
535 decoder_inst->decoder = NULL;
536 OPENSSL_free(decoder_inst);
537 decoder_inst = NULL;
538 }
539}
540
541void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx)
542{
543 if (ctx != NULL) {
544 if (ctx->cleanup != NULL)
545 ctx->cleanup(ctx->construct_data);
546 sk_OSSL_DECODER_INSTANCE_pop_free(ctx->decoder_insts,
547 OSSL_DECODER_INSTANCE_free);
548 OSSL_DECODER_CTX_set_passphrase_ui(ctx, NULL, NULL);
549 OSSL_DECODER_CTX_set_passphrase(ctx, NULL, 0);
550 OPENSSL_free(ctx);
551 }
552}