From ca89174bc92c16f0a2a7eb86359b6c6fd1dd7a4d Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Thu, 6 Sep 2018 22:09:11 +0200 Subject: [PATCH] ASN.1 DER: Make INT32 / INT64 types read badly encoded LONG zeroes The deprecated ASN.1 type LONG / ZLONG (incorrectly) produced zero length INTEGER encoding for zeroes. For the sake of backward compatibility, we allow those to be read without fault when using the replacement types INT32 / UINT32 / INT64 / UINT64. Fixes #7134 Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/7144) --- crypto/asn1/x_int64.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/crypto/asn1/x_int64.c b/crypto/asn1/x_int64.c index f07ca3cfe9..0ee552cf0a 100644 --- a/crypto/asn1/x_int64.c +++ b/crypto/asn1/x_int64.c @@ -81,6 +81,16 @@ static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, return 0; cp = (char *)*pval; + + /* + * Strictly speaking, zero length is malformed. However, long_c2i + * (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course), + * so for the sake of backward compatibility, we still decode zero + * length INTEGERs as the number zero. + */ + if (len == 0) + goto long_compat; + if (!c2i_uint64_int(&utmp, &neg, &cont, len)) return 0; if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { @@ -95,6 +105,8 @@ static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, if (neg) /* c2i_uint64_int() returns positive values */ utmp = 0 - utmp; + + long_compat: memcpy(cp, &utmp, sizeof(utmp)); return 1; } @@ -172,6 +184,16 @@ static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, return 0; cp = (char *)*pval; + + /* + * Strictly speaking, zero length is malformed. However, long_c2i + * (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course), + * so for the sake of backward compatibility, we still decode zero + * length INTEGERs as the number zero. + */ + if (len == 0) + goto long_compat; + if (!c2i_uint64_int(&utmp, &neg, &cont, len)) return 0; if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { @@ -191,6 +213,8 @@ static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, return 0; } } + + long_compat: utmp2 = (uint32_t)utmp; memcpy(cp, &utmp2, sizeof(utmp2)); return 1; -- GitLab