tasn_new.c revision 325337
1/* tasn_new.c */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4 * 2000. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2000-2004 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#include <stddef.h> 61#include <openssl/asn1.h> 62#include <openssl/objects.h> 63#include <openssl/err.h> 64#include <openssl/asn1t.h> 65#include <string.h> 66#include "asn1_int.h" 67 68static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, 69 int combine); 70static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); 71static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); 72static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); 73 74ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) 75{ 76 ASN1_VALUE *ret = NULL; 77 if (ASN1_item_ex_new(&ret, it) > 0) 78 return ret; 79 return NULL; 80} 81 82/* Allocate an ASN1 structure */ 83 84int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) 85{ 86 return asn1_item_ex_combine_new(pval, it, 0); 87} 88 89static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, 90 int combine) 91{ 92 const ASN1_TEMPLATE *tt = NULL; 93 const ASN1_COMPAT_FUNCS *cf; 94 const ASN1_EXTERN_FUNCS *ef; 95 const ASN1_AUX *aux = it->funcs; 96 ASN1_aux_cb *asn1_cb; 97 ASN1_VALUE **pseqval; 98 int i; 99 if (aux && aux->asn1_cb) 100 asn1_cb = aux->asn1_cb; 101 else 102 asn1_cb = 0; 103 104#ifdef CRYPTO_MDEBUG 105 if (it->sname) 106 CRYPTO_push_info(it->sname); 107#endif 108 109 switch (it->itype) { 110 111 case ASN1_ITYPE_EXTERN: 112 ef = it->funcs; 113 if (ef && ef->asn1_ex_new) { 114 if (!ef->asn1_ex_new(pval, it)) 115 goto memerr; 116 } 117 break; 118 119 case ASN1_ITYPE_COMPAT: 120 cf = it->funcs; 121 if (cf && cf->asn1_new) { 122 *pval = cf->asn1_new(); 123 if (!*pval) 124 goto memerr; 125 } 126 break; 127 128 case ASN1_ITYPE_PRIMITIVE: 129 if (it->templates) { 130 if (!ASN1_template_new(pval, it->templates)) 131 goto memerr; 132 } else if (!ASN1_primitive_new(pval, it)) 133 goto memerr; 134 break; 135 136 case ASN1_ITYPE_MSTRING: 137 if (!ASN1_primitive_new(pval, it)) 138 goto memerr; 139 break; 140 141 case ASN1_ITYPE_CHOICE: 142 if (asn1_cb) { 143 i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); 144 if (!i) 145 goto auxerr; 146 if (i == 2) { 147#ifdef CRYPTO_MDEBUG 148 if (it->sname) 149 CRYPTO_pop_info(); 150#endif 151 return 1; 152 } 153 } 154 if (!combine) { 155 *pval = OPENSSL_malloc(it->size); 156 if (!*pval) 157 goto memerr; 158 memset(*pval, 0, it->size); 159 } 160 asn1_set_choice_selector(pval, -1, it); 161 if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) 162 goto auxerr2; 163 break; 164 165 case ASN1_ITYPE_NDEF_SEQUENCE: 166 case ASN1_ITYPE_SEQUENCE: 167 if (asn1_cb) { 168 i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); 169 if (!i) 170 goto auxerr; 171 if (i == 2) { 172#ifdef CRYPTO_MDEBUG 173 if (it->sname) 174 CRYPTO_pop_info(); 175#endif 176 return 1; 177 } 178 } 179 if (!combine) { 180 *pval = OPENSSL_malloc(it->size); 181 if (!*pval) 182 goto memerr; 183 memset(*pval, 0, it->size); 184 asn1_do_lock(pval, 0, it); 185 asn1_enc_init(pval, it); 186 } 187 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { 188 pseqval = asn1_get_field_ptr(pval, tt); 189 if (!ASN1_template_new(pseqval, tt)) 190 goto memerr2; 191 } 192 if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) 193 goto auxerr2; 194 break; 195 } 196#ifdef CRYPTO_MDEBUG 197 if (it->sname) 198 CRYPTO_pop_info(); 199#endif 200 return 1; 201 202 memerr2: 203 asn1_item_combine_free(pval, it, combine); 204 memerr: 205 ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ERR_R_MALLOC_FAILURE); 206#ifdef CRYPTO_MDEBUG 207 if (it->sname) 208 CRYPTO_pop_info(); 209#endif 210 return 0; 211 212 auxerr2: 213 asn1_item_combine_free(pval, it, combine); 214 auxerr: 215 ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ASN1_R_AUX_ERROR); 216#ifdef CRYPTO_MDEBUG 217 if (it->sname) 218 CRYPTO_pop_info(); 219#endif 220 return 0; 221 222} 223 224static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) 225{ 226 const ASN1_EXTERN_FUNCS *ef; 227 228 switch (it->itype) { 229 230 case ASN1_ITYPE_EXTERN: 231 ef = it->funcs; 232 if (ef && ef->asn1_ex_clear) 233 ef->asn1_ex_clear(pval, it); 234 else 235 *pval = NULL; 236 break; 237 238 case ASN1_ITYPE_PRIMITIVE: 239 if (it->templates) 240 asn1_template_clear(pval, it->templates); 241 else 242 asn1_primitive_clear(pval, it); 243 break; 244 245 case ASN1_ITYPE_MSTRING: 246 asn1_primitive_clear(pval, it); 247 break; 248 249 case ASN1_ITYPE_COMPAT: 250 case ASN1_ITYPE_CHOICE: 251 case ASN1_ITYPE_SEQUENCE: 252 case ASN1_ITYPE_NDEF_SEQUENCE: 253 *pval = NULL; 254 break; 255 } 256} 257 258int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) 259{ 260 const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); 261 int ret; 262 if (tt->flags & ASN1_TFLG_OPTIONAL) { 263 asn1_template_clear(pval, tt); 264 return 1; 265 } 266 /* If ANY DEFINED BY nothing to do */ 267 268 if (tt->flags & ASN1_TFLG_ADB_MASK) { 269 *pval = NULL; 270 return 1; 271 } 272#ifdef CRYPTO_MDEBUG 273 if (tt->field_name) 274 CRYPTO_push_info(tt->field_name); 275#endif 276 /* If SET OF or SEQUENCE OF, its a STACK */ 277 if (tt->flags & ASN1_TFLG_SK_MASK) { 278 STACK_OF(ASN1_VALUE) *skval; 279 skval = sk_ASN1_VALUE_new_null(); 280 if (!skval) { 281 ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE); 282 ret = 0; 283 goto done; 284 } 285 *pval = (ASN1_VALUE *)skval; 286 ret = 1; 287 goto done; 288 } 289 /* Otherwise pass it back to the item routine */ 290 ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE); 291 done: 292#ifdef CRYPTO_MDEBUG 293 if (it->sname) 294 CRYPTO_pop_info(); 295#endif 296 return ret; 297} 298 299static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) 300{ 301 /* If ADB or STACK just NULL the field */ 302 if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) 303 *pval = NULL; 304 else 305 asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item)); 306} 307 308/* 309 * NB: could probably combine most of the real XXX_new() behaviour and junk 310 * all the old functions. 311 */ 312 313int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) 314{ 315 ASN1_TYPE *typ; 316 ASN1_STRING *str; 317 int utype; 318 319 if (!it) 320 return 0; 321 322 if (it->funcs) { 323 const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; 324 if (pf->prim_new) 325 return pf->prim_new(pval, it); 326 } 327 328 if (it->itype == ASN1_ITYPE_MSTRING) 329 utype = -1; 330 else 331 utype = it->utype; 332 switch (utype) { 333 case V_ASN1_OBJECT: 334 *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); 335 return 1; 336 337 case V_ASN1_BOOLEAN: 338 *(ASN1_BOOLEAN *)pval = it->size; 339 return 1; 340 341 case V_ASN1_NULL: 342 *pval = (ASN1_VALUE *)1; 343 return 1; 344 345 case V_ASN1_ANY: 346 typ = OPENSSL_malloc(sizeof(ASN1_TYPE)); 347 if (!typ) 348 return 0; 349 typ->value.ptr = NULL; 350 typ->type = -1; 351 *pval = (ASN1_VALUE *)typ; 352 break; 353 354 default: 355 str = ASN1_STRING_type_new(utype); 356 if (it->itype == ASN1_ITYPE_MSTRING && str) 357 str->flags |= ASN1_STRING_FLAG_MSTRING; 358 *pval = (ASN1_VALUE *)str; 359 break; 360 } 361 if (*pval) 362 return 1; 363 return 0; 364} 365 366static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) 367{ 368 int utype; 369 if (it && it->funcs) { 370 const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; 371 if (pf->prim_clear) 372 pf->prim_clear(pval, it); 373 else 374 *pval = NULL; 375 return; 376 } 377 if (!it || (it->itype == ASN1_ITYPE_MSTRING)) 378 utype = -1; 379 else 380 utype = it->utype; 381 if (utype == V_ASN1_BOOLEAN) 382 *(ASN1_BOOLEAN *)pval = it->size; 383 else 384 *pval = NULL; 385} 386