1109998Smarkm/* tasn_fre.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280304Sjkim * 2000. 5109998Smarkm */ 6109998Smarkm/* ==================================================================== 7109998Smarkm * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 8109998Smarkm * 9109998Smarkm * Redistribution and use in source and binary forms, with or without 10109998Smarkm * modification, are permitted provided that the following conditions 11109998Smarkm * are met: 12109998Smarkm * 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 17109998Smarkm * notice, this list of conditions and the following disclaimer in 18109998Smarkm * the documentation and/or other materials provided with the 19109998Smarkm * distribution. 20109998Smarkm * 21109998Smarkm * 3. All advertising materials mentioning features or use of this 22109998Smarkm * software must display the following acknowledgment: 23109998Smarkm * "This product includes software developed by the OpenSSL Project 24109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25109998Smarkm * 26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27109998Smarkm * endorse or promote products derived from this software without 28109998Smarkm * prior written permission. For written permission, please contact 29109998Smarkm * licensing@OpenSSL.org. 30109998Smarkm * 31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 32109998Smarkm * nor may "OpenSSL" appear in their names without prior written 33109998Smarkm * permission of the OpenSSL Project. 34109998Smarkm * 35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 36109998Smarkm * acknowledgment: 37109998Smarkm * "This product includes software developed by the OpenSSL Project 38109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39109998Smarkm * 40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 52109998Smarkm * ==================================================================== 53109998Smarkm * 54109998Smarkm * This product includes cryptographic software written by Eric Young 55109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 56109998Smarkm * Hudson (tjh@cryptsoft.com). 57109998Smarkm * 58109998Smarkm */ 59109998Smarkm 60109998Smarkm#include <stddef.h> 61109998Smarkm#include <openssl/asn1.h> 62109998Smarkm#include <openssl/asn1t.h> 63109998Smarkm#include <openssl/objects.h> 64109998Smarkm 65280304Sjkimstatic void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, 66280304Sjkim int combine); 67109998Smarkm 68109998Smarkm/* Free up an ASN1 structure */ 69109998Smarkm 70109998Smarkmvoid ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) 71280304Sjkim{ 72280304Sjkim asn1_item_combine_free(&val, it, 0); 73280304Sjkim} 74109998Smarkm 75109998Smarkmvoid ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) 76280304Sjkim{ 77280304Sjkim asn1_item_combine_free(pval, it, 0); 78280304Sjkim} 79109998Smarkm 80280304Sjkimstatic void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, 81280304Sjkim int combine) 82280304Sjkim{ 83280304Sjkim const ASN1_TEMPLATE *tt = NULL, *seqtt; 84280304Sjkim const ASN1_EXTERN_FUNCS *ef; 85280304Sjkim const ASN1_COMPAT_FUNCS *cf; 86280304Sjkim const ASN1_AUX *aux = it->funcs; 87280304Sjkim ASN1_aux_cb *asn1_cb; 88280304Sjkim int i; 89280304Sjkim if (!pval) 90280304Sjkim return; 91280304Sjkim if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) 92280304Sjkim return; 93280304Sjkim if (aux && aux->asn1_cb) 94280304Sjkim asn1_cb = aux->asn1_cb; 95280304Sjkim else 96280304Sjkim asn1_cb = 0; 97109998Smarkm 98280304Sjkim switch (it->itype) { 99109998Smarkm 100280304Sjkim case ASN1_ITYPE_PRIMITIVE: 101280304Sjkim if (it->templates) 102280304Sjkim ASN1_template_free(pval, it->templates); 103280304Sjkim else 104280304Sjkim ASN1_primitive_free(pval, it); 105280304Sjkim break; 106109998Smarkm 107280304Sjkim case ASN1_ITYPE_MSTRING: 108280304Sjkim ASN1_primitive_free(pval, it); 109280304Sjkim break; 110109998Smarkm 111280304Sjkim case ASN1_ITYPE_CHOICE: 112280304Sjkim if (asn1_cb) { 113280304Sjkim i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); 114280304Sjkim if (i == 2) 115280304Sjkim return; 116280304Sjkim } 117280304Sjkim i = asn1_get_choice_selector(pval, it); 118280304Sjkim if ((i >= 0) && (i < it->tcount)) { 119280304Sjkim ASN1_VALUE **pchval; 120280304Sjkim tt = it->templates + i; 121280304Sjkim pchval = asn1_get_field_ptr(pval, tt); 122280304Sjkim ASN1_template_free(pchval, tt); 123280304Sjkim } 124280304Sjkim if (asn1_cb) 125280304Sjkim asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); 126280304Sjkim if (!combine) { 127280304Sjkim OPENSSL_free(*pval); 128280304Sjkim *pval = NULL; 129280304Sjkim } 130280304Sjkim break; 131109998Smarkm 132280304Sjkim case ASN1_ITYPE_COMPAT: 133280304Sjkim cf = it->funcs; 134280304Sjkim if (cf && cf->asn1_free) 135280304Sjkim cf->asn1_free(*pval); 136280304Sjkim break; 137109998Smarkm 138280304Sjkim case ASN1_ITYPE_EXTERN: 139280304Sjkim ef = it->funcs; 140280304Sjkim if (ef && ef->asn1_ex_free) 141280304Sjkim ef->asn1_ex_free(pval, it); 142280304Sjkim break; 143109998Smarkm 144280304Sjkim case ASN1_ITYPE_NDEF_SEQUENCE: 145280304Sjkim case ASN1_ITYPE_SEQUENCE: 146280304Sjkim if (asn1_do_lock(pval, -1, it) > 0) 147280304Sjkim return; 148280304Sjkim if (asn1_cb) { 149280304Sjkim i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); 150280304Sjkim if (i == 2) 151280304Sjkim return; 152280304Sjkim } 153280304Sjkim asn1_enc_free(pval, it); 154280304Sjkim /* 155280304Sjkim * If we free up as normal we will invalidate any ANY DEFINED BY 156280304Sjkim * field and we wont be able to determine the type of the field it 157280304Sjkim * defines. So free up in reverse order. 158280304Sjkim */ 159280304Sjkim tt = it->templates + it->tcount - 1; 160280304Sjkim for (i = 0; i < it->tcount; tt--, i++) { 161280304Sjkim ASN1_VALUE **pseqval; 162280304Sjkim seqtt = asn1_do_adb(pval, tt, 0); 163280304Sjkim if (!seqtt) 164280304Sjkim continue; 165280304Sjkim pseqval = asn1_get_field_ptr(pval, seqtt); 166280304Sjkim ASN1_template_free(pseqval, seqtt); 167280304Sjkim } 168280304Sjkim if (asn1_cb) 169280304Sjkim asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); 170280304Sjkim if (!combine) { 171280304Sjkim OPENSSL_free(*pval); 172280304Sjkim *pval = NULL; 173280304Sjkim } 174280304Sjkim break; 175280304Sjkim } 176280304Sjkim} 177109998Smarkm 178109998Smarkmvoid ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) 179280304Sjkim{ 180280304Sjkim int i; 181280304Sjkim if (tt->flags & ASN1_TFLG_SK_MASK) { 182280304Sjkim STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; 183280304Sjkim for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 184280304Sjkim ASN1_VALUE *vtmp; 185280304Sjkim vtmp = sk_ASN1_VALUE_value(sk, i); 186280304Sjkim asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0); 187280304Sjkim } 188280304Sjkim sk_ASN1_VALUE_free(sk); 189280304Sjkim *pval = NULL; 190280304Sjkim } else 191280304Sjkim asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item), 192280304Sjkim tt->flags & ASN1_TFLG_COMBINE); 193280304Sjkim} 194109998Smarkm 195109998Smarkmvoid ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) 196280304Sjkim{ 197280304Sjkim int utype; 198280304Sjkim if (it) { 199280304Sjkim const ASN1_PRIMITIVE_FUNCS *pf; 200280304Sjkim pf = it->funcs; 201280304Sjkim if (pf && pf->prim_free) { 202280304Sjkim pf->prim_free(pval, it); 203280304Sjkim return; 204280304Sjkim } 205280304Sjkim } 206280304Sjkim /* Special case: if 'it' is NULL free contents of ASN1_TYPE */ 207280304Sjkim if (!it) { 208280304Sjkim ASN1_TYPE *typ = (ASN1_TYPE *)*pval; 209280304Sjkim utype = typ->type; 210280304Sjkim pval = &typ->value.asn1_value; 211280304Sjkim if (!*pval) 212280304Sjkim return; 213280304Sjkim } else if (it->itype == ASN1_ITYPE_MSTRING) { 214280304Sjkim utype = -1; 215280304Sjkim if (!*pval) 216280304Sjkim return; 217280304Sjkim } else { 218280304Sjkim utype = it->utype; 219280304Sjkim if ((utype != V_ASN1_BOOLEAN) && !*pval) 220280304Sjkim return; 221280304Sjkim } 222109998Smarkm 223280304Sjkim switch (utype) { 224280304Sjkim case V_ASN1_OBJECT: 225280304Sjkim ASN1_OBJECT_free((ASN1_OBJECT *)*pval); 226280304Sjkim break; 227109998Smarkm 228280304Sjkim case V_ASN1_BOOLEAN: 229280304Sjkim if (it) 230280304Sjkim *(ASN1_BOOLEAN *)pval = it->size; 231280304Sjkim else 232280304Sjkim *(ASN1_BOOLEAN *)pval = -1; 233280304Sjkim return; 234109998Smarkm 235280304Sjkim case V_ASN1_NULL: 236280304Sjkim break; 237109998Smarkm 238280304Sjkim case V_ASN1_ANY: 239280304Sjkim ASN1_primitive_free(pval, NULL); 240280304Sjkim OPENSSL_free(*pval); 241280304Sjkim break; 242109998Smarkm 243280304Sjkim default: 244280304Sjkim ASN1_STRING_free((ASN1_STRING *)*pval); 245280304Sjkim *pval = NULL; 246280304Sjkim break; 247280304Sjkim } 248280304Sjkim *pval = NULL; 249280304Sjkim} 250