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
63void
64initialize (void)
65{
66	openpgp_trust_init();
67}
68
69#else
70
71#include <openssl/err.h>
72
73/**
74 * @brief initialize OpenSSL
75 */
76void
77initialize(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 */
93char *
94get_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 */
108ssize_t
109decode_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 */
191static 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
204static const char *
205get_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
225static int
226verify_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;
251fail:
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 */
281int
282openpgp_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	}
385oops:
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 */
397static 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
420int
421openpgp_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 */
455unsigned char *
456verify_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