1*0Sstevel@tonic-gate /* crypto/evp/bio_ber.c */ 2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*0Sstevel@tonic-gate * All rights reserved. 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * This package is an SSL implementation written 6*0Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 7*0Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 10*0Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 11*0Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 12*0Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*0Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 14*0Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 17*0Sstevel@tonic-gate * the code are not to be removed. 18*0Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 19*0Sstevel@tonic-gate * as the author of the parts of the library used. 20*0Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 21*0Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 32*0Sstevel@tonic-gate * must display the following acknowledgement: 33*0Sstevel@tonic-gate * "This product includes cryptographic software written by 34*0Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 35*0Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 36*0Sstevel@tonic-gate * being used are not cryptographic related :-). 37*0Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 38*0Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 39*0Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*0Sstevel@tonic-gate * SUCH DAMAGE. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 54*0Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 55*0Sstevel@tonic-gate * copied and put under another distribution licence 56*0Sstevel@tonic-gate * [including the GNU Public Licence.] 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include <stdio.h> 60*0Sstevel@tonic-gate #include <errno.h> 61*0Sstevel@tonic-gate #include "cryptlib.h" 62*0Sstevel@tonic-gate #include <openssl/buffer.h> 63*0Sstevel@tonic-gate #include <openssl/evp.h> 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate static int ber_write(BIO *h,char *buf,int num); 66*0Sstevel@tonic-gate static int ber_read(BIO *h,char *buf,int size); 67*0Sstevel@tonic-gate /*static int ber_puts(BIO *h,char *str); */ 68*0Sstevel@tonic-gate /*static int ber_gets(BIO *h,char *str,int size); */ 69*0Sstevel@tonic-gate static long ber_ctrl(BIO *h,int cmd,long arg1,char *arg2); 70*0Sstevel@tonic-gate static int ber_new(BIO *h); 71*0Sstevel@tonic-gate static int ber_free(BIO *data); 72*0Sstevel@tonic-gate static long ber_callback_ctrl(BIO *h,int cmd,void *(*fp)()); 73*0Sstevel@tonic-gate #define BER_BUF_SIZE (32) 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate /* This is used to hold the state of the BER objects being read. */ 76*0Sstevel@tonic-gate typedef struct ber_struct 77*0Sstevel@tonic-gate { 78*0Sstevel@tonic-gate int tag; 79*0Sstevel@tonic-gate int class; 80*0Sstevel@tonic-gate long length; 81*0Sstevel@tonic-gate int inf; 82*0Sstevel@tonic-gate int num_left; 83*0Sstevel@tonic-gate int depth; 84*0Sstevel@tonic-gate } BER_CTX; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate typedef struct bio_ber_struct 87*0Sstevel@tonic-gate { 88*0Sstevel@tonic-gate int tag; 89*0Sstevel@tonic-gate int class; 90*0Sstevel@tonic-gate long length; 91*0Sstevel@tonic-gate int inf; 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate /* most of the following are used when doing non-blocking IO */ 94*0Sstevel@tonic-gate /* reading */ 95*0Sstevel@tonic-gate long num_left; /* number of bytes still to read/write in block */ 96*0Sstevel@tonic-gate int depth; /* used with indefinite encoding. */ 97*0Sstevel@tonic-gate int finished; /* No more read data */ 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* writting */ 100*0Sstevel@tonic-gate char *w_addr; 101*0Sstevel@tonic-gate int w_offset; 102*0Sstevel@tonic-gate int w_left; 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate int buf_len; 105*0Sstevel@tonic-gate int buf_off; 106*0Sstevel@tonic-gate unsigned char buf[BER_BUF_SIZE]; 107*0Sstevel@tonic-gate } BIO_BER_CTX; 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate static BIO_METHOD methods_ber= 110*0Sstevel@tonic-gate { 111*0Sstevel@tonic-gate BIO_TYPE_CIPHER,"cipher", 112*0Sstevel@tonic-gate ber_write, 113*0Sstevel@tonic-gate ber_read, 114*0Sstevel@tonic-gate NULL, /* ber_puts, */ 115*0Sstevel@tonic-gate NULL, /* ber_gets, */ 116*0Sstevel@tonic-gate ber_ctrl, 117*0Sstevel@tonic-gate ber_new, 118*0Sstevel@tonic-gate ber_free, 119*0Sstevel@tonic-gate ber_callback_ctrl, 120*0Sstevel@tonic-gate }; 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate BIO_METHOD *BIO_f_ber(void) 123*0Sstevel@tonic-gate { 124*0Sstevel@tonic-gate return(&methods_ber); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate static int ber_new(BIO *bi) 128*0Sstevel@tonic-gate { 129*0Sstevel@tonic-gate BIO_BER_CTX *ctx; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate ctx=(BIO_BER_CTX *)OPENSSL_malloc(sizeof(BIO_BER_CTX)); 132*0Sstevel@tonic-gate if (ctx == NULL) return(0); 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate memset((char *)ctx,0,sizeof(BIO_BER_CTX)); 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate bi->init=0; 137*0Sstevel@tonic-gate bi->ptr=(char *)ctx; 138*0Sstevel@tonic-gate bi->flags=0; 139*0Sstevel@tonic-gate return(1); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate static int ber_free(BIO *a) 143*0Sstevel@tonic-gate { 144*0Sstevel@tonic-gate BIO_BER_CTX *b; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate if (a == NULL) return(0); 147*0Sstevel@tonic-gate b=(BIO_BER_CTX *)a->ptr; 148*0Sstevel@tonic-gate OPENSSL_cleanse(a->ptr,sizeof(BIO_BER_CTX)); 149*0Sstevel@tonic-gate OPENSSL_free(a->ptr); 150*0Sstevel@tonic-gate a->ptr=NULL; 151*0Sstevel@tonic-gate a->init=0; 152*0Sstevel@tonic-gate a->flags=0; 153*0Sstevel@tonic-gate return(1); 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate int bio_ber_get_header(BIO *bio, BIO_BER_CTX *ctx) 157*0Sstevel@tonic-gate { 158*0Sstevel@tonic-gate char buf[64]; 159*0Sstevel@tonic-gate int i,j,n; 160*0Sstevel@tonic-gate int ret; 161*0Sstevel@tonic-gate unsigned char *p; 162*0Sstevel@tonic-gate unsigned long length 163*0Sstevel@tonic-gate int tag; 164*0Sstevel@tonic-gate int class; 165*0Sstevel@tonic-gate long max; 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate BIO_clear_retry_flags(b); 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate /* Pack the buffer down if there is a hole at the front */ 170*0Sstevel@tonic-gate if (ctx->buf_off != 0) 171*0Sstevel@tonic-gate { 172*0Sstevel@tonic-gate p=ctx->buf; 173*0Sstevel@tonic-gate j=ctx->buf_off; 174*0Sstevel@tonic-gate n=ctx->buf_len-j; 175*0Sstevel@tonic-gate for (i=0; i<n; i++) 176*0Sstevel@tonic-gate { 177*0Sstevel@tonic-gate p[0]=p[j]; 178*0Sstevel@tonic-gate p++; 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate ctx->buf_len-j; 181*0Sstevel@tonic-gate ctx->buf_off=0; 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* If there is more room, read some more data */ 185*0Sstevel@tonic-gate i=BER_BUF_SIZE-ctx->buf_len; 186*0Sstevel@tonic-gate if (i) 187*0Sstevel@tonic-gate { 188*0Sstevel@tonic-gate i=BIO_read(bio->next_bio,&(ctx->buf[ctx->buf_len]),i); 189*0Sstevel@tonic-gate if (i <= 0) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate BIO_copy_next_retry(b); 192*0Sstevel@tonic-gate return(i); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate else 195*0Sstevel@tonic-gate ctx->buf_len+=i; 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate max=ctx->buf_len; 199*0Sstevel@tonic-gate p=ctx->buf; 200*0Sstevel@tonic-gate ret=ASN1_get_object(&p,&length,&tag,&class,max); 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate if (ret & 0x80) 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate if ((ctx->buf_len < BER_BUF_SIZE) && 205*0Sstevel@tonic-gate (ERR_GET_REASON(ERR_peek_error()) == ASN1_R_TOO_LONG)) 206*0Sstevel@tonic-gate { 207*0Sstevel@tonic-gate ERR_get_error(); /* clear the error */ 208*0Sstevel@tonic-gate BIO_set_retry_read(b); 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate return(-1); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* We have no error, we have a header, so make use of it */ 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate if ((ctx->tag >= 0) && (ctx->tag != tag)) 216*0Sstevel@tonic-gate { 217*0Sstevel@tonic-gate BIOerr(BIO_F_BIO_BER_GET_HEADER,BIO_R_TAG_MISMATCH); 218*0Sstevel@tonic-gate sprintf(buf,"tag=%d, got %d",ctx->tag,tag); 219*0Sstevel@tonic-gate ERR_add_error_data(1,buf); 220*0Sstevel@tonic-gate return(-1); 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate if (ret & 0x01) 223*0Sstevel@tonic-gate if (ret & V_ASN1_CONSTRUCTED) 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate static int ber_read(BIO *b, char *out, int outl) 227*0Sstevel@tonic-gate { 228*0Sstevel@tonic-gate int ret=0,i,n; 229*0Sstevel@tonic-gate BIO_BER_CTX *ctx; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate BIO_clear_retry_flags(b); 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate if (out == NULL) return(0); 234*0Sstevel@tonic-gate ctx=(BIO_BER_CTX *)b->ptr; 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate if ((ctx == NULL) || (b->next_bio == NULL)) return(0); 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate if (ctx->finished) return(0); 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate again: 241*0Sstevel@tonic-gate /* First see if we are half way through reading a block */ 242*0Sstevel@tonic-gate if (ctx->num_left > 0) 243*0Sstevel@tonic-gate { 244*0Sstevel@tonic-gate if (ctx->num_left < outl) 245*0Sstevel@tonic-gate n=ctx->num_left; 246*0Sstevel@tonic-gate else 247*0Sstevel@tonic-gate n=outl; 248*0Sstevel@tonic-gate i=BIO_read(b->next_bio,out,n); 249*0Sstevel@tonic-gate if (i <= 0) 250*0Sstevel@tonic-gate { 251*0Sstevel@tonic-gate BIO_copy_next_retry(b); 252*0Sstevel@tonic-gate return(i); 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate ctx->num_left-=i; 255*0Sstevel@tonic-gate outl-=i; 256*0Sstevel@tonic-gate ret+=i; 257*0Sstevel@tonic-gate if (ctx->num_left <= 0) 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate ctx->depth--; 260*0Sstevel@tonic-gate if (ctx->depth <= 0) 261*0Sstevel@tonic-gate ctx->finished=1; 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate if (outl <= 0) 264*0Sstevel@tonic-gate return(ret); 265*0Sstevel@tonic-gate else 266*0Sstevel@tonic-gate goto again; 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate else /* we need to read another BER header */ 269*0Sstevel@tonic-gate { 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate static int ber_write(BIO *b, char *in, int inl) 274*0Sstevel@tonic-gate { 275*0Sstevel@tonic-gate int ret=0,n,i; 276*0Sstevel@tonic-gate BIO_ENC_CTX *ctx; 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate ctx=(BIO_ENC_CTX *)b->ptr; 279*0Sstevel@tonic-gate ret=inl; 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate BIO_clear_retry_flags(b); 282*0Sstevel@tonic-gate n=ctx->buf_len-ctx->buf_off; 283*0Sstevel@tonic-gate while (n > 0) 284*0Sstevel@tonic-gate { 285*0Sstevel@tonic-gate i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 286*0Sstevel@tonic-gate if (i <= 0) 287*0Sstevel@tonic-gate { 288*0Sstevel@tonic-gate BIO_copy_next_retry(b); 289*0Sstevel@tonic-gate return(i); 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate ctx->buf_off+=i; 292*0Sstevel@tonic-gate n-=i; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate /* at this point all pending data has been written */ 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate if ((in == NULL) || (inl <= 0)) return(0); 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate ctx->buf_off=0; 299*0Sstevel@tonic-gate while (inl > 0) 300*0Sstevel@tonic-gate { 301*0Sstevel@tonic-gate n=(inl > ENC_BLOCK_SIZE)?ENC_BLOCK_SIZE:inl; 302*0Sstevel@tonic-gate EVP_CipherUpdate(&(ctx->cipher), 303*0Sstevel@tonic-gate (unsigned char *)ctx->buf,&ctx->buf_len, 304*0Sstevel@tonic-gate (unsigned char *)in,n); 305*0Sstevel@tonic-gate inl-=n; 306*0Sstevel@tonic-gate in+=n; 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate ctx->buf_off=0; 309*0Sstevel@tonic-gate n=ctx->buf_len; 310*0Sstevel@tonic-gate while (n > 0) 311*0Sstevel@tonic-gate { 312*0Sstevel@tonic-gate i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 313*0Sstevel@tonic-gate if (i <= 0) 314*0Sstevel@tonic-gate { 315*0Sstevel@tonic-gate BIO_copy_next_retry(b); 316*0Sstevel@tonic-gate return(i); 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate n-=i; 319*0Sstevel@tonic-gate ctx->buf_off+=i; 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate ctx->buf_len=0; 322*0Sstevel@tonic-gate ctx->buf_off=0; 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate BIO_copy_next_retry(b); 325*0Sstevel@tonic-gate return(ret); 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate static long ber_ctrl(BIO *b, int cmd, long num, char *ptr) 329*0Sstevel@tonic-gate { 330*0Sstevel@tonic-gate BIO *dbio; 331*0Sstevel@tonic-gate BIO_ENC_CTX *ctx,*dctx; 332*0Sstevel@tonic-gate long ret=1; 333*0Sstevel@tonic-gate int i; 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate ctx=(BIO_ENC_CTX *)b->ptr; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate switch (cmd) 338*0Sstevel@tonic-gate { 339*0Sstevel@tonic-gate case BIO_CTRL_RESET: 340*0Sstevel@tonic-gate ctx->ok=1; 341*0Sstevel@tonic-gate ctx->finished=0; 342*0Sstevel@tonic-gate EVP_CipherInit_ex(&(ctx->cipher),NULL,NULL,NULL,NULL, 343*0Sstevel@tonic-gate ctx->cipher.berrypt); 344*0Sstevel@tonic-gate ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 345*0Sstevel@tonic-gate break; 346*0Sstevel@tonic-gate case BIO_CTRL_EOF: /* More to read */ 347*0Sstevel@tonic-gate if (ctx->cont <= 0) 348*0Sstevel@tonic-gate ret=1; 349*0Sstevel@tonic-gate else 350*0Sstevel@tonic-gate ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 351*0Sstevel@tonic-gate break; 352*0Sstevel@tonic-gate case BIO_CTRL_WPENDING: 353*0Sstevel@tonic-gate ret=ctx->buf_len-ctx->buf_off; 354*0Sstevel@tonic-gate if (ret <= 0) 355*0Sstevel@tonic-gate ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 356*0Sstevel@tonic-gate break; 357*0Sstevel@tonic-gate case BIO_CTRL_PENDING: /* More to read in buffer */ 358*0Sstevel@tonic-gate ret=ctx->buf_len-ctx->buf_off; 359*0Sstevel@tonic-gate if (ret <= 0) 360*0Sstevel@tonic-gate ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 361*0Sstevel@tonic-gate break; 362*0Sstevel@tonic-gate case BIO_CTRL_FLUSH: 363*0Sstevel@tonic-gate /* do a final write */ 364*0Sstevel@tonic-gate again: 365*0Sstevel@tonic-gate while (ctx->buf_len != ctx->buf_off) 366*0Sstevel@tonic-gate { 367*0Sstevel@tonic-gate i=ber_write(b,NULL,0); 368*0Sstevel@tonic-gate if (i < 0) 369*0Sstevel@tonic-gate { 370*0Sstevel@tonic-gate ret=i; 371*0Sstevel@tonic-gate break; 372*0Sstevel@tonic-gate } 373*0Sstevel@tonic-gate } 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate if (!ctx->finished) 376*0Sstevel@tonic-gate { 377*0Sstevel@tonic-gate ctx->finished=1; 378*0Sstevel@tonic-gate ctx->buf_off=0; 379*0Sstevel@tonic-gate ret=EVP_CipherFinal_ex(&(ctx->cipher), 380*0Sstevel@tonic-gate (unsigned char *)ctx->buf, 381*0Sstevel@tonic-gate &(ctx->buf_len)); 382*0Sstevel@tonic-gate ctx->ok=(int)ret; 383*0Sstevel@tonic-gate if (ret <= 0) break; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate /* push out the bytes */ 386*0Sstevel@tonic-gate goto again; 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate /* Finally flush the underlying BIO */ 390*0Sstevel@tonic-gate ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 391*0Sstevel@tonic-gate break; 392*0Sstevel@tonic-gate case BIO_C_GET_CIPHER_STATUS: 393*0Sstevel@tonic-gate ret=(long)ctx->ok; 394*0Sstevel@tonic-gate break; 395*0Sstevel@tonic-gate case BIO_C_DO_STATE_MACHINE: 396*0Sstevel@tonic-gate BIO_clear_retry_flags(b); 397*0Sstevel@tonic-gate ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 398*0Sstevel@tonic-gate BIO_copy_next_retry(b); 399*0Sstevel@tonic-gate break; 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate case BIO_CTRL_DUP: 402*0Sstevel@tonic-gate dbio=(BIO *)ptr; 403*0Sstevel@tonic-gate dctx=(BIO_ENC_CTX *)dbio->ptr; 404*0Sstevel@tonic-gate memcpy(&(dctx->cipher),&(ctx->cipher),sizeof(ctx->cipher)); 405*0Sstevel@tonic-gate dbio->init=1; 406*0Sstevel@tonic-gate break; 407*0Sstevel@tonic-gate default: 408*0Sstevel@tonic-gate ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 409*0Sstevel@tonic-gate break; 410*0Sstevel@tonic-gate } 411*0Sstevel@tonic-gate return(ret); 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate static long ber_callback_ctrl(BIO *b, int cmd, void *(*fp)()) 415*0Sstevel@tonic-gate { 416*0Sstevel@tonic-gate long ret=1; 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate if (b->next_bio == NULL) return(0); 419*0Sstevel@tonic-gate switch (cmd) 420*0Sstevel@tonic-gate { 421*0Sstevel@tonic-gate default: 422*0Sstevel@tonic-gate ret=BIO_callback_ctrl(b->next_bio,cmd,fp); 423*0Sstevel@tonic-gate break; 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate return(ret); 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate /* 429*0Sstevel@tonic-gate void BIO_set_cipher_ctx(b,c) 430*0Sstevel@tonic-gate BIO *b; 431*0Sstevel@tonic-gate EVP_CIPHER_ctx *c; 432*0Sstevel@tonic-gate { 433*0Sstevel@tonic-gate if (b == NULL) return; 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate if ((b->callback != NULL) && 436*0Sstevel@tonic-gate (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) 437*0Sstevel@tonic-gate return; 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate b->init=1; 440*0Sstevel@tonic-gate ctx=(BIO_ENC_CTX *)b->ptr; 441*0Sstevel@tonic-gate memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX)); 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate if (b->callback != NULL) 444*0Sstevel@tonic-gate b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate */ 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate void BIO_set_cipher(BIO *b, EVP_CIPHER *c, unsigned char *k, unsigned char *i, 449*0Sstevel@tonic-gate int e) 450*0Sstevel@tonic-gate { 451*0Sstevel@tonic-gate BIO_ENC_CTX *ctx; 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate if (b == NULL) return; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate if ((b->callback != NULL) && 456*0Sstevel@tonic-gate (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) 457*0Sstevel@tonic-gate return; 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate b->init=1; 460*0Sstevel@tonic-gate ctx=(BIO_ENC_CTX *)b->ptr; 461*0Sstevel@tonic-gate EVP_CipherInit_ex(&(ctx->cipher),c,NULL,k,i,e); 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate if (b->callback != NULL) 464*0Sstevel@tonic-gate b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); 465*0Sstevel@tonic-gate } 466*0Sstevel@tonic-gate 467