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: Rich Salz <rsalz@openssl.org>
This commit is contained in:
parent
05e97f1d4f
commit
de17bd5d7f
7 changed files with 72 additions and 13 deletions
|
@ -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"},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
OPENSSL_free(*pval);
|
||||
*pval = 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
*pval = OPENSSL_zalloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
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)
|
||||
|
|
|
@ -943,7 +943,7 @@ void ERR_load_ASN1_strings(void);
|
|||
# define ASN1_F_ASN1_ITEM_D2I_FP 206
|
||||
# define ASN1_F_ASN1_ITEM_DUP 191
|
||||
# define ASN1_F_ASN1_ITEM_EX_D2I 120
|
||||
# define ASN1_F_ASN1_ITEM_EX_NEW 121
|
||||
# define ASN1_F_ASN1_ITEM_EMBED_NEW 121
|
||||
# define ASN1_F_ASN1_ITEM_I2D_BIO 192
|
||||
# define ASN1_F_ASN1_ITEM_I2D_FP 193
|
||||
# define ASN1_F_ASN1_ITEM_PACK 198
|
||||
|
|
|
@ -390,6 +390,8 @@ extern "C" {
|
|||
# endif
|
||||
/* Plain simple type */
|
||||
# define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type)
|
||||
/* Embedded simple type */
|
||||
# define ASN1_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_EMBED,0, stname, field, type)
|
||||
|
||||
/* OPTIONAL simple type */
|
||||
# define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type)
|
||||
|
@ -616,6 +618,9 @@ struct ASN1_ADB_TABLE_st {
|
|||
|
||||
# define ASN1_TFLG_NDEF (0x1<<11)
|
||||
|
||||
/* Field is embedded and not a pointer */
|
||||
# define ASN1_TFLG_EMBED (0x1 << 12)
|
||||
|
||||
/* This is the actual ASN1 item itself */
|
||||
|
||||
struct ASN1_ITEM_st {
|
||||
|
|
Loading…
Reference in a new issue