tasn_fre.c 5.3 KB
Newer Older
1
/*
R
Rich Salz 已提交
2
 * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
D
 
Dr. Stephen Henson 已提交
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
D
 
Dr. Stephen Henson 已提交
8 9 10 11 12 13
 */

#include <stddef.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
14
#include "asn1_local.h"
D
 
Dr. Stephen Henson 已提交
15 16 17 18

/* Free up an ASN1 structure */

void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
19
{
D
Dr. Stephen Henson 已提交
20
    asn1_item_embed_free(&val, it, 0);
21
}
D
 
Dr. Stephen Henson 已提交
22 23

void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
D
Dr. Stephen Henson 已提交
24 25 26 27
{
    asn1_item_embed_free(pval, it, 0);
}

28
void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
29 30 31 32 33 34
{
    const ASN1_TEMPLATE *tt = NULL, *seqtt;
    const ASN1_EXTERN_FUNCS *ef;
    const ASN1_AUX *aux = it->funcs;
    ASN1_aux_cb *asn1_cb;
    int i;
R
Rich Salz 已提交
35

36 37 38 39 40 41 42 43 44 45 46 47 48
    if (!pval)
        return;
    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
        return;
    if (aux && aux->asn1_cb)
        asn1_cb = aux->asn1_cb;
    else
        asn1_cb = 0;

    switch (it->itype) {

    case ASN1_ITYPE_PRIMITIVE:
        if (it->templates)
49
            asn1_template_free(pval, it->templates);
50
        else
D
Dr. Stephen Henson 已提交
51
            asn1_primitive_free(pval, it, embed);
52 53 54
        break;

    case ASN1_ITYPE_MSTRING:
D
Dr. Stephen Henson 已提交
55
        asn1_primitive_free(pval, it, embed);
56 57 58 59 60 61 62 63 64 65 66
        break;

    case ASN1_ITYPE_CHOICE:
        if (asn1_cb) {
            i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
            if (i == 2)
                return;
        }
        i = asn1_get_choice_selector(pval, it);
        if ((i >= 0) && (i < it->tcount)) {
            ASN1_VALUE **pchval;
R
Rich Salz 已提交
67

68 69
            tt = it->templates + i;
            pchval = asn1_get_field_ptr(pval, tt);
70
            asn1_template_free(pchval, tt);
71 72 73
        }
        if (asn1_cb)
            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
D
Dr. Stephen Henson 已提交
74 75 76 77
        if (embed == 0) {
            OPENSSL_free(*pval);
            *pval = NULL;
        }
78 79 80 81 82 83 84 85 86 87
        break;

    case ASN1_ITYPE_EXTERN:
        ef = it->funcs;
        if (ef && ef->asn1_ex_free)
            ef->asn1_ex_free(pval, it);
        break;

    case ASN1_ITYPE_NDEF_SEQUENCE:
    case ASN1_ITYPE_SEQUENCE:
88
        if (asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */
89 90 91 92 93 94 95 96 97
            return;
        if (asn1_cb) {
            i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
            if (i == 2)
                return;
        }
        asn1_enc_free(pval, it);
        /*
         * If we free up as normal we will invalidate any ANY DEFINED BY
98
         * field and we won't be able to determine the type of the field it
99 100
         * defines. So free up in reverse order.
         */
K
Kurt Roeckx 已提交
101 102
        tt = it->templates + it->tcount;
        for (i = 0; i < it->tcount; i++) {
103
            ASN1_VALUE **pseqval;
K
Kurt Roeckx 已提交
104 105

            tt--;
106 107 108 109
            seqtt = asn1_do_adb(pval, tt, 0);
            if (!seqtt)
                continue;
            pseqval = asn1_get_field_ptr(pval, seqtt);
110
            asn1_template_free(pseqval, seqtt);
111 112 113
        }
        if (asn1_cb)
            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
D
Dr. Stephen Henson 已提交
114 115 116 117
        if (embed == 0) {
            OPENSSL_free(*pval);
            *pval = NULL;
        }
118 119 120
        break;
    }
}
D
 
Dr. Stephen Henson 已提交
121

122
void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
123
{
D
Dr. Stephen Henson 已提交
124 125 126 127 128 129
    int embed = tt->flags & ASN1_TFLG_EMBED;
    ASN1_VALUE *tval;
    if (embed) {
        tval = (ASN1_VALUE *)pval;
        pval = &tval;
    }
130 131
    if (tt->flags & ASN1_TFLG_SK_MASK) {
        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
R
Rich Salz 已提交
132 133
        int i;

134
        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
R
Rich Salz 已提交
135 136
            ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i);

D
Dr. Stephen Henson 已提交
137
            asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
138 139 140
        }
        sk_ASN1_VALUE_free(sk);
        *pval = NULL;
R
Rich Salz 已提交
141
    } else {
D
Dr. Stephen Henson 已提交
142
        asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
R
Rich Salz 已提交
143
    }
144
}
D
 
Dr. Stephen Henson 已提交
145

D
Dr. Stephen Henson 已提交
146
void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
147 148
{
    int utype;
R
Rich Salz 已提交
149 150

    /* Special case: if 'it' is a primitive with a free_func, use that. */
151
    if (it) {
R
Rich Salz 已提交
152 153
        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;

154 155 156 157 158 159
        if (embed) {
            if (pf && pf->prim_clear) {
                pf->prim_clear(pval, it);
                return;
            }
        } else if (pf && pf->prim_free) {
160 161 162 163
            pf->prim_free(pval, it);
            return;
        }
    }
R
Rich Salz 已提交
164 165

    /* Special case: if 'it' is NULL, free contents of ASN1_TYPE */
166 167
    if (!it) {
        ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
R
Rich Salz 已提交
168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
        utype = typ->type;
        pval = &typ->value.asn1_value;
        if (!*pval)
            return;
    } else if (it->itype == ASN1_ITYPE_MSTRING) {
        utype = -1;
        if (!*pval)
            return;
    } else {
        utype = it->utype;
        if ((utype != V_ASN1_BOOLEAN) && !*pval)
            return;
    }

    switch (utype) {
    case V_ASN1_OBJECT:
        ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
        break;

    case V_ASN1_BOOLEAN:
        if (it)
            *(ASN1_BOOLEAN *)pval = it->size;
        else
            *(ASN1_BOOLEAN *)pval = -1;
        return;

    case V_ASN1_NULL:
        break;

    case V_ASN1_ANY:
D
Dr. Stephen Henson 已提交
199
        asn1_primitive_free(pval, NULL, 0);
200 201 202 203
        OPENSSL_free(*pval);
        break;

    default:
D
Dr. Stephen Henson 已提交
204
        asn1_string_embed_free((ASN1_STRING *)*pval, embed);
205 206
        break;
    }
207
    *pval = NULL;
208
}