xref: /openbsd/usr.sbin/rpki-client/gbr.c (revision 73471bf0)
1 /*	$OpenBSD: gbr.c,v 1.11 2021/10/26 10:52:50 claudio Exp $ */
2 /*
3  * Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <assert.h>
19 #include <err.h>
20 #include <stdarg.h>
21 #include <stdint.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 
27 #include <openssl/x509.h>
28 
29 #include "extern.h"
30 
31 /*
32  * Parse results and data of the manifest file.
33  */
34 struct	parse {
35 	const char	 *fn; /* manifest file name */
36 	struct gbr	 *res; /* results */
37 };
38 
39 static ASN1_OBJECT	*gbr_oid;
40 
41 /*
42  * Parse a full RFC 6493 file and signed by the certificate "cacert"
43  * (the latter is optional and may be passed as NULL to disable).
44  * Returns the payload or NULL if the document was malformed.
45  */
46 struct gbr *
47 gbr_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len)
48 {
49 	struct parse	 p;
50 	size_t		 cmsz;
51 	unsigned char	*cms;
52 
53 	memset(&p, 0, sizeof(struct parse));
54 	p.fn = fn;
55 
56 	/* OID from section 9.1, RFC 6493. */
57 	if (gbr_oid == NULL) {
58 		gbr_oid = OBJ_txt2obj("1.2.840.113549.1.9.16.1.35", 1);
59 		if (gbr_oid == NULL)
60 			errx(1, "OBJ_txt2obj for %s failed",
61 			    "1.2.840.113549.1.9.16.1.35");
62 	}
63 
64 	cms = cms_parse_validate(x509, fn, der, len, gbr_oid, &cmsz);
65 	if (cms == NULL)
66 		return NULL;
67 
68 	if ((p.res = calloc(1, sizeof(*p.res))) == NULL)
69 		err(1, NULL);
70 	if ((p.res->vcard = strndup(cms, cmsz)) == NULL)
71 		err(1, NULL);
72 	free(cms);
73 
74 	p.res->aia = x509_get_aia(*x509, fn);
75 	p.res->aki = x509_get_aki(*x509, 0, fn);
76 	p.res->ski = x509_get_ski(*x509, fn);
77 	if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
78 		warnx("%s: RFC 6487 section 4.8: "
79 		    "missing AIA, AKI or SKI X509 extension", fn);
80 		gbr_free(p.res);
81 		X509_free(*x509);
82 		*x509 = NULL;
83 		return NULL;
84 	}
85 
86 	return p.res;
87 }
88 
89 /*
90  * Free a GBR pointer.
91  * Safe to call with NULL.
92  */
93 void
94 gbr_free(struct gbr *p)
95 {
96 
97 	if (p == NULL)
98 		return;
99 	free(p->aia);
100 	free(p->aki);
101 	free(p->ski);
102 	free(p->vcard);
103 	free(p);
104 }
105