DESERIALIZER: Implement decryption of password protected objects
[openssl.git] / crypto / serializer / deserializer_lib.c
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_names.h>
11 #include <openssl/bio.h>
12 #include <openssl/params.h>
13 #include <openssl/provider.h>
14 #include "serializer_local.h"
15 #include "e_os.h"
16
17 struct deser_process_data_st {
18     OSSL_DESERIALIZER_CTX *ctx;
19
20     /* Current BIO */
21     BIO *bio;
22
23     /* Index of the current deserializer instance to be processed */
24     size_t current_deser_inst_index;
25 };
26
27 static int deser_process(const OSSL_PARAM params[], void *arg);
28
29 int OSSL_DESERIALIZER_from_bio(OSSL_DESERIALIZER_CTX *ctx, BIO *in)
30 {
31     struct deser_process_data_st data;
32     int ok = 0;
33
34     memset(&data, 0, sizeof(data));
35     data.ctx = ctx;
36     data.bio = in;
37
38     ok = deser_process(NULL, &data);
39
40     /* Clear any cached passphrase */
41     OPENSSL_clear_free(ctx->cached_passphrase, ctx->cached_passphrase_len);
42     ctx->cached_passphrase = NULL;
43     ctx->cached_passphrase_len = 0;
44     return ok;
45 }
46
47 #ifndef OPENSSL_NO_STDIO
48 static BIO *bio_from_file(FILE *fp)
49 {
50     BIO *b;
51
52     if ((b = BIO_new(BIO_s_file())) == NULL) {
53         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_BIO_LIB);
54         return NULL;
55     }
56     BIO_set_fp(b, fp, BIO_NOCLOSE);
57     return b;
58 }
59
60 int OSSL_DESERIALIZER_from_fp(OSSL_DESERIALIZER_CTX *ctx, FILE *fp)
61 {
62     BIO *b = bio_from_file(fp);
63     int ret = 0;
64
65     if (b != NULL)
66         ret = OSSL_DESERIALIZER_from_bio(ctx, b);
67
68     BIO_free(b);
69     return ret;
70 }
71 #endif
72
73 int OSSL_DESERIALIZER_CTX_set_input_type(OSSL_DESERIALIZER_CTX *ctx,
74                                          const char *input_type)
75 {
76     if (!ossl_assert(ctx != NULL)) {
77         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
78         return 0;
79     }
80
81     /*
82      * NULL is a valid starting input type, and means that the caller leaves
83      * it to code to discover what the starting input type is.
84      */
85     ctx->start_input_type = input_type;
86     return 1;
87 }
88
89 int OSSL_DESERIALIZER_CTX_add_deserializer(OSSL_DESERIALIZER_CTX *ctx,
90                                            OSSL_DESERIALIZER *deser)
91 {
92     OSSL_DESERIALIZER_INSTANCE *deser_inst = NULL;
93     const OSSL_PROVIDER *prov = NULL;
94     OSSL_PARAM params[2];
95     void *provctx = NULL;
96
97     if (!ossl_assert(ctx != NULL) || !ossl_assert(deser != NULL)) {
98         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
99         return 0;
100     }
101
102     if (deser->get_params == NULL) {
103         ERR_raise(ERR_LIB_OSSL_DESERIALIZER,
104                   OSSL_DESERIALIZER_R_MISSING_GET_PARAMS);
105         return 0;
106     }
107
108     if (ctx->deser_insts == NULL
109         && (ctx->deser_insts =
110             sk_OSSL_DESERIALIZER_INSTANCE_new_null()) == NULL) {
111         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE);
112         return 0;
113     }
114     if ((deser_inst = OPENSSL_zalloc(sizeof(*deser_inst))) == NULL) {
115         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_MALLOC_FAILURE);
116         return 0;
117     }
118     if (!OSSL_DESERIALIZER_up_ref(deser)) {
119         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_INTERNAL_ERROR);
120         goto err;
121     }
122     deser_inst->deser = deser;
123
124     prov = OSSL_DESERIALIZER_provider(deser_inst->deser);
125     provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
126
127     /* Cache the input type for this serializer */
128     params[0] =
129         OSSL_PARAM_construct_utf8_ptr(OSSL_DESERIALIZER_PARAM_INPUT_TYPE,
130                                       (char **)&deser_inst->input_type, 0);
131     params[1] = OSSL_PARAM_construct_end();
132
133     if (!deser_inst->deser->get_params(params)
134         || !OSSL_PARAM_modified(&params[0]))
135         goto err;
136
137     if ((deser_inst->deserctx = deser_inst->deser->newctx(provctx))
138         == NULL)
139         goto err;
140
141     if (sk_OSSL_DESERIALIZER_INSTANCE_push(ctx->deser_insts, deser_inst) <= 0)
142         goto err;
143
144     return 1;
145  err:
146     if (deser_inst != NULL) {
147         if (deser_inst->deser != NULL)
148             deser_inst->deser->freectx(deser_inst->deserctx);
149         OSSL_DESERIALIZER_free(deser_inst->deser);
150         OPENSSL_free(deser_inst);
151     }
152     return 0;
153 }
154
155 int OSSL_DESERIALIZER_CTX_add_extra(OSSL_DESERIALIZER_CTX *ctx,
156                                     OPENSSL_CTX *libctx, const char *propq)
157 {
158     /*
159      * This function goes through existing deserializer methods in
160      * |ctx->deser_insts|, and tries to fetch new deserializers that produce
161      * what the existing ones want as input, and push those newly fetched
162      * deserializers on top of the same stack.
163      * Then it does the same again, but looping over the newly fetched
164      * deserializers, until there are no more serializers to be fetched, or
165      * when we have done this 10 times.
166      *
167      * we do this with sliding windows on the stack by keeping track of indexes
168      * and of the end.
169      *
170      * +----------------+
171      * |   DER to RSA   | <--- w_prev_start
172      * +----------------+
173      * |   DER to DSA   |
174      * +----------------+
175      * |   DER to DH    |
176      * +----------------+
177      * |   PEM to DER   | <--- w_prev_end, w_new_start
178      * +----------------+
179      *                    <--- w_new_end
180      */
181     size_t w_prev_start, w_prev_end; /* "previous" deserializers */
182     size_t w_new_start, w_new_end;   /* "new" deserializers */
183     size_t count = 0; /* Calculates how many were added in each iteration */
184     size_t depth = 0; /* Counts the number of iterations */
185
186     if (!ossl_assert(ctx != NULL)) {
187         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
188         return 0;
189     }
190
191     /*
192      * If there is no stack of OSSL_DESERIALIZER_INSTANCE, we have nothing
193      * more to add.  That's fine.
194      */
195     if (ctx->deser_insts == NULL)
196         return 1;
197
198     w_prev_start = 0;
199     w_prev_end = sk_OSSL_DESERIALIZER_INSTANCE_num(ctx->deser_insts);
200     do {
201         size_t i;
202
203         w_new_start = w_new_end = w_prev_end;
204
205         for (i = w_prev_start; i < w_prev_end; i++) {
206             OSSL_DESERIALIZER_INSTANCE *deser_inst =
207                 sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts, i);
208             const char *name = deser_inst->input_type;
209             OSSL_DESERIALIZER *deser = NULL;
210
211             /*
212              * If the caller has specified what the initial input should be,
213              * and the deserializer implementation we're looking at has that
214              * input type, there's no point adding on more implementations
215              * on top of this one, so we don't.
216              */
217             if (ctx->start_input_type != NULL
218                 && strcasecmp(ctx->start_input_type,
219                               deser_inst->input_type) != 0)
220                 continue;
221
222             ERR_set_mark();
223             deser = OSSL_DESERIALIZER_fetch(libctx, name, propq);
224             ERR_pop_to_mark();
225
226             if (deser != NULL) {
227                 size_t j;
228
229                 /*
230                  * Check that we don't already have this deserializer in our
231                  * stack We only need to check among the newly added ones.
232                  */
233                 for (j = w_new_start; j < w_new_end; j++) {
234                     OSSL_DESERIALIZER_INSTANCE *check_inst =
235                         sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts, j);
236
237                     if (deser == check_inst->deser) {
238                         /* We found it, so drop the new fetch */
239                         OSSL_DESERIALIZER_free(deser);
240                         deser = NULL;
241                         break;
242                     }
243                 }
244             }
245
246             if (deser == NULL)
247                 continue;
248
249             /*
250              * Apart from keeping w_new_end up to date, We don't care about
251              * errors here.  If it doesn't collect, then it doesn't...
252              */
253             if (OSSL_DESERIALIZER_CTX_add_deserializer(ctx, deser)) /* ref++ */
254                 w_new_end++;
255             OSSL_DESERIALIZER_free(deser); /* ref-- */
256         }
257         /* How many were added in this iteration */
258         count = w_new_end - w_new_start;
259
260         /* Slide the "previous deserializer" windows */
261         w_prev_start = w_new_start;
262         w_prev_end = w_new_end;
263
264         depth++;
265     } while (count != 0 && depth <= 10);
266
267     return 1;
268 }
269
270 int OSSL_DESERIALIZER_CTX_num_deserializers(OSSL_DESERIALIZER_CTX *ctx)
271 {
272     if (ctx == NULL || ctx->deser_insts == NULL)
273         return 0;
274     return sk_OSSL_DESERIALIZER_INSTANCE_num(ctx->deser_insts);
275 }
276
277 int OSSL_DESERIALIZER_CTX_set_finalizer(OSSL_DESERIALIZER_CTX *ctx,
278                                         OSSL_DESERIALIZER_FINALIZER *finalizer,
279                                         OSSL_DESERIALIZER_CLEANER *cleaner,
280                                         void *finalize_arg)
281 {
282     if (!ossl_assert(ctx != NULL)) {
283         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
284         return 0;
285     }
286     ctx->finalizer = finalizer;
287     ctx->cleaner = cleaner;
288     ctx->finalize_arg = finalize_arg;
289     return 1;
290 }
291
292 int OSSL_DESERIALIZER_export(OSSL_DESERIALIZER_INSTANCE *deser_inst,
293                              void *reference, size_t reference_sz,
294                              OSSL_CALLBACK *export_cb, void *export_cbarg)
295 {
296     if (!(ossl_assert(deser_inst != NULL)
297           && ossl_assert(reference != NULL)
298           && ossl_assert(export_cb != NULL)
299           && ossl_assert(export_cbarg != NULL))) {
300         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
301         return 0;
302     }
303
304     return deser_inst->deser->export_object(deser_inst->deserctx,
305                                             reference, reference_sz,
306                                             export_cb, export_cbarg);
307 }
308
309 OSSL_DESERIALIZER *OSSL_DESERIALIZER_INSTANCE_deserializer
310     (OSSL_DESERIALIZER_INSTANCE *deser_inst)
311 {
312     if (deser_inst == NULL)
313         return NULL;
314     return deser_inst->deser;
315 }
316
317 void *OSSL_DESERIALIZER_INSTANCE_deserializer_ctx
318     (OSSL_DESERIALIZER_INSTANCE *deser_inst)
319 {
320     if (deser_inst == NULL)
321         return NULL;
322     return deser_inst->deserctx;
323 }
324
325 static int deser_process(const OSSL_PARAM params[], void *arg)
326 {
327     struct deser_process_data_st *data = arg;
328     OSSL_DESERIALIZER_CTX *ctx = data->ctx;
329     OSSL_DESERIALIZER_INSTANCE *deser_inst = NULL;
330     OSSL_DESERIALIZER *deser = NULL;
331     BIO *bio = data->bio;
332     long loc;
333     size_t i;
334     int ok = 0;
335     /* For recursions */
336     struct deser_process_data_st new_data;
337
338     memset(&new_data, 0, sizeof(new_data));
339     new_data.ctx = data->ctx;
340
341     if (params == NULL) {
342         /* First iteration, where we prepare for what is to come */
343
344         data->current_deser_inst_index =
345             OSSL_DESERIALIZER_CTX_num_deserializers(ctx);
346
347         bio = data->bio;
348     } else {
349         const OSSL_PARAM *p;
350
351         deser_inst =
352             sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts,
353                                                 data->current_deser_inst_index);
354         deser = OSSL_DESERIALIZER_INSTANCE_deserializer(deser_inst);
355
356         if (ctx->finalizer(deser_inst, params, ctx->finalize_arg)) {
357             ok = 1;
358             goto end;
359         }
360
361         /* The finalizer didn't return success */
362
363         /*
364          * so we try to use the object we got and feed it to any next
365          * deserializer that will take it.  Object references are not
366          * allowed for this.
367          * If this data isn't present, deserialization has failed.
368          */
369
370         p = OSSL_PARAM_locate_const(params, OSSL_DESERIALIZER_PARAM_DATA);
371         if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING)
372             goto end;
373         new_data.bio = BIO_new_mem_buf(p->data, (int)p->data_size);
374         if (new_data.bio == NULL)
375             goto end;
376         bio = new_data.bio;
377     }
378
379     /*
380      * If we have no more deserializers to look through at this point,
381      * we failed
382      */
383     if (data->current_deser_inst_index == 0)
384         goto end;
385
386     if ((loc = BIO_tell(bio)) < 0) {
387         ERR_raise(ERR_LIB_OSSL_DESERIALIZER, ERR_R_BIO_LIB);
388         goto end;
389     }
390
391     for (i = data->current_deser_inst_index; i-- > 0;) {
392         OSSL_DESERIALIZER_INSTANCE *new_deser_inst =
393             sk_OSSL_DESERIALIZER_INSTANCE_value(ctx->deser_insts, i);
394         OSSL_DESERIALIZER *new_deser =
395             OSSL_DESERIALIZER_INSTANCE_deserializer(new_deser_inst);
396
397         /*
398          * If |deser| is NULL, it means we've just started, and the caller
399          * may have specified what it expects the initial input to be.  If
400          * that's the case, we do this extra check.
401          */
402         if (deser == NULL && ctx->start_input_type != NULL
403             && strcasecmp(ctx->start_input_type, deser_inst->input_type) != 0)
404             continue;
405
406         /*
407          * If we have a previous deserializer, we check that the input type
408          * of the next to be used matches the type of this previous one.
409          * deser_inst->input_type is a cache of the parameter "input-type"
410          * value for that deserializer.
411          */
412         if (deser != NULL
413             && !OSSL_DESERIALIZER_is_a(deser, new_deser_inst->input_type))
414             continue;
415
416         if (loc == 0) {
417             if (BIO_reset(bio) <= 0)
418                 goto end;
419         } else {
420             if (BIO_seek(bio, loc) <= 0)
421                 goto end;
422         }
423
424         /* Recurse */
425         new_data.current_deser_inst_index = i;
426         ok = new_deser->deserialize(new_deser_inst->deserctx,
427                                     (OSSL_CORE_BIO *)bio,
428                                     deser_process, &new_data,
429                                     NULL /* ossl_deserializer_passphrase_in_cb */,
430                                     new_data.ctx);
431         if (ok)
432             break;
433     }
434
435  end:
436     BIO_free(new_data.bio);
437     return ok;
438 }