11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci/* 111cb0ef41Sopenharmony_ci * Experimental ASN1 BIO. When written through the data is converted to an 121cb0ef41Sopenharmony_ci * ASN1 string type: default is OCTET STRING. Additional functions can be 131cb0ef41Sopenharmony_ci * provided to add prefix and suffix data. 141cb0ef41Sopenharmony_ci */ 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci#include <string.h> 171cb0ef41Sopenharmony_ci#include "internal/bio.h" 181cb0ef41Sopenharmony_ci#include <openssl/asn1.h> 191cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci/* Must be large enough for biggest tag+length */ 221cb0ef41Sopenharmony_ci#define DEFAULT_ASN1_BUF_SIZE 20 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_citypedef enum { 251cb0ef41Sopenharmony_ci ASN1_STATE_START, 261cb0ef41Sopenharmony_ci ASN1_STATE_PRE_COPY, 271cb0ef41Sopenharmony_ci ASN1_STATE_HEADER, 281cb0ef41Sopenharmony_ci ASN1_STATE_HEADER_COPY, 291cb0ef41Sopenharmony_ci ASN1_STATE_DATA_COPY, 301cb0ef41Sopenharmony_ci ASN1_STATE_POST_COPY, 311cb0ef41Sopenharmony_ci ASN1_STATE_DONE 321cb0ef41Sopenharmony_ci} asn1_bio_state_t; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_citypedef struct BIO_ASN1_EX_FUNCS_st { 351cb0ef41Sopenharmony_ci asn1_ps_func *ex_func; 361cb0ef41Sopenharmony_ci asn1_ps_func *ex_free_func; 371cb0ef41Sopenharmony_ci} BIO_ASN1_EX_FUNCS; 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_citypedef struct BIO_ASN1_BUF_CTX_t { 401cb0ef41Sopenharmony_ci /* Internal state */ 411cb0ef41Sopenharmony_ci asn1_bio_state_t state; 421cb0ef41Sopenharmony_ci /* Internal buffer */ 431cb0ef41Sopenharmony_ci unsigned char *buf; 441cb0ef41Sopenharmony_ci /* Size of buffer */ 451cb0ef41Sopenharmony_ci int bufsize; 461cb0ef41Sopenharmony_ci /* Current position in buffer */ 471cb0ef41Sopenharmony_ci int bufpos; 481cb0ef41Sopenharmony_ci /* Current buffer length */ 491cb0ef41Sopenharmony_ci int buflen; 501cb0ef41Sopenharmony_ci /* Amount of data to copy */ 511cb0ef41Sopenharmony_ci int copylen; 521cb0ef41Sopenharmony_ci /* Class and tag to use */ 531cb0ef41Sopenharmony_ci int asn1_class, asn1_tag; 541cb0ef41Sopenharmony_ci asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free; 551cb0ef41Sopenharmony_ci /* Extra buffer for prefix and suffix data */ 561cb0ef41Sopenharmony_ci unsigned char *ex_buf; 571cb0ef41Sopenharmony_ci int ex_len; 581cb0ef41Sopenharmony_ci int ex_pos; 591cb0ef41Sopenharmony_ci void *ex_arg; 601cb0ef41Sopenharmony_ci} BIO_ASN1_BUF_CTX; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_cistatic int asn1_bio_write(BIO *h, const char *buf, int num); 631cb0ef41Sopenharmony_cistatic int asn1_bio_read(BIO *h, char *buf, int size); 641cb0ef41Sopenharmony_cistatic int asn1_bio_puts(BIO *h, const char *str); 651cb0ef41Sopenharmony_cistatic int asn1_bio_gets(BIO *h, char *str, int size); 661cb0ef41Sopenharmony_cistatic long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2); 671cb0ef41Sopenharmony_cistatic int asn1_bio_new(BIO *h); 681cb0ef41Sopenharmony_cistatic int asn1_bio_free(BIO *data); 691cb0ef41Sopenharmony_cistatic long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_cistatic int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size); 721cb0ef41Sopenharmony_cistatic int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, 731cb0ef41Sopenharmony_ci asn1_ps_func *cleanup, asn1_bio_state_t next); 741cb0ef41Sopenharmony_cistatic int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, 751cb0ef41Sopenharmony_ci asn1_ps_func *setup, 761cb0ef41Sopenharmony_ci asn1_bio_state_t ex_state, 771cb0ef41Sopenharmony_ci asn1_bio_state_t other_state); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_cistatic const BIO_METHOD methods_asn1 = { 801cb0ef41Sopenharmony_ci BIO_TYPE_ASN1, 811cb0ef41Sopenharmony_ci "asn1", 821cb0ef41Sopenharmony_ci bwrite_conv, 831cb0ef41Sopenharmony_ci asn1_bio_write, 841cb0ef41Sopenharmony_ci bread_conv, 851cb0ef41Sopenharmony_ci asn1_bio_read, 861cb0ef41Sopenharmony_ci asn1_bio_puts, 871cb0ef41Sopenharmony_ci asn1_bio_gets, 881cb0ef41Sopenharmony_ci asn1_bio_ctrl, 891cb0ef41Sopenharmony_ci asn1_bio_new, 901cb0ef41Sopenharmony_ci asn1_bio_free, 911cb0ef41Sopenharmony_ci asn1_bio_callback_ctrl, 921cb0ef41Sopenharmony_ci}; 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ciconst BIO_METHOD *BIO_f_asn1(void) 951cb0ef41Sopenharmony_ci{ 961cb0ef41Sopenharmony_ci return &methods_asn1; 971cb0ef41Sopenharmony_ci} 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_cistatic int asn1_bio_new(BIO *b) 1001cb0ef41Sopenharmony_ci{ 1011cb0ef41Sopenharmony_ci BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci if (ctx == NULL) { 1041cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); 1051cb0ef41Sopenharmony_ci return 0; 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) { 1081cb0ef41Sopenharmony_ci OPENSSL_free(ctx); 1091cb0ef41Sopenharmony_ci return 0; 1101cb0ef41Sopenharmony_ci } 1111cb0ef41Sopenharmony_ci BIO_set_data(b, ctx); 1121cb0ef41Sopenharmony_ci BIO_set_init(b, 1); 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci return 1; 1151cb0ef41Sopenharmony_ci} 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_cistatic int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size) 1181cb0ef41Sopenharmony_ci{ 1191cb0ef41Sopenharmony_ci if (size <= 0 || (ctx->buf = OPENSSL_malloc(size)) == NULL) { 1201cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); 1211cb0ef41Sopenharmony_ci return 0; 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci ctx->bufsize = size; 1241cb0ef41Sopenharmony_ci ctx->asn1_class = V_ASN1_UNIVERSAL; 1251cb0ef41Sopenharmony_ci ctx->asn1_tag = V_ASN1_OCTET_STRING; 1261cb0ef41Sopenharmony_ci ctx->state = ASN1_STATE_START; 1271cb0ef41Sopenharmony_ci return 1; 1281cb0ef41Sopenharmony_ci} 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_cistatic int asn1_bio_free(BIO *b) 1311cb0ef41Sopenharmony_ci{ 1321cb0ef41Sopenharmony_ci BIO_ASN1_BUF_CTX *ctx; 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci if (b == NULL) 1351cb0ef41Sopenharmony_ci return 0; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci ctx = BIO_get_data(b); 1381cb0ef41Sopenharmony_ci if (ctx == NULL) 1391cb0ef41Sopenharmony_ci return 0; 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci if (ctx->prefix_free != NULL) 1421cb0ef41Sopenharmony_ci ctx->prefix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg); 1431cb0ef41Sopenharmony_ci if (ctx->suffix_free != NULL) 1441cb0ef41Sopenharmony_ci ctx->suffix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg); 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci OPENSSL_free(ctx->buf); 1471cb0ef41Sopenharmony_ci OPENSSL_free(ctx); 1481cb0ef41Sopenharmony_ci BIO_set_data(b, NULL); 1491cb0ef41Sopenharmony_ci BIO_set_init(b, 0); 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci return 1; 1521cb0ef41Sopenharmony_ci} 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_cistatic int asn1_bio_write(BIO *b, const char *in, int inl) 1551cb0ef41Sopenharmony_ci{ 1561cb0ef41Sopenharmony_ci BIO_ASN1_BUF_CTX *ctx; 1571cb0ef41Sopenharmony_ci int wrmax, wrlen, ret; 1581cb0ef41Sopenharmony_ci unsigned char *p; 1591cb0ef41Sopenharmony_ci BIO *next; 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci ctx = BIO_get_data(b); 1621cb0ef41Sopenharmony_ci next = BIO_next(b); 1631cb0ef41Sopenharmony_ci if (in == NULL || inl < 0 || ctx == NULL || next == NULL) 1641cb0ef41Sopenharmony_ci return 0; 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci wrlen = 0; 1671cb0ef41Sopenharmony_ci ret = -1; 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci for (;;) { 1701cb0ef41Sopenharmony_ci switch (ctx->state) { 1711cb0ef41Sopenharmony_ci /* Setup prefix data, call it */ 1721cb0ef41Sopenharmony_ci case ASN1_STATE_START: 1731cb0ef41Sopenharmony_ci if (!asn1_bio_setup_ex(b, ctx, ctx->prefix, 1741cb0ef41Sopenharmony_ci ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER)) 1751cb0ef41Sopenharmony_ci return -1; 1761cb0ef41Sopenharmony_ci break; 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci /* Copy any pre data first */ 1791cb0ef41Sopenharmony_ci case ASN1_STATE_PRE_COPY: 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free, 1821cb0ef41Sopenharmony_ci ASN1_STATE_HEADER); 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci if (ret <= 0) 1851cb0ef41Sopenharmony_ci goto done; 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci break; 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci case ASN1_STATE_HEADER: 1901cb0ef41Sopenharmony_ci ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl; 1911cb0ef41Sopenharmony_ci if (!ossl_assert(ctx->buflen <= ctx->bufsize)) 1921cb0ef41Sopenharmony_ci return -1; 1931cb0ef41Sopenharmony_ci p = ctx->buf; 1941cb0ef41Sopenharmony_ci ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class); 1951cb0ef41Sopenharmony_ci ctx->copylen = inl; 1961cb0ef41Sopenharmony_ci ctx->state = ASN1_STATE_HEADER_COPY; 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci break; 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci case ASN1_STATE_HEADER_COPY: 2011cb0ef41Sopenharmony_ci ret = BIO_write(next, ctx->buf + ctx->bufpos, ctx->buflen); 2021cb0ef41Sopenharmony_ci if (ret <= 0) 2031cb0ef41Sopenharmony_ci goto done; 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci ctx->buflen -= ret; 2061cb0ef41Sopenharmony_ci if (ctx->buflen) 2071cb0ef41Sopenharmony_ci ctx->bufpos += ret; 2081cb0ef41Sopenharmony_ci else { 2091cb0ef41Sopenharmony_ci ctx->bufpos = 0; 2101cb0ef41Sopenharmony_ci ctx->state = ASN1_STATE_DATA_COPY; 2111cb0ef41Sopenharmony_ci } 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci break; 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci case ASN1_STATE_DATA_COPY: 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci if (inl > ctx->copylen) 2181cb0ef41Sopenharmony_ci wrmax = ctx->copylen; 2191cb0ef41Sopenharmony_ci else 2201cb0ef41Sopenharmony_ci wrmax = inl; 2211cb0ef41Sopenharmony_ci ret = BIO_write(next, in, wrmax); 2221cb0ef41Sopenharmony_ci if (ret <= 0) 2231cb0ef41Sopenharmony_ci goto done; 2241cb0ef41Sopenharmony_ci wrlen += ret; 2251cb0ef41Sopenharmony_ci ctx->copylen -= ret; 2261cb0ef41Sopenharmony_ci in += ret; 2271cb0ef41Sopenharmony_ci inl -= ret; 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci if (ctx->copylen == 0) 2301cb0ef41Sopenharmony_ci ctx->state = ASN1_STATE_HEADER; 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci if (inl == 0) 2331cb0ef41Sopenharmony_ci goto done; 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci break; 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci case ASN1_STATE_POST_COPY: 2381cb0ef41Sopenharmony_ci case ASN1_STATE_DONE: 2391cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2401cb0ef41Sopenharmony_ci return 0; 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci done: 2471cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2481cb0ef41Sopenharmony_ci BIO_copy_next_retry(b); 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci return (wrlen > 0) ? wrlen : ret; 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci} 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_cistatic int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, 2551cb0ef41Sopenharmony_ci asn1_ps_func *cleanup, asn1_bio_state_t next) 2561cb0ef41Sopenharmony_ci{ 2571cb0ef41Sopenharmony_ci int ret; 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci if (ctx->ex_len <= 0) 2601cb0ef41Sopenharmony_ci return 1; 2611cb0ef41Sopenharmony_ci for (;;) { 2621cb0ef41Sopenharmony_ci ret = BIO_write(BIO_next(b), ctx->ex_buf + ctx->ex_pos, ctx->ex_len); 2631cb0ef41Sopenharmony_ci if (ret <= 0) 2641cb0ef41Sopenharmony_ci break; 2651cb0ef41Sopenharmony_ci ctx->ex_len -= ret; 2661cb0ef41Sopenharmony_ci if (ctx->ex_len > 0) 2671cb0ef41Sopenharmony_ci ctx->ex_pos += ret; 2681cb0ef41Sopenharmony_ci else { 2691cb0ef41Sopenharmony_ci if (cleanup) 2701cb0ef41Sopenharmony_ci cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg); 2711cb0ef41Sopenharmony_ci ctx->state = next; 2721cb0ef41Sopenharmony_ci ctx->ex_pos = 0; 2731cb0ef41Sopenharmony_ci break; 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci } 2761cb0ef41Sopenharmony_ci return ret; 2771cb0ef41Sopenharmony_ci} 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_cistatic int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, 2801cb0ef41Sopenharmony_ci asn1_ps_func *setup, 2811cb0ef41Sopenharmony_ci asn1_bio_state_t ex_state, 2821cb0ef41Sopenharmony_ci asn1_bio_state_t other_state) 2831cb0ef41Sopenharmony_ci{ 2841cb0ef41Sopenharmony_ci if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) { 2851cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2861cb0ef41Sopenharmony_ci return 0; 2871cb0ef41Sopenharmony_ci } 2881cb0ef41Sopenharmony_ci if (ctx->ex_len > 0) 2891cb0ef41Sopenharmony_ci ctx->state = ex_state; 2901cb0ef41Sopenharmony_ci else 2911cb0ef41Sopenharmony_ci ctx->state = other_state; 2921cb0ef41Sopenharmony_ci return 1; 2931cb0ef41Sopenharmony_ci} 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_cistatic int asn1_bio_read(BIO *b, char *in, int inl) 2961cb0ef41Sopenharmony_ci{ 2971cb0ef41Sopenharmony_ci BIO *next = BIO_next(b); 2981cb0ef41Sopenharmony_ci if (next == NULL) 2991cb0ef41Sopenharmony_ci return 0; 3001cb0ef41Sopenharmony_ci return BIO_read(next, in, inl); 3011cb0ef41Sopenharmony_ci} 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_cistatic int asn1_bio_puts(BIO *b, const char *str) 3041cb0ef41Sopenharmony_ci{ 3051cb0ef41Sopenharmony_ci return asn1_bio_write(b, str, strlen(str)); 3061cb0ef41Sopenharmony_ci} 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_cistatic int asn1_bio_gets(BIO *b, char *str, int size) 3091cb0ef41Sopenharmony_ci{ 3101cb0ef41Sopenharmony_ci BIO *next = BIO_next(b); 3111cb0ef41Sopenharmony_ci if (next == NULL) 3121cb0ef41Sopenharmony_ci return 0; 3131cb0ef41Sopenharmony_ci return BIO_gets(next, str, size); 3141cb0ef41Sopenharmony_ci} 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_cistatic long asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 3171cb0ef41Sopenharmony_ci{ 3181cb0ef41Sopenharmony_ci BIO *next = BIO_next(b); 3191cb0ef41Sopenharmony_ci if (next == NULL) 3201cb0ef41Sopenharmony_ci return 0; 3211cb0ef41Sopenharmony_ci return BIO_callback_ctrl(next, cmd, fp); 3221cb0ef41Sopenharmony_ci} 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_cistatic long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2) 3251cb0ef41Sopenharmony_ci{ 3261cb0ef41Sopenharmony_ci BIO_ASN1_BUF_CTX *ctx; 3271cb0ef41Sopenharmony_ci BIO_ASN1_EX_FUNCS *ex_func; 3281cb0ef41Sopenharmony_ci long ret = 1; 3291cb0ef41Sopenharmony_ci BIO *next; 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci ctx = BIO_get_data(b); 3321cb0ef41Sopenharmony_ci if (ctx == NULL) 3331cb0ef41Sopenharmony_ci return 0; 3341cb0ef41Sopenharmony_ci next = BIO_next(b); 3351cb0ef41Sopenharmony_ci switch (cmd) { 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci case BIO_C_SET_PREFIX: 3381cb0ef41Sopenharmony_ci ex_func = arg2; 3391cb0ef41Sopenharmony_ci ctx->prefix = ex_func->ex_func; 3401cb0ef41Sopenharmony_ci ctx->prefix_free = ex_func->ex_free_func; 3411cb0ef41Sopenharmony_ci break; 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci case BIO_C_GET_PREFIX: 3441cb0ef41Sopenharmony_ci ex_func = arg2; 3451cb0ef41Sopenharmony_ci ex_func->ex_func = ctx->prefix; 3461cb0ef41Sopenharmony_ci ex_func->ex_free_func = ctx->prefix_free; 3471cb0ef41Sopenharmony_ci break; 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci case BIO_C_SET_SUFFIX: 3501cb0ef41Sopenharmony_ci ex_func = arg2; 3511cb0ef41Sopenharmony_ci ctx->suffix = ex_func->ex_func; 3521cb0ef41Sopenharmony_ci ctx->suffix_free = ex_func->ex_free_func; 3531cb0ef41Sopenharmony_ci break; 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci case BIO_C_GET_SUFFIX: 3561cb0ef41Sopenharmony_ci ex_func = arg2; 3571cb0ef41Sopenharmony_ci ex_func->ex_func = ctx->suffix; 3581cb0ef41Sopenharmony_ci ex_func->ex_free_func = ctx->suffix_free; 3591cb0ef41Sopenharmony_ci break; 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci case BIO_C_SET_EX_ARG: 3621cb0ef41Sopenharmony_ci ctx->ex_arg = arg2; 3631cb0ef41Sopenharmony_ci break; 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci case BIO_C_GET_EX_ARG: 3661cb0ef41Sopenharmony_ci *(void **)arg2 = ctx->ex_arg; 3671cb0ef41Sopenharmony_ci break; 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci case BIO_CTRL_FLUSH: 3701cb0ef41Sopenharmony_ci if (next == NULL) 3711cb0ef41Sopenharmony_ci return 0; 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_ci /* Call post function if possible */ 3741cb0ef41Sopenharmony_ci if (ctx->state == ASN1_STATE_HEADER) { 3751cb0ef41Sopenharmony_ci if (!asn1_bio_setup_ex(b, ctx, ctx->suffix, 3761cb0ef41Sopenharmony_ci ASN1_STATE_POST_COPY, ASN1_STATE_DONE)) 3771cb0ef41Sopenharmony_ci return 0; 3781cb0ef41Sopenharmony_ci } 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ci if (ctx->state == ASN1_STATE_POST_COPY) { 3811cb0ef41Sopenharmony_ci ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free, 3821cb0ef41Sopenharmony_ci ASN1_STATE_DONE); 3831cb0ef41Sopenharmony_ci if (ret <= 0) 3841cb0ef41Sopenharmony_ci return ret; 3851cb0ef41Sopenharmony_ci } 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci if (ctx->state == ASN1_STATE_DONE) 3881cb0ef41Sopenharmony_ci return BIO_ctrl(next, cmd, arg1, arg2); 3891cb0ef41Sopenharmony_ci else { 3901cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 3911cb0ef41Sopenharmony_ci return 0; 3921cb0ef41Sopenharmony_ci } 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ci default: 3951cb0ef41Sopenharmony_ci if (next == NULL) 3961cb0ef41Sopenharmony_ci return 0; 3971cb0ef41Sopenharmony_ci return BIO_ctrl(next, cmd, arg1, arg2); 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci } 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ci return ret; 4021cb0ef41Sopenharmony_ci} 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_cistatic int asn1_bio_set_ex(BIO *b, int cmd, 4051cb0ef41Sopenharmony_ci asn1_ps_func *ex_func, asn1_ps_func *ex_free_func) 4061cb0ef41Sopenharmony_ci{ 4071cb0ef41Sopenharmony_ci BIO_ASN1_EX_FUNCS extmp; 4081cb0ef41Sopenharmony_ci extmp.ex_func = ex_func; 4091cb0ef41Sopenharmony_ci extmp.ex_free_func = ex_free_func; 4101cb0ef41Sopenharmony_ci return BIO_ctrl(b, cmd, 0, &extmp); 4111cb0ef41Sopenharmony_ci} 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_cistatic int asn1_bio_get_ex(BIO *b, int cmd, 4141cb0ef41Sopenharmony_ci asn1_ps_func **ex_func, 4151cb0ef41Sopenharmony_ci asn1_ps_func **ex_free_func) 4161cb0ef41Sopenharmony_ci{ 4171cb0ef41Sopenharmony_ci BIO_ASN1_EX_FUNCS extmp; 4181cb0ef41Sopenharmony_ci int ret; 4191cb0ef41Sopenharmony_ci ret = BIO_ctrl(b, cmd, 0, &extmp); 4201cb0ef41Sopenharmony_ci if (ret > 0) { 4211cb0ef41Sopenharmony_ci *ex_func = extmp.ex_func; 4221cb0ef41Sopenharmony_ci *ex_free_func = extmp.ex_free_func; 4231cb0ef41Sopenharmony_ci } 4241cb0ef41Sopenharmony_ci return ret; 4251cb0ef41Sopenharmony_ci} 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ciint BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, 4281cb0ef41Sopenharmony_ci asn1_ps_func *prefix_free) 4291cb0ef41Sopenharmony_ci{ 4301cb0ef41Sopenharmony_ci return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free); 4311cb0ef41Sopenharmony_ci} 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ciint BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, 4341cb0ef41Sopenharmony_ci asn1_ps_func **pprefix_free) 4351cb0ef41Sopenharmony_ci{ 4361cb0ef41Sopenharmony_ci return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free); 4371cb0ef41Sopenharmony_ci} 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ciint BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, 4401cb0ef41Sopenharmony_ci asn1_ps_func *suffix_free) 4411cb0ef41Sopenharmony_ci{ 4421cb0ef41Sopenharmony_ci return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free); 4431cb0ef41Sopenharmony_ci} 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ciint BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, 4461cb0ef41Sopenharmony_ci asn1_ps_func **psuffix_free) 4471cb0ef41Sopenharmony_ci{ 4481cb0ef41Sopenharmony_ci return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free); 4491cb0ef41Sopenharmony_ci} 450