The branch master has been updated via 3e73111d133dda63ec42437ff5706ac3142f17a5 (commit) via db76a35e26ea09781caa5b941bdfeacb52e720d8 (commit) from c0e724fcbe3b78f098534fd5b76c1d0393b2a42c (commit)
- Log ----------------------------------------------------------------- commit 3e73111d133dda63ec42437ff5706ac3142f17a5 Author: Dr. David von Oheimb <david.von.ohe...@siemens.com> Date: Mon Mar 1 14:45:23 2021 +0100 ASN.1: Add some sanity checks for input len <= 0; related coding improvements Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14357) commit db76a35e26ea09781caa5b941bdfeacb52e720d8 Author: Dr. David von Oheimb <david.von.ohe...@siemens.com> Date: Mon Mar 1 14:43:19 2021 +0100 tasn_dec.c: Add checks for it == NULL arguments; improve coding style Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14357) ----------------------------------------------------------------------- Summary of changes: crypto/asn1/a_d2i_fp.c | 16 +++++++++----- crypto/asn1/asn1_lib.c | 6 +++-- crypto/asn1/tasn_dec.c | 59 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c index 4151a96561..6dfa37c7a2 100644 --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -101,6 +101,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) uint32_t eos = 0; size_t off = 0; size_t len = 0; + size_t diff; const unsigned char *q; long slen; @@ -114,15 +115,16 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) ERR_clear_error(); for (;;) { - if (want >= (len - off)) { - want -= (len - off); + diff = len - off; + if (want >= diff) { + want -= diff; if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } i = BIO_read(in, &(b->data[len]), want); - if ((i < 0) && ((len - off) == 0)) { + if (i < 0 && diff == 0) { ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA); goto err; } @@ -138,15 +140,17 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) p = (unsigned char *)&(b->data[off]); q = p; - inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off); + diff = len - off; + if (diff == 0) + goto err; + inf = ASN1_get_object(&q, &slen, &tag, &xclass, diff); if (inf & 0x80) { unsigned long e; e = ERR_GET_REASON(ERR_peek_error()); if (e != ASN1_R_TOO_LONG) goto err; - else - ERR_clear_error(); /* clear error */ + ERR_clear_error(); } i = q - p; /* header length */ off += i; /* end of data */ diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index d45419e5f0..72d15acc7e 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -52,8 +52,10 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, int tag, xclass, inf; long max = omax; - if (!max) - goto err; + if (omax <= 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); + return 0x80; + } ret = (*p & V_ASN1_CONSTRUCTED); xclass = (*p & V_ASN1_PRIVATE); i = *p & V_ASN1_PRIMITIVE_TAG; diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index ef29a16394..20717df461 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -90,7 +90,7 @@ unsigned long ASN1_tag2bit(int tag) /* Macro to initialize and invalidate the cache */ -#define asn1_tlc_clear(c) if (c) (c)->valid = 0 +#define asn1_tlc_clear(c) if ((c) != NULL) (c)->valid = 0 /* Version to avoid compiler warning about 'c' always non-NULL */ #define asn1_tlc_clear_nc(c) (c)->valid = 0 @@ -121,6 +121,11 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, int tag, int aclass, char opt, ASN1_TLC *ctx) { int rv; + + if (pval == NULL || it == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0); if (rv <= 0) ASN1_item_ex_free(pval, it); @@ -139,7 +144,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, { const ASN1_TEMPLATE *tt, *errtt = NULL; const ASN1_EXTERN_FUNCS *ef; - const ASN1_AUX *aux = it->funcs; + const ASN1_AUX *aux; ASN1_aux_cb *asn1_cb; const unsigned char *p = NULL, *q; unsigned char oclass; @@ -150,8 +155,15 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, int ret = 0; ASN1_VALUE **pchptr; - if (pval == NULL) + if (pval == NULL || it == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (len <= 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); return 0; + } + aux = it->funcs; if (aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; else @@ -1100,7 +1112,11 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, p = *in; q = p; - if (ctx && ctx->valid) { + if (len <= 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); + goto err; + } + if (ctx != NULL && ctx->valid) { i = ctx->ret; plen = ctx->plen; pclass = ctx->pclass; @@ -1108,7 +1124,7 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, p += ctx->hdrlen; } else { i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); - if (ctx) { + if (ctx != NULL) { ctx->ret = i; ctx->plen = plen; ctx->pclass = pclass; @@ -1119,29 +1135,26 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, * If definite length, and no error, length + header can't exceed * total amount of data available. */ - if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { + if ((i & 0x81) == 0 && (plen + ctx->hdrlen) > len) { ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); - asn1_tlc_clear(ctx); - return 0; + goto err; } } } - if (i & 0x80) { + if ((i & 0x80) != 0) { ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_OBJECT_HEADER); - asn1_tlc_clear(ctx); - return 0; + goto err; } if (exptag >= 0) { - if ((exptag != ptag) || (expclass != pclass)) { + if (exptag != ptag || expclass != pclass) { /* * If type is OPTIONAL, not an error: indicate missing type. */ - if (opt) + if (opt != 0) return -1; - asn1_tlc_clear(ctx); ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_TAG); - return 0; + goto err; } /* * We have a tag and class match: assume we are going to do something @@ -1150,24 +1163,28 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, asn1_tlc_clear(ctx); } - if (i & 1) + if ((i & 1) != 0) plen = len - (p - q); - if (inf) + if (inf != NULL) *inf = i & 1; - if (cst) + if (cst != NULL) *cst = i & V_ASN1_CONSTRUCTED; - if (olen) + if (olen != NULL) *olen = plen; - if (oclass) + if (oclass != NULL) *oclass = pclass; - if (otag) + if (otag != NULL) *otag = ptag; *in = p; return 1; + + err: + asn1_tlc_clear(ctx); + return 0; }