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