1 /*
2 * Copyright 2006-2021 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 /*
11 * Experimental ASN1 BIO. When written through the data is converted to an
12 * ASN1 string type: default is OCTET STRING. Additional functions can be
13 * provided to add prefix and suffix data.
14 */
15
16 #include <string.h>
17 #include "internal/bio.h"
18 #include <openssl/asn1.h>
19 #include "internal/cryptlib.h"
20
21 /* Must be large enough for biggest tag+length */
22 #define DEFAULT_ASN1_BUF_SIZE 20
23
24 typedef enum {
25 ASN1_STATE_START,
26 ASN1_STATE_PRE_COPY,
27 ASN1_STATE_HEADER,
28 ASN1_STATE_HEADER_COPY,
29 ASN1_STATE_DATA_COPY,
30 ASN1_STATE_POST_COPY,
31 ASN1_STATE_DONE
32 } asn1_bio_state_t;
33
34 typedef struct BIO_ASN1_EX_FUNCS_st {
35 asn1_ps_func *ex_func;
36 asn1_ps_func *ex_free_func;
37 } BIO_ASN1_EX_FUNCS;
38
39 typedef struct BIO_ASN1_BUF_CTX_t {
40 /* Internal state */
41 asn1_bio_state_t state;
42 /* Internal buffer */
43 unsigned char *buf;
44 /* Size of buffer */
45 int bufsize;
46 /* Current position in buffer */
47 int bufpos;
48 /* Current buffer length */
49 int buflen;
50 /* Amount of data to copy */
51 int copylen;
52 /* Class and tag to use */
53 int asn1_class, asn1_tag;
54 asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
55 /* Extra buffer for prefix and suffix data */
56 unsigned char *ex_buf;
57 int ex_len;
58 int ex_pos;
59 void *ex_arg;
60 } BIO_ASN1_BUF_CTX;
61
62 static int asn1_bio_write(BIO *h, const char *buf, int num);
63 static int asn1_bio_read(BIO *h, char *buf, int size);
64 static int asn1_bio_puts(BIO *h, const char *str);
65 static int asn1_bio_gets(BIO *h, char *str, int size);
66 static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
67 static int asn1_bio_new(BIO *h);
68 static int asn1_bio_free(BIO *data);
69 static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
70
71 static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
72 static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
73 asn1_ps_func *cleanup, asn1_bio_state_t next);
74 static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
75 asn1_ps_func *setup,
76 asn1_bio_state_t ex_state,
77 asn1_bio_state_t other_state);
78
79 static const BIO_METHOD methods_asn1 = {
80 BIO_TYPE_ASN1,
81 "asn1",
82 bwrite_conv,
83 asn1_bio_write,
84 bread_conv,
85 asn1_bio_read,
86 asn1_bio_puts,
87 asn1_bio_gets,
88 asn1_bio_ctrl,
89 asn1_bio_new,
90 asn1_bio_free,
91 asn1_bio_callback_ctrl,
92 };
93
BIO_f_asn1(void)94 const BIO_METHOD *BIO_f_asn1(void)
95 {
96 return &methods_asn1;
97 }
98
asn1_bio_new(BIO * b)99 static int asn1_bio_new(BIO *b)
100 {
101 BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
102
103 if (ctx == NULL)
104 return 0;
105 if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
106 OPENSSL_free(ctx);
107 return 0;
108 }
109 BIO_set_data(b, ctx);
110 BIO_set_init(b, 1);
111
112 return 1;
113 }
114
asn1_bio_init(BIO_ASN1_BUF_CTX * ctx,int size)115 static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
116 {
117 if (size <= 0) {
118 ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_INVALID_ARGUMENT);
119 return 0;
120 }
121 if ((ctx->buf = OPENSSL_malloc(size)) == NULL)
122 return 0;
123 ctx->bufsize = size;
124 ctx->asn1_class = V_ASN1_UNIVERSAL;
125 ctx->asn1_tag = V_ASN1_OCTET_STRING;
126 ctx->state = ASN1_STATE_START;
127 return 1;
128 }
129
asn1_bio_free(BIO * b)130 static int asn1_bio_free(BIO *b)
131 {
132 BIO_ASN1_BUF_CTX *ctx;
133
134 if (b == NULL)
135 return 0;
136
137 ctx = BIO_get_data(b);
138 if (ctx == NULL)
139 return 0;
140
141 if (ctx->prefix_free != NULL)
142 ctx->prefix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
143 if (ctx->suffix_free != NULL)
144 ctx->suffix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
145
146 OPENSSL_free(ctx->buf);
147 OPENSSL_free(ctx);
148 BIO_set_data(b, NULL);
149 BIO_set_init(b, 0);
150
151 return 1;
152 }
153
asn1_bio_write(BIO * b,const char * in,int inl)154 static int asn1_bio_write(BIO *b, const char *in, int inl)
155 {
156 BIO_ASN1_BUF_CTX *ctx;
157 int wrmax, wrlen, ret;
158 unsigned char *p;
159 BIO *next;
160
161 ctx = BIO_get_data(b);
162 next = BIO_next(b);
163 if (in == NULL || inl < 0 || ctx == NULL || next == NULL)
164 return 0;
165
166 wrlen = 0;
167 ret = -1;
168
169 for (;;) {
170 switch (ctx->state) {
171 /* Setup prefix data, call it */
172 case ASN1_STATE_START:
173 if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
174 ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
175 return -1;
176 break;
177
178 /* Copy any pre data first */
179 case ASN1_STATE_PRE_COPY:
180
181 ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
182 ASN1_STATE_HEADER);
183
184 if (ret <= 0)
185 goto done;
186
187 break;
188
189 case ASN1_STATE_HEADER:
190 ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
191 if (!ossl_assert(ctx->buflen <= ctx->bufsize))
192 return -1;
193 p = ctx->buf;
194 ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
195 ctx->copylen = inl;
196 ctx->state = ASN1_STATE_HEADER_COPY;
197
198 break;
199
200 case ASN1_STATE_HEADER_COPY:
201 ret = BIO_write(next, ctx->buf + ctx->bufpos, ctx->buflen);
202 if (ret <= 0)
203 goto done;
204
205 ctx->buflen -= ret;
206 if (ctx->buflen)
207 ctx->bufpos += ret;
208 else {
209 ctx->bufpos = 0;
210 ctx->state = ASN1_STATE_DATA_COPY;
211 }
212
213 break;
214
215 case ASN1_STATE_DATA_COPY:
216
217 if (inl > ctx->copylen)
218 wrmax = ctx->copylen;
219 else
220 wrmax = inl;
221 ret = BIO_write(next, in, wrmax);
222 if (ret <= 0)
223 goto done;
224 wrlen += ret;
225 ctx->copylen -= ret;
226 in += ret;
227 inl -= ret;
228
229 if (ctx->copylen == 0)
230 ctx->state = ASN1_STATE_HEADER;
231
232 if (inl == 0)
233 goto done;
234
235 break;
236
237 case ASN1_STATE_POST_COPY:
238 case ASN1_STATE_DONE:
239 BIO_clear_retry_flags(b);
240 return 0;
241 }
242 }
243
244 done:
245 BIO_clear_retry_flags(b);
246 BIO_copy_next_retry(b);
247
248 return (wrlen > 0) ? wrlen : ret;
249 }
250
asn1_bio_flush_ex(BIO * b,BIO_ASN1_BUF_CTX * ctx,asn1_ps_func * cleanup,asn1_bio_state_t next)251 static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
252 asn1_ps_func *cleanup, asn1_bio_state_t next)
253 {
254 int ret;
255
256 if (ctx->ex_len <= 0)
257 return 1;
258 for (;;) {
259 ret = BIO_write(BIO_next(b), ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
260 if (ret <= 0)
261 break;
262 ctx->ex_len -= ret;
263 if (ctx->ex_len > 0)
264 ctx->ex_pos += ret;
265 else {
266 if (cleanup)
267 cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
268 ctx->state = next;
269 ctx->ex_pos = 0;
270 break;
271 }
272 }
273 return ret;
274 }
275
asn1_bio_setup_ex(BIO * b,BIO_ASN1_BUF_CTX * ctx,asn1_ps_func * setup,asn1_bio_state_t ex_state,asn1_bio_state_t other_state)276 static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
277 asn1_ps_func *setup,
278 asn1_bio_state_t ex_state,
279 asn1_bio_state_t other_state)
280 {
281 if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
282 BIO_clear_retry_flags(b);
283 return 0;
284 }
285 if (ctx->ex_len > 0)
286 ctx->state = ex_state;
287 else
288 ctx->state = other_state;
289 return 1;
290 }
291
asn1_bio_read(BIO * b,char * in,int inl)292 static int asn1_bio_read(BIO *b, char *in, int inl)
293 {
294 BIO *next = BIO_next(b);
295 if (next == NULL)
296 return 0;
297 return BIO_read(next, in, inl);
298 }
299
asn1_bio_puts(BIO * b,const char * str)300 static int asn1_bio_puts(BIO *b, const char *str)
301 {
302 return asn1_bio_write(b, str, strlen(str));
303 }
304
asn1_bio_gets(BIO * b,char * str,int size)305 static int asn1_bio_gets(BIO *b, char *str, int size)
306 {
307 BIO *next = BIO_next(b);
308 if (next == NULL)
309 return 0;
310 return BIO_gets(next, str, size);
311 }
312
asn1_bio_callback_ctrl(BIO * b,int cmd,BIO_info_cb * fp)313 static long asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
314 {
315 BIO *next = BIO_next(b);
316 if (next == NULL)
317 return 0;
318 return BIO_callback_ctrl(next, cmd, fp);
319 }
320
asn1_bio_ctrl(BIO * b,int cmd,long arg1,void * arg2)321 static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
322 {
323 BIO_ASN1_BUF_CTX *ctx;
324 BIO_ASN1_EX_FUNCS *ex_func;
325 long ret = 1;
326 BIO *next;
327
328 ctx = BIO_get_data(b);
329 if (ctx == NULL)
330 return 0;
331 next = BIO_next(b);
332 switch (cmd) {
333
334 case BIO_C_SET_PREFIX:
335 ex_func = arg2;
336 ctx->prefix = ex_func->ex_func;
337 ctx->prefix_free = ex_func->ex_free_func;
338 break;
339
340 case BIO_C_GET_PREFIX:
341 ex_func = arg2;
342 ex_func->ex_func = ctx->prefix;
343 ex_func->ex_free_func = ctx->prefix_free;
344 break;
345
346 case BIO_C_SET_SUFFIX:
347 ex_func = arg2;
348 ctx->suffix = ex_func->ex_func;
349 ctx->suffix_free = ex_func->ex_free_func;
350 break;
351
352 case BIO_C_GET_SUFFIX:
353 ex_func = arg2;
354 ex_func->ex_func = ctx->suffix;
355 ex_func->ex_free_func = ctx->suffix_free;
356 break;
357
358 case BIO_C_SET_EX_ARG:
359 ctx->ex_arg = arg2;
360 break;
361
362 case BIO_C_GET_EX_ARG:
363 *(void **)arg2 = ctx->ex_arg;
364 break;
365
366 case BIO_CTRL_FLUSH:
367 if (next == NULL)
368 return 0;
369
370 /* Call post function if possible */
371 if (ctx->state == ASN1_STATE_HEADER) {
372 if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
373 ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
374 return 0;
375 }
376
377 if (ctx->state == ASN1_STATE_POST_COPY) {
378 ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
379 ASN1_STATE_DONE);
380 if (ret <= 0)
381 return ret;
382 }
383
384 if (ctx->state == ASN1_STATE_DONE)
385 return BIO_ctrl(next, cmd, arg1, arg2);
386 else {
387 BIO_clear_retry_flags(b);
388 return 0;
389 }
390
391 default:
392 if (next == NULL)
393 return 0;
394 return BIO_ctrl(next, cmd, arg1, arg2);
395 }
396
397 return ret;
398 }
399
asn1_bio_set_ex(BIO * b,int cmd,asn1_ps_func * ex_func,asn1_ps_func * ex_free_func)400 static int asn1_bio_set_ex(BIO *b, int cmd,
401 asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
402 {
403 BIO_ASN1_EX_FUNCS extmp;
404 extmp.ex_func = ex_func;
405 extmp.ex_free_func = ex_free_func;
406 return BIO_ctrl(b, cmd, 0, &extmp);
407 }
408
asn1_bio_get_ex(BIO * b,int cmd,asn1_ps_func ** ex_func,asn1_ps_func ** ex_free_func)409 static int asn1_bio_get_ex(BIO *b, int cmd,
410 asn1_ps_func **ex_func,
411 asn1_ps_func **ex_free_func)
412 {
413 BIO_ASN1_EX_FUNCS extmp;
414 int ret;
415 ret = BIO_ctrl(b, cmd, 0, &extmp);
416 if (ret > 0) {
417 *ex_func = extmp.ex_func;
418 *ex_free_func = extmp.ex_free_func;
419 }
420 return ret;
421 }
422
BIO_asn1_set_prefix(BIO * b,asn1_ps_func * prefix,asn1_ps_func * prefix_free)423 int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
424 asn1_ps_func *prefix_free)
425 {
426 return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
427 }
428
BIO_asn1_get_prefix(BIO * b,asn1_ps_func ** pprefix,asn1_ps_func ** pprefix_free)429 int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
430 asn1_ps_func **pprefix_free)
431 {
432 return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
433 }
434
BIO_asn1_set_suffix(BIO * b,asn1_ps_func * suffix,asn1_ps_func * suffix_free)435 int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
436 asn1_ps_func *suffix_free)
437 {
438 return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
439 }
440
BIO_asn1_get_suffix(BIO * b,asn1_ps_func ** psuffix,asn1_ps_func ** psuffix_free)441 int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
442 asn1_ps_func **psuffix_free)
443 {
444 return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
445 }
446