xref: /freebsd/lib/libsecureboot/openpgp/opgp_key.c (revision b9f654b163bce26de79705e77b872427c9f2afa1)
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 __FBSDID("$FreeBSD$");
28 
29 #include "../libsecureboot-priv.h"
30 
31 #include "decode.h"
32 #include "packet.h"
33 
34 /**
35  * @brief decode user-id packet
36  *
37  * This is trivial
38  *
39  * @sa rfc4880:5.11
40  */
41 ssize_t
42 decode_user(int tag, unsigned char **pptr, size_t len, OpenPGP_user *user)
43 {
44 	char *cp;
45 
46 	if (tag == 13) {
47 		user->id = malloc(len + 1);
48 		strncpy(user->id, (char *)*pptr, len);
49 		user->id[len] = '\0';
50 		user->name = user->id;
51 		cp = strchr(user->id, '<');
52 		if (cp > user->id) {
53 			user->id = strdup(user->id);
54 			cp[-1] = '\0';
55 		}
56 	}
57 	*pptr += len;
58 	return ((ssize_t)len);
59 }
60 
61 /**
62  * @brief decode a key packet
63  *
64  * We only really support v4 and RSA
65  *
66  * @sa rfc4880:5.5.1.1
67  */
68 ssize_t
69 decode_key(int tag, unsigned char **pptr, size_t len, OpenPGP_key *key)
70 {
71 	unsigned char *ptr;
72 	int version;
73 #ifdef USE_BEARSSL
74 	br_sha1_context mctx;
75 	unsigned char mdata[br_sha512_SIZE];
76 	size_t mlen;
77 #else
78 	RSA *rsa = NULL;
79 	const EVP_MD *md = NULL;
80 	EVP_MD_CTX mctx;
81 	unsigned char mdata[EVP_MAX_MD_SIZE];
82 	unsigned int mlen;
83 #endif
84 
85 	if (tag != 6)
86 		return (-1);
87 
88 	key->key = NULL;
89 	ptr = *pptr;
90 	version = *ptr;
91 	if (version == 4) {		/* all we support really */
92 		/* comput key fingerprint and id @sa rfc4880:12.2 */
93 		mdata[0] = 0x99;	/* rfc4880: 12.2.a.1 */
94 		mdata[1] = (len >> 8) & 0xff;
95 		mdata[2] = len & 0xff;
96 
97 #ifdef USE_BEARSSL
98 		br_sha1_init(&mctx);
99 		br_sha1_update(&mctx, mdata, 3);
100 		br_sha1_update(&mctx, ptr, len);
101 		br_sha1_out(&mctx, mdata);
102 		mlen = br_sha1_SIZE;
103 #else
104 		md = EVP_get_digestbyname("sha1");
105 		EVP_DigestInit(&mctx, md);
106 		EVP_DigestUpdate(&mctx, mdata, 3);
107 		EVP_DigestUpdate(&mctx, ptr, len);
108 		mlen = (unsigned int)sizeof(mdata);
109 		EVP_DigestFinal(&mctx, mdata, &mlen);
110 #endif
111 		key->id = octets2hex(&mdata[mlen - 8], 8);
112 	}
113 	ptr += 1;			/* done with version */
114 	ptr += 4;			/* skip ctime */
115 	if (version == 3)
116 		ptr += 2;		/* valid days */
117 	key->sig_alg = *ptr++;
118 	if (key->sig_alg == 1) {	/* RSA */
119 #ifdef USE_BEARSSL
120 		key->key = NEW(br_rsa_public_key);
121 		if (!key->key)
122 			goto oops;
123 		key->key->n = mpi2bn(&ptr, &key->key->nlen);
124 		key->key->e = mpi2bn(&ptr, &key->key->elen);
125 #else
126 		rsa = RSA_new();
127 		if (!rsa)
128 			goto oops;
129 		rsa->n = mpi2bn(&ptr);
130 		rsa->e = mpi2bn(&ptr);
131 		key->key = EVP_PKEY_new();
132 		if (!key->key || !rsa->n || !rsa->e) {
133 			goto oops;
134 		}
135 		if (!EVP_PKEY_set1_RSA(key->key, rsa))
136 			goto oops;
137 #endif
138 	}
139 	/* we are done */
140 	return ((ssize_t)len);
141 oops:
142 #ifdef USE_BEARSSL
143 	free(key->key);
144 	key->key = NULL;
145 #else
146 	if (rsa)
147 		RSA_free(rsa);
148 	if (key->key) {
149 		EVP_PKEY_free(key->key);
150 		key->key = NULL;
151 	}
152 #endif
153 	return (-1);
154 }
155 
156 static OpenPGP_key *
157 load_key_buf(unsigned char *buf, size_t nbytes)
158 {
159 	unsigned char *data = NULL;
160 	unsigned char *ptr;
161 	ssize_t rc;
162 	int tag;
163 	OpenPGP_key *key;
164 
165 	if (!buf)
166 		return (NULL);
167 
168 	initialize();
169 
170 	if (!(buf[0] & OPENPGP_TAG_ISTAG)) {
171 		/* Note: we do *not* free data */
172 		data = dearmor((char *)buf, nbytes, &nbytes);
173 		ptr = data;
174 	} else
175 		ptr = buf;
176 	key = NEW(OpenPGP_key);
177 	if (key) {
178 		rc = decode_packet(0, &ptr, nbytes, (decoder_t)decode_key,
179 		    key);
180 		if (rc < 0) {
181 			free(key);
182 			key = NULL;
183 		} else if (rc > 8) {
184 			int isnew, ltype;
185 
186 			tag = decode_tag(ptr, &isnew, &ltype);
187 			if (tag == 13) {
188 				key->user = NEW(OpenPGP_user);
189 				rc = decode_packet(0, &ptr, (size_t)rc,
190 				    (decoder_t)decode_user, key->user);
191 			}
192 		}
193 	}
194 	return (key);
195 }
196 
197 static LIST_HEAD(, OpenPGP_key_) trust_list;
198 
199 /**
200  * @brief add a key to our list
201  */
202 void
203 openpgp_trust_add(OpenPGP_key *key)
204 {
205 	static int once = 0;
206 
207 	if (!once) {
208 		once = 1;
209 
210 		LIST_INIT(&trust_list);
211 	}
212 	if (key) {
213 		DEBUG_PRINTF(2, ("openpgp_trust_add(%s)\n", key->id));
214 		LIST_INSERT_HEAD(&trust_list, key, entries);
215 	}
216 }
217 
218 /**
219  * @brief if keyID is in our list return the key
220  *
221  * @return key or NULL
222  */
223 OpenPGP_key *
224 openpgp_trust_get(const char *keyID)
225 {
226 	OpenPGP_key *key;
227 
228 	openpgp_trust_add(NULL);	/* initialize if needed */
229 
230 	LIST_FOREACH(key, &trust_list, entries) {
231 		if (strcmp(key->id, keyID) == 0)
232 			return (key);
233 	}
234 	return (NULL);
235 }
236 
237 /**
238  * @brief load a key from file
239  */
240 OpenPGP_key *
241 load_key_file(const char *kfile)
242 {
243 	unsigned char *data = NULL;
244 	size_t n;
245 	OpenPGP_key *key;
246 
247 	data = read_file(kfile, &n);
248 	key = load_key_buf(data, n);
249 	free(data);
250 	openpgp_trust_add(key);
251 	return (key);
252 }
253 
254 #include <ta_asc.h>
255 
256 #ifndef _STANDALONE
257 /* we can lookup keyID in filesystem */
258 
259 static const char *trust_store[] = {
260 	"/var/db/trust",
261 	"/etc/db/trust",
262 	NULL,
263 };
264 
265 /**
266  * @brief lookup key id in trust store
267  *
268  */
269 static OpenPGP_key *
270 load_trusted_key_id(const char *keyID)
271 {
272 	char kfile[MAXPATHLEN];
273 	const char **tp;
274 	size_t n;
275 
276 	for (tp = trust_store; *tp; tp++) {
277 		n = (size_t)snprintf(kfile, sizeof(kfile), "%s/%s", *tp, keyID);
278 		if (n >= sizeof(kfile))
279 			return (NULL);
280 		if (access(kfile, R_OK) == 0) {
281 			return (load_key_file(kfile));
282 		}
283 	}
284 	return (NULL);
285 }
286 #endif
287 
288 /**
289  * @brief return key if trusted
290  */
291 OpenPGP_key *
292 load_key_id(const char *keyID)
293 {
294 	OpenPGP_key *key;
295 
296 	key = openpgp_trust_get(keyID);
297 #ifndef _STANDALONE
298 	if (!key)
299 		key = load_trusted_key_id(keyID);
300 #endif
301 	DEBUG_PRINTF(2, ("load_key_id(%s): %s\n", keyID, key ? "found" : "nope"));
302 	return (key);
303 }
304 
305 /**
306  * @brief initialize our internal trust store if any
307  */
308 int
309 openpgp_trust_init(void)
310 {
311 	static int once = -1;
312 #ifdef HAVE_TA_ASC
313 	OpenPGP_key *key;
314 	const char **tp;
315 	char *cp;
316 	size_t n;
317 #endif
318 
319 	if (once < 0) {
320 		once = 0;
321 #ifdef HAVE_TA_ASC
322 		for (tp = ta_ASC; *tp; tp++) {
323 			if ((cp = strdup(*tp))) {
324 				n = strlen(cp);
325 				key = load_key_buf((unsigned char *)cp, n);
326 				free(cp);
327 				if (key) {
328 					openpgp_trust_add(key);
329 					once++;
330 				}
331 			}
332 		}
333 	}
334 #endif
335 	return (once);
336 }
337 
338 /**
339  * @brief test that we can verify a signature
340  *
341  * Unlike X.509 certificates, we only support RSA keys
342  * so we stop after first successful signature verification
343  * (which should also be the first attempt ;-)
344  */
345 int
346 openpgp_self_tests(void)
347 {
348 	static int rc = -1;		/* remember result */
349 #ifdef HAVE_VC_ASC
350 	const char **vp, **tp;
351 	char *fdata, *sdata = NULL;
352 	size_t fbytes, sbytes;
353 
354 	if (openpgp_trust_init() > 0) {
355 		for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) {
356 			if ((fdata = strdup(*tp)) &&
357 			    (sdata = strdup(*vp))) {
358 				fbytes = strlen(fdata);
359 				sbytes = strlen(sdata);
360 				rc = openpgp_verify("ta_ASC",
361 				    (unsigned char *)fdata, fbytes,
362 				    (unsigned char *)sdata, sbytes, 0);
363 				printf("Testing verify OpenPGP signature:\t\t%s\n",
364 				    rc ? "Failed" : "Passed");
365 			}
366 			free(fdata);
367 			free(sdata);
368 		}
369 	}
370 #endif
371 	return (rc);
372 }
373