1 /* 2 * Copyright 2008-2018 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 BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) 53 { 54 NDEF_SUPPORT *ndef_aux = NULL; 55 BIO *asn_bio = NULL; 56 const ASN1_AUX *aux = it->funcs; 57 ASN1_STREAM_ARG sarg; 58 59 if (!aux || !aux->asn1_cb) { 60 ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); 61 return NULL; 62 } 63 ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux)); 64 asn_bio = BIO_new(BIO_f_asn1()); 65 if (ndef_aux == NULL || asn_bio == NULL) 66 goto err; 67 68 /* ASN1 bio needs to be next to output BIO */ 69 out = BIO_push(asn_bio, out); 70 if (out == NULL) 71 goto err; 72 73 BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free); 74 BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free); 75 76 /* 77 * Now let callback prepends any digest, cipher etc BIOs ASN1 structure 78 * needs. 79 */ 80 81 sarg.out = out; 82 sarg.ndef_bio = NULL; 83 sarg.boundary = NULL; 84 85 if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) 86 goto err; 87 88 ndef_aux->val = val; 89 ndef_aux->it = it; 90 ndef_aux->ndef_bio = sarg.ndef_bio; 91 ndef_aux->boundary = sarg.boundary; 92 ndef_aux->out = out; 93 94 BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux); 95 96 return sarg.ndef_bio; 97 98 err: 99 BIO_free(asn_bio); 100 OPENSSL_free(ndef_aux); 101 return NULL; 102 } 103 104 static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 105 { 106 NDEF_SUPPORT *ndef_aux; 107 unsigned char *p; 108 int derlen; 109 110 if (!parg) 111 return 0; 112 113 ndef_aux = *(NDEF_SUPPORT **)parg; 114 115 derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 116 if ((p = OPENSSL_malloc(derlen)) == NULL) { 117 ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE); 118 return 0; 119 } 120 121 ndef_aux->derbuf = p; 122 *pbuf = p; 123 derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 124 125 if (!*ndef_aux->boundary) 126 return 0; 127 128 *plen = *ndef_aux->boundary - *pbuf; 129 130 return 1; 131 } 132 133 static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 134 void *parg) 135 { 136 NDEF_SUPPORT *ndef_aux; 137 138 if (!parg) 139 return 0; 140 141 ndef_aux = *(NDEF_SUPPORT **)parg; 142 143 OPENSSL_free(ndef_aux->derbuf); 144 145 ndef_aux->derbuf = NULL; 146 *pbuf = NULL; 147 *plen = 0; 148 return 1; 149 } 150 151 static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 152 void *parg) 153 { 154 NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg; 155 if (!ndef_prefix_free(b, pbuf, plen, parg)) 156 return 0; 157 OPENSSL_free(*pndef_aux); 158 *pndef_aux = NULL; 159 return 1; 160 } 161 162 static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 163 { 164 NDEF_SUPPORT *ndef_aux; 165 unsigned char *p; 166 int derlen; 167 const ASN1_AUX *aux; 168 ASN1_STREAM_ARG sarg; 169 170 if (!parg) 171 return 0; 172 173 ndef_aux = *(NDEF_SUPPORT **)parg; 174 175 aux = ndef_aux->it->funcs; 176 177 /* Finalize structures */ 178 sarg.ndef_bio = ndef_aux->ndef_bio; 179 sarg.out = ndef_aux->out; 180 sarg.boundary = ndef_aux->boundary; 181 if (aux->asn1_cb(ASN1_OP_STREAM_POST, 182 &ndef_aux->val, ndef_aux->it, &sarg) <= 0) 183 return 0; 184 185 derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 186 if ((p = OPENSSL_malloc(derlen)) == NULL) { 187 ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE); 188 return 0; 189 } 190 191 ndef_aux->derbuf = p; 192 *pbuf = p; 193 derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 194 195 if (!*ndef_aux->boundary) 196 return 0; 197 *pbuf = *ndef_aux->boundary; 198 *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf); 199 200 return 1; 201 } 202