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 }
245
246 done:
247 BIO_clear_retry_flags(b);
248 BIO_copy_next_retry(b);
249
250 return (wrlen > 0) ? wrlen : ret;
251
252 }
253
asn1_bio_flush_ex(BIO * b,BIO_ASN1_BUF_CTX * ctx,asn1_ps_func * cleanup,asn1_bio_state_t next)254 static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
255 asn1_ps_func *cleanup, asn1_bio_state_t next)
256 {
257 int ret;
258
259 if (ctx->ex_len <= 0)
260 return 1;
261 for (;;) {
262 ret = BIO_write(BIO_next(b), ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
263 if (ret <= 0)
264 break;
265 ctx->ex_len -= ret;
266 if (ctx->ex_len > 0)
267 ctx->ex_pos += ret;
268 else {
269 if (cleanup)
270 cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
271 ctx->state = next;
272 ctx->ex_pos = 0;
273 break;
274 }
275 }
276 return ret;
277 }
278
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)279 static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
280 asn1_ps_func *setup,
281 asn1_bio_state_t ex_state,
282 asn1_bio_state_t other_state)
283 {
284 if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
285 BIO_clear_retry_flags(b);
286 return 0;
287 }
288 if (ctx->ex_len > 0)
289 ctx->state = ex_state;
290 else
291 ctx->state = other_state;
292 return 1;
293 }
294
asn1_bio_read(BIO * b,char * in,int inl)295 static int asn1_bio_read(BIO *b, char *in, int inl)
296 {
297 BIO *next = BIO_next(b);
298 if (next == NULL)
299 return 0;
300 return BIO_read(next, in, inl);
301 }
302
asn1_bio_puts(BIO * b,const char * str)303 static int asn1_bio_puts(BIO *b, const char *str)
304 {
305 return asn1_bio_write(b, str, strlen(str));
306 }
307
asn1_bio_gets(BIO * b,char * str,int size)308 static int asn1_bio_gets(BIO *b, char *str, int size)
309 {
310 BIO *next = BIO_next(b);
311 if (next == NULL)
312 return 0;
313 return BIO_gets(next, str, size);
314 }
315
asn1_bio_callback_ctrl(BIO * b,int cmd,BIO_info_cb * fp)316 static long asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
317 {
318 BIO *next = BIO_next(b);
319 if (next == NULL)
320 return 0;
321 return BIO_callback_ctrl(next, cmd, fp);
322 }
323
asn1_bio_ctrl(BIO * b,int cmd,long arg1,void * arg2)324 static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
325 {
326 BIO_ASN1_BUF_CTX *ctx;
327 BIO_ASN1_EX_FUNCS *ex_func;
328 long ret = 1;
329 BIO *next;
330
331 ctx = BIO_get_data(b);
332 if (ctx == NULL)
333 return 0;
334 next = BIO_next(b);
335 switch (cmd) {
336
337 case BIO_C_SET_PREFIX:
338 ex_func = arg2;
339 ctx->prefix = ex_func->ex_func;
340 ctx->prefix_free = ex_func->ex_free_func;
341 break;
342
343 case BIO_C_GET_PREFIX:
344 ex_func = arg2;
345 ex_func->ex_func = ctx->prefix;
346 ex_func->ex_free_func = ctx->prefix_free;
347 break;
348
349 case BIO_C_SET_SUFFIX:
350 ex_func = arg2;
351 ctx->suffix = ex_func->ex_func;
352 ctx->suffix_free = ex_func->ex_free_func;
353 break;
354
355 case BIO_C_GET_SUFFIX:
356 ex_func = arg2;
357 ex_func->ex_func = ctx->suffix;
358 ex_func->ex_free_func = ctx->suffix_free;
359 break;
360
361 case BIO_C_SET_EX_ARG:
362 ctx->ex_arg = arg2;
363 break;
364
365 case BIO_C_GET_EX_ARG:
366 *(void **)arg2 = ctx->ex_arg;
367 break;
368
369 case BIO_CTRL_FLUSH:
370 if (next == NULL)
371 return 0;
372
373 /* Call post function if possible */
374 if (ctx->state == ASN1_STATE_HEADER) {
375 if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
376 ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
377 return 0;
378 }
379
380 if (ctx->state == ASN1_STATE_POST_COPY) {
381 ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
382 ASN1_STATE_DONE);
383 if (ret <= 0)
384 return ret;
385 }
386
387 if (ctx->state == ASN1_STATE_DONE)
388 return BIO_ctrl(next, cmd, arg1, arg2);
389 else {
390 BIO_clear_retry_flags(b);
391 return 0;
392 }
393
394 default:
395 if (next == NULL)
396 return 0;
397 return BIO_ctrl(next, cmd, arg1, arg2);
398
399 }
400
401 return ret;
402 }
403
asn1_bio_set_ex(BIO * b,int cmd,asn1_ps_func * ex_func,asn1_ps_func * ex_free_func)404 static int asn1_bio_set_ex(BIO *b, int cmd,
405 asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
406 {
407 BIO_ASN1_EX_FUNCS extmp;
408 extmp.ex_func = ex_func;
409 extmp.ex_free_func = ex_free_func;
410 return BIO_ctrl(b, cmd, 0, &extmp);
411 }
412
asn1_bio_get_ex(BIO * b,int cmd,asn1_ps_func ** ex_func,asn1_ps_func ** ex_free_func)413 static int asn1_bio_get_ex(BIO *b, int cmd,
414 asn1_ps_func **ex_func,
415 asn1_ps_func **ex_free_func)
416 {
417 BIO_ASN1_EX_FUNCS extmp;
418 int ret;
419 ret = BIO_ctrl(b, cmd, 0, &extmp);
420 if (ret > 0) {
421 *ex_func = extmp.ex_func;
422 *ex_free_func = extmp.ex_free_func;
423 }
424 return ret;
425 }
426
BIO_asn1_set_prefix(BIO * b,asn1_ps_func * prefix,asn1_ps_func * prefix_free)427 int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
428 asn1_ps_func *prefix_free)
429 {
430 return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
431 }
432
BIO_asn1_get_prefix(BIO * b,asn1_ps_func ** pprefix,asn1_ps_func ** pprefix_free)433 int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
434 asn1_ps_func **pprefix_free)
435 {
436 return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
437 }
438
BIO_asn1_set_suffix(BIO * b,asn1_ps_func * suffix,asn1_ps_func * suffix_free)439 int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
440 asn1_ps_func *suffix_free)
441 {
442 return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
443 }
444
BIO_asn1_get_suffix(BIO * b,asn1_ps_func ** psuffix,asn1_ps_func ** psuffix_free)445 int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
446 asn1_ps_func **psuffix_free)
447 {
448 return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
449 }
450