160662d10Schristos /*
2*1dcdf01fSchristos  * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
360662d10Schristos  *
4*1dcdf01fSchristos  * Licensed under the OpenSSL license (the "License").  You may not use
5*1dcdf01fSchristos  * this file except in compliance with the License.  You can obtain a copy
6*1dcdf01fSchristos  * in the file LICENSE in the source distribution or at
7*1dcdf01fSchristos  * https://www.openssl.org/source/license.html
860662d10Schristos  */
960662d10Schristos 
1060662d10Schristos #include <openssl/asn1.h>
1160662d10Schristos #include <openssl/asn1t.h>
1260662d10Schristos #include <openssl/bio.h>
1360662d10Schristos #include <openssl/err.h>
1460662d10Schristos 
1560662d10Schristos #include <stdio.h>
1660662d10Schristos 
1760662d10Schristos /* Experimental NDEF ASN1 BIO support routines */
1860662d10Schristos 
1960662d10Schristos /*
2060662d10Schristos  * The usage is quite simple, initialize an ASN1 structure, get a BIO from it
2160662d10Schristos  * then any data written through the BIO will end up translated to
22*1dcdf01fSchristos  * appropriate format on the fly. The data is streamed out and does *not*
2360662d10Schristos  * need to be all held in memory at once. When the BIO is flushed the output
2460662d10Schristos  * is finalized and any signatures etc written out. The BIO is a 'proper'
2560662d10Schristos  * BIO and can handle non blocking I/O correctly. The usage is simple. The
2660662d10Schristos  * implementation is *not*...
2760662d10Schristos  */
2860662d10Schristos 
2960662d10Schristos /* BIO support data stored in the ASN1 BIO ex_arg */
3060662d10Schristos 
3160662d10Schristos typedef struct ndef_aux_st {
3260662d10Schristos     /* ASN1 structure this BIO refers to */
3360662d10Schristos     ASN1_VALUE *val;
3460662d10Schristos     const ASN1_ITEM *it;
3560662d10Schristos     /* Top of the BIO chain */
3660662d10Schristos     BIO *ndef_bio;
3760662d10Schristos     /* Output BIO */
3860662d10Schristos     BIO *out;
3960662d10Schristos     /* Boundary where content is inserted */
4060662d10Schristos     unsigned char **boundary;
4160662d10Schristos     /* DER buffer start */
4260662d10Schristos     unsigned char *derbuf;
4360662d10Schristos } NDEF_SUPPORT;
4460662d10Schristos 
4560662d10Schristos static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
4660662d10Schristos static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
4760662d10Schristos                             void *parg);
4860662d10Schristos static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
4960662d10Schristos static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
5060662d10Schristos                             void *parg);
5160662d10Schristos 
52*1dcdf01fSchristos /*
53*1dcdf01fSchristos  * On success, the returned BIO owns the input BIO as part of its BIO chain.
54*1dcdf01fSchristos  * On failure, NULL is returned and the input BIO is owned by the caller.
55*1dcdf01fSchristos  *
56*1dcdf01fSchristos  * Unfortunately cannot constify this due to CMS_stream() and PKCS7_stream()
57*1dcdf01fSchristos  */
BIO_new_NDEF(BIO * out,ASN1_VALUE * val,const ASN1_ITEM * it)5860662d10Schristos BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
5960662d10Schristos {
6060662d10Schristos     NDEF_SUPPORT *ndef_aux = NULL;
6160662d10Schristos     BIO *asn_bio = NULL;
6260662d10Schristos     const ASN1_AUX *aux = it->funcs;
6360662d10Schristos     ASN1_STREAM_ARG sarg;
64*1dcdf01fSchristos     BIO *pop_bio = NULL;
6560662d10Schristos 
6660662d10Schristos     if (!aux || !aux->asn1_cb) {
6760662d10Schristos         ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
6860662d10Schristos         return NULL;
6960662d10Schristos     }
70*1dcdf01fSchristos     ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux));
7160662d10Schristos     asn_bio = BIO_new(BIO_f_asn1());
72*1dcdf01fSchristos     if (ndef_aux == NULL || asn_bio == NULL)
7360662d10Schristos         goto err;
7460662d10Schristos 
75*1dcdf01fSchristos     /* ASN1 bio needs to be next to output BIO */
76*1dcdf01fSchristos     out = BIO_push(asn_bio, out);
77*1dcdf01fSchristos     if (out == NULL)
78*1dcdf01fSchristos         goto err;
79*1dcdf01fSchristos     pop_bio = asn_bio;
80*1dcdf01fSchristos 
81*1dcdf01fSchristos     if (BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free) <= 0
82*1dcdf01fSchristos             || BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free) <= 0
83*1dcdf01fSchristos             || BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux) <= 0)
84*1dcdf01fSchristos         goto err;
8560662d10Schristos 
8660662d10Schristos     /*
87*1dcdf01fSchristos      * Now let the callback prepend any digest, cipher, etc., that the BIO's
88*1dcdf01fSchristos      * ASN1 structure needs.
8960662d10Schristos      */
9060662d10Schristos 
9160662d10Schristos     sarg.out = out;
9260662d10Schristos     sarg.ndef_bio = NULL;
9360662d10Schristos     sarg.boundary = NULL;
9460662d10Schristos 
95*1dcdf01fSchristos     /*
96*1dcdf01fSchristos      * The asn1_cb(), must not have mutated asn_bio on error, leaving it in the
97*1dcdf01fSchristos      * middle of some partially built, but not returned BIO chain.
98*1dcdf01fSchristos      */
99*1dcdf01fSchristos     if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) {
100*1dcdf01fSchristos         /*
101*1dcdf01fSchristos          * ndef_aux is now owned by asn_bio so we must not free it in the err
102*1dcdf01fSchristos          * clean up block
103*1dcdf01fSchristos          */
104*1dcdf01fSchristos         ndef_aux = NULL;
10560662d10Schristos         goto err;
106*1dcdf01fSchristos     }
107*1dcdf01fSchristos 
108*1dcdf01fSchristos     /*
109*1dcdf01fSchristos      * We must not fail now because the callback has prepended additional
110*1dcdf01fSchristos      * BIOs to the chain
111*1dcdf01fSchristos      */
11260662d10Schristos 
11360662d10Schristos     ndef_aux->val = val;
11460662d10Schristos     ndef_aux->it = it;
11560662d10Schristos     ndef_aux->ndef_bio = sarg.ndef_bio;
11660662d10Schristos     ndef_aux->boundary = sarg.boundary;
11760662d10Schristos     ndef_aux->out = out;
11860662d10Schristos 
11960662d10Schristos     return sarg.ndef_bio;
12060662d10Schristos 
12160662d10Schristos  err:
122*1dcdf01fSchristos     /* BIO_pop() is NULL safe */
123*1dcdf01fSchristos     (void)BIO_pop(pop_bio);
12460662d10Schristos     BIO_free(asn_bio);
12560662d10Schristos     OPENSSL_free(ndef_aux);
12660662d10Schristos     return NULL;
12760662d10Schristos }
12860662d10Schristos 
ndef_prefix(BIO * b,unsigned char ** pbuf,int * plen,void * parg)12960662d10Schristos static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
13060662d10Schristos {
13160662d10Schristos     NDEF_SUPPORT *ndef_aux;
13260662d10Schristos     unsigned char *p;
13360662d10Schristos     int derlen;
13460662d10Schristos 
13560662d10Schristos     if (!parg)
13660662d10Schristos         return 0;
13760662d10Schristos 
13860662d10Schristos     ndef_aux = *(NDEF_SUPPORT **)parg;
13960662d10Schristos 
14060662d10Schristos     derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
141*1dcdf01fSchristos     if (derlen < 0)
14260662d10Schristos         return 0;
143*1dcdf01fSchristos     if ((p = OPENSSL_malloc(derlen)) == NULL) {
144*1dcdf01fSchristos         ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE);
145*1dcdf01fSchristos         return 0;
146*1dcdf01fSchristos     }
14760662d10Schristos 
14860662d10Schristos     ndef_aux->derbuf = p;
14960662d10Schristos     *pbuf = p;
15060662d10Schristos     derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
15160662d10Schristos 
15260662d10Schristos     if (!*ndef_aux->boundary)
15360662d10Schristos         return 0;
15460662d10Schristos 
15560662d10Schristos     *plen = *ndef_aux->boundary - *pbuf;
15660662d10Schristos 
15760662d10Schristos     return 1;
15860662d10Schristos }
15960662d10Schristos 
ndef_prefix_free(BIO * b,unsigned char ** pbuf,int * plen,void * parg)16060662d10Schristos static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
16160662d10Schristos                             void *parg)
16260662d10Schristos {
16360662d10Schristos     NDEF_SUPPORT *ndef_aux;
16460662d10Schristos 
16560662d10Schristos     if (!parg)
16660662d10Schristos         return 0;
16760662d10Schristos 
16860662d10Schristos     ndef_aux = *(NDEF_SUPPORT **)parg;
16960662d10Schristos 
170*1dcdf01fSchristos     if (ndef_aux == NULL)
171*1dcdf01fSchristos         return 0;
172*1dcdf01fSchristos 
17360662d10Schristos     OPENSSL_free(ndef_aux->derbuf);
17460662d10Schristos 
17560662d10Schristos     ndef_aux->derbuf = NULL;
17660662d10Schristos     *pbuf = NULL;
17760662d10Schristos     *plen = 0;
17860662d10Schristos     return 1;
17960662d10Schristos }
18060662d10Schristos 
ndef_suffix_free(BIO * b,unsigned char ** pbuf,int * plen,void * parg)18160662d10Schristos static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
18260662d10Schristos                             void *parg)
18360662d10Schristos {
18460662d10Schristos     NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
18560662d10Schristos     if (!ndef_prefix_free(b, pbuf, plen, parg))
18660662d10Schristos         return 0;
18760662d10Schristos     OPENSSL_free(*pndef_aux);
18860662d10Schristos     *pndef_aux = NULL;
18960662d10Schristos     return 1;
19060662d10Schristos }
19160662d10Schristos 
ndef_suffix(BIO * b,unsigned char ** pbuf,int * plen,void * parg)19260662d10Schristos static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
19360662d10Schristos {
19460662d10Schristos     NDEF_SUPPORT *ndef_aux;
19560662d10Schristos     unsigned char *p;
19660662d10Schristos     int derlen;
19760662d10Schristos     const ASN1_AUX *aux;
19860662d10Schristos     ASN1_STREAM_ARG sarg;
19960662d10Schristos 
20060662d10Schristos     if (!parg)
20160662d10Schristos         return 0;
20260662d10Schristos 
20360662d10Schristos     ndef_aux = *(NDEF_SUPPORT **)parg;
20460662d10Schristos 
20560662d10Schristos     aux = ndef_aux->it->funcs;
20660662d10Schristos 
20760662d10Schristos     /* Finalize structures */
20860662d10Schristos     sarg.ndef_bio = ndef_aux->ndef_bio;
20960662d10Schristos     sarg.out = ndef_aux->out;
21060662d10Schristos     sarg.boundary = ndef_aux->boundary;
21160662d10Schristos     if (aux->asn1_cb(ASN1_OP_STREAM_POST,
21260662d10Schristos                      &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
21360662d10Schristos         return 0;
21460662d10Schristos 
21560662d10Schristos     derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
216*1dcdf01fSchristos     if ((p = OPENSSL_malloc(derlen)) == NULL) {
217*1dcdf01fSchristos         ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE);
21860662d10Schristos         return 0;
219*1dcdf01fSchristos     }
22060662d10Schristos 
22160662d10Schristos     ndef_aux->derbuf = p;
22260662d10Schristos     *pbuf = p;
22360662d10Schristos     derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
22460662d10Schristos 
22560662d10Schristos     if (!*ndef_aux->boundary)
22660662d10Schristos         return 0;
22760662d10Schristos     *pbuf = *ndef_aux->boundary;
22860662d10Schristos     *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
22960662d10Schristos 
23060662d10Schristos     return 1;
23160662d10Schristos }
232