On Tue, Feb 21, 2023 at 03:07:00AM +0100, Theo Buehler wrote:
> By design of d2i, it's the caller's responsibility to check a DER object
> has been fully consumed. We read files from the disk, check hashes,
> parse and validate the DER we encounter, but we do not make sure that
> nothing follows the DER blob we parsed.
>
> As Job noticed, it is possible to append data to a CRL and still have a
> manifest display "Validation: OK" in file mode. This is partly possible
> due to the fact that filemode has a rather lax notion of validity (since
> it is an inspection tool), but also due to these missing checks.
>
> The diff below checks for !=. Barring bugs in ASN1_item_d2i() (unheard
> of!), only the < case should be possible, but it seems better to allow
> for > as well. I guess we could assert <=.
OK claudio@
> Index: cert.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.101
> diff -u -p -r1.101 cert.c
> --- cert.c 30 Nov 2022 09:12:34 -0000 1.101
> +++ cert.c 21 Feb 2023 01:48:00 -0000
> @@ -641,13 +641,14 @@ cert_parse_ee_cert(const char *fn, X509
> struct cert *
> cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
> {
> - int extsz;
> - int sia_present = 0;
> - size_t i;
> - X509 *x = NULL;
> - X509_EXTENSION *ext = NULL;
> - ASN1_OBJECT *obj;
> - struct parse p;
> + const unsigned char *oder;
> + int extsz;
> + int sia_present = 0;
> + size_t i;
> + X509 *x = NULL;
> + X509_EXTENSION *ext = NULL;
> + ASN1_OBJECT *obj;
> + struct parse p;
>
> /* just fail for empty buffers, the warning was printed elsewhere */
> if (der == NULL)
> @@ -658,8 +659,13 @@ cert_parse_pre(const char *fn, const uns
> if ((p.res = calloc(1, sizeof(struct cert))) == NULL)
> err(1, NULL);
>
> + oder = der;
> if ((x = d2i_X509(NULL, &der, len)) == NULL) {
> cryptowarnx("%s: d2i_X509", p.fn);
> + goto out;
> + }
> + if (der != oder + len) {
> + warnx("%s: %td bytes trailing garbage", fn, oder + len - der);
> goto out;
> }
>
> Index: cms.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cms.c,v
> retrieving revision 1.26
> diff -u -p -r1.26 cms.c
> --- cms.c 28 Dec 2022 21:30:18 -0000 1.26
> +++ cms.c 21 Feb 2023 01:45:37 -0000
> @@ -64,9 +64,10 @@ cms_extract_econtent(const char *fn, CMS
>
> static int
> cms_parse_validate_internal(X509 **xp, const char *fn, const unsigned char
> *der,
> - size_t derlen, const ASN1_OBJECT *oid, BIO *bio, unsigned char **res,
> + size_t len, const ASN1_OBJECT *oid, BIO *bio, unsigned char **res,
> size_t *rsz)
> {
> + const unsigned char *oder;
> char buf[128], obuf[128];
> const ASN1_OBJECT *obj, *octype;
> ASN1_OCTET_STRING *kid = NULL;
> @@ -89,8 +90,13 @@ cms_parse_validate_internal(X509 **xp, c
> if (der == NULL)
> return 0;
>
> - if ((cms = d2i_CMS_ContentInfo(NULL, &der, derlen)) == NULL) {
> + oder = der;
> + if ((cms = d2i_CMS_ContentInfo(NULL, &der, len)) == NULL) {
> cryptowarnx("%s: RFC 6488: failed CMS parse", fn);
> + goto out;
> + }
> + if (der != oder + len) {
> + warnx("%s: %td bytes trailing garbage", fn, oder + len - der);
> goto out;
> }
>
> Index: crl.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/crl.c,v
> retrieving revision 1.21
> diff -u -p -r1.21 crl.c
> --- crl.c 30 Nov 2022 09:03:44 -0000 1.21
> +++ crl.c 21 Feb 2023 01:47:31 -0000
> @@ -25,9 +25,10 @@
> struct crl *
> crl_parse(const char *fn, const unsigned char *der, size_t len)
> {
> - struct crl *crl;
> - const ASN1_TIME *at;
> - int rc = 0;
> + const unsigned char *oder;
> + struct crl *crl;
> + const ASN1_TIME *at;
> + int rc = 0;
>
> /* just fail for empty buffers, the warning was printed elsewhere */
> if (der == NULL)
> @@ -36,8 +37,13 @@ crl_parse(const char *fn, const unsigned
> if ((crl = calloc(1, sizeof(*crl))) == NULL)
> err(1, NULL);
>
> + oder = der;
> if ((crl->x509_crl = d2i_X509_CRL(NULL, &der, len)) == NULL) {
> cryptowarnx("%s: d2i_X509_CRL", fn);
> + goto out;
> + }
> + if (der != oder + len) {
> + warnx("%s: %td bytes trailing garbage", fn, oder + len - der);
> goto out;
> }
>
>
--
:wq Claudio