xref: /freebsd/lib/libsecureboot/openpgp/opgp_sig.c (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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
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
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 			default:
343 				warnx("unsupported hash algorithm: %s", hname);
344 				goto oops;
345 			}
346 			md->init(&mctx.vtable);
347 			md->update(&mctx.vtable, fdata, fbytes);
348 			md->update(&mctx.vtable, sig->pgpbytes,
349 			    sig->pgpbytes_len);
350 			md->out(&mctx.vtable, mdata);
351 
352 			rc = verify_rsa_digest(key->key, hash_oid,
353 			    mdata, mlen, sig->sig, sig->sig_len);
354 #else
355 			md = EVP_get_digestbyname(hname);
356 			EVP_DigestInit(&mctx, md);
357 			EVP_DigestUpdate(&mctx, fdata, fbytes);
358 			EVP_DigestUpdate(&mctx, sig->pgpbytes,
359 			    sig->pgpbytes_len);
360 			mlen = sizeof(mdata);
361 			EVP_DigestFinal(&mctx,mdata,(unsigned int *)&mlen);
362 
363 			rc = verify_digest(key->key, hname, mdata, mlen,
364 			    sig->sig, sig->sig_len);
365 #endif
366 
367 			if (rc > 0) {
368 				if ((flags & VEF_VERBOSE))
369 					printf("Verified %s signed by %s\n",
370 					    filename,
371 					    key->user ? key->user->name : "someone");
372 				rc = 0;	/* success */
373 			} else if (rc == 0) {
374 				printf("Unverified %s: %s\n",
375 				    filename, get_error_string());
376 				rc = 1;
377 			} else {
378 				printf("Unverified %s\n", filename);
379 			}
380 		}
381 	} else {
382 		warnx("cannot decode signature for %s", filename);
383 		rc = -1;
384 	}
385 oops:
386 	free(ddata);
387 	free(sig);
388 	return (rc);
389 }
390 
391 #ifndef _STANDALONE
392 /**
393  * @brief list of extensions we handle
394  *
395  * ".asc" is preferred as it works seamlessly with openpgp
396  */
397 static const char *sig_exts[] = {
398 	".asc",
399 	".pgp",
400 	".psig",
401 	NULL,
402 };
403 
404 /**
405  * @brief verify OpenPGP signed file
406  *
407  *
408  * @param[in] filename
409  *	used to determine the signature name
410  *
411  * @param[in] fdata
412  *	content of filename
413  *
414  * @param[in] nbytes
415  *	of fdata
416  *
417  * @return
418  */
419 
420 int
421 openpgp_verify_file(const char *filename, unsigned char *fdata, size_t nbytes)
422 {
423 	char pbuf[MAXPATHLEN];
424 	unsigned char *sdata;
425 	const char *sname = NULL;
426 	const char **ep;
427 	size_t sz;
428 	int n;
429 
430 	for (ep = sig_exts; *ep; ep++) {
431 		n = snprintf(pbuf, sizeof(pbuf), "%s%s", filename, *ep);
432 		if (n >= (int)sizeof(pbuf)) {
433 			warnx("cannot form signature name for %s", filename);
434 			return (-1);
435 		}
436 		if (access(pbuf, R_OK) == 0) {
437 			sname = pbuf;
438 			break;
439 		}
440 	}
441 	if (!sname) {
442 		warnx("cannot find signature for %s", filename);
443 		return (-1);
444 	}
445 	sdata = read_file(sname, &sz);
446 	return (openpgp_verify(filename, fdata, nbytes, sdata, sz, VerifyFlags));
447 }
448 #endif
449 
450 /**
451  * @brief verify OpenPGP signature
452  *
453  * @return content of signed file
454  */
455 unsigned char *
456 verify_asc(const char *sigfile, int flags)
457 {
458 	char pbuf[MAXPATHLEN];
459 	char *cp;
460 	size_t n;
461 	unsigned char *fdata, *sdata;
462 	size_t fbytes, sbytes;
463 
464 	fdata = NULL;
465 	if ((sdata = read_file(sigfile, &sbytes))) {
466 		n = strlcpy(pbuf, sigfile, sizeof(pbuf));
467 		if (n < sizeof(pbuf)) {
468 			if ((cp = strrchr(pbuf, '.')))
469 				*cp = '\0';
470 			if ((fdata = read_file(pbuf, &fbytes))) {
471 				if (openpgp_verify(pbuf, fdata, fbytes, sdata,
472 					sbytes, flags)) {
473 					free(fdata);
474 					fdata = NULL;
475 				}
476 			}
477 		}
478 	}
479 	free(sdata);
480 	return (fdata);
481 }
482