GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/asn1/bio_asn1.c Lines: 0 166 0.0 %
Date: 2017-11-07 Branches: 0 84 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: bio_asn1.c,v 1.12 2015/12/23 01:46:33 mmcc Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    licensing@OpenSSL.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com).
56
 *
57
 */
58
59
/* Experimental ASN1 BIO. When written through the data is converted
60
 * to an ASN1 string type: default is OCTET STRING. Additional functions
61
 * can be provided to add prefix and suffix data.
62
 */
63
64
#include <stdlib.h>
65
#include <string.h>
66
67
#include <openssl/bio.h>
68
#include <openssl/asn1.h>
69
70
/* Must be large enough for biggest tag+length */
71
#define DEFAULT_ASN1_BUF_SIZE 20
72
73
typedef enum {
74
	ASN1_STATE_START,
75
	ASN1_STATE_PRE_COPY,
76
	ASN1_STATE_HEADER,
77
	ASN1_STATE_HEADER_COPY,
78
	ASN1_STATE_DATA_COPY,
79
	ASN1_STATE_POST_COPY,
80
	ASN1_STATE_DONE
81
} asn1_bio_state_t;
82
83
typedef struct BIO_ASN1_EX_FUNCS_st {
84
	asn1_ps_func	*ex_func;
85
	asn1_ps_func	*ex_free_func;
86
} BIO_ASN1_EX_FUNCS;
87
88
typedef struct BIO_ASN1_BUF_CTX_t {
89
	/* Internal state */
90
	asn1_bio_state_t state;
91
	/* Internal buffer */
92
	unsigned char *buf;
93
	/* Size of buffer */
94
	int bufsize;
95
	/* Current position in buffer */
96
	int bufpos;
97
	/* Current buffer length */
98
	int buflen;
99
	/* Amount of data to copy */
100
	int copylen;
101
	/* Class and tag to use */
102
	int asn1_class, asn1_tag;
103
	asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
104
	/* Extra buffer for prefix and suffix data */
105
	unsigned char *ex_buf;
106
	int ex_len;
107
	int ex_pos;
108
	void *ex_arg;
109
} BIO_ASN1_BUF_CTX;
110
111
112
static int asn1_bio_write(BIO *h, const char *buf, int num);
113
static int asn1_bio_read(BIO *h, char *buf, int size);
114
static int asn1_bio_puts(BIO *h, const char *str);
115
static int asn1_bio_gets(BIO *h, char *str, int size);
116
static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
117
static int asn1_bio_new(BIO *h);
118
static int asn1_bio_free(BIO *data);
119
static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
120
121
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
122
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
123
    asn1_ps_func *cleanup, asn1_bio_state_t next);
124
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
125
    asn1_ps_func *setup, asn1_bio_state_t ex_state,
126
    asn1_bio_state_t other_state);
127
128
static BIO_METHOD methods_asn1 = {
129
	.type = BIO_TYPE_ASN1,
130
	.name = "asn1",
131
	.bwrite = asn1_bio_write,
132
	.bread = asn1_bio_read,
133
	.bputs = asn1_bio_puts,
134
	.bgets = asn1_bio_gets,
135
	.ctrl = asn1_bio_ctrl,
136
	.create = asn1_bio_new,
137
	.destroy = asn1_bio_free,
138
	.callback_ctrl = asn1_bio_callback_ctrl
139
};
140
141
BIO_METHOD *
142
BIO_f_asn1(void)
143
{
144
	return (&methods_asn1);
145
}
146
147
static int
148
asn1_bio_new(BIO *b)
149
{
150
	BIO_ASN1_BUF_CTX *ctx;
151
	ctx = malloc(sizeof(BIO_ASN1_BUF_CTX));
152
	if (!ctx)
153
		return 0;
154
	if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
155
		free(ctx);
156
		return 0;
157
	}
158
	b->init = 1;
159
	b->ptr = (char *)ctx;
160
	b->flags = 0;
161
	return 1;
162
}
163
164
static int
165
asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
166
{
167
	ctx->buf = malloc(size);
168
	if (!ctx->buf)
169
		return 0;
170
	ctx->bufsize = size;
171
	ctx->bufpos = 0;
172
	ctx->buflen = 0;
173
	ctx->copylen = 0;
174
	ctx->asn1_class = V_ASN1_UNIVERSAL;
175
	ctx->asn1_tag = V_ASN1_OCTET_STRING;
176
	ctx->ex_buf = NULL;
177
	ctx->ex_pos = 0;
178
	ctx->ex_len = 0;
179
	ctx->state = ASN1_STATE_START;
180
	return 1;
181
}
182
183
static int
184
asn1_bio_free(BIO *b)
185
{
186
	BIO_ASN1_BUF_CTX *ctx;
187
188
	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
189
	if (ctx == NULL)
190
		return 0;
191
	free(ctx->buf);
192
	free(ctx);
193
	b->init = 0;
194
	b->ptr = NULL;
195
	b->flags = 0;
196
	return 1;
197
}
198
199
static int
200
asn1_bio_write(BIO *b, const char *in , int inl)
201
{
202
	BIO_ASN1_BUF_CTX *ctx;
203
	int wrmax, wrlen, ret, buflen;
204
	unsigned char *p;
205
206
	if (!in || (inl < 0) || (b->next_bio == NULL))
207
		return 0;
208
	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
209
	if (ctx == NULL)
210
		return 0;
211
212
	wrlen = 0;
213
	ret = -1;
214
215
	for (;;) {
216
		switch (ctx->state) {
217
218
			/* Setup prefix data, call it */
219
		case ASN1_STATE_START:
220
			if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
221
				    ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
222
				return 0;
223
			break;
224
225
			/* Copy any pre data first */
226
		case ASN1_STATE_PRE_COPY:
227
			ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
228
			    ASN1_STATE_HEADER);
229
			if (ret <= 0)
230
				goto done;
231
			break;
232
233
		case ASN1_STATE_HEADER:
234
			buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
235
			if (buflen <= 0 || buflen > ctx->bufsize)
236
				return -1;
237
			ctx->buflen = buflen;
238
			p = ctx->buf;
239
			ASN1_put_object(&p, 0, inl,
240
			    ctx->asn1_tag, ctx->asn1_class);
241
			ctx->copylen = inl;
242
			ctx->state = ASN1_STATE_HEADER_COPY;
243
			break;
244
245
		case ASN1_STATE_HEADER_COPY:
246
			ret = BIO_write(b->next_bio,
247
			    ctx->buf + ctx->bufpos, ctx->buflen);
248
			if (ret <= 0)
249
				goto done;
250
251
			ctx->buflen -= ret;
252
			if (ctx->buflen)
253
				ctx->bufpos += ret;
254
			else {
255
				ctx->bufpos = 0;
256
				ctx->state = ASN1_STATE_DATA_COPY;
257
			}
258
			break;
259
260
		case ASN1_STATE_DATA_COPY:
261
262
			if (inl > ctx->copylen)
263
				wrmax = ctx->copylen;
264
			else
265
				wrmax = inl;
266
			ret = BIO_write(b->next_bio, in, wrmax);
267
			if (ret <= 0)
268
				break;
269
			wrlen += ret;
270
			ctx->copylen -= ret;
271
			in += ret;
272
			inl -= ret;
273
274
			if (ctx->copylen == 0)
275
				ctx->state = ASN1_STATE_HEADER;
276
			if (inl == 0)
277
				goto done;
278
			break;
279
280
		default:
281
			BIO_clear_retry_flags(b);
282
			return 0;
283
		}
284
285
	}
286
287
done:
288
	BIO_clear_retry_flags(b);
289
	BIO_copy_next_retry(b);
290
291
	return (wrlen > 0) ? wrlen : ret;
292
}
293
294
static int
295
asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, asn1_ps_func *cleanup,
296
    asn1_bio_state_t next)
297
{
298
	int ret;
299
300
	if (ctx->ex_len <= 0)
301
		return 1;
302
	for (;;) {
303
		ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
304
		    ctx->ex_len);
305
		if (ret <= 0)
306
			break;
307
		ctx->ex_len -= ret;
308
		if (ctx->ex_len > 0)
309
			ctx->ex_pos += ret;
310
		else {
311
			if (cleanup)
312
				cleanup(b, &ctx->ex_buf, &ctx->ex_len,
313
				    &ctx->ex_arg);
314
			ctx->state = next;
315
			ctx->ex_pos = 0;
316
			break;
317
		}
318
	}
319
	return ret;
320
}
321
322
static int
323
asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, asn1_ps_func *setup,
324
    asn1_bio_state_t ex_state, asn1_bio_state_t other_state)
325
{
326
	if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
327
		BIO_clear_retry_flags(b);
328
		return 0;
329
	}
330
	if (ctx->ex_len > 0)
331
		ctx->state = ex_state;
332
	else
333
		ctx->state = other_state;
334
	return 1;
335
}
336
337
static int
338
asn1_bio_read(BIO *b, char *in , int inl)
339
{
340
	if (!b->next_bio)
341
		return 0;
342
	return BIO_read(b->next_bio, in , inl);
343
}
344
345
static int
346
asn1_bio_puts(BIO *b, const char *str)
347
{
348
	return asn1_bio_write(b, str, strlen(str));
349
}
350
351
static int
352
asn1_bio_gets(BIO *b, char *str, int size)
353
{
354
	if (!b->next_bio)
355
		return 0;
356
	return BIO_gets(b->next_bio, str , size);
357
}
358
359
static long
360
asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
361
{
362
	if (b->next_bio == NULL)
363
		return (0);
364
	return BIO_callback_ctrl(b->next_bio, cmd, fp);
365
}
366
367
static long
368
asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
369
{
370
	BIO_ASN1_BUF_CTX *ctx;
371
	BIO_ASN1_EX_FUNCS *ex_func;
372
	long ret = 1;
373
374
	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
375
	if (ctx == NULL)
376
		return 0;
377
	switch (cmd) {
378
379
	case BIO_C_SET_PREFIX:
380
		ex_func = arg2;
381
		ctx->prefix = ex_func->ex_func;
382
		ctx->prefix_free = ex_func->ex_free_func;
383
		break;
384
385
	case BIO_C_GET_PREFIX:
386
		ex_func = arg2;
387
		ex_func->ex_func = ctx->prefix;
388
		ex_func->ex_free_func = ctx->prefix_free;
389
		break;
390
391
	case BIO_C_SET_SUFFIX:
392
		ex_func = arg2;
393
		ctx->suffix = ex_func->ex_func;
394
		ctx->suffix_free = ex_func->ex_free_func;
395
		break;
396
397
	case BIO_C_GET_SUFFIX:
398
		ex_func = arg2;
399
		ex_func->ex_func = ctx->suffix;
400
		ex_func->ex_free_func = ctx->suffix_free;
401
		break;
402
403
	case BIO_C_SET_EX_ARG:
404
		ctx->ex_arg = arg2;
405
		break;
406
407
	case BIO_C_GET_EX_ARG:
408
		*(void **)arg2 = ctx->ex_arg;
409
		break;
410
411
	case BIO_CTRL_FLUSH:
412
		if (!b->next_bio)
413
			return 0;
414
415
		/* Call post function if possible */
416
		if (ctx->state == ASN1_STATE_HEADER) {
417
			if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
418
			    ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
419
				return 0;
420
		}
421
422
		if (ctx->state == ASN1_STATE_POST_COPY) {
423
			ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
424
			    ASN1_STATE_DONE);
425
			if (ret <= 0)
426
				return ret;
427
		}
428
429
		if (ctx->state == ASN1_STATE_DONE)
430
			return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
431
		else {
432
			BIO_clear_retry_flags(b);
433
			return 0;
434
		}
435
		break;
436
437
438
	default:
439
		if (!b->next_bio)
440
			return 0;
441
		return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
442
443
	}
444
445
	return ret;
446
}
447
448
static int
449
asn1_bio_set_ex(BIO *b, int cmd, asn1_ps_func *ex_func, asn1_ps_func
450
    *ex_free_func)
451
{
452
	BIO_ASN1_EX_FUNCS extmp;
453
454
	extmp.ex_func = ex_func;
455
	extmp.ex_free_func = ex_free_func;
456
	return BIO_ctrl(b, cmd, 0, &extmp);
457
}
458
459
static int
460
asn1_bio_get_ex(BIO *b, int cmd, asn1_ps_func **ex_func,
461
    asn1_ps_func **ex_free_func)
462
{
463
	BIO_ASN1_EX_FUNCS extmp;
464
	int ret;
465
466
	ret = BIO_ctrl(b, cmd, 0, &extmp);
467
	if (ret > 0) {
468
		*ex_func = extmp.ex_func;
469
		*ex_free_func = extmp.ex_free_func;
470
	}
471
	return ret;
472
}
473
474
int
475
BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
476
{
477
	return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
478
}
479
480
int
481
BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
482
{
483
	return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
484
}
485
486
int
487
BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
488
{
489
	return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
490
}
491
492
int
493
BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
494
{
495
	return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
496
}