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