xref: /freebsd/lib/libsecureboot/openpgp/opgp_sig.c (revision dae4eb623e862789533dca8b644ea531502a088f)
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  * RCSid:
27  *	from: signer.c,v 1.10 2018/03/23 01:14:30 sjg
28  *
29  *	This file is provided in the hope that it will
30  *	be of use.  There is absolutely NO WARRANTY.
31  *	Permission to copy, redistribute or otherwise
32  *	use this file is hereby granted provided that
33  *	the above copyright notice and this notice are
34  *	left intact.
35  *
36  *	Please send copies of changes and bug-fixes to:
37  *	sjg@crufty.net
38  */
39 
40 #include <sys/cdefs.h>
41 #include "../libsecureboot-priv.h"
42 #ifdef _STANDALONE
43 #define warnx printf
44 #else
45 
46 #include <sys/param.h>
47 #include <sys/stat.h>
48 #include <unistd.h>
49 #include <stdio.h>
50 #include <fcntl.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <err.h>
54 #endif
55 
56 #include "decode.h"
57 #include "packet.h"
58 
59 #ifdef USE_BEARSSL
60 
61 #define get_error_string ve_error_get
62 
63 void
initialize(void)64 initialize (void)
65 {
66 	openpgp_trust_init();
67 }
68 
69 #else
70 
71 #include <openssl/err.h>
72 
73 /**
74  * @brief initialize OpenSSL
75  */
76 void
initialize(void)77 initialize(void)
78 {
79 	static int once;
80 
81 	if (once)
82 		return);
83 	once = 1;
84 	//CRYPTO_malloc_init();
85 	ERR_load_crypto_strings();
86 	OpenSSL_add_all_algorithms();
87 }
88 
89 /**
90  * @brief
91  * last error from OpenSSL as a string
92  */
93 char *
94 get_error_string(void)
95 {
96 	initialize();
97 	return (ERR_error_string(ERR_get_error(), NULL));
98 }
99 #endif
100 
101 /**
102  * @brief decode a signature packet
103  *
104  * We only support RSA
105  *
106  * @sa rfc4880:5.2
107  */
108 ssize_t
109 decode_sig(int tag, unsigned char **pptr, size_t len, OpenPGP_sig *sig)
110 {
111 	unsigned char *ptr;
112 	unsigned char *pgpbytes;
113 	unsigned char *sp;
114 	int version;
115 	int hcount = 0;
116 	int ucount = 0;
117 	int stag = 0;
118 	int n;
119 
120 	n = tag;			/* avoid unused */
121 
122 	/*
123 	 * We need to keep a reference to the packet bytes
124 	 * as these form part of the signature data.
125 	 *
126 	 * @sa rfc4880:5.2.4
127 	 */
128 	pgpbytes = ptr = *pptr;
129 	version = *ptr++;
130 	if (version == 3) {
131 		ptr++;
132 		sig->pgpbytes = malloc(5);
133 		if (!sig->pgpbytes)
134 			return (-1);
135 		memcpy(sig->pgpbytes, ptr, 5);
136 		sig->pgpbytes_len = 5;
137 		sig->sig_type = *ptr++;
138 		ptr += 4;
139 		sig->key_id = octets2hex(ptr, 8);
140 		ptr += 8;
141 		sig->sig_alg = *ptr++;
142 		sig->hash_alg = *ptr++;
143 	} else if (version == 4) {
144 		sig->sig_type = *ptr++;
145 		sig->sig_alg = *ptr++;
146 		sig->hash_alg = *ptr++;
147 		hcount = octets2i(ptr, 2);
148 		ptr += 2;
149 		sig->pgpbytes_len = (size_t)hcount + 6;
150 		sig->pgpbytes = malloc(sig->pgpbytes_len + 6);
151 		if (!sig->pgpbytes)
152 			return (-1);
153 		memcpy(sig->pgpbytes, pgpbytes, sig->pgpbytes_len);
154 		sp = &sig->pgpbytes[sig->pgpbytes_len];
155 		*sp++ = 4;
156 		*sp++ = 255;
157 		memcpy(sp, i2octets(4, (int)sig->pgpbytes_len), 4);
158 		sig->pgpbytes_len += 6;
159 
160 		while (hcount > 0) {
161 			sp = decode_subpacket(&ptr, &stag, &n);
162 			hcount -= n;
163 			/* can check stag to see if we care */
164 		}
165 		ucount = octets2i(ptr, 2);
166 		ptr += 2;
167 		while (ucount > 0) {
168 			sp = decode_subpacket(&ptr, &stag, &n);
169 			ucount -= n;
170 			/* can check stag to see if we care */
171 			if (stag == 16) {
172 				free(sig->key_id);
173 				sig->key_id = octets2hex(sp, 8);
174 			}
175 		}
176 	} else
177 		return (-1);
178 	ptr += 2;			/* skip hash16 */
179 	if (sig->sig_alg == 1) {	/* RSA */
180 		sig->sig = decode_mpi(&ptr, &sig->sig_len);
181 	}
182 	/* we are done */
183 	return ((ssize_t)len);
184 }
185 
186 /**
187  * @brief map OpenPGP hash algorithm id's to name
188  *
189  * @sa rfc4880:9.4
190  */
191 static struct hash_alg_map {
192 	int halg;
193 	const char *hname;
194 } hash_algs[] = {
195 	{1, "md5"},
196 	{2, "sha1"},
197 	{8, "sha256"},
198 	{9, "sha384"},
199 	{10, "sha512"},
200 	{11, "sha224"},
201 	{0, NULL},
202 };
203 
204 static const char *
205 get_hname(int hash_alg)
206 {
207 	struct hash_alg_map *hmp;
208 
209 	for (hmp = hash_algs; hmp->halg > 0; hmp++) {
210 		if (hmp->halg == hash_alg)
211 			return (hmp->hname);
212 	}
213 	return (NULL);
214 }
215 
216 /* lifted from signer.c */
217 /**
218  * @brief verify a digest
219  *
220  * The public key, digest name, file and signature data.
221  *
222  * @return 1 on success 0 on failure, -1 on error
223  */
224 #ifndef USE_BEARSSL
225 static int
226 verify_digest (EVP_PKEY *pkey,
227     const char *digest,
228     unsigned char *mdata, size_t mlen,
229     unsigned char *sdata, size_t slen)
230 {
231 	EVP_MD_CTX ctx;
232 	const EVP_MD *md = NULL;
233 	EVP_PKEY_CTX *pctx = NULL;
234 	int rc = 0;
235 	int i = -1;
236 
237 	initialize();
238 	md = EVP_get_digestbyname(digest);
239 	EVP_DigestInit(&ctx, md);
240 
241 	pctx = EVP_PKEY_CTX_new(pkey, NULL);
242 	if (!pctx)
243 		goto fail;
244 	if (EVP_PKEY_verify_init(pctx) <= 0)
245 		goto fail;
246 	if (EVP_PKEY_CTX_set_signature_md(pctx, ctx.digest) <= 0)
247 		goto fail;
248 	i = EVP_PKEY_verify(pctx, sdata, slen, mdata, mlen);
249 	if (i >= 0)
250 		rc = i;
251 fail:
252 	EVP_PKEY_CTX_free(pctx);
253 	return (rc);
254 }
255 #endif
256 
257 
258 /**
259  * @brief verify OpenPGP signed file
260  *
261  *
262  * @param[in] filename
263  *	used to determine the signature name
264  *
265  * @param[in] fdata
266  *	content of filename
267  *
268  * @param[in] fbytes
269  *	of fdata
270  *
271  * @param[in] sdata
272  *	content of signature
273  *
274  * @param[in] sbytes
275  *	of sdata
276  *
277  * @param[in] flags
278  *
279  * @return 0 on success
280  */
281 int
282 openpgp_verify(const char *filename,
283     unsigned char *fdata, size_t fbytes,
284     unsigned char *sdata, size_t sbytes,
285     int flags)
286 {
287 	OpenPGP_key *key;
288 	OpenPGP_sig *sig;
289 #ifdef USE_BEARSSL
290 	const br_hash_class *md;
291 	br_hash_compat_context mctx;
292 	const unsigned char *hash_oid;
293 #else
294 	const EVP_MD *md = NULL;
295 	EVP_MD_CTX mctx;
296 #endif
297 	unsigned char mdata[64];
298 	unsigned char *ptr;
299 	unsigned char *ddata = NULL;
300 	const char *hname;
301 	size_t mlen;
302 	int rc = -1;
303 
304 	initialize();
305 
306 	sig = NEW(OpenPGP_sig);
307 	if (!sdata || !sig) {
308 		warnx("cannot verify %s", filename);
309 		goto oops;
310 	}
311 	if (!(sdata[0] & OPENPGP_TAG_ISTAG))
312 		sdata = ddata = dearmor((char *)sdata, sbytes, &sbytes);
313 	ptr = sdata;
314 	rc = decode_packet(2, &ptr, sbytes, (decoder_t)decode_sig, sig);
315 	DEBUG_PRINTF(2, ("rc=%d keyID=%s\n", rc, sig->key_id ? sig->key_id : "?"));
316 	if (rc == 0 && sig->key_id) {
317 		key = load_key_id(sig->key_id);
318 		if (!key) {
319 			warnx("cannot find key-id: %s", sig->key_id);
320 			rc = -1;
321 		} else if (!(hname = get_hname(sig->hash_alg))) {
322 			warnx("unsupported hash algorithm: %d", sig->hash_alg);
323 			rc = -1;
324 		} else {
325 			/*
326 			 * Hash fdata according to the OpenPGP recipe
327 			 *
328 			 * @sa rfc4880:5.2.4
329 			 */
330 #ifdef USE_BEARSSL
331 			switch (sig->hash_alg) { /* see hash_algs above */
332 			case 2:			 /* sha1 */
333 				md = &br_sha1_vtable;
334 				mlen = br_sha1_SIZE;
335 				hash_oid = BR_HASH_OID_SHA1;
336 				break;
337 			case 8:			/* sha256 */
338 				md = &br_sha256_vtable;
339 				mlen = br_sha256_SIZE;
340 				hash_oid = BR_HASH_OID_SHA256;
341 				break;
342 			case 9:			/* sha384 */
343 				md = &br_sha384_vtable;
344 				mlen = br_sha384_SIZE;
345 				hash_oid = BR_HASH_OID_SHA384;
346 				break;
347 			case 10:		/* sha512 */
348 				md = &br_sha512_vtable;
349 				mlen = br_sha512_SIZE;
350 				hash_oid = BR_HASH_OID_SHA512;
351 				break;
352 			default:
353 				warnx("unsupported hash algorithm: %s", hname);
354 				rc = -1;
355 				goto oops;
356 			}
357 			md->init(&mctx.vtable);
358 			md->update(&mctx.vtable, fdata, fbytes);
359 			md->update(&mctx.vtable, sig->pgpbytes,
360 			    sig->pgpbytes_len);
361 			md->out(&mctx.vtable, mdata);
362 
363 			rc = verify_rsa_digest(key->key, hash_oid,
364 			    mdata, mlen, sig->sig, sig->sig_len);
365 #else
366 			md = EVP_get_digestbyname(hname);
367 			EVP_DigestInit(&mctx, md);
368 			EVP_DigestUpdate(&mctx, fdata, fbytes);
369 			EVP_DigestUpdate(&mctx, sig->pgpbytes,
370 			    sig->pgpbytes_len);
371 			mlen = sizeof(mdata);
372 			EVP_DigestFinal(&mctx,mdata,(unsigned int *)&mlen);
373 
374 			rc = verify_digest(key->key, hname, mdata, mlen,
375 			    sig->sig, sig->sig_len);
376 #endif
377 
378 			if (rc > 0) {
379 				if ((flags & VEF_VERBOSE))
380 					printf("Verified %s signed by %s\n",
381 					    filename,
382 					    key->user ? key->user->name : "someone");
383 				rc = 0;	/* success */
384 			} else if (rc == 0) {
385 				printf("Unverified %s: %s\n",
386 				    filename, get_error_string());
387 				rc = 1;
388 			} else {
389 				printf("Unverified %s\n", filename);
390 			}
391 		}
392 	} else {
393 		warnx("cannot decode signature for %s", filename);
394 		rc = -1;
395 	}
396 oops:
397 	free(ddata);
398 	free(sig);
399 	return (rc);
400 }
401 
402 #ifndef _STANDALONE
403 /**
404  * @brief list of extensions we handle
405  *
406  * ".asc" is preferred as it works seamlessly with openpgp
407  */
408 static const char *sig_exts[] = {
409 	".asc",
410 	".pgp",
411 	".psig",
412 	NULL,
413 };
414 
415 /**
416  * @brief verify OpenPGP signed file
417  *
418  *
419  * @param[in] filename
420  *	used to determine the signature name
421  *
422  * @param[in] fdata
423  *	content of filename
424  *
425  * @param[in] nbytes
426  *	of fdata
427  *
428  * @return
429  */
430 
431 int
432 openpgp_verify_file(const char *filename, unsigned char *fdata, size_t nbytes)
433 {
434 	char pbuf[MAXPATHLEN];
435 	unsigned char *sdata;
436 	const char *sname = NULL;
437 	const char **ep;
438 	size_t sz;
439 	int n;
440 
441 	for (ep = sig_exts; *ep; ep++) {
442 		n = snprintf(pbuf, sizeof(pbuf), "%s%s", filename, *ep);
443 		if (n >= (int)sizeof(pbuf)) {
444 			warnx("cannot form signature name for %s", filename);
445 			return (-1);
446 		}
447 		if (access(pbuf, R_OK) == 0) {
448 			sname = pbuf;
449 			break;
450 		}
451 	}
452 	if (!sname) {
453 		warnx("cannot find signature for %s", filename);
454 		return (-1);
455 	}
456 	sdata = read_file(sname, &sz);
457 	return (openpgp_verify(filename, fdata, nbytes, sdata, sz, VerifyFlags));
458 }
459 #endif
460 
461 /**
462  * @brief verify OpenPGP signature
463  *
464  * @return content of signed file
465  */
466 unsigned char *
467 verify_asc(const char *sigfile, int flags)
468 {
469 	char pbuf[MAXPATHLEN];
470 	char *cp;
471 	size_t n;
472 	unsigned char *fdata, *sdata;
473 	size_t fbytes, sbytes;
474 
475 	fdata = NULL;
476 	if ((sdata = read_file(sigfile, &sbytes))) {
477 		n = strlcpy(pbuf, sigfile, sizeof(pbuf));
478 		if (n < sizeof(pbuf)) {
479 			if ((cp = strrchr(pbuf, '.')))
480 				*cp = '\0';
481 			if ((fdata = read_file(pbuf, &fbytes))) {
482 				if (openpgp_verify(pbuf, fdata, fbytes, sdata,
483 					sbytes, flags)) {
484 					free(fdata);
485 					fdata = NULL;
486 				}
487 			}
488 		}
489 	}
490 	free(sdata);
491 	return (fdata);
492 }
493