1221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* bio_asn1.c */
2221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * project.
4221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
5221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* ====================================================================
6221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
8221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Redistribution and use in source and binary forms, with or without
9221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * modification, are permitted provided that the following conditions
10221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * are met:
11221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
12221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 1. Redistributions of source code must retain the above copyright
13221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    notice, this list of conditions and the following disclaimer.
14221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
15221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 2. Redistributions in binary form must reproduce the above copyright
16221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    notice, this list of conditions and the following disclaimer in
17221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    the documentation and/or other materials provided with the
18221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    distribution.
19221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
20221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 3. All advertising materials mentioning features or use of this
21221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    software must display the following acknowledgment:
22221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
23221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
25221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    endorse or promote products derived from this software without
27221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    prior written permission. For written permission, please contact
28221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    licensing@OpenSSL.org.
29221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
30221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 5. Products derived from this software may not be called "OpenSSL"
31221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    nor may "OpenSSL" appear in their names without prior written
32221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    permission of the OpenSSL Project.
33221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
34221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 6. Redistributions of any form whatsoever must retain the following
35221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    acknowledgment:
36221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
37221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
39221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * OF THE POSSIBILITY OF SUCH DAMAGE.
51221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ====================================================================
52221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
53221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * This product includes cryptographic software written by Eric Young
54221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * (eay@cryptsoft.com).  This product includes software written by Tim
55221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Hudson (tjh@cryptsoft.com).
56221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
57221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
58221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
59221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Experimental ASN1 BIO. When written through the data is converted
60221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * to an ASN1 string type: default is OCTET STRING. Additional functions
61221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * can be provided to add prefix and suffix data.
62221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
63221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
64221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <string.h>
65221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/bio.h>
66221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/asn1.h>
67221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
68221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Must be large enough for biggest tag+length */
69221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define DEFAULT_ASN1_BUF_SIZE 20
70221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
71221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromtypedef enum
72221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
73221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ASN1_STATE_START,
74221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ASN1_STATE_PRE_COPY,
75221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ASN1_STATE_HEADER,
76221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ASN1_STATE_HEADER_COPY,
77221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ASN1_STATE_DATA_COPY,
78221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ASN1_STATE_POST_COPY,
79221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ASN1_STATE_DONE
80221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} asn1_bio_state_t;
81221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
82221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromtypedef struct BIO_ASN1_EX_FUNCS_st
83221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
84221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_ps_func	*ex_func;
85221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_ps_func	*ex_free_func;
86221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} BIO_ASN1_EX_FUNCS;
87221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
88221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromtypedef struct BIO_ASN1_BUF_CTX_t
89221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
90221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Internal state */
91221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_state_t state;
92221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Internal buffer */
93221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *buf;
94221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Size of buffer */
95221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int bufsize;
96221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Current position in buffer */
97221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int bufpos;
98221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Current buffer length */
99221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int buflen;
100221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Amount of data to copy */
101221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int copylen;
102221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Class and tag to use */
103221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int asn1_class, asn1_tag;
104221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
105221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Extra buffer for prefix and suffix data */
106221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *ex_buf;
107221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int ex_len;
108221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int ex_pos;
109221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	void *ex_arg;
110221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} BIO_ASN1_BUF_CTX;
111221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
112221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
113221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_write(BIO *h, const char *buf,int num);
114221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_read(BIO *h, char *buf, int size);
115221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_puts(BIO *h, const char *str);
116221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_gets(BIO *h, char *str, int size);
117221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
118221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_new(BIO *h);
119221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_free(BIO *data);
120221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
121221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
122221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
123221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
124221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				asn1_ps_func *cleanup, asn1_bio_state_t next);
125221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
126221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				asn1_ps_func *setup,
127221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				asn1_bio_state_t ex_state,
128221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				asn1_bio_state_t other_state);
129221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
130221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic BIO_METHOD methods_asn1=
131221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
132221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_TYPE_ASN1,
133221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	"asn1",
134221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_write,
135221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_read,
136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_puts,
137221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_gets,
138221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_ctrl,
139221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_new,
140221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_free,
141221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	asn1_bio_callback_ctrl,
142221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	};
143221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
144221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromBIO_METHOD *BIO_f_asn1(void)
145221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
146221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return(&methods_asn1);
147221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
148221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
149221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
150221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_new(BIO *b)
151221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
152221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_ASN1_BUF_CTX *ctx;
153221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
154221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!ctx)
155221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
156221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
157c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		{
158c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		OPENSSL_free(ctx);
159221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
160c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		}
161221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	b->init = 1;
162221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	b->ptr = (char *)ctx;
163221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	b->flags = 0;
164221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 1;
165221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
166221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
167221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
168221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
169221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->buf = OPENSSL_malloc(size);
170221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!ctx->buf)
171221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
172221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->bufsize = size;
173221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->bufpos = 0;
174221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->buflen = 0;
175221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->copylen = 0;
176221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->asn1_class = V_ASN1_UNIVERSAL;
177221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->asn1_tag = V_ASN1_OCTET_STRING;
178221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->ex_buf = 0;
179221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->ex_pos = 0;
180221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->ex_len = 0;
181221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx->state = ASN1_STATE_START;
182221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 1;
183221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
184221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
185221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_free(BIO *b)
186221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
187221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_ASN1_BUF_CTX *ctx;
188221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
189221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ctx == NULL)
190221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
191221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ctx->buf)
192221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		OPENSSL_free(ctx->buf);
193221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	OPENSSL_free(ctx);
194221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	b->init = 0;
195221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	b->ptr = NULL;
196221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	b->flags = 0;
197221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 1;
198221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
199221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
200221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_write(BIO *b, const char *in , int inl)
201221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
202221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_ASN1_BUF_CTX *ctx;
203221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int wrmax, wrlen, ret;
204221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *p;
205221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!in || (inl < 0) || (b->next_bio == NULL))
206221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
207221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
208221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ctx == NULL)
209221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
210221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
211221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	wrlen = 0;
212221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret = -1;
213221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
214221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	for(;;)
215221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
216221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (ctx->state)
217221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
218221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
219221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			/* Setup prefix data, call it */
220221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case ASN1_STATE_START:
221221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
222221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
223221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				return 0;
224221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			break;
225221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
226221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			/* Copy any pre data first */
227221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case ASN1_STATE_PRE_COPY:
228221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
229221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
230221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom							ASN1_STATE_HEADER);
231221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
232221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (ret <= 0)
233221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				goto done;
234221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
235221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			break;
236221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
237221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case ASN1_STATE_HEADER:
238221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ctx->buflen =
239221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
240221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			OPENSSL_assert(ctx->buflen <= ctx->bufsize);
241221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			p = ctx->buf;
242221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ASN1_put_object(&p, 0, inl,
243221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					ctx->asn1_tag, ctx->asn1_class);
244221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ctx->copylen = inl;
245221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ctx->state = ASN1_STATE_HEADER_COPY;
246221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
247221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			break;
248221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
249221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case ASN1_STATE_HEADER_COPY:
250221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ret = BIO_write(b->next_bio,
251221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					ctx->buf + ctx->bufpos, ctx->buflen);
252221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (ret <= 0)
253221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				goto done;
254221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
255221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ctx->buflen -= ret;
256221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (ctx->buflen)
257221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ctx->bufpos += ret;
258221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			else
259221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				{
260221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ctx->bufpos = 0;
261221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ctx->state = ASN1_STATE_DATA_COPY;
262221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				}
263221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
264221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			break;
265221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
266221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case ASN1_STATE_DATA_COPY:
267221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
268221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (inl > ctx->copylen)
269221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				wrmax = ctx->copylen;
270221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			else
271221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				wrmax = inl;
272221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ret = BIO_write(b->next_bio, in, wrmax);
273221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (ret <= 0)
274221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
275221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			wrlen += ret;
276221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ctx->copylen -= ret;
277221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			in += ret;
278221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			inl -= ret;
279221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
280221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (ctx->copylen == 0)
281221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ctx->state = ASN1_STATE_HEADER;
282221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
283221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (inl == 0)
284221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				goto done;
285221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
286221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			break;
287221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
288221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			default:
289221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			BIO_clear_retry_flags(b);
290221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
291221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
292221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
293221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
294221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
295221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
296221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	done:
297221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_clear_retry_flags(b);
298221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_copy_next_retry(b);
299221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
300221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return (wrlen > 0) ? wrlen : ret;
301221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
302221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
303221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
304221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
305221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				asn1_ps_func *cleanup, asn1_bio_state_t next)
306221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
307221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int ret;
308221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ctx->ex_len <= 0)
309221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 1;
310221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	for(;;)
311221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
312221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
313221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom								ctx->ex_len);
314221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (ret <= 0)
315221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			break;
316221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ctx->ex_len -= ret;
317221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (ctx->ex_len > 0)
318221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ctx->ex_pos += ret;
319221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else
320221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
321221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if(cleanup)
322221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				cleanup(b, &ctx->ex_buf, &ctx->ex_len,
323221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom								&ctx->ex_arg);
324221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ctx->state = next;
325221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ctx->ex_pos = 0;
326221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			break;
327221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
328221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
329221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
330221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
331221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
332221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
333221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				asn1_ps_func *setup,
334221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				asn1_bio_state_t ex_state,
335221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				asn1_bio_state_t other_state)
336221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
337221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
338221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
339221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		BIO_clear_retry_flags(b);
340221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
341221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
342221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ctx->ex_len > 0)
343221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ctx->state = ex_state;
344221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
345221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ctx->state = other_state;
346221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 1;
347221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
348221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
349221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_read(BIO *b, char *in , int inl)
350221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
351221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!b->next_bio)
352221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
353221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return BIO_read(b->next_bio, in , inl);
354221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
355221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
356221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_puts(BIO *b, const char *str)
357221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
358221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return asn1_bio_write(b, str, strlen(str));
359221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
360221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
361221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_gets(BIO *b, char *str, int size)
362221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
363221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!b->next_bio)
364221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
365221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return BIO_gets(b->next_bio, str , size);
366221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
367221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
368221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
369221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
370221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (b->next_bio == NULL) return(0);
371221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return BIO_callback_ctrl(b->next_bio,cmd,fp);
372221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
373221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
374221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
375221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
376221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_ASN1_BUF_CTX *ctx;
377221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_ASN1_EX_FUNCS *ex_func;
378221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	long ret = 1;
379221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
380221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ctx == NULL)
381221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
382221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	switch(cmd)
383221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
384221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
385221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case BIO_C_SET_PREFIX:
386221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ex_func = arg2;
387221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ctx->prefix  = ex_func->ex_func;
388221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ctx->prefix_free  = ex_func->ex_free_func;
389221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
390221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
391221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case BIO_C_GET_PREFIX:
392221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ex_func = arg2;
393221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ex_func->ex_func = ctx->prefix;
394221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ex_func->ex_free_func = ctx->prefix_free;
395221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
396221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
397221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case BIO_C_SET_SUFFIX:
398221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ex_func = arg2;
399221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ctx->suffix  = ex_func->ex_func;
400221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ctx->suffix_free  = ex_func->ex_free_func;
401221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
402221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
403221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case BIO_C_GET_SUFFIX:
404221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ex_func = arg2;
405221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ex_func->ex_func = ctx->suffix;
406221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ex_func->ex_free_func = ctx->suffix_free;
407221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
408221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
409221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case BIO_C_SET_EX_ARG:
410221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ctx->ex_arg = arg2;
411221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
412221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
413221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case BIO_C_GET_EX_ARG:
414221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*(void **)arg2 = ctx->ex_arg;
415221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
416221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
417221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case BIO_CTRL_FLUSH:
418221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!b->next_bio)
419221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
420221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
421221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		/* Call post function if possible */
422221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (ctx->state == ASN1_STATE_HEADER)
423221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
424221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
425221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
426221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				return 0;
427221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
428221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
429221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (ctx->state == ASN1_STATE_POST_COPY)
430221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
431221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
432221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom							ASN1_STATE_DONE);
433221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (ret <= 0)
434221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				return ret;
435221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
436221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
437221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (ctx->state == ASN1_STATE_DONE)
438221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
439221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else
440221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
441221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			BIO_clear_retry_flags(b);
442221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
443221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
444221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
445221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
446221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
447221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		default:
448221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!b->next_bio)
449221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
450221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
451221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
452221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
453221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
454221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
455221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
456221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
457221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_set_ex(BIO *b, int cmd,
458221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
459221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
460221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_ASN1_EX_FUNCS extmp;
461221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	extmp.ex_func = ex_func;
462221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	extmp.ex_free_func = ex_free_func;
463221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return BIO_ctrl(b, cmd, 0, &extmp);
464221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
465221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
466221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_bio_get_ex(BIO *b, int cmd,
467221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
468221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
469221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BIO_ASN1_EX_FUNCS extmp;
470221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int ret;
471221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret = BIO_ctrl(b, cmd, 0, &extmp);
472221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ret > 0)
473221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
474221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*ex_func = extmp.ex_func;
475221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*ex_free_func = extmp.ex_free_func;
476221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
477221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
478221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
479221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
480221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
481221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
482221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
483221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
484221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
485221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
486221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
487221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
488221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
489221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
490221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
491221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
492221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
493221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
494221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
495221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
496221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
497221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
498221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
499