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