Fix overflow checks when converting ASN.1 integers to long.

(Credit to libFuzzer for finding this.)

Change-Id: I0353d686d883703d39145c5bdd1e56368a587a35
Reviewed-on: https://boringssl-review.googlesource.com/22324
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
Adam Langley 2017-10-27 10:37:27 -07:00 committed by CQ bot account: commit-bot@chromium.org
parent f5beb883c2
commit 2a768d04c6
2 changed files with 41 additions and 19 deletions

View File

@ -56,6 +56,7 @@
#include <openssl/asn1.h> #include <openssl/asn1.h>
#include <limits.h>
#include <string.h> #include <string.h>
#include <openssl/err.h> #include <openssl/err.h>
@ -110,7 +111,6 @@ int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a) long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
{ {
int neg = 0, i; int neg = 0, i;
long r = 0;
if (a == NULL) if (a == NULL)
return (0L); return (0L);
@ -120,20 +120,31 @@ long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
else if (i != V_ASN1_ENUMERATED) else if (i != V_ASN1_ENUMERATED)
return -1; return -1;
if (a->length > (int)sizeof(long)) { OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) >= sizeof(long),
/* hmm... a bit ugly */ long_larger_than_uint64_t);
return (0xffffffffL);
}
if (a->data == NULL)
return 0;
for (i = 0; i < a->length; i++) { if (a->length > (int)sizeof(uint64_t)) {
r <<= 8; /* hmm... a bit ugly */
r |= (unsigned char)a->data[i]; return -1;
} }
uint64_t r64 = 0;
if (a->data != NULL) {
for (i = 0; i < a->length; i++) {
r64 <<= 8;
r64 |= (unsigned char)a->data[i];
}
if (r64 > LONG_MAX) {
return -1;
}
}
long r = (long) r64;
if (neg) if (neg)
r = -r; r = -r;
return (r);
return r;
} }
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai) ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)

View File

@ -57,6 +57,7 @@
#include <openssl/asn1.h> #include <openssl/asn1.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/mem.h> #include <openssl/mem.h>
@ -385,7 +386,6 @@ int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
long ASN1_INTEGER_get(const ASN1_INTEGER *a) long ASN1_INTEGER_get(const ASN1_INTEGER *a)
{ {
int neg = 0, i; int neg = 0, i;
long r = 0;
if (a == NULL) if (a == NULL)
return (0L); return (0L);
@ -395,20 +395,31 @@ long ASN1_INTEGER_get(const ASN1_INTEGER *a)
else if (i != V_ASN1_INTEGER) else if (i != V_ASN1_INTEGER)
return -1; return -1;
if (a->length > (int)sizeof(long)) { OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) >= sizeof(long),
long_larger_than_uint64_t);
if (a->length > (int)sizeof(uint64_t)) {
/* hmm... a bit ugly, return all ones */ /* hmm... a bit ugly, return all ones */
return -1; return -1;
} }
if (a->data == NULL)
return 0;
uint64_t r64 = 0;
if (a->data != NULL) {
for (i = 0; i < a->length; i++) { for (i = 0; i < a->length; i++) {
r <<= 8; r64 <<= 8;
r |= (unsigned char)a->data[i]; r64 |= (unsigned char)a->data[i];
} }
if (r64 > LONG_MAX) {
return -1;
}
}
long r = (long) r64;
if (neg) if (neg)
r = -r; r = -r;
return (r);
return r;
} }
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)