LibreSSL 3.6 added ASN1_INTEGER_get_uint64() from OpenSSL. While this
still isn't great, at least it allows for unambiguous error checking.

In as_id_parse() we can replace some hand-rolled parsing which
simplifies things a bit.

The ASN1_INTEGER_get() API should not be used since it doesn't allow you
to distinguish errors from the (sometimes) legitimate return value -1.
Either you ignore that or you get to do some extra dances.

The conversion of the ASN1_INTEGER_get() uses is straightforward. The
price to pay is a cast for the printing, since that is the lesser evil
than the ugly PRIu64 macro.

Index: as.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/as.c,v
retrieving revision 1.11
diff -u -p -r1.11 as.c
--- as.c        30 Nov 2022 08:17:21 -0000      1.11
+++ as.c        9 May 2023 11:16:58 -0000
@@ -23,38 +23,16 @@
 
 #include "extern.h"
 
-/*
- * Parse a uint32_t AS identifier from an ASN1_INTEGER.
- * This relies on the specification for ASN1_INTEGER itself, which is
- * essentially a series of big-endian bytes in the unsigned case.
- * All we do here is check if the number is negative then start copying
- * over bytes.
- * This is necessary because ASN1_INTEGER_get() on a 32-bit machine
- * (e.g., i386) will fail for AS numbers of UINT32_MAX.
- */
+/* Parse a uint32_t AS identifier from an ASN1_INTEGER. */
 int
 as_id_parse(const ASN1_INTEGER *v, uint32_t *out)
 {
-       int      i;
-       uint32_t res = 0;
+       uint64_t res = 0;
 
-       /* If the negative bit is set, this is wrong. */
-
-       if (v->type & V_ASN1_NEG)
+       if (!ASN1_INTEGER_get_uint64(&res, v))
                return 0;
-
-       /* Too many bytes for us to consider. */
-
-       if ((size_t)v->length > sizeof(uint32_t))
+       if (res > UINT32_MAX)
                return 0;
-
-       /* Stored as big-endian bytes. */
-
-       for (i = 0; i < v->length; i++) {
-               res <<= 8;
-               res |= v->data[i];
-       }
-
        *out = res;
        return 1;
 }
Index: roa.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
retrieving revision 1.66
diff -u -p -r1.66 roa.c
--- roa.c       26 Apr 2023 16:32:41 -0000      1.66
+++ roa.c       9 May 2023 11:59:44 -0000
@@ -107,7 +107,7 @@ roa_parse_econtent(const unsigned char *
        int                              addrsz;
        enum afi                         afi;
        const ROAIPAddress              *addr;
-       long                             maxlen;
+       uint64_t                         maxlen;
        struct ip_addr                   ipaddr;
        struct roa_ip                   *res;
        int                              ipaddrblocksz;
@@ -168,21 +168,23 @@ roa_parse_econtent(const unsigned char *
                        maxlen = ipaddr.prefixlen;
 
                        if (addr->maxLength != NULL) {
-                               maxlen = ASN1_INTEGER_get(addr->maxLength);
-                               if (maxlen < 0) {
+                               if (!ASN1_INTEGER_get_uint64(&maxlen,
+                                   addr->maxLength)) {
                                        warnx("%s: RFC 6482 section 3.2: "
-                                           "ASN1_INTEGER_get failed", p->fn);
+                                           "ASN1_INTEGER_get_uint64 failed",
+                                           p->fn);
                                        goto out;
                                }
                                if (ipaddr.prefixlen > maxlen) {
                                        warnx("%s: prefixlen (%d) larger than "
-                                           "maxLength (%ld)", p->fn,
-                                           ipaddr.prefixlen, maxlen);
+                                           "maxLength (%llu)", p->fn,
+                                           ipaddr.prefixlen,
+                                           (unsigned long long)maxlen);
                                        goto out;
                                }
                                if (maxlen > ((afi == AFI_IPV4) ? 32 : 128)) {
-                                       warnx("%s: maxLength (%ld) too large",
-                                           p->fn, maxlen);
+                                       warnx("%s: maxLength (%llu) too large",
+                                           p->fn, (unsigned long long)maxlen);
                                        goto out;
                                }
                        }
Index: validate.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/validate.c,v
retrieving revision 1.61
diff -u -p -r1.61 validate.c
--- validate.c  11 May 2023 14:05:31 -0000      1.61
+++ validate.c  12 May 2023 05:37:43 -0000
@@ -516,13 +516,13 @@ valid_rsc(const char *fn, struct cert *c
 int
 valid_econtent_version(const char *fn, const ASN1_INTEGER *aint)
 {
-       long version;
+       uint64_t version;
 
        if (aint == NULL)
                return 1;
 
-       if ((version = ASN1_INTEGER_get(aint)) < 0) {
-               warnx("%s: ASN1_INTEGER_get failed", fn);
+       if (!ASN1_INTEGER_get_uint64(&version, aint)) {
+               warnx("%s: ASN1_INTEGER_get_uint64 failed", fn);
                return 0;
        }
 
@@ -531,7 +531,8 @@ valid_econtent_version(const char *fn, c
                warnx("%s: incorrect encoding for version 0", fn);
                return 0;
        default:
-               warnx("%s: version %ld not supported (yet)", fn, version);
+               warnx("%s: version %llu not supported (yet)", fn,
+                   (unsigned long long)version);
                return 0;
        }
 }

Reply via email to