/* $OpenBSD: gbr.c,v 1.29 2023/10/13 12:06:49 job Exp $ */ /* * Copyright (c) 2020 Claudio Jeker * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "extern.h" /* * Parse results and data of the manifest file. */ struct parse { const char *fn; /* manifest file name */ struct gbr *res; /* results */ }; extern ASN1_OBJECT *gbr_oid; /* * Parse a full RFC 6493 file and signed by the certificate "cacert" * (the latter is optional and may be passed as NULL to disable). * Returns the payload or NULL if the document was malformed. */ struct gbr * gbr_parse(X509 **x509, const char *fn, int talid, const unsigned char *der, size_t len) { struct parse p; struct cert *cert = NULL; size_t cmsz; unsigned char *cms; time_t signtime = 0; memset(&p, 0, sizeof(struct parse)); p.fn = fn; cms = cms_parse_validate(x509, fn, der, len, gbr_oid, &cmsz, &signtime); if (cms == NULL) return NULL; if ((p.res = calloc(1, sizeof(*p.res))) == NULL) err(1, NULL); p.res->signtime = signtime; if ((p.res->vcard = strndup(cms, cmsz)) == NULL) err(1, NULL); free(cms); if (!x509_get_aia(*x509, fn, &p.res->aia)) goto out; if (!x509_get_aki(*x509, fn, &p.res->aki)) goto out; if (!x509_get_sia(*x509, fn, &p.res->sia)) goto out; if (!x509_get_ski(*x509, fn, &p.res->ski)) goto out; if (p.res->aia == NULL || p.res->aki == NULL || p.res->sia == NULL || p.res->ski == NULL) { warnx("%s: RFC 6487 section 4.8: " "missing AIA, AKI, SIA or SKI X509 extension", fn); goto out; } if (!x509_get_notbefore(*x509, fn, &p.res->notbefore)) goto out; if (!x509_get_notafter(*x509, fn, &p.res->notafter)) goto out; if (!x509_inherits(*x509)) { warnx("%s: RFC 3779 extension not set to inherit", fn); goto out; } if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL) goto out; return p.res; out: gbr_free(p.res); X509_free(*x509); *x509 = NULL; cert_free(cert); return NULL; } /* * Free a GBR pointer. * Safe to call with NULL. */ void gbr_free(struct gbr *p) { if (p == NULL) return; free(p->aia); free(p->aki); free(p->sia); free(p->ski); free(p->vcard); free(p); }