diff options
author | Dr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> | 2018-04-26 20:36:41 +0200 |
---|---|---|
committer | Dr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> | 2018-05-02 20:36:21 +0200 |
commit | c6718437709108b4bcb784d774fb3df124df48e5 (patch) | |
tree | 87cc250d01bd4b08adc5480bc9f3338683c9f5cc /crypto | |
parent | 6ebb49f3f9c9333611192561979bb799fa1eb76d (diff) |
a_strex.c: prevent out of bound read in do_buf()
which is used for ASN1_STRING_print_ex*() and X509_NAME_print_ex*().
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6105)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/asn1/a_strex.c | 25 | ||||
-rw-r--r-- | crypto/asn1/asn1_err.c | 1 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 1 |
3 files changed, 25 insertions, 2 deletions
diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index 1d34f56b0b..6a67bc8c33 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -139,7 +139,7 @@ static int do_buf(unsigned char *buf, int buflen, int type, unsigned short flags, char *quotes, char_io *io_ch, void *arg) { - int i, outlen, len; + int i, outlen, len, charwidth; unsigned short orflags; unsigned char *p, *q; unsigned long c; @@ -147,12 +147,32 @@ static int do_buf(unsigned char *buf, int buflen, p = buf; q = buf + buflen; outlen = 0; + charwidth = type & BUF_TYPE_WIDTH_MASK; + + switch (charwidth) { + case 4: + if (buflen & 3) { + ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); + return -1; + } + break; + case 2: + if (buflen & 1) { + ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH); + return -1; + } + break; + default: + break; + } + while (p != q) { if (p == buf && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_FIRST_ESC_2253; else orflags = 0; - switch (type & BUF_TYPE_WIDTH_MASK) { + + switch (charwidth) { case 4: c = ((unsigned long)*p++) << 24; c |= ((unsigned long)*p++) << 16; @@ -173,6 +193,7 @@ static int do_buf(unsigned char *buf, int buflen, i = UTF8_getc(p, buflen, &c); if (i < 0) return -1; /* Invalid UTF8String */ + buflen -= i; p += i; break; default: diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index 751d4414ac..22bf06f032 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -109,6 +109,7 @@ static const ERR_STRING_DATA ASN1_str_functs[] = { "d2i_AutoPrivateKey"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_TCREATE, 0), "do_tcreate"}, diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 155a8f3739..209bd0d3c3 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -82,6 +82,7 @@ ASN1_F_D2I_ASN1_UINTEGER:150:d2i_ASN1_UINTEGER ASN1_F_D2I_AUTOPRIVATEKEY:207:d2i_AutoPrivateKey ASN1_F_D2I_PRIVATEKEY:154:d2i_PrivateKey ASN1_F_D2I_PUBLICKEY:155:d2i_PublicKey +ASN1_F_DO_BUF:142:do_buf ASN1_F_DO_CREATE:124:do_create ASN1_F_DO_DUMP:125:do_dump ASN1_F_DO_TCREATE:222:do_tcreate |