xref: /freebsd-src/crypto/openssl/providers/implementations/storemgmt/file_store_any2obj.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery /*
11*b077aed3SPierre Pronchery  * This is a decoder that's completely internal to the 'file:' store
12*b077aed3SPierre Pronchery  * implementation.  Only code in file_store.c know about this one.  Because
13*b077aed3SPierre Pronchery  * of this close relationship, we can cut certain corners, such as making
14*b077aed3SPierre Pronchery  * assumptions about the "provider context", which is currently simply the
15*b077aed3SPierre Pronchery  * provider context that the file_store.c code operates within.
16*b077aed3SPierre Pronchery  *
17*b077aed3SPierre Pronchery  * All this does is to read known binary encodings (currently: DER, MSBLOB,
18*b077aed3SPierre Pronchery  * PVK) from the input if it can, and passes it on to the data callback as
19*b077aed3SPierre Pronchery  * an object abstraction, leaving it to the callback to figure out what it
20*b077aed3SPierre Pronchery  * actually is.
21*b077aed3SPierre Pronchery  *
22*b077aed3SPierre Pronchery  * This MUST be made the last decoder in a chain, leaving it to other more
23*b077aed3SPierre Pronchery  * specialized decoders to recognise and process their stuff first.
24*b077aed3SPierre Pronchery  */
25*b077aed3SPierre Pronchery 
26*b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
27*b077aed3SPierre Pronchery #include <openssl/core_names.h>
28*b077aed3SPierre Pronchery #include <openssl/core_object.h>
29*b077aed3SPierre Pronchery #include <openssl/bio.h>
30*b077aed3SPierre Pronchery #include <openssl/buffer.h>
31*b077aed3SPierre Pronchery #include <openssl/err.h>
32*b077aed3SPierre Pronchery #include <openssl/asn1err.h>
33*b077aed3SPierre Pronchery #include <openssl/params.h>
34*b077aed3SPierre Pronchery #include "internal/asn1.h"
35*b077aed3SPierre Pronchery #include "crypto/pem.h"          /* For internal PVK and "blob" headers */
36*b077aed3SPierre Pronchery #include "prov/bio.h"
37*b077aed3SPierre Pronchery #include "file_store_local.h"
38*b077aed3SPierre Pronchery 
39*b077aed3SPierre Pronchery /*
40*b077aed3SPierre Pronchery  * newctx and freectx are not strictly necessary.  However, the method creator,
41*b077aed3SPierre Pronchery  * ossl_decoder_from_algorithm(), demands that they exist, so we make sure to
42*b077aed3SPierre Pronchery  * oblige.
43*b077aed3SPierre Pronchery  */
44*b077aed3SPierre Pronchery 
45*b077aed3SPierre Pronchery static OSSL_FUNC_decoder_newctx_fn any2obj_newctx;
46*b077aed3SPierre Pronchery static OSSL_FUNC_decoder_freectx_fn any2obj_freectx;
47*b077aed3SPierre Pronchery 
any2obj_newctx(void * provctx)48*b077aed3SPierre Pronchery static void *any2obj_newctx(void *provctx)
49*b077aed3SPierre Pronchery {
50*b077aed3SPierre Pronchery     return provctx;
51*b077aed3SPierre Pronchery }
52*b077aed3SPierre Pronchery 
any2obj_freectx(void * vctx)53*b077aed3SPierre Pronchery static void any2obj_freectx(void *vctx)
54*b077aed3SPierre Pronchery {
55*b077aed3SPierre Pronchery }
56*b077aed3SPierre Pronchery 
any2obj_decode_final(void * provctx,int objtype,BUF_MEM * mem,OSSL_CALLBACK * data_cb,void * data_cbarg)57*b077aed3SPierre Pronchery static int any2obj_decode_final(void *provctx, int objtype, BUF_MEM *mem,
58*b077aed3SPierre Pronchery                                 OSSL_CALLBACK *data_cb, void *data_cbarg)
59*b077aed3SPierre Pronchery {
60*b077aed3SPierre Pronchery     /*
61*b077aed3SPierre Pronchery      * 1 indicates that we successfully decoded something, or not at all.
62*b077aed3SPierre Pronchery      * Ending up "empty handed" is not an error.
63*b077aed3SPierre Pronchery      */
64*b077aed3SPierre Pronchery     int ok = 1;
65*b077aed3SPierre Pronchery 
66*b077aed3SPierre Pronchery     if (mem != NULL) {
67*b077aed3SPierre Pronchery         OSSL_PARAM params[3];
68*b077aed3SPierre Pronchery 
69*b077aed3SPierre Pronchery         params[0] =
70*b077aed3SPierre Pronchery             OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
71*b077aed3SPierre Pronchery         params[1] =
72*b077aed3SPierre Pronchery             OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
73*b077aed3SPierre Pronchery                                               mem->data, mem->length);
74*b077aed3SPierre Pronchery         params[2] = OSSL_PARAM_construct_end();
75*b077aed3SPierre Pronchery 
76*b077aed3SPierre Pronchery         ok = data_cb(params, data_cbarg);
77*b077aed3SPierre Pronchery         BUF_MEM_free(mem);
78*b077aed3SPierre Pronchery     }
79*b077aed3SPierre Pronchery     return ok;
80*b077aed3SPierre Pronchery }
81*b077aed3SPierre Pronchery 
82*b077aed3SPierre Pronchery static OSSL_FUNC_decoder_decode_fn der2obj_decode;
der2obj_decode(void * provctx,OSSL_CORE_BIO * cin,int selection,OSSL_CALLBACK * data_cb,void * data_cbarg,OSSL_PASSPHRASE_CALLBACK * pw_cb,void * pw_cbarg)83*b077aed3SPierre Pronchery static int der2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
84*b077aed3SPierre Pronchery                           OSSL_CALLBACK *data_cb, void *data_cbarg,
85*b077aed3SPierre Pronchery                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
86*b077aed3SPierre Pronchery {
87*b077aed3SPierre Pronchery     BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
88*b077aed3SPierre Pronchery     BUF_MEM *mem = NULL;
89*b077aed3SPierre Pronchery     int ok;
90*b077aed3SPierre Pronchery 
91*b077aed3SPierre Pronchery     if (in == NULL)
92*b077aed3SPierre Pronchery         return 0;
93*b077aed3SPierre Pronchery 
94*b077aed3SPierre Pronchery     ERR_set_mark();
95*b077aed3SPierre Pronchery     ok = (asn1_d2i_read_bio(in, &mem) >= 0);
96*b077aed3SPierre Pronchery     ERR_pop_to_mark();
97*b077aed3SPierre Pronchery     if (!ok && mem != NULL) {
98*b077aed3SPierre Pronchery         BUF_MEM_free(mem);
99*b077aed3SPierre Pronchery         mem = NULL;
100*b077aed3SPierre Pronchery     }
101*b077aed3SPierre Pronchery     BIO_free(in);
102*b077aed3SPierre Pronchery 
103*b077aed3SPierre Pronchery     /* any2obj_decode_final() frees |mem| for us */
104*b077aed3SPierre Pronchery     return any2obj_decode_final(provctx, OSSL_OBJECT_UNKNOWN, mem,
105*b077aed3SPierre Pronchery                                 data_cb, data_cbarg);
106*b077aed3SPierre Pronchery }
107*b077aed3SPierre Pronchery 
108*b077aed3SPierre Pronchery static OSSL_FUNC_decoder_decode_fn msblob2obj_decode;
msblob2obj_decode(void * provctx,OSSL_CORE_BIO * cin,int selection,OSSL_CALLBACK * data_cb,void * data_cbarg,OSSL_PASSPHRASE_CALLBACK * pw_cb,void * pw_cbarg)109*b077aed3SPierre Pronchery static int msblob2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
110*b077aed3SPierre Pronchery                              OSSL_CALLBACK *data_cb, void *data_cbarg,
111*b077aed3SPierre Pronchery                              OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
112*b077aed3SPierre Pronchery {
113*b077aed3SPierre Pronchery     BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
114*b077aed3SPierre Pronchery     BUF_MEM *mem = NULL;
115*b077aed3SPierre Pronchery     size_t mem_len = 0, mem_want;
116*b077aed3SPierre Pronchery     const unsigned char *p;
117*b077aed3SPierre Pronchery     unsigned int bitlen, magic;
118*b077aed3SPierre Pronchery     int isdss = -1;
119*b077aed3SPierre Pronchery     int ispub = -1;
120*b077aed3SPierre Pronchery     int ok = 0;
121*b077aed3SPierre Pronchery 
122*b077aed3SPierre Pronchery     if (in == NULL)
123*b077aed3SPierre Pronchery         goto err;
124*b077aed3SPierre Pronchery 
125*b077aed3SPierre Pronchery     mem_want = 16;               /* The size of the MSBLOB header */
126*b077aed3SPierre Pronchery     if ((mem = BUF_MEM_new()) == NULL
127*b077aed3SPierre Pronchery         || !BUF_MEM_grow(mem, mem_want)) {
128*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
129*b077aed3SPierre Pronchery         goto err;
130*b077aed3SPierre Pronchery     }
131*b077aed3SPierre Pronchery 
132*b077aed3SPierre Pronchery     ERR_set_mark();
133*b077aed3SPierre Pronchery     ok = BIO_read(in, &mem->data[0], mem_want) == (int)mem_want;
134*b077aed3SPierre Pronchery     mem_len += mem_want;
135*b077aed3SPierre Pronchery     ERR_pop_to_mark();
136*b077aed3SPierre Pronchery     if (!ok)
137*b077aed3SPierre Pronchery         goto next;
138*b077aed3SPierre Pronchery 
139*b077aed3SPierre Pronchery 
140*b077aed3SPierre Pronchery     ERR_set_mark();
141*b077aed3SPierre Pronchery     p = (unsigned char *)&mem->data[0];
142*b077aed3SPierre Pronchery     ok = ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) > 0;
143*b077aed3SPierre Pronchery     ERR_pop_to_mark();
144*b077aed3SPierre Pronchery     if (!ok)
145*b077aed3SPierre Pronchery         goto next;
146*b077aed3SPierre Pronchery 
147*b077aed3SPierre Pronchery     ok = 0;
148*b077aed3SPierre Pronchery     mem_want = ossl_blob_length(bitlen, isdss, ispub);
149*b077aed3SPierre Pronchery     if (!BUF_MEM_grow(mem, mem_len + mem_want)) {
150*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
151*b077aed3SPierre Pronchery         goto err;
152*b077aed3SPierre Pronchery     }
153*b077aed3SPierre Pronchery 
154*b077aed3SPierre Pronchery     ERR_set_mark();
155*b077aed3SPierre Pronchery     ok = BIO_read(in, &mem->data[mem_len], mem_want) == (int)mem_want;
156*b077aed3SPierre Pronchery     mem_len += mem_want;
157*b077aed3SPierre Pronchery     ERR_pop_to_mark();
158*b077aed3SPierre Pronchery 
159*b077aed3SPierre Pronchery  next:
160*b077aed3SPierre Pronchery     /* Free resources we no longer need. */
161*b077aed3SPierre Pronchery     BIO_free(in);
162*b077aed3SPierre Pronchery     if (!ok && mem != NULL) {
163*b077aed3SPierre Pronchery         BUF_MEM_free(mem);
164*b077aed3SPierre Pronchery         mem = NULL;
165*b077aed3SPierre Pronchery     }
166*b077aed3SPierre Pronchery 
167*b077aed3SPierre Pronchery     /* any2obj_decode_final() frees |mem| for us */
168*b077aed3SPierre Pronchery     return any2obj_decode_final(provctx, OSSL_OBJECT_PKEY, mem,
169*b077aed3SPierre Pronchery                                 data_cb, data_cbarg);
170*b077aed3SPierre Pronchery 
171*b077aed3SPierre Pronchery  err:
172*b077aed3SPierre Pronchery     BIO_free(in);
173*b077aed3SPierre Pronchery     BUF_MEM_free(mem);
174*b077aed3SPierre Pronchery     return 0;
175*b077aed3SPierre Pronchery }
176*b077aed3SPierre Pronchery 
177*b077aed3SPierre Pronchery static OSSL_FUNC_decoder_decode_fn pvk2obj_decode;
pvk2obj_decode(void * provctx,OSSL_CORE_BIO * cin,int selection,OSSL_CALLBACK * data_cb,void * data_cbarg,OSSL_PASSPHRASE_CALLBACK * pw_cb,void * pw_cbarg)178*b077aed3SPierre Pronchery static int pvk2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection,
179*b077aed3SPierre Pronchery                              OSSL_CALLBACK *data_cb, void *data_cbarg,
180*b077aed3SPierre Pronchery                              OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
181*b077aed3SPierre Pronchery {
182*b077aed3SPierre Pronchery     BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
183*b077aed3SPierre Pronchery     BUF_MEM *mem = NULL;
184*b077aed3SPierre Pronchery     size_t mem_len = 0, mem_want;
185*b077aed3SPierre Pronchery     const unsigned char *p;
186*b077aed3SPierre Pronchery     unsigned int saltlen, keylen;
187*b077aed3SPierre Pronchery     int ok = 0;
188*b077aed3SPierre Pronchery 
189*b077aed3SPierre Pronchery     if (in == NULL)
190*b077aed3SPierre Pronchery         goto err;
191*b077aed3SPierre Pronchery 
192*b077aed3SPierre Pronchery     mem_want = 24;               /* The size of the PVK header */
193*b077aed3SPierre Pronchery     if ((mem = BUF_MEM_new()) == NULL
194*b077aed3SPierre Pronchery         || !BUF_MEM_grow(mem, mem_want)) {
195*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
196*b077aed3SPierre Pronchery         goto err;
197*b077aed3SPierre Pronchery     }
198*b077aed3SPierre Pronchery 
199*b077aed3SPierre Pronchery     ERR_set_mark();
200*b077aed3SPierre Pronchery     ok = BIO_read(in, &mem->data[0], mem_want) == (int)mem_want;
201*b077aed3SPierre Pronchery     mem_len += mem_want;
202*b077aed3SPierre Pronchery     ERR_pop_to_mark();
203*b077aed3SPierre Pronchery     if (!ok)
204*b077aed3SPierre Pronchery         goto next;
205*b077aed3SPierre Pronchery 
206*b077aed3SPierre Pronchery 
207*b077aed3SPierre Pronchery     ERR_set_mark();
208*b077aed3SPierre Pronchery     p = (unsigned char *)&mem->data[0];
209*b077aed3SPierre Pronchery     ok = ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen) > 0;
210*b077aed3SPierre Pronchery     ERR_pop_to_mark();
211*b077aed3SPierre Pronchery     if (!ok)
212*b077aed3SPierre Pronchery         goto next;
213*b077aed3SPierre Pronchery 
214*b077aed3SPierre Pronchery     ok = 0;
215*b077aed3SPierre Pronchery     mem_want = saltlen + keylen;
216*b077aed3SPierre Pronchery     if (!BUF_MEM_grow(mem, mem_len + mem_want)) {
217*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE);
218*b077aed3SPierre Pronchery         goto err;
219*b077aed3SPierre Pronchery     }
220*b077aed3SPierre Pronchery 
221*b077aed3SPierre Pronchery     ERR_set_mark();
222*b077aed3SPierre Pronchery     ok = BIO_read(in, &mem->data[mem_len], mem_want) == (int)mem_want;
223*b077aed3SPierre Pronchery     mem_len += mem_want;
224*b077aed3SPierre Pronchery     ERR_pop_to_mark();
225*b077aed3SPierre Pronchery 
226*b077aed3SPierre Pronchery  next:
227*b077aed3SPierre Pronchery     /* Free resources we no longer need. */
228*b077aed3SPierre Pronchery     BIO_free(in);
229*b077aed3SPierre Pronchery     if (!ok && mem != NULL) {
230*b077aed3SPierre Pronchery         BUF_MEM_free(mem);
231*b077aed3SPierre Pronchery         mem = NULL;
232*b077aed3SPierre Pronchery     }
233*b077aed3SPierre Pronchery 
234*b077aed3SPierre Pronchery     /* any2obj_decode_final() frees |mem| for us */
235*b077aed3SPierre Pronchery     return any2obj_decode_final(provctx, OSSL_OBJECT_PKEY, mem,
236*b077aed3SPierre Pronchery                                 data_cb, data_cbarg);
237*b077aed3SPierre Pronchery 
238*b077aed3SPierre Pronchery  err:
239*b077aed3SPierre Pronchery     BIO_free(in);
240*b077aed3SPierre Pronchery     BUF_MEM_free(mem);
241*b077aed3SPierre Pronchery     return 0;
242*b077aed3SPierre Pronchery }
243*b077aed3SPierre Pronchery 
244*b077aed3SPierre Pronchery #define MAKE_DECODER(fromtype, objtype)                                      \
245*b077aed3SPierre Pronchery     static const OSSL_DISPATCH fromtype##_to_obj_decoder_functions[] = {     \
246*b077aed3SPierre Pronchery         { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))any2obj_newctx },        \
247*b077aed3SPierre Pronchery         { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))any2obj_freectx },      \
248*b077aed3SPierre Pronchery         { OSSL_FUNC_DECODER_DECODE, (void (*)(void))fromtype##2obj_decode }, \
249*b077aed3SPierre Pronchery         { 0, NULL }                                                          \
250*b077aed3SPierre Pronchery     }
251*b077aed3SPierre Pronchery 
252*b077aed3SPierre Pronchery MAKE_DECODER(der, OSSL_OBJECT_UNKNOWN);
253*b077aed3SPierre Pronchery MAKE_DECODER(msblob, OSSL_OBJECT_PKEY);
254*b077aed3SPierre Pronchery MAKE_DECODER(pvk, OSSL_OBJECT_PKEY);
255*b077aed3SPierre Pronchery 
256*b077aed3SPierre Pronchery const OSSL_ALGORITHM ossl_any_to_obj_algorithm[] = {
257*b077aed3SPierre Pronchery     { "obj", "input=DER", der_to_obj_decoder_functions },
258*b077aed3SPierre Pronchery     { "obj", "input=MSBLOB", msblob_to_obj_decoder_functions },
259*b077aed3SPierre Pronchery     { "obj", "input=PVK", pvk_to_obj_decoder_functions },
260*b077aed3SPierre Pronchery     { NULL, }
261*b077aed3SPierre Pronchery };
262