diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2015-09-15 15:54:19 +0100 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2015-09-16 22:17:39 +0100 |
commit | de17bd5d7f8286d8b1f0a04a3f8f5782033f5ebd (patch) | |
tree | 5fab90b0d760d271e1fe90cde99271f2407f96ed /crypto/asn1 | |
parent | 05e97f1d4f940c765e5c93771fe20820acca4438 (diff) | |
download | openssl-de17bd5d7f8286d8b1f0a04a3f8f5782033f5ebd.tar.gz |
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>
Diffstat (limited to 'crypto/asn1')
-rw-r--r-- | crypto/asn1/asn1_err.c | 2 | ||||
-rw-r--r-- | crypto/asn1/tasn_dec.c | 10 | ||||
-rw-r--r-- | crypto/asn1/tasn_enc.c | 10 | ||||
-rw-r--r-- | crypto/asn1/tasn_fre.c | 27 | ||||
-rw-r--r-- | crypto/asn1/tasn_new.c | 29 |
5 files changed, 66 insertions, 12 deletions
diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index 5dfd21be4a..0d1cf0cf57 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -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"}, diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 732b4253d1..939ee205be 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -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; diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c index 35860e4514..e2feee0ec3 100644 --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -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 diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c index e846561e21..e219e2c0a3 100644 --- a/crypto/asn1/tasn_fre.c +++ b/crypto/asn1/tasn_fre.c @@ -63,15 +63,24 @@ #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; const ASN1_AUX *aux = it->funcs; @@ -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); } } diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c index e7ceda3c54..294912c188 100644 --- a/crypto/asn1/tasn_new.c +++ b/crypto/asn1/tasn_new.c @@ -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); @@ -83,6 +85,11 @@ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) 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; const ASN1_AUX *aux = it->funcs; @@ -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) |