1238384Sjkim/* bio_asn1.c */
2238384Sjkim/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3238384Sjkim * project.
4238384Sjkim */
5238384Sjkim/* ====================================================================
6238384Sjkim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10238384Sjkim * are met:
11238384Sjkim *
12238384Sjkim * 1. Redistributions of source code must retain the above copyright
13238384Sjkim *    notice, this list of conditions and the following disclaimer.
14238384Sjkim *
15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
16238384Sjkim *    notice, this list of conditions and the following disclaimer in
17238384Sjkim *    the documentation and/or other materials provided with the
18238384Sjkim *    distribution.
19238384Sjkim *
20238384Sjkim * 3. All advertising materials mentioning features or use of this
21238384Sjkim *    software must display the following acknowledgment:
22238384Sjkim *    "This product includes software developed by the OpenSSL Project
23238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24238384Sjkim *
25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26238384Sjkim *    endorse or promote products derived from this software without
27238384Sjkim *    prior written permission. For written permission, please contact
28238384Sjkim *    licensing@OpenSSL.org.
29238384Sjkim *
30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
31238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
32238384Sjkim *    permission of the OpenSSL Project.
33238384Sjkim *
34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
35238384Sjkim *    acknowledgment:
36238384Sjkim *    "This product includes software developed by the OpenSSL Project
37238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38238384Sjkim *
39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
51238384Sjkim * ====================================================================
52238384Sjkim *
53238384Sjkim * This product includes cryptographic software written by Eric Young
54238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
55238384Sjkim * Hudson (tjh@cryptsoft.com).
56238384Sjkim *
57238384Sjkim */
58238384Sjkim
59238384Sjkim/* Experimental ASN1 BIO. When written through the data is converted
60238384Sjkim * to an ASN1 string type: default is OCTET STRING. Additional functions
61238384Sjkim * can be provided to add prefix and suffix data.
62238384Sjkim */
63238384Sjkim
64238384Sjkim#include <string.h>
65238384Sjkim#include <openssl/bio.h>
66238384Sjkim#include <openssl/asn1.h>
67238384Sjkim
68238384Sjkim/* Must be large enough for biggest tag+length */
69238384Sjkim#define DEFAULT_ASN1_BUF_SIZE 20
70238384Sjkim
71238384Sjkimtypedef enum
72238384Sjkim	{
73238384Sjkim	ASN1_STATE_START,
74238384Sjkim	ASN1_STATE_PRE_COPY,
75238384Sjkim	ASN1_STATE_HEADER,
76238384Sjkim	ASN1_STATE_HEADER_COPY,
77238384Sjkim	ASN1_STATE_DATA_COPY,
78238384Sjkim	ASN1_STATE_POST_COPY,
79238384Sjkim	ASN1_STATE_DONE
80238384Sjkim	} asn1_bio_state_t;
81238384Sjkim
82238384Sjkimtypedef struct BIO_ASN1_EX_FUNCS_st
83238384Sjkim	{
84238384Sjkim	asn1_ps_func	*ex_func;
85238384Sjkim	asn1_ps_func	*ex_free_func;
86238384Sjkim	} BIO_ASN1_EX_FUNCS;
87238384Sjkim
88238384Sjkimtypedef struct BIO_ASN1_BUF_CTX_t
89238384Sjkim	{
90238384Sjkim	/* Internal state */
91238384Sjkim	asn1_bio_state_t state;
92238384Sjkim	/* Internal buffer */
93238384Sjkim	unsigned char *buf;
94238384Sjkim	/* Size of buffer */
95238384Sjkim	int bufsize;
96238384Sjkim	/* Current position in buffer */
97238384Sjkim	int bufpos;
98238384Sjkim	/* Current buffer length */
99238384Sjkim	int buflen;
100238384Sjkim	/* Amount of data to copy */
101238384Sjkim	int copylen;
102238384Sjkim	/* Class and tag to use */
103238384Sjkim	int asn1_class, asn1_tag;
104238384Sjkim	asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
105238384Sjkim	/* Extra buffer for prefix and suffix data */
106238384Sjkim	unsigned char *ex_buf;
107238384Sjkim	int ex_len;
108238384Sjkim	int ex_pos;
109238384Sjkim	void *ex_arg;
110238384Sjkim	} BIO_ASN1_BUF_CTX;
111238384Sjkim
112238384Sjkim
113238384Sjkimstatic int asn1_bio_write(BIO *h, const char *buf,int num);
114238384Sjkimstatic int asn1_bio_read(BIO *h, char *buf, int size);
115238384Sjkimstatic int asn1_bio_puts(BIO *h, const char *str);
116238384Sjkimstatic int asn1_bio_gets(BIO *h, char *str, int size);
117238384Sjkimstatic long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
118238384Sjkimstatic int asn1_bio_new(BIO *h);
119238384Sjkimstatic int asn1_bio_free(BIO *data);
120238384Sjkimstatic long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
121238384Sjkim
122238384Sjkimstatic int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
123238384Sjkimstatic int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
124238384Sjkim				asn1_ps_func *cleanup, asn1_bio_state_t next);
125238384Sjkimstatic int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
126238384Sjkim				asn1_ps_func *setup,
127238384Sjkim				asn1_bio_state_t ex_state,
128238384Sjkim				asn1_bio_state_t other_state);
129238384Sjkim
130238384Sjkimstatic BIO_METHOD methods_asn1=
131238384Sjkim	{
132238384Sjkim	BIO_TYPE_ASN1,
133238384Sjkim	"asn1",
134238384Sjkim	asn1_bio_write,
135238384Sjkim	asn1_bio_read,
136238384Sjkim	asn1_bio_puts,
137238384Sjkim	asn1_bio_gets,
138238384Sjkim	asn1_bio_ctrl,
139238384Sjkim	asn1_bio_new,
140238384Sjkim	asn1_bio_free,
141238384Sjkim	asn1_bio_callback_ctrl,
142238384Sjkim	};
143238384Sjkim
144238384SjkimBIO_METHOD *BIO_f_asn1(void)
145238384Sjkim	{
146238384Sjkim	return(&methods_asn1);
147238384Sjkim	}
148238384Sjkim
149238384Sjkim
150238384Sjkimstatic int asn1_bio_new(BIO *b)
151238384Sjkim	{
152238384Sjkim	BIO_ASN1_BUF_CTX *ctx;
153238384Sjkim	ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
154238384Sjkim	if (!ctx)
155238384Sjkim		return 0;
156238384Sjkim	if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
157279264Sdelphij		{
158279264Sdelphij		OPENSSL_free(ctx);
159238384Sjkim		return 0;
160279264Sdelphij		}
161238384Sjkim	b->init = 1;
162238384Sjkim	b->ptr = (char *)ctx;
163238384Sjkim	b->flags = 0;
164238384Sjkim	return 1;
165238384Sjkim	}
166238384Sjkim
167238384Sjkimstatic int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
168238384Sjkim	{
169238384Sjkim	ctx->buf = OPENSSL_malloc(size);
170238384Sjkim	if (!ctx->buf)
171238384Sjkim		return 0;
172238384Sjkim	ctx->bufsize = size;
173238384Sjkim	ctx->bufpos = 0;
174238384Sjkim	ctx->buflen = 0;
175238384Sjkim	ctx->copylen = 0;
176238384Sjkim	ctx->asn1_class = V_ASN1_UNIVERSAL;
177238384Sjkim	ctx->asn1_tag = V_ASN1_OCTET_STRING;
178238384Sjkim	ctx->ex_buf = 0;
179238384Sjkim	ctx->ex_pos = 0;
180238384Sjkim	ctx->ex_len = 0;
181238384Sjkim	ctx->state = ASN1_STATE_START;
182238384Sjkim	return 1;
183238384Sjkim	}
184238384Sjkim
185238384Sjkimstatic int asn1_bio_free(BIO *b)
186238384Sjkim	{
187238384Sjkim	BIO_ASN1_BUF_CTX *ctx;
188238384Sjkim	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
189238384Sjkim	if (ctx == NULL)
190238384Sjkim		return 0;
191238384Sjkim	if (ctx->buf)
192238384Sjkim		OPENSSL_free(ctx->buf);
193238384Sjkim	OPENSSL_free(ctx);
194238384Sjkim	b->init = 0;
195238384Sjkim	b->ptr = NULL;
196238384Sjkim	b->flags = 0;
197238384Sjkim	return 1;
198238384Sjkim	}
199238384Sjkim
200238384Sjkimstatic int asn1_bio_write(BIO *b, const char *in , int inl)
201238384Sjkim	{
202238384Sjkim	BIO_ASN1_BUF_CTX *ctx;
203238384Sjkim	int wrmax, wrlen, ret;
204238384Sjkim	unsigned char *p;
205238384Sjkim	if (!in || (inl < 0) || (b->next_bio == NULL))
206238384Sjkim		return 0;
207238384Sjkim	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
208238384Sjkim	if (ctx == NULL)
209238384Sjkim		return 0;
210238384Sjkim
211238384Sjkim	wrlen = 0;
212238384Sjkim	ret = -1;
213238384Sjkim
214238384Sjkim	for(;;)
215238384Sjkim		{
216238384Sjkim		switch (ctx->state)
217238384Sjkim			{
218238384Sjkim
219238384Sjkim			/* Setup prefix data, call it */
220238384Sjkim			case ASN1_STATE_START:
221238384Sjkim			if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
222238384Sjkim				ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
223238384Sjkim				return 0;
224238384Sjkim			break;
225238384Sjkim
226238384Sjkim			/* Copy any pre data first */
227238384Sjkim			case ASN1_STATE_PRE_COPY:
228238384Sjkim
229238384Sjkim			ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
230238384Sjkim							ASN1_STATE_HEADER);
231238384Sjkim
232238384Sjkim			if (ret <= 0)
233238384Sjkim				goto done;
234238384Sjkim
235238384Sjkim			break;
236238384Sjkim
237238384Sjkim			case ASN1_STATE_HEADER:
238238384Sjkim			ctx->buflen =
239238384Sjkim				ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
240238384Sjkim			OPENSSL_assert(ctx->buflen <= ctx->bufsize);
241238384Sjkim			p = ctx->buf;
242238384Sjkim			ASN1_put_object(&p, 0, inl,
243238384Sjkim					ctx->asn1_tag, ctx->asn1_class);
244238384Sjkim			ctx->copylen = inl;
245238384Sjkim			ctx->state = ASN1_STATE_HEADER_COPY;
246238384Sjkim
247238384Sjkim			break;
248238384Sjkim
249238384Sjkim			case ASN1_STATE_HEADER_COPY:
250238384Sjkim			ret = BIO_write(b->next_bio,
251238384Sjkim					ctx->buf + ctx->bufpos, ctx->buflen);
252238384Sjkim			if (ret <= 0)
253238384Sjkim				goto done;
254238384Sjkim
255238384Sjkim			ctx->buflen -= ret;
256238384Sjkim			if (ctx->buflen)
257238384Sjkim				ctx->bufpos += ret;
258238384Sjkim			else
259238384Sjkim				{
260238384Sjkim				ctx->bufpos = 0;
261238384Sjkim				ctx->state = ASN1_STATE_DATA_COPY;
262238384Sjkim				}
263238384Sjkim
264238384Sjkim			break;
265238384Sjkim
266238384Sjkim			case ASN1_STATE_DATA_COPY:
267238384Sjkim
268238384Sjkim			if (inl > ctx->copylen)
269238384Sjkim				wrmax = ctx->copylen;
270238384Sjkim			else
271238384Sjkim				wrmax = inl;
272238384Sjkim			ret = BIO_write(b->next_bio, in, wrmax);
273238384Sjkim			if (ret <= 0)
274238384Sjkim				break;
275238384Sjkim			wrlen += ret;
276238384Sjkim			ctx->copylen -= ret;
277238384Sjkim			in += ret;
278238384Sjkim			inl -= ret;
279238384Sjkim
280238384Sjkim			if (ctx->copylen == 0)
281238384Sjkim				ctx->state = ASN1_STATE_HEADER;
282238384Sjkim
283238384Sjkim			if (inl == 0)
284238384Sjkim				goto done;
285238384Sjkim
286238384Sjkim			break;
287238384Sjkim
288238384Sjkim			default:
289238384Sjkim			BIO_clear_retry_flags(b);
290238384Sjkim			return 0;
291238384Sjkim
292238384Sjkim			}
293238384Sjkim
294238384Sjkim		}
295238384Sjkim
296238384Sjkim	done:
297238384Sjkim	BIO_clear_retry_flags(b);
298238384Sjkim	BIO_copy_next_retry(b);
299238384Sjkim
300238384Sjkim	return (wrlen > 0) ? wrlen : ret;
301238384Sjkim
302238384Sjkim	}
303238384Sjkim
304238384Sjkimstatic int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
305238384Sjkim				asn1_ps_func *cleanup, asn1_bio_state_t next)
306238384Sjkim	{
307238384Sjkim	int ret;
308238384Sjkim	if (ctx->ex_len <= 0)
309238384Sjkim		return 1;
310238384Sjkim	for(;;)
311238384Sjkim		{
312238384Sjkim		ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
313238384Sjkim								ctx->ex_len);
314238384Sjkim		if (ret <= 0)
315238384Sjkim			break;
316238384Sjkim		ctx->ex_len -= ret;
317238384Sjkim		if (ctx->ex_len > 0)
318238384Sjkim			ctx->ex_pos += ret;
319238384Sjkim		else
320238384Sjkim			{
321238384Sjkim			if(cleanup)
322238384Sjkim				cleanup(b, &ctx->ex_buf, &ctx->ex_len,
323238384Sjkim								&ctx->ex_arg);
324238384Sjkim			ctx->state = next;
325238384Sjkim			ctx->ex_pos = 0;
326238384Sjkim			break;
327238384Sjkim			}
328238384Sjkim		}
329238384Sjkim	return ret;
330238384Sjkim	}
331238384Sjkim
332238384Sjkimstatic int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
333238384Sjkim				asn1_ps_func *setup,
334238384Sjkim				asn1_bio_state_t ex_state,
335238384Sjkim				asn1_bio_state_t other_state)
336238384Sjkim	{
337238384Sjkim	if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
338238384Sjkim		{
339238384Sjkim		BIO_clear_retry_flags(b);
340238384Sjkim		return 0;
341238384Sjkim		}
342238384Sjkim	if (ctx->ex_len > 0)
343238384Sjkim		ctx->state = ex_state;
344238384Sjkim	else
345238384Sjkim		ctx->state = other_state;
346238384Sjkim	return 1;
347238384Sjkim	}
348238384Sjkim
349238384Sjkimstatic int asn1_bio_read(BIO *b, char *in , int inl)
350238384Sjkim	{
351238384Sjkim	if (!b->next_bio)
352238384Sjkim		return 0;
353238384Sjkim	return BIO_read(b->next_bio, in , inl);
354238384Sjkim	}
355238384Sjkim
356238384Sjkimstatic int asn1_bio_puts(BIO *b, const char *str)
357238384Sjkim	{
358238384Sjkim	return asn1_bio_write(b, str, strlen(str));
359238384Sjkim	}
360238384Sjkim
361238384Sjkimstatic int asn1_bio_gets(BIO *b, char *str, int size)
362238384Sjkim	{
363238384Sjkim	if (!b->next_bio)
364238384Sjkim		return 0;
365238384Sjkim	return BIO_gets(b->next_bio, str , size);
366238384Sjkim	}
367238384Sjkim
368238384Sjkimstatic long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
369238384Sjkim	{
370238384Sjkim	if (b->next_bio == NULL) return(0);
371238384Sjkim	return BIO_callback_ctrl(b->next_bio,cmd,fp);
372238384Sjkim	}
373238384Sjkim
374238384Sjkimstatic long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
375238384Sjkim	{
376238384Sjkim	BIO_ASN1_BUF_CTX *ctx;
377238384Sjkim	BIO_ASN1_EX_FUNCS *ex_func;
378238384Sjkim	long ret = 1;
379238384Sjkim	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
380238384Sjkim	if (ctx == NULL)
381238384Sjkim		return 0;
382238384Sjkim	switch(cmd)
383238384Sjkim		{
384238384Sjkim
385238384Sjkim		case BIO_C_SET_PREFIX:
386238384Sjkim		ex_func = arg2;
387238384Sjkim		ctx->prefix  = ex_func->ex_func;
388238384Sjkim		ctx->prefix_free  = ex_func->ex_free_func;
389238384Sjkim		break;
390238384Sjkim
391238384Sjkim		case BIO_C_GET_PREFIX:
392238384Sjkim		ex_func = arg2;
393238384Sjkim		ex_func->ex_func = ctx->prefix;
394238384Sjkim		ex_func->ex_free_func = ctx->prefix_free;
395238384Sjkim		break;
396238384Sjkim
397238384Sjkim		case BIO_C_SET_SUFFIX:
398238384Sjkim		ex_func = arg2;
399238384Sjkim		ctx->suffix  = ex_func->ex_func;
400238384Sjkim		ctx->suffix_free  = ex_func->ex_free_func;
401238384Sjkim		break;
402238384Sjkim
403238384Sjkim		case BIO_C_GET_SUFFIX:
404238384Sjkim		ex_func = arg2;
405238384Sjkim		ex_func->ex_func = ctx->suffix;
406238384Sjkim		ex_func->ex_free_func = ctx->suffix_free;
407238384Sjkim		break;
408238384Sjkim
409238384Sjkim		case BIO_C_SET_EX_ARG:
410238384Sjkim		ctx->ex_arg = arg2;
411238384Sjkim		break;
412238384Sjkim
413238384Sjkim		case BIO_C_GET_EX_ARG:
414238384Sjkim		*(void **)arg2 = ctx->ex_arg;
415238384Sjkim		break;
416238384Sjkim
417238384Sjkim		case BIO_CTRL_FLUSH:
418238384Sjkim		if (!b->next_bio)
419238384Sjkim			return 0;
420238384Sjkim
421238384Sjkim		/* Call post function if possible */
422238384Sjkim		if (ctx->state == ASN1_STATE_HEADER)
423238384Sjkim			{
424238384Sjkim			if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
425238384Sjkim				ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
426238384Sjkim				return 0;
427238384Sjkim			}
428238384Sjkim
429238384Sjkim		if (ctx->state == ASN1_STATE_POST_COPY)
430238384Sjkim			{
431238384Sjkim			ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
432238384Sjkim							ASN1_STATE_DONE);
433238384Sjkim			if (ret <= 0)
434238384Sjkim				return ret;
435238384Sjkim			}
436238384Sjkim
437238384Sjkim		if (ctx->state == ASN1_STATE_DONE)
438238384Sjkim			return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
439238384Sjkim		else
440238384Sjkim			{
441238384Sjkim			BIO_clear_retry_flags(b);
442238384Sjkim			return 0;
443238384Sjkim			}
444238384Sjkim		break;
445238384Sjkim
446238384Sjkim
447238384Sjkim		default:
448238384Sjkim		if (!b->next_bio)
449238384Sjkim			return 0;
450238384Sjkim		return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
451238384Sjkim
452238384Sjkim		}
453238384Sjkim
454238384Sjkim	return ret;
455238384Sjkim	}
456238384Sjkim
457238384Sjkimstatic int asn1_bio_set_ex(BIO *b, int cmd,
458238384Sjkim		asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
459238384Sjkim	{
460238384Sjkim	BIO_ASN1_EX_FUNCS extmp;
461238384Sjkim	extmp.ex_func = ex_func;
462238384Sjkim	extmp.ex_free_func = ex_free_func;
463238384Sjkim	return BIO_ctrl(b, cmd, 0, &extmp);
464238384Sjkim	}
465238384Sjkim
466238384Sjkimstatic int asn1_bio_get_ex(BIO *b, int cmd,
467238384Sjkim		asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
468238384Sjkim	{
469238384Sjkim	BIO_ASN1_EX_FUNCS extmp;
470238384Sjkim	int ret;
471238384Sjkim	ret = BIO_ctrl(b, cmd, 0, &extmp);
472238384Sjkim	if (ret > 0)
473238384Sjkim		{
474238384Sjkim		*ex_func = extmp.ex_func;
475238384Sjkim		*ex_free_func = extmp.ex_free_func;
476238384Sjkim		}
477238384Sjkim	return ret;
478238384Sjkim	}
479238384Sjkim
480238384Sjkimint BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
481238384Sjkim	{
482238384Sjkim	return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
483238384Sjkim	}
484238384Sjkim
485238384Sjkimint BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
486238384Sjkim	{
487238384Sjkim	return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
488238384Sjkim	}
489238384Sjkim
490238384Sjkimint BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
491238384Sjkim	{
492238384Sjkim	return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
493238384Sjkim	}
494238384Sjkim
495238384Sjkimint BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
496238384Sjkim	{
497238384Sjkim	return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
498238384Sjkim	}
499