Don't print small, negative serial numbers in decimal.
X509_print_ex tries to print negative serial numbers in decimal. In
doing so, it ends up passing a signed long to %lx and trips
-Wformat-signed.
A minimal fix would be to cast to unsigned long, but this unsigned long
is the absolute value of a signed long (l = -l). This is tricky because
-LONG_MIN does not fit in long. It all works because the length check
only allows one bit short of sizeof(long)*8 bits (ASN1_INTEGER is
sign-and-magnitude).
Still, this is a whole lot of subtlety to account for an invalid case.
Instead, send negative serial numbers down the generic path.
Bug: 450
Change-Id: Ib215fd23863de27e01f7ededf95578f9c800da37
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50766
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c
index 7c32a87..486c4ec 100644
--- a/crypto/x509/t_x509.c
+++ b/crypto/x509/t_x509.c
@@ -54,6 +54,8 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
+#include <assert.h>
+
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/digest.h>
@@ -98,7 +100,6 @@
char *m = NULL, mlch = ' ';
int nmindent = 0;
X509_CINF *ci;
- ASN1_INTEGER *bs;
EVP_PKEY *pkey = NULL;
const char *neg;
@@ -123,33 +124,32 @@
goto err;
}
if (!(cflag & X509_FLAG_NO_SERIAL)) {
-
- if (BIO_write(bp, " Serial Number:", 22) <= 0)
+ if (BIO_write(bp, " Serial Number:", 22) <= 0) {
goto err;
-
- bs = X509_get_serialNumber(x);
- if (bs->length < (int)sizeof(long)
- || (bs->length == sizeof(long) && (bs->data[0] & 0x80) == 0)) {
- l = ASN1_INTEGER_get(bs);
- if (bs->type == V_ASN1_NEG_INTEGER) {
- l = -l;
- neg = "-";
- } else
- neg = "";
- if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, l, neg, l) <= 0)
- goto err;
- } else {
- neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
- if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0)
- goto err;
-
- for (i = 0; i < bs->length; i++) {
- if (BIO_printf(bp, "%02x%c", bs->data[i],
- ((i + 1 == bs->length) ? '\n' : ':')) <= 0)
- goto err;
- }
}
+ const ASN1_INTEGER *serial = X509_get0_serialNumber(x);
+ /* |ASN1_INTEGER_get| returns -1 on overflow, so this check skips
+ * negative and large serial numbers. */
+ l = ASN1_INTEGER_get(serial);
+ if (l >= 0) {
+ assert(serial->type != V_ASN1_NEG_INTEGER);
+ if (BIO_printf(bp, " %ld (0x%lx)\n", l, (unsigned long)l) <= 0) {
+ goto err;
+ }
+ } else {
+ neg = (serial->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
+ if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) {
+ goto err;
+ }
+
+ for (i = 0; i < serial->length; i++) {
+ if (BIO_printf(bp, "%02x%c", serial->data[i],
+ ((i + 1 == serial->length) ? '\n' : ':')) <= 0) {
+ goto err;
+ }
+ }
+ }
}
if (!(cflag & X509_FLAG_NO_SIGNAME)) {