1 /*	$OpenBSD: gbr.c,v 1.14 2022/01/18 16:24:55 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 extern 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 *
gbr_parse(X509 ** x509,const char * fn,const unsigned char * der,size_t len)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 	cms = cms_parse_validate(x509, fn, der, len, gbr_oid, &cmsz);
57 	if (cms == NULL)
58 		return NULL;
59 
60 	if ((p.res = calloc(1, sizeof(*p.res))) == NULL)
61 		err(1, NULL);
62 	if ((p.res->vcard = strndup(cms, cmsz)) == NULL)
63 		err(1, NULL);
64 	free(cms);
65 
66 	p.res->aia = x509_get_aia(*x509, fn);
67 	p.res->aki = x509_get_aki(*x509, 0, fn);
68 	p.res->ski = x509_get_ski(*x509, fn);
69 	if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
70 		warnx("%s: RFC 6487 section 4.8: "
71 		    "missing AIA, AKI or SKI X509 extension", fn);
72 		gbr_free(p.res);
73 		X509_free(*x509);
74 		*x509 = NULL;
75 		return NULL;
76 	}
77 
78 	return p.res;
79 }
80 
81 /*
82  * Free a GBR pointer.
83  * Safe to call with NULL.
84  */
85 void
gbr_free(struct gbr * p)86 gbr_free(struct gbr *p)
87 {
88 
89 	if (p == NULL)
90 		return;
91 	free(p->aia);
92 	free(p->aki);
93 	free(p->ski);
94 	free(p->vcard);
95 	free(p);
96 }
97