1/*-
2 * Copyright (c) 2018, Juniper Networks, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27#include "../libsecureboot-priv.h"
28
29#include "decode.h"
30#include "packet.h"
31
32/**
33 * @brief decode user-id packet
34 *
35 * This is trivial
36 *
37 * @sa rfc4880:5.11
38 */
39ssize_t
40decode_user(int tag, unsigned char **pptr, size_t len, OpenPGP_user *user)
41{
42	char *cp;
43
44	if (tag == 13) {
45		user->id = malloc(len + 1);
46		strncpy(user->id, (char *)*pptr, len);
47		user->id[len] = '\0';
48		user->name = user->id;
49		cp = strchr(user->id, '<');
50		if (cp > user->id) {
51			user->id = strdup(user->id);
52			cp[-1] = '\0';
53		}
54	}
55	*pptr += len;
56	return ((ssize_t)len);
57}
58
59/**
60 * @brief decode a key packet
61 *
62 * We only really support v4 and RSA
63 *
64 * @sa rfc4880:5.5.1.1
65 */
66ssize_t
67decode_key(int tag, unsigned char **pptr, size_t len, OpenPGP_key *key)
68{
69	unsigned char *ptr;
70	int version;
71#ifdef USE_BEARSSL
72	br_sha1_context mctx;
73	unsigned char mdata[br_sha512_SIZE];
74	size_t mlen;
75#else
76	RSA *rsa = NULL;
77	const EVP_MD *md = NULL;
78	EVP_MD_CTX mctx;
79	unsigned char mdata[EVP_MAX_MD_SIZE];
80	unsigned int mlen;
81#endif
82
83	if (tag != 6)
84		return (-1);
85
86	key->key = NULL;
87	ptr = *pptr;
88	version = *ptr;
89	if (version == 4) {		/* all we support really */
90		/* comput key fingerprint and id @sa rfc4880:12.2 */
91		mdata[0] = 0x99;	/* rfc4880: 12.2.a.1 */
92		mdata[1] = (len >> 8) & 0xff;
93		mdata[2] = len & 0xff;
94
95#ifdef USE_BEARSSL
96		br_sha1_init(&mctx);
97		br_sha1_update(&mctx, mdata, 3);
98		br_sha1_update(&mctx, ptr, len);
99		br_sha1_out(&mctx, mdata);
100		mlen = br_sha1_SIZE;
101#else
102		md = EVP_get_digestbyname("sha1");
103		EVP_DigestInit(&mctx, md);
104		EVP_DigestUpdate(&mctx, mdata, 3);
105		EVP_DigestUpdate(&mctx, ptr, len);
106		mlen = (unsigned int)sizeof(mdata);
107		EVP_DigestFinal(&mctx, mdata, &mlen);
108#endif
109		key->id = octets2hex(&mdata[mlen - 8], 8);
110	}
111	ptr += 1;			/* done with version */
112	ptr += 4;			/* skip ctime */
113	if (version == 3)
114		ptr += 2;		/* valid days */
115	key->sig_alg = *ptr++;
116	if (key->sig_alg == 1) {	/* RSA */
117#ifdef USE_BEARSSL
118		key->key = NEW(br_rsa_public_key);
119		if (!key->key)
120			goto oops;
121		key->key->n = mpi2bn(&ptr, &key->key->nlen);
122		key->key->e = mpi2bn(&ptr, &key->key->elen);
123#else
124		rsa = RSA_new();
125		if (!rsa)
126			goto oops;
127		rsa->n = mpi2bn(&ptr);
128		rsa->e = mpi2bn(&ptr);
129		key->key = EVP_PKEY_new();
130		if (!key->key || !rsa->n || !rsa->e) {
131			goto oops;
132		}
133		if (!EVP_PKEY_set1_RSA(key->key, rsa))
134			goto oops;
135#endif
136	}
137	/* we are done */
138	return ((ssize_t)len);
139oops:
140#ifdef USE_BEARSSL
141	free(key->key);
142	key->key = NULL;
143#else
144	if (rsa)
145		RSA_free(rsa);
146	if (key->key) {
147		EVP_PKEY_free(key->key);
148		key->key = NULL;
149	}
150#endif
151	return (-1);
152}
153
154static OpenPGP_key *
155load_key_buf(unsigned char *buf, size_t nbytes)
156{
157	unsigned char *data = NULL;
158	unsigned char *ptr;
159	ssize_t rc;
160	int tag;
161	OpenPGP_key *key;
162
163	if (!buf)
164		return (NULL);
165
166	initialize();
167
168	if (!(buf[0] & OPENPGP_TAG_ISTAG)) {
169		/* Note: we do *not* free data */
170		data = dearmor((char *)buf, nbytes, &nbytes);
171		ptr = data;
172	} else
173		ptr = buf;
174	key = NEW(OpenPGP_key);
175	if (key) {
176		rc = decode_packet(0, &ptr, nbytes, (decoder_t)decode_key,
177		    key);
178		if (rc < 0) {
179			free(key);
180			key = NULL;
181		} else if (rc > 8) {
182			int isnew, ltype;
183
184			tag = decode_tag(ptr, &isnew, &ltype);
185			if (tag == 13) {
186				key->user = NEW(OpenPGP_user);
187				rc = decode_packet(0, &ptr, (size_t)rc,
188				    (decoder_t)decode_user, key->user);
189			}
190		}
191	}
192	return (key);
193}
194
195static LIST_HEAD(, OpenPGP_key_) trust_list;
196
197/**
198 * @brief add a key to our list
199 */
200void
201openpgp_trust_add(OpenPGP_key *key)
202{
203	static int once = 0;
204
205	if (!once) {
206		once = 1;
207
208		LIST_INIT(&trust_list);
209	}
210	if (key && openpgp_trust_get(key->id) == NULL) {
211		if (ve_anchor_verbose_get())
212			printf("openpgp_trust_add(%s)\n", key->id);
213		LIST_INSERT_HEAD(&trust_list, key, entries);
214	}
215}
216
217/**
218 * @brief add trust anchor from buf
219 */
220int
221openpgp_trust_add_buf(unsigned char *buf, size_t nbytes)
222{
223	OpenPGP_key *key;
224
225	if ((key = load_key_buf(buf, nbytes))) {
226		openpgp_trust_add(key);
227	}
228	return (key != NULL);
229}
230
231
232/**
233 * @brief if keyID is in our list clobber it
234 *
235 * @return true if keyID removed
236 */
237int
238openpgp_trust_revoke(const char *keyID)
239{
240	OpenPGP_key *key, *tkey;
241
242	openpgp_trust_add(NULL);	/* initialize if needed */
243
244	LIST_FOREACH(key, &trust_list, entries) {
245		if (strcmp(key->id, keyID) == 0) {
246			tkey = key;
247			LIST_REMOVE(tkey, entries);
248			printf("openpgp_trust_revoke(%s)\n", key->id);
249			memset(key, 0, sizeof(OpenPGP_key));
250			free(key);
251			return (1);
252		}
253	}
254	return (0);
255}
256
257/**
258 * @brief if keyID is in our list return the key
259 *
260 * @return key or NULL
261 */
262OpenPGP_key *
263openpgp_trust_get(const char *keyID)
264{
265	OpenPGP_key *key;
266
267	openpgp_trust_add(NULL);	/* initialize if needed */
268
269	LIST_FOREACH(key, &trust_list, entries) {
270		if (strcmp(key->id, keyID) == 0)
271			return (key);
272	}
273	return (NULL);
274}
275
276/**
277 * @brief load a key from file
278 */
279OpenPGP_key *
280load_key_file(const char *kfile)
281{
282	unsigned char *data = NULL;
283	size_t n;
284	OpenPGP_key *key;
285
286	data = read_file(kfile, &n);
287	key = load_key_buf(data, n);
288	free(data);
289	openpgp_trust_add(key);
290	return (key);
291}
292
293#ifdef HAVE_TA_ASC_H
294#include <ta_asc.h>
295#endif
296
297#ifndef _STANDALONE
298/* we can lookup keyID in filesystem */
299
300static const char *trust_store[] = {
301	"/var/db/trust",
302	"/etc/db/trust",
303	NULL,
304};
305
306/**
307 * @brief lookup key id in trust store
308 *
309 */
310static OpenPGP_key *
311load_trusted_key_id(const char *keyID)
312{
313	char kfile[MAXPATHLEN];
314	const char **tp;
315	size_t n;
316
317	for (tp = trust_store; *tp; tp++) {
318		n = (size_t)snprintf(kfile, sizeof(kfile), "%s/%s", *tp, keyID);
319		if (n >= sizeof(kfile))
320			return (NULL);
321		if (access(kfile, R_OK) == 0) {
322			return (load_key_file(kfile));
323		}
324	}
325	return (NULL);
326}
327#endif
328
329/**
330 * @brief return key if trusted
331 */
332OpenPGP_key *
333load_key_id(const char *keyID)
334{
335	OpenPGP_key *key;
336
337	key = openpgp_trust_get(keyID);
338#ifndef _STANDALONE
339	if (!key)
340		key = load_trusted_key_id(keyID);
341#endif
342	DEBUG_PRINTF(2, ("load_key_id(%s): %s\n", keyID, key ? "found" : "nope"));
343	return (key);
344}
345
346/**
347 * @brief initialize our internal trust store if any
348 */
349int
350openpgp_trust_init(void)
351{
352	static int once = -1;
353#ifdef HAVE_TA_ASC
354	OpenPGP_key *key;
355	const char **tp;
356	char *cp;
357	size_t n;
358#endif
359
360	if (once < 0) {
361		once = 0;
362#ifdef HAVE_TA_ASC
363		for (tp = ta_ASC; *tp; tp++) {
364			if ((cp = strdup(*tp))) {
365				n = strlen(cp);
366				key = load_key_buf((unsigned char *)cp, n);
367				free(cp);
368				if (key) {
369					openpgp_trust_add(key);
370					once++;
371				}
372			}
373		}
374#endif
375	}
376	return (once);
377}
378
379/**
380 * @brief test that we can verify a signature
381 *
382 * Unlike X.509 certificates, we only support RSA keys
383 * so we stop after first successful signature verification
384 * (which should also be the first attempt ;-)
385 */
386int
387openpgp_self_tests(void)
388{
389	static int rc = -1;		/* remember result */
390#ifdef HAVE_VC_ASC
391	const char **vp, **tp;
392	char *fdata, *sdata = NULL;
393	size_t fbytes, sbytes;
394
395	if (openpgp_trust_init() > 0) {
396		for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) {
397			if ((fdata = strdup(*tp)) &&
398			    (sdata = strdup(*vp))) {
399				fbytes = strlen(fdata);
400				sbytes = strlen(sdata);
401				rc = openpgp_verify("ta_ASC",
402				    (unsigned char *)fdata, fbytes,
403				    (unsigned char *)sdata, sbytes, 0);
404				printf("Testing verify OpenPGP signature:\t\t%s\n",
405				    rc ? "Failed" : "Passed");
406			}
407			free(fdata);
408			free(sdata);
409		}
410	}
411#endif
412	return (rc);
413}
414