1 /* 2 * Copyright 2008-2023 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 <openssl/asn1.h> 11 #include <openssl/asn1t.h> 12 #include <openssl/bio.h> 13 #include <openssl/err.h> 14 15 #include <stdio.h> 16 17 /* Experimental NDEF ASN1 BIO support routines */ 18 19 /* 20 * The usage is quite simple, initialize an ASN1 structure, get a BIO from it 21 * then any data written through the BIO will end up translated to 22 * appropriate format on the fly. The data is streamed out and does *not* 23 * need to be all held in memory at once. When the BIO is flushed the output 24 * is finalized and any signatures etc written out. The BIO is a 'proper' 25 * BIO and can handle non blocking I/O correctly. The usage is simple. The 26 * implementation is *not*... 27 */ 28 29 /* BIO support data stored in the ASN1 BIO ex_arg */ 30 31 typedef struct ndef_aux_st { 32 /* ASN1 structure this BIO refers to */ 33 ASN1_VALUE *val; 34 const ASN1_ITEM *it; 35 /* Top of the BIO chain */ 36 BIO *ndef_bio; 37 /* Output BIO */ 38 BIO *out; 39 /* Boundary where content is inserted */ 40 unsigned char **boundary; 41 /* DER buffer start */ 42 unsigned char *derbuf; 43 } NDEF_SUPPORT; 44 45 static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 46 static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 47 void *parg); 48 static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 49 static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 50 void *parg); 51 52 /* 53 * On success, the returned BIO owns the input BIO as part of its BIO chain. 54 * On failure, NULL is returned and the input BIO is owned by the caller. 55 * 56 * Unfortunately cannot constify this due to CMS_stream() and PKCS7_stream() 57 */ 58 BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) 59 { 60 NDEF_SUPPORT *ndef_aux = NULL; 61 BIO *asn_bio = NULL; 62 const ASN1_AUX *aux = it->funcs; 63 ASN1_STREAM_ARG sarg; 64 BIO *pop_bio = NULL; 65 66 if (!aux || !aux->asn1_cb) { 67 ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); 68 return NULL; 69 } 70 ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux)); 71 asn_bio = BIO_new(BIO_f_asn1()); 72 if (ndef_aux == NULL || asn_bio == NULL) 73 goto err; 74 75 /* ASN1 bio needs to be next to output BIO */ 76 out = BIO_push(asn_bio, out); 77 if (out == NULL) 78 goto err; 79 pop_bio = asn_bio; 80 81 if (BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free) <= 0 82 || BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free) <= 0 83 || BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux) <= 0) 84 goto err; 85 86 /* 87 * Now let the callback prepend any digest, cipher, etc., that the BIO's 88 * ASN1 structure needs. 89 */ 90 91 sarg.out = out; 92 sarg.ndef_bio = NULL; 93 sarg.boundary = NULL; 94 95 /* 96 * The asn1_cb(), must not have mutated asn_bio on error, leaving it in the 97 * middle of some partially built, but not returned BIO chain. 98 */ 99 if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) { 100 /* 101 * ndef_aux is now owned by asn_bio so we must not free it in the err 102 * clean up block 103 */ 104 ndef_aux = NULL; 105 goto err; 106 } 107 108 /* 109 * We must not fail now because the callback has prepended additional 110 * BIOs to the chain 111 */ 112 113 ndef_aux->val = val; 114 ndef_aux->it = it; 115 ndef_aux->ndef_bio = sarg.ndef_bio; 116 ndef_aux->boundary = sarg.boundary; 117 ndef_aux->out = out; 118 119 return sarg.ndef_bio; 120 121 err: 122 /* BIO_pop() is NULL safe */ 123 (void)BIO_pop(pop_bio); 124 BIO_free(asn_bio); 125 OPENSSL_free(ndef_aux); 126 return NULL; 127 } 128 129 static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 130 { 131 NDEF_SUPPORT *ndef_aux; 132 unsigned char *p; 133 int derlen; 134 135 if (!parg) 136 return 0; 137 138 ndef_aux = *(NDEF_SUPPORT **)parg; 139 140 derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 141 if (derlen < 0) 142 return 0; 143 if ((p = OPENSSL_malloc(derlen)) == NULL) { 144 ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE); 145 return 0; 146 } 147 148 ndef_aux->derbuf = p; 149 *pbuf = p; 150 derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 151 152 if (!*ndef_aux->boundary) 153 return 0; 154 155 *plen = *ndef_aux->boundary - *pbuf; 156 157 return 1; 158 } 159 160 static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 161 void *parg) 162 { 163 NDEF_SUPPORT *ndef_aux; 164 165 if (!parg) 166 return 0; 167 168 ndef_aux = *(NDEF_SUPPORT **)parg; 169 170 if (ndef_aux == NULL) 171 return 0; 172 173 OPENSSL_free(ndef_aux->derbuf); 174 175 ndef_aux->derbuf = NULL; 176 *pbuf = NULL; 177 *plen = 0; 178 return 1; 179 } 180 181 static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 182 void *parg) 183 { 184 NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg; 185 if (!ndef_prefix_free(b, pbuf, plen, parg)) 186 return 0; 187 OPENSSL_free(*pndef_aux); 188 *pndef_aux = NULL; 189 return 1; 190 } 191 192 static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 193 { 194 NDEF_SUPPORT *ndef_aux; 195 unsigned char *p; 196 int derlen; 197 const ASN1_AUX *aux; 198 ASN1_STREAM_ARG sarg; 199 200 if (!parg) 201 return 0; 202 203 ndef_aux = *(NDEF_SUPPORT **)parg; 204 205 aux = ndef_aux->it->funcs; 206 207 /* Finalize structures */ 208 sarg.ndef_bio = ndef_aux->ndef_bio; 209 sarg.out = ndef_aux->out; 210 sarg.boundary = ndef_aux->boundary; 211 if (aux->asn1_cb(ASN1_OP_STREAM_POST, 212 &ndef_aux->val, ndef_aux->it, &sarg) <= 0) 213 return 0; 214 215 derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 216 if ((p = OPENSSL_malloc(derlen)) == NULL) { 217 ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE); 218 return 0; 219 } 220 221 ndef_aux->derbuf = p; 222 *pbuf = p; 223 derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 224 225 if (!*ndef_aux->boundary) 226 return 0; 227 *pbuf = *ndef_aux->boundary; 228 *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf); 229 230 return 1; 231 } 232