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