On Mon, May 22, 2023 at 05:48:01PM +0200, Theo Buehler wrote:
> 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.
Looks good to me but did not manage to test it yet.
This is a big improvement over the previous mess.
OK claudio@
> 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;
> }
> }
>
--
:wq Claudio