bio_asn1.c revision 306195
1250003Sadrian/* bio_asn1.c */
2250003Sadrian/*
3250003Sadrian * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4250003Sadrian * project.
5250003Sadrian */
6250003Sadrian/* ====================================================================
7250003Sadrian * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
8250003Sadrian *
9250003Sadrian * Redistribution and use in source and binary forms, with or without
10250003Sadrian * modification, are permitted provided that the following conditions
11250003Sadrian * are met:
12250003Sadrian *
13250003Sadrian * 1. Redistributions of source code must retain the above copyright
14250003Sadrian *    notice, this list of conditions and the following disclaimer.
15250003Sadrian *
16250003Sadrian * 2. Redistributions in binary form must reproduce the above copyright
17250003Sadrian *    notice, this list of conditions and the following disclaimer in
18250003Sadrian *    the documentation and/or other materials provided with the
19250003Sadrian *    distribution.
20250003Sadrian *
21250003Sadrian * 3. All advertising materials mentioning features or use of this
22250003Sadrian *    software must display the following acknowledgment:
23250003Sadrian *    "This product includes software developed by the OpenSSL Project
24250003Sadrian *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25250003Sadrian *
26250003Sadrian * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27250003Sadrian *    endorse or promote products derived from this software without
28250003Sadrian *    prior written permission. For written permission, please contact
29250003Sadrian *    licensing@OpenSSL.org.
30250003Sadrian *
31250003Sadrian * 5. Products derived from this software may not be called "OpenSSL"
32250003Sadrian *    nor may "OpenSSL" appear in their names without prior written
33250003Sadrian *    permission of the OpenSSL Project.
34250003Sadrian *
35250003Sadrian * 6. Redistributions of any form whatsoever must retain the following
36250003Sadrian *    acknowledgment:
37250003Sadrian *    "This product includes software developed by the OpenSSL Project
38250003Sadrian *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39250003Sadrian *
40250003Sadrian * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41250003Sadrian * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42250003Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43250003Sadrian * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44250003Sadrian * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45250003Sadrian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46250003Sadrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47250003Sadrian * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48250003Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49250003Sadrian * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50250003Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51250003Sadrian * OF THE POSSIBILITY OF SUCH DAMAGE.
52250003Sadrian * ====================================================================
53250003Sadrian *
54250003Sadrian * This product includes cryptographic software written by Eric Young
55250003Sadrian * (eay@cryptsoft.com).  This product includes software written by Tim
56250003Sadrian * Hudson (tjh@cryptsoft.com).
57250003Sadrian *
58250003Sadrian */
59250003Sadrian
60250003Sadrian/*
61250003Sadrian * Experimental ASN1 BIO. When written through the data is converted to an
62250003Sadrian * ASN1 string type: default is OCTET STRING. Additional functions can be
63250003Sadrian * provided to add prefix and suffix data.
64250003Sadrian */
65250003Sadrian
66250003Sadrian#include <string.h>
67250003Sadrian#include <openssl/bio.h>
68250003Sadrian#include <openssl/asn1.h>
69250003Sadrian
70250003Sadrian/* Must be large enough for biggest tag+length */
71250003Sadrian#define DEFAULT_ASN1_BUF_SIZE 20
72250003Sadrian
73250003Sadriantypedef enum {
74250003Sadrian    ASN1_STATE_START,
75250003Sadrian    ASN1_STATE_PRE_COPY,
76250003Sadrian    ASN1_STATE_HEADER,
77250003Sadrian    ASN1_STATE_HEADER_COPY,
78250003Sadrian    ASN1_STATE_DATA_COPY,
79250003Sadrian    ASN1_STATE_POST_COPY,
80250003Sadrian    ASN1_STATE_DONE
81250003Sadrian} asn1_bio_state_t;
82250003Sadrian
83250003Sadriantypedef struct BIO_ASN1_EX_FUNCS_st {
84250003Sadrian    asn1_ps_func *ex_func;
85250003Sadrian    asn1_ps_func *ex_free_func;
86250003Sadrian} BIO_ASN1_EX_FUNCS;
87250003Sadrian
88250003Sadriantypedef struct BIO_ASN1_BUF_CTX_t {
89250003Sadrian    /* Internal state */
90250003Sadrian    asn1_bio_state_t state;
91250003Sadrian    /* Internal buffer */
92250003Sadrian    unsigned char *buf;
93250003Sadrian    /* Size of buffer */
94250003Sadrian    int bufsize;
95250003Sadrian    /* Current position in buffer */
96250003Sadrian    int bufpos;
97250003Sadrian    /* Current buffer length */
98250003Sadrian    int buflen;
99250003Sadrian    /* Amount of data to copy */
100250003Sadrian    int copylen;
101250003Sadrian    /* Class and tag to use */
102250003Sadrian    int asn1_class, asn1_tag;
103250003Sadrian    asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
104250003Sadrian    /* Extra buffer for prefix and suffix data */
105250003Sadrian    unsigned char *ex_buf;
106250003Sadrian    int ex_len;
107250003Sadrian    int ex_pos;
108250003Sadrian    void *ex_arg;
109250003Sadrian} BIO_ASN1_BUF_CTX;
110250003Sadrian
111250003Sadrianstatic int asn1_bio_write(BIO *h, const char *buf, int num);
112250003Sadrianstatic int asn1_bio_read(BIO *h, char *buf, int size);
113250003Sadrianstatic int asn1_bio_puts(BIO *h, const char *str);
114250003Sadrianstatic int asn1_bio_gets(BIO *h, char *str, int size);
115250003Sadrianstatic long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
116250003Sadrianstatic int asn1_bio_new(BIO *h);
117250003Sadrianstatic int asn1_bio_free(BIO *data);
118250003Sadrianstatic long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
119250003Sadrian
120250003Sadrianstatic int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
121250003Sadrianstatic int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
122250003Sadrian                             asn1_ps_func *cleanup, asn1_bio_state_t next);
123250003Sadrianstatic int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
124250003Sadrian                             asn1_ps_func *setup,
125250003Sadrian                             asn1_bio_state_t ex_state,
126250003Sadrian                             asn1_bio_state_t other_state);
127250003Sadrian
128250003Sadrianstatic BIO_METHOD methods_asn1 = {
129250003Sadrian    BIO_TYPE_ASN1,
130250003Sadrian    "asn1",
131250003Sadrian    asn1_bio_write,
132250003Sadrian    asn1_bio_read,
133250003Sadrian    asn1_bio_puts,
134250003Sadrian    asn1_bio_gets,
135250003Sadrian    asn1_bio_ctrl,
136250003Sadrian    asn1_bio_new,
137250003Sadrian    asn1_bio_free,
138250003Sadrian    asn1_bio_callback_ctrl,
139250003Sadrian};
140250003Sadrian
141250003SadrianBIO_METHOD *BIO_f_asn1(void)
142250003Sadrian{
143250003Sadrian    return (&methods_asn1);
144250003Sadrian}
145250003Sadrian
146250003Sadrianstatic int asn1_bio_new(BIO *b)
147250003Sadrian{
148250003Sadrian    BIO_ASN1_BUF_CTX *ctx;
149250003Sadrian    ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
150250003Sadrian    if (!ctx)
151250003Sadrian        return 0;
152250003Sadrian    if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
153250003Sadrian        OPENSSL_free(ctx);
154250003Sadrian        return 0;
155250003Sadrian    }
156250003Sadrian    b->init = 1;
157250003Sadrian    b->ptr = (char *)ctx;
158250003Sadrian    b->flags = 0;
159250003Sadrian    return 1;
160250003Sadrian}
161250003Sadrian
162250003Sadrianstatic int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
163250003Sadrian{
164250003Sadrian    ctx->buf = OPENSSL_malloc(size);
165250003Sadrian    if (!ctx->buf)
166250003Sadrian        return 0;
167250003Sadrian    ctx->bufsize = size;
168250003Sadrian    ctx->bufpos = 0;
169250003Sadrian    ctx->buflen = 0;
170250003Sadrian    ctx->copylen = 0;
171250003Sadrian    ctx->asn1_class = V_ASN1_UNIVERSAL;
172250003Sadrian    ctx->asn1_tag = V_ASN1_OCTET_STRING;
173250003Sadrian    ctx->ex_buf = NULL;
174250003Sadrian    ctx->ex_len = 0;
175250003Sadrian    ctx->ex_pos = 0;
176250003Sadrian    ctx->state = ASN1_STATE_START;
177250003Sadrian    ctx->prefix = ctx->prefix_free = ctx->suffix = ctx->suffix_free = NULL;
178250003Sadrian    ctx->ex_arg = NULL;
179250003Sadrian    return 1;
180250003Sadrian}
181250003Sadrian
182250003Sadrianstatic int asn1_bio_free(BIO *b)
183250003Sadrian{
184250003Sadrian    BIO_ASN1_BUF_CTX *ctx;
185250003Sadrian    ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
186250003Sadrian    if (ctx == NULL)
187250003Sadrian        return 0;
188250003Sadrian    if (ctx->buf)
189250003Sadrian        OPENSSL_free(ctx->buf);
190250003Sadrian    OPENSSL_free(ctx);
191250003Sadrian    b->init = 0;
192250003Sadrian    b->ptr = NULL;
193250003Sadrian    b->flags = 0;
194250003Sadrian    return 1;
195250003Sadrian}
196250003Sadrian
197250003Sadrianstatic int asn1_bio_write(BIO *b, const char *in, int inl)
198250003Sadrian{
199250003Sadrian    BIO_ASN1_BUF_CTX *ctx;
200250003Sadrian    int wrmax, wrlen, ret;
201250003Sadrian    unsigned char *p;
202250003Sadrian    if (!in || (inl < 0) || (b->next_bio == NULL))
203250003Sadrian        return 0;
204250003Sadrian    ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
205250003Sadrian    if (ctx == NULL)
206250003Sadrian        return 0;
207250003Sadrian
208250003Sadrian    wrlen = 0;
209250003Sadrian    ret = -1;
210250003Sadrian
211250003Sadrian    for (;;) {
212250003Sadrian        switch (ctx->state) {
213250003Sadrian
214250003Sadrian            /* Setup prefix data, call it */
215250003Sadrian        case ASN1_STATE_START:
216250003Sadrian            if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
217250003Sadrian                                   ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
218250003Sadrian                return 0;
219250003Sadrian            break;
220250003Sadrian
221250003Sadrian            /* Copy any pre data first */
222250003Sadrian        case ASN1_STATE_PRE_COPY:
223250003Sadrian
224250003Sadrian            ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
225250003Sadrian                                    ASN1_STATE_HEADER);
226250003Sadrian
227250003Sadrian            if (ret <= 0)
228250003Sadrian                goto done;
229250003Sadrian
230250003Sadrian            break;
231250003Sadrian
232250003Sadrian        case ASN1_STATE_HEADER:
233250003Sadrian            ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
234250003Sadrian            OPENSSL_assert(ctx->buflen <= ctx->bufsize);
235250003Sadrian            p = ctx->buf;
236250003Sadrian            ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
237250003Sadrian            ctx->copylen = inl;
238250003Sadrian            ctx->state = ASN1_STATE_HEADER_COPY;
239250003Sadrian
240250003Sadrian            break;
241250003Sadrian
242250003Sadrian        case ASN1_STATE_HEADER_COPY:
243250003Sadrian            ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
244250003Sadrian            if (ret <= 0)
245250003Sadrian                goto done;
246250003Sadrian
247250003Sadrian            ctx->buflen -= ret;
248250003Sadrian            if (ctx->buflen)
249250003Sadrian                ctx->bufpos += ret;
250250003Sadrian            else {
251250003Sadrian                ctx->bufpos = 0;
252250003Sadrian                ctx->state = ASN1_STATE_DATA_COPY;
253250003Sadrian            }
254250003Sadrian
255250003Sadrian            break;
256250003Sadrian
257250003Sadrian        case ASN1_STATE_DATA_COPY:
258250003Sadrian
259250003Sadrian            if (inl > ctx->copylen)
260250003Sadrian                wrmax = ctx->copylen;
261250003Sadrian            else
262250003Sadrian                wrmax = inl;
263250003Sadrian            ret = BIO_write(b->next_bio, in, wrmax);
264250003Sadrian            if (ret <= 0)
265250003Sadrian                break;
266250003Sadrian            wrlen += ret;
267250003Sadrian            ctx->copylen -= ret;
268250003Sadrian            in += ret;
269250003Sadrian            inl -= ret;
270250003Sadrian
271250003Sadrian            if (ctx->copylen == 0)
272250003Sadrian                ctx->state = ASN1_STATE_HEADER;
273250003Sadrian
274250003Sadrian            if (inl == 0)
275250003Sadrian                goto done;
276250003Sadrian
277250003Sadrian            break;
278250003Sadrian
279250003Sadrian        default:
280250003Sadrian            BIO_clear_retry_flags(b);
281250003Sadrian            return 0;
282250003Sadrian
283250003Sadrian        }
284250003Sadrian
285250003Sadrian    }
286250003Sadrian
287250003Sadrian done:
288250003Sadrian    BIO_clear_retry_flags(b);
289250003Sadrian    BIO_copy_next_retry(b);
290250003Sadrian
291250003Sadrian    return (wrlen > 0) ? wrlen : ret;
292250003Sadrian
293250003Sadrian}
294250003Sadrian
295250003Sadrianstatic int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
296250003Sadrian                             asn1_ps_func *cleanup, asn1_bio_state_t next)
297250003Sadrian{
298250003Sadrian    int ret;
299250003Sadrian    if (ctx->ex_len <= 0)
300250003Sadrian        return 1;
301250003Sadrian    for (;;) {
302250003Sadrian        ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
303250003Sadrian        if (ret <= 0)
304250003Sadrian            break;
305250003Sadrian        ctx->ex_len -= ret;
306250003Sadrian        if (ctx->ex_len > 0)
307250003Sadrian            ctx->ex_pos += ret;
308250003Sadrian        else {
309250003Sadrian            if (cleanup)
310250003Sadrian                cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
311250003Sadrian            ctx->state = next;
312250003Sadrian            ctx->ex_pos = 0;
313250003Sadrian            break;
314250003Sadrian        }
315250003Sadrian    }
316250003Sadrian    return ret;
317250003Sadrian}
318250003Sadrian
319250003Sadrianstatic int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
320250003Sadrian                             asn1_ps_func *setup,
321250003Sadrian                             asn1_bio_state_t ex_state,
322250003Sadrian                             asn1_bio_state_t other_state)
323250003Sadrian{
324250003Sadrian    if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
325250003Sadrian        BIO_clear_retry_flags(b);
326250003Sadrian        return 0;
327250003Sadrian    }
328250003Sadrian    if (ctx->ex_len > 0)
329250003Sadrian        ctx->state = ex_state;
330250003Sadrian    else
331250003Sadrian        ctx->state = other_state;
332250003Sadrian    return 1;
333250003Sadrian}
334250003Sadrian
335250003Sadrianstatic int asn1_bio_read(BIO *b, char *in, int inl)
336250003Sadrian{
337250003Sadrian    if (!b->next_bio)
338250003Sadrian        return 0;
339250003Sadrian    return BIO_read(b->next_bio, in, inl);
340250003Sadrian}
341250003Sadrian
342250003Sadrianstatic int asn1_bio_puts(BIO *b, const char *str)
343250003Sadrian{
344250003Sadrian    return asn1_bio_write(b, str, strlen(str));
345250003Sadrian}
346250003Sadrian
347250003Sadrianstatic int asn1_bio_gets(BIO *b, char *str, int size)
348250003Sadrian{
349250003Sadrian    if (!b->next_bio)
350250003Sadrian        return 0;
351250003Sadrian    return BIO_gets(b->next_bio, str, size);
352250003Sadrian}
353250003Sadrian
354250003Sadrianstatic long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
355250003Sadrian{
356250003Sadrian    if (b->next_bio == NULL)
357250003Sadrian        return (0);
358250003Sadrian    return BIO_callback_ctrl(b->next_bio, cmd, fp);
359250003Sadrian}
360250003Sadrian
361250003Sadrianstatic long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
362250003Sadrian{
363250003Sadrian    BIO_ASN1_BUF_CTX *ctx;
364250003Sadrian    BIO_ASN1_EX_FUNCS *ex_func;
365250003Sadrian    long ret = 1;
366250003Sadrian    ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
367250003Sadrian    if (ctx == NULL)
368250003Sadrian        return 0;
369250003Sadrian    switch (cmd) {
370250003Sadrian
371250003Sadrian    case BIO_C_SET_PREFIX:
372250003Sadrian        ex_func = arg2;
373250003Sadrian        ctx->prefix = ex_func->ex_func;
374250003Sadrian        ctx->prefix_free = ex_func->ex_free_func;
375250003Sadrian        break;
376250003Sadrian
377250003Sadrian    case BIO_C_GET_PREFIX:
378250003Sadrian        ex_func = arg2;
379250003Sadrian        ex_func->ex_func = ctx->prefix;
380250003Sadrian        ex_func->ex_free_func = ctx->prefix_free;
381250003Sadrian        break;
382250003Sadrian
383250003Sadrian    case BIO_C_SET_SUFFIX:
384250003Sadrian        ex_func = arg2;
385250003Sadrian        ctx->suffix = ex_func->ex_func;
386250003Sadrian        ctx->suffix_free = ex_func->ex_free_func;
387250003Sadrian        break;
388250003Sadrian
389250003Sadrian    case BIO_C_GET_SUFFIX:
390250003Sadrian        ex_func = arg2;
391250003Sadrian        ex_func->ex_func = ctx->suffix;
392250003Sadrian        ex_func->ex_free_func = ctx->suffix_free;
393250003Sadrian        break;
394250003Sadrian
395250003Sadrian    case BIO_C_SET_EX_ARG:
396250003Sadrian        ctx->ex_arg = arg2;
397250003Sadrian        break;
398250003Sadrian
399250003Sadrian    case BIO_C_GET_EX_ARG:
400250003Sadrian        *(void **)arg2 = ctx->ex_arg;
401250003Sadrian        break;
402250003Sadrian
403250003Sadrian    case BIO_CTRL_FLUSH:
404250003Sadrian        if (!b->next_bio)
405250003Sadrian            return 0;
406250003Sadrian
407250003Sadrian        /* Call post function if possible */
408250003Sadrian        if (ctx->state == ASN1_STATE_HEADER) {
409250003Sadrian            if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
410250003Sadrian                                   ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
411250003Sadrian                return 0;
412250003Sadrian        }
413250003Sadrian
414250003Sadrian        if (ctx->state == ASN1_STATE_POST_COPY) {
415250003Sadrian            ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
416250003Sadrian                                    ASN1_STATE_DONE);
417250003Sadrian            if (ret <= 0)
418250003Sadrian                return ret;
419250003Sadrian        }
420250003Sadrian
421250003Sadrian        if (ctx->state == ASN1_STATE_DONE)
422250003Sadrian            return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
423250003Sadrian        else {
424250003Sadrian            BIO_clear_retry_flags(b);
425250003Sadrian            return 0;
426250003Sadrian        }
427250003Sadrian        break;
428250003Sadrian
429250003Sadrian    default:
430250003Sadrian        if (!b->next_bio)
431250003Sadrian            return 0;
432250003Sadrian        return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
433250003Sadrian
434250003Sadrian    }
435250003Sadrian
436250003Sadrian    return ret;
437250003Sadrian}
438250003Sadrian
439250003Sadrianstatic int asn1_bio_set_ex(BIO *b, int cmd,
440250003Sadrian                           asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
441250003Sadrian{
442250003Sadrian    BIO_ASN1_EX_FUNCS extmp;
443250003Sadrian    extmp.ex_func = ex_func;
444250003Sadrian    extmp.ex_free_func = ex_free_func;
445250003Sadrian    return BIO_ctrl(b, cmd, 0, &extmp);
446250003Sadrian}
447250003Sadrian
448250003Sadrianstatic int asn1_bio_get_ex(BIO *b, int cmd,
449250003Sadrian                           asn1_ps_func **ex_func,
450250003Sadrian                           asn1_ps_func **ex_free_func)
451250003Sadrian{
452250003Sadrian    BIO_ASN1_EX_FUNCS extmp;
453250003Sadrian    int ret;
454250003Sadrian    ret = BIO_ctrl(b, cmd, 0, &extmp);
455250003Sadrian    if (ret > 0) {
456250003Sadrian        *ex_func = extmp.ex_func;
457250003Sadrian        *ex_free_func = extmp.ex_free_func;
458250003Sadrian    }
459250003Sadrian    return ret;
460250003Sadrian}
461250003Sadrian
462250003Sadrianint BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
463250003Sadrian                        asn1_ps_func *prefix_free)
464250003Sadrian{
465250003Sadrian    return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
466250003Sadrian}
467250003Sadrian
468250003Sadrianint BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
469250003Sadrian                        asn1_ps_func **pprefix_free)
470250003Sadrian{
471250003Sadrian    return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
472250003Sadrian}
473250003Sadrian
474250003Sadrianint BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
475250003Sadrian                        asn1_ps_func *suffix_free)
476250003Sadrian{
477250003Sadrian    return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
478250003Sadrian}
479250003Sadrian
480250003Sadrianint BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
481250003Sadrian                        asn1_ps_func **psuffix_free)
482250003Sadrian{
483250003Sadrian    return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
484250003Sadrian}
485250003Sadrian