Commit de17bd5d authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

New ASN.1 embed macro.



New ASN.1 macro ASN1_EMBED. This is the same as ASN1_SIMPLE except the
structure is not allocated: it is part of the parent. That is instead of

FOO *x;

it must be:

FOO x;

This reduces memory fragmentation and make it impossible to accidentally
set a mandatory field to NULL.

This currently only works for SEQUENCE and since it is equivalent to
ASN1_SIMPLE it cannot be tagged, OPTIONAL, SET OF or SEQUENCE OF.

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
parent 05e97f1d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ static ERR_STRING_DATA ASN1_str_functs[] = {
    {ERR_FUNC(ASN1_F_ASN1_ITEM_D2I_FP), "ASN1_item_d2i_fp"},
    {ERR_FUNC(ASN1_F_ASN1_ITEM_DUP), "ASN1_item_dup"},
    {ERR_FUNC(ASN1_F_ASN1_ITEM_EX_D2I), "ASN1_ITEM_EX_D2I"},
    {ERR_FUNC(ASN1_F_ASN1_ITEM_EX_NEW), "ASN1_ITEM_EX_NEW"},
    {ERR_FUNC(ASN1_F_ASN1_ITEM_EMBED_NEW), "ASN1_ITEM_EMBED_NEW"},
    {ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_BIO), "ASN1_item_i2d_bio"},
    {ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_FP), "ASN1_item_i2d_fp"},
    {ERR_FUNC(ASN1_F_ASN1_ITEM_PACK), "ASN1_item_pack"},
+10 −0
Original line number Diff line number Diff line
@@ -524,6 +524,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
{
    int flags, aclass;
    int ret;
    ASN1_VALUE *tval;
    const unsigned char *p, *q;
    if (!val)
        return 0;
@@ -533,6 +534,15 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
    p = *in;
    q = p;

    /*
     * If field is embedded then val needs fixing so it is a pointer to
     * a pointer to a field.
     */
    if (tt->flags & ASN1_TFLG_EMBED) {
        tval = (ASN1_VALUE *)val;
        val = &tval;
    }

    if (flags & ASN1_TFLG_SK_MASK) {
        /* SET OF, SEQUENCE OF */
        int sktag, skaclass;
+10 −0
Original line number Diff line number Diff line
@@ -244,7 +244,17 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
                                const ASN1_TEMPLATE *tt, int tag, int iclass)
{
    int i, ret, flags, ttag, tclass, ndef;
    ASN1_VALUE *tval;
    flags = tt->flags;

    /*
     * If field is embedded then val needs fixing so it is a pointer to
     * a pointer to a field.
     */
    if (flags & ASN1_TFLG_EMBED) {
        tval = (ASN1_VALUE *)pval;
        pval = &tval;
    }
    /*
     * Work out tag and class to use: tagging may come either from the
     * template or the arguments, not both because this would create
+22 −5
Original line number Diff line number Diff line
@@ -63,14 +63,23 @@
#include <openssl/objects.h>
#include "asn1_locl.h"

static void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
                                 int embed);

/* Free up an ASN1 structure */

void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
{
    ASN1_item_ex_free(&val, it);
    asn1_item_embed_free(&val, it, 0);
}

void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
    asn1_item_embed_free(pval, it, 0);
}

static void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
                                 int embed)
{
    const ASN1_TEMPLATE *tt = NULL, *seqtt;
    const ASN1_EXTERN_FUNCS *ef;
@@ -152,14 +161,22 @@ void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
        }
        if (asn1_cb)
            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
        if (embed == 0) {
            OPENSSL_free(*pval);
            *pval = NULL;
        }
        break;
    }
}

void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
    int embed = tt->flags & ASN1_TFLG_EMBED;
    ASN1_VALUE *tval;
    if (embed) {
        tval = (ASN1_VALUE *)pval;
        pval = &tval;
    }
    if (tt->flags & ASN1_TFLG_SK_MASK) {
        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
        int i;
@@ -167,12 +184,12 @@ void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
            ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i);

            ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item));
            asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
        }
        sk_ASN1_VALUE_free(sk);
        *pval = NULL;
    } else {
        ASN1_item_ex_free(pval, ASN1_ITEM_ptr(tt->item));
        asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
    }
}

+23 −6
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@
#include <string.h>
#include "asn1_locl.h"

static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
                               int embed);
static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
@@ -82,6 +84,11 @@ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
/* Allocate an ASN1 structure */

int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
    return asn1_item_embed_new(pval, it, 0);
}

int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
{
    const ASN1_TEMPLATE *tt = NULL;
    const ASN1_EXTERN_FUNCS *ef;
@@ -157,9 +164,13 @@ int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
                return 1;
            }
        }
        if (embed) {
            memset(*pval, 0, it->size);
        } else {
            *pval = OPENSSL_zalloc(it->size);
            if (!*pval)
                goto memerr;
        }
        asn1_do_lock(pval, 0, it);
        asn1_enc_init(pval, it);
        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
@@ -178,7 +189,7 @@ int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
    return 1;

 memerr:
    ASN1err(ASN1_F_ASN1_ITEM_EX_NEW, ERR_R_MALLOC_FAILURE);
    ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
    if (it->sname)
        CRYPTO_pop_info();
@@ -186,7 +197,7 @@ int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
    return 0;

 auxerr:
    ASN1err(ASN1_F_ASN1_ITEM_EX_NEW, ASN1_R_AUX_ERROR);
    ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR);
    ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
    if (it->sname)
@@ -232,7 +243,13 @@ static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
    const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
    int embed = tt->flags & ASN1_TFLG_EMBED;
    ASN1_VALUE *tval;
    int ret;
    if (embed) {
        tval = (ASN1_VALUE *)pval;
        pval = &tval;
    }
    if (tt->flags & ASN1_TFLG_OPTIONAL) {
        asn1_template_clear(pval, tt);
        return 1;
@@ -261,7 +278,7 @@ static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
        goto done;
    }
    /* Otherwise pass it back to the item routine */
    ret = ASN1_item_ex_new(pval, it);
    ret = asn1_item_embed_new(pval, it, embed);
 done:
#ifdef CRYPTO_MDEBUG
    if (it->sname)
Loading