summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2018-09-06 22:09:11 +0200
committerRichard Levitte <levitte@openssl.org>2018-09-09 03:39:37 +0200
commitca89174bc92c16f0a2a7eb86359b6c6fd1dd7a4d (patch)
treeb61c993d5e2656f3e5096974d71cbf4ef45578e9 /crypto
parentc2278c8bc41b01df9fac5fc3d7134430a88dd0e5 (diff)
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 <tjh@openssl.org> (Merged from https://github.com/openssl/openssl/pull/7144)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asn1/x_int64.c24
1 files changed, 24 insertions, 0 deletions
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;