xref: /freebsd/lib/libsecureboot/openpgp/opgp_sig.c (revision e5ec655d6796974a79f51967b55de84b297994db)
15fff9558SSimon J. Gerraty /*-
25fff9558SSimon J. Gerraty  * Copyright (c) 2018, Juniper Networks, Inc.
35fff9558SSimon J. Gerraty  *
45fff9558SSimon J. Gerraty  * Redistribution and use in source and binary forms, with or without
55fff9558SSimon J. Gerraty  * modification, are permitted provided that the following conditions
65fff9558SSimon J. Gerraty  * are met:
75fff9558SSimon J. Gerraty  * 1. Redistributions of source code must retain the above copyright
85fff9558SSimon J. Gerraty  *    notice, this list of conditions and the following disclaimer.
95fff9558SSimon J. Gerraty  * 2. Redistributions in binary form must reproduce the above copyright
105fff9558SSimon J. Gerraty  *    notice, this list of conditions and the following disclaimer in the
115fff9558SSimon J. Gerraty  *    documentation and/or other materials provided with the distribution.
125fff9558SSimon J. Gerraty  *
135fff9558SSimon J. Gerraty  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
145fff9558SSimon J. Gerraty  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
155fff9558SSimon J. Gerraty  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
165fff9558SSimon J. Gerraty  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
175fff9558SSimon J. Gerraty  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
185fff9558SSimon J. Gerraty  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
195fff9558SSimon J. Gerraty  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
205fff9558SSimon J. Gerraty  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
215fff9558SSimon J. Gerraty  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225fff9558SSimon J. Gerraty  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235fff9558SSimon J. Gerraty  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245fff9558SSimon J. Gerraty  */
255fff9558SSimon J. Gerraty /*
265fff9558SSimon J. Gerraty  * RCSid:
275fff9558SSimon J. Gerraty  *	from: signer.c,v 1.10 2018/03/23 01:14:30 sjg
285fff9558SSimon J. Gerraty  *
295fff9558SSimon J. Gerraty  *	@(#) Copyright (c) 2012 Simon J. Gerraty
305fff9558SSimon J. Gerraty  *
315fff9558SSimon J. Gerraty  *	This file is provided in the hope that it will
325fff9558SSimon J. Gerraty  *	be of use.  There is absolutely NO WARRANTY.
335fff9558SSimon J. Gerraty  *	Permission to copy, redistribute or otherwise
345fff9558SSimon J. Gerraty  *	use this file is hereby granted provided that
355fff9558SSimon J. Gerraty  *	the above copyright notice and this notice are
365fff9558SSimon J. Gerraty  *	left intact.
375fff9558SSimon J. Gerraty  *
385fff9558SSimon J. Gerraty  *	Please send copies of changes and bug-fixes to:
395fff9558SSimon J. Gerraty  *	sjg@crufty.net
405fff9558SSimon J. Gerraty  */
415fff9558SSimon J. Gerraty 
425fff9558SSimon J. Gerraty #include <sys/cdefs.h>
435fff9558SSimon J. Gerraty __FBSDID("$FreeBSD$");
445fff9558SSimon J. Gerraty 
455fff9558SSimon J. Gerraty #include "../libsecureboot-priv.h"
465fff9558SSimon J. Gerraty #ifdef _STANDALONE
475fff9558SSimon J. Gerraty #define warnx printf
485fff9558SSimon J. Gerraty #else
495fff9558SSimon J. Gerraty 
505fff9558SSimon J. Gerraty #include <sys/param.h>
515fff9558SSimon J. Gerraty #include <sys/stat.h>
525fff9558SSimon J. Gerraty #include <unistd.h>
535fff9558SSimon J. Gerraty #include <stdio.h>
545fff9558SSimon J. Gerraty #include <fcntl.h>
555fff9558SSimon J. Gerraty #include <stdlib.h>
565fff9558SSimon J. Gerraty #include <string.h>
575fff9558SSimon J. Gerraty #include <err.h>
585fff9558SSimon J. Gerraty #endif
595fff9558SSimon J. Gerraty 
605fff9558SSimon J. Gerraty #include "decode.h"
615fff9558SSimon J. Gerraty #include "packet.h"
625fff9558SSimon J. Gerraty 
635fff9558SSimon J. Gerraty #ifdef USE_BEARSSL
645fff9558SSimon J. Gerraty 
655fff9558SSimon J. Gerraty #define get_error_string ve_error_get
665fff9558SSimon J. Gerraty 
675fff9558SSimon J. Gerraty void
685fff9558SSimon J. Gerraty initialize (void)
695fff9558SSimon J. Gerraty {
705fff9558SSimon J. Gerraty #ifdef _STANDALONE
715fff9558SSimon J. Gerraty     ve_trust_init();
725fff9558SSimon J. Gerraty #endif
735fff9558SSimon J. Gerraty }
745fff9558SSimon J. Gerraty 
755fff9558SSimon J. Gerraty #else
765fff9558SSimon J. Gerraty 
775fff9558SSimon J. Gerraty #include <openssl/err.h>
785fff9558SSimon J. Gerraty 
795fff9558SSimon J. Gerraty /**
805fff9558SSimon J. Gerraty  * @brief intialize OpenSSL
815fff9558SSimon J. Gerraty  */
825fff9558SSimon J. Gerraty void
835fff9558SSimon J. Gerraty initialize(void)
845fff9558SSimon J. Gerraty {
855fff9558SSimon J. Gerraty 	static int once;
865fff9558SSimon J. Gerraty 
875fff9558SSimon J. Gerraty 	if (once)
885fff9558SSimon J. Gerraty 		return);
895fff9558SSimon J. Gerraty 	once = 1;
905fff9558SSimon J. Gerraty 	//CRYPTO_malloc_init();
915fff9558SSimon J. Gerraty 	ERR_load_crypto_strings();
925fff9558SSimon J. Gerraty 	OpenSSL_add_all_algorithms();
935fff9558SSimon J. Gerraty }
945fff9558SSimon J. Gerraty 
955fff9558SSimon J. Gerraty /**
965fff9558SSimon J. Gerraty  * @brief
975fff9558SSimon J. Gerraty  * last error from OpenSSL as a string
985fff9558SSimon J. Gerraty  */
995fff9558SSimon J. Gerraty char *
1005fff9558SSimon J. Gerraty get_error_string(void)
1015fff9558SSimon J. Gerraty {
1025fff9558SSimon J. Gerraty 	initialize();
1035fff9558SSimon J. Gerraty 	return (ERR_error_string(ERR_get_error(), NULL));
1045fff9558SSimon J. Gerraty }
1055fff9558SSimon J. Gerraty #endif
1065fff9558SSimon J. Gerraty 
1075fff9558SSimon J. Gerraty /**
1085fff9558SSimon J. Gerraty  * @brief decode a signature packet
1095fff9558SSimon J. Gerraty  *
1105fff9558SSimon J. Gerraty  * We only support RSA
1115fff9558SSimon J. Gerraty  *
1125fff9558SSimon J. Gerraty  * @sa rfc4880:5.2
1135fff9558SSimon J. Gerraty  */
1145fff9558SSimon J. Gerraty ssize_t
1155fff9558SSimon J. Gerraty decode_sig(int tag, unsigned char **pptr, size_t len, OpenPGP_sig *sig)
1165fff9558SSimon J. Gerraty {
1175fff9558SSimon J. Gerraty 	unsigned char *ptr;
1185fff9558SSimon J. Gerraty 	unsigned char *pgpbytes;
1195fff9558SSimon J. Gerraty 	unsigned char *sp;
1205fff9558SSimon J. Gerraty 	int version;
1215fff9558SSimon J. Gerraty 	int hcount = 0;
1225fff9558SSimon J. Gerraty 	int ucount = 0;
1235fff9558SSimon J. Gerraty 	int stag = 0;
1245fff9558SSimon J. Gerraty 	int n;
1255fff9558SSimon J. Gerraty 
1265fff9558SSimon J. Gerraty 	n = tag;			/* avoid unused */
1275fff9558SSimon J. Gerraty 
1285fff9558SSimon J. Gerraty 	/*
1295fff9558SSimon J. Gerraty 	 * We need to keep a reference to the packet bytes
1305fff9558SSimon J. Gerraty 	 * as these form part of the signature data.
1315fff9558SSimon J. Gerraty 	 *
1325fff9558SSimon J. Gerraty 	 * @sa rfc4880:5.2.4
1335fff9558SSimon J. Gerraty 	 */
1345fff9558SSimon J. Gerraty 	pgpbytes = ptr = *pptr;
1355fff9558SSimon J. Gerraty 	version = *ptr++;
1365fff9558SSimon J. Gerraty 	if (version == 3) {
1375fff9558SSimon J. Gerraty 		ptr++;
1385fff9558SSimon J. Gerraty 		sig->pgpbytes = malloc(5);
1395fff9558SSimon J. Gerraty 		if (!sig->pgpbytes)
1405fff9558SSimon J. Gerraty 			return (-1);
1415fff9558SSimon J. Gerraty 		memcpy(sig->pgpbytes, ptr, 5);
1425fff9558SSimon J. Gerraty 		sig->pgpbytes_len = 5;
1435fff9558SSimon J. Gerraty 		sig->sig_type = *ptr++;
1445fff9558SSimon J. Gerraty 		ptr += 4;
1455fff9558SSimon J. Gerraty 		sig->key_id = octets2hex(ptr, 8);
1465fff9558SSimon J. Gerraty 		ptr += 8;
1475fff9558SSimon J. Gerraty 		sig->sig_alg = *ptr++;
1485fff9558SSimon J. Gerraty 		sig->hash_alg = *ptr++;
1495fff9558SSimon J. Gerraty 	} else if (version == 4) {
1505fff9558SSimon J. Gerraty 		sig->sig_type = *ptr++;
1515fff9558SSimon J. Gerraty 		sig->sig_alg = *ptr++;
1525fff9558SSimon J. Gerraty 		sig->hash_alg = *ptr++;
1535fff9558SSimon J. Gerraty 		hcount = octets2i(ptr, 2);
1545fff9558SSimon J. Gerraty 		ptr += 2;
1555fff9558SSimon J. Gerraty 		sig->pgpbytes_len = (size_t)hcount + 6;
1565fff9558SSimon J. Gerraty 		sig->pgpbytes = malloc(sig->pgpbytes_len + 6);
1575fff9558SSimon J. Gerraty 		if (!sig->pgpbytes)
1585fff9558SSimon J. Gerraty 			return (-1);
1595fff9558SSimon J. Gerraty 		memcpy(sig->pgpbytes, pgpbytes, sig->pgpbytes_len);
1605fff9558SSimon J. Gerraty 		sp = &sig->pgpbytes[sig->pgpbytes_len];
1615fff9558SSimon J. Gerraty 		*sp++ = 4;
1625fff9558SSimon J. Gerraty 		*sp++ = 255;
1635fff9558SSimon J. Gerraty 		memcpy(sp, i2octets(4, (int)sig->pgpbytes_len), 4);
1645fff9558SSimon J. Gerraty 		sig->pgpbytes_len += 6;
1655fff9558SSimon J. Gerraty 
1665fff9558SSimon J. Gerraty 		while (hcount > 0) {
1675fff9558SSimon J. Gerraty 			sp = decode_subpacket(&ptr, &stag, &n);
1685fff9558SSimon J. Gerraty 			hcount -= n;
1695fff9558SSimon J. Gerraty 			/* can check stag to see if we care */
1705fff9558SSimon J. Gerraty 		}
1715fff9558SSimon J. Gerraty 		ucount = octets2i(ptr, 2);
1725fff9558SSimon J. Gerraty 		ptr += 2;
1735fff9558SSimon J. Gerraty 		while (ucount > 0) {
1745fff9558SSimon J. Gerraty 			sp = decode_subpacket(&ptr, &stag, &n);
1755fff9558SSimon J. Gerraty 			ucount -= n;
1765fff9558SSimon J. Gerraty 			/* can check stag to see if we care */
1775fff9558SSimon J. Gerraty 			if (stag == 16) {
1785fff9558SSimon J. Gerraty 				free(sig->key_id);
1795fff9558SSimon J. Gerraty 				sig->key_id = octets2hex(sp, 8);
1805fff9558SSimon J. Gerraty 			}
1815fff9558SSimon J. Gerraty 		}
1825fff9558SSimon J. Gerraty 	} else
1835fff9558SSimon J. Gerraty 		return (-1);
1845fff9558SSimon J. Gerraty 	ptr += 2;			/* skip hash16 */
1855fff9558SSimon J. Gerraty 	if (sig->sig_alg == 1) {	/* RSA */
1865fff9558SSimon J. Gerraty 		sig->sig = decode_mpi(&ptr, &sig->sig_len);
1875fff9558SSimon J. Gerraty 	}
1885fff9558SSimon J. Gerraty 	/* we are done */
1895fff9558SSimon J. Gerraty 	return ((ssize_t)len);
1905fff9558SSimon J. Gerraty }
1915fff9558SSimon J. Gerraty 
1925fff9558SSimon J. Gerraty /**
1935fff9558SSimon J. Gerraty  * @brief map OpenPGP hash algorithm id's to name
1945fff9558SSimon J. Gerraty  *
1955fff9558SSimon J. Gerraty  * @sa rfc4880:9.4
1965fff9558SSimon J. Gerraty  */
1975fff9558SSimon J. Gerraty static struct hash_alg_map {
1985fff9558SSimon J. Gerraty 	int halg;
1995fff9558SSimon J. Gerraty 	const char *hname;
2005fff9558SSimon J. Gerraty } hash_algs[] = {
2015fff9558SSimon J. Gerraty 	{1, "md5"},
2025fff9558SSimon J. Gerraty 	{2, "sha1"},
2035fff9558SSimon J. Gerraty 	{8, "sha256"},
2045fff9558SSimon J. Gerraty 	{9, "sha384"},
2055fff9558SSimon J. Gerraty 	{10, "sha512"},
2065fff9558SSimon J. Gerraty 	{11, "sha224"},
2075fff9558SSimon J. Gerraty 	{0, NULL},
2085fff9558SSimon J. Gerraty };
2095fff9558SSimon J. Gerraty 
2105fff9558SSimon J. Gerraty static const char *
2115fff9558SSimon J. Gerraty get_hname(int hash_alg)
2125fff9558SSimon J. Gerraty {
2135fff9558SSimon J. Gerraty 	struct hash_alg_map *hmp;
2145fff9558SSimon J. Gerraty 
2155fff9558SSimon J. Gerraty 	for (hmp = hash_algs; hmp->halg > 0; hmp++) {
2165fff9558SSimon J. Gerraty 		if (hmp->halg == hash_alg)
2175fff9558SSimon J. Gerraty 			return (hmp->hname);
2185fff9558SSimon J. Gerraty 	}
2195fff9558SSimon J. Gerraty 	return (NULL);
2205fff9558SSimon J. Gerraty }
2215fff9558SSimon J. Gerraty 
2225fff9558SSimon J. Gerraty /* lifted from signer.c */
2235fff9558SSimon J. Gerraty /**
2245fff9558SSimon J. Gerraty  * @brief verify a digest
2255fff9558SSimon J. Gerraty  *
2265fff9558SSimon J. Gerraty  * The public key, digest name, file and signature data.
2275fff9558SSimon J. Gerraty  *
2285fff9558SSimon J. Gerraty  * @return 1 on success 0 on failure, -1 on error
2295fff9558SSimon J. Gerraty  */
2305fff9558SSimon J. Gerraty #ifndef USE_BEARSSL
2315fff9558SSimon J. Gerraty static int
2325fff9558SSimon J. Gerraty verify_digest (EVP_PKEY *pkey,
2335fff9558SSimon J. Gerraty     const char *digest,
2345fff9558SSimon J. Gerraty     unsigned char *mdata, size_t mlen,
2355fff9558SSimon J. Gerraty     unsigned char *sdata, size_t slen)
2365fff9558SSimon J. Gerraty {
2375fff9558SSimon J. Gerraty 	EVP_MD_CTX ctx;
2385fff9558SSimon J. Gerraty 	const EVP_MD *md = NULL;
2395fff9558SSimon J. Gerraty 	EVP_PKEY_CTX *pctx = NULL;
2405fff9558SSimon J. Gerraty 	int rc = 0;
2415fff9558SSimon J. Gerraty 	int i = -1;
2425fff9558SSimon J. Gerraty 
2435fff9558SSimon J. Gerraty 	initialize();
2445fff9558SSimon J. Gerraty 	md = EVP_get_digestbyname(digest);
2455fff9558SSimon J. Gerraty 	EVP_DigestInit(&ctx, md);
2465fff9558SSimon J. Gerraty 
2475fff9558SSimon J. Gerraty 	pctx = EVP_PKEY_CTX_new(pkey, NULL);
2485fff9558SSimon J. Gerraty 	if (!pctx)
2495fff9558SSimon J. Gerraty 		goto fail;
2505fff9558SSimon J. Gerraty 	if (EVP_PKEY_verify_init(pctx) <= 0)
2515fff9558SSimon J. Gerraty 		goto fail;
2525fff9558SSimon J. Gerraty 	if (EVP_PKEY_CTX_set_signature_md(pctx, ctx.digest) <= 0)
2535fff9558SSimon J. Gerraty 		goto fail;
2545fff9558SSimon J. Gerraty 	i = EVP_PKEY_verify(pctx, sdata, slen, mdata, mlen);
2555fff9558SSimon J. Gerraty 	if (i >= 0)
2565fff9558SSimon J. Gerraty 		rc = i;
2575fff9558SSimon J. Gerraty fail:
2585fff9558SSimon J. Gerraty 	EVP_PKEY_CTX_free(pctx);
2595fff9558SSimon J. Gerraty 	return (rc);
2605fff9558SSimon J. Gerraty }
2615fff9558SSimon J. Gerraty #endif
2625fff9558SSimon J. Gerraty 
2635fff9558SSimon J. Gerraty 
2645fff9558SSimon J. Gerraty /**
2655fff9558SSimon J. Gerraty  * @brief verify OpenPGP signed file
2665fff9558SSimon J. Gerraty  *
2675fff9558SSimon J. Gerraty  *
2685fff9558SSimon J. Gerraty  * @param[in] filename
2695fff9558SSimon J. Gerraty  *	used to determine the signature name
2705fff9558SSimon J. Gerraty  *
2715fff9558SSimon J. Gerraty  * @param[in] fdata
2725fff9558SSimon J. Gerraty  *	content of filename
2735fff9558SSimon J. Gerraty  *
2745fff9558SSimon J. Gerraty  * @param[in] fbytes
2755fff9558SSimon J. Gerraty  *	of fdata
2765fff9558SSimon J. Gerraty  *
2775fff9558SSimon J. Gerraty  * @param[in] sdata
2785fff9558SSimon J. Gerraty  *	content of signature
2795fff9558SSimon J. Gerraty  *
2805fff9558SSimon J. Gerraty  * @param[in] sbytes
2815fff9558SSimon J. Gerraty  *	of sdata
2825fff9558SSimon J. Gerraty  *
2835fff9558SSimon J. Gerraty  * @param[in] flags
2845fff9558SSimon J. Gerraty  *
2855fff9558SSimon J. Gerraty  * @return 0 on success
2865fff9558SSimon J. Gerraty  */
2875fff9558SSimon J. Gerraty int
2885fff9558SSimon J. Gerraty openpgp_verify(const char *filename,
2895fff9558SSimon J. Gerraty     unsigned char *fdata, size_t fbytes,
2905fff9558SSimon J. Gerraty     unsigned char *sdata, size_t sbytes,
2915fff9558SSimon J. Gerraty     int flags)
2925fff9558SSimon J. Gerraty {
2935fff9558SSimon J. Gerraty 	OpenPGP_key *key;
2945fff9558SSimon J. Gerraty 	OpenPGP_sig *sig;
2955fff9558SSimon J. Gerraty #ifdef USE_BEARSSL
2965fff9558SSimon J. Gerraty 	const br_hash_class *md;
2975fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
2985fff9558SSimon J. Gerraty 	const unsigned char *hash_oid;
2995fff9558SSimon J. Gerraty #else
3005fff9558SSimon J. Gerraty 	const EVP_MD *md = NULL;
3015fff9558SSimon J. Gerraty 	EVP_MD_CTX mctx;
3025fff9558SSimon J. Gerraty #endif
3035fff9558SSimon J. Gerraty 	unsigned char mdata[64];
3045fff9558SSimon J. Gerraty 	unsigned char *ptr;
3055fff9558SSimon J. Gerraty 	unsigned char *ddata = NULL;
3065fff9558SSimon J. Gerraty 	const char *hname;
3075fff9558SSimon J. Gerraty 	size_t mlen;
3085fff9558SSimon J. Gerraty 	int rc = -1;
3095fff9558SSimon J. Gerraty 
3105fff9558SSimon J. Gerraty 	initialize();
3115fff9558SSimon J. Gerraty 
3125fff9558SSimon J. Gerraty 	sig = NEW(OpenPGP_sig);
3135fff9558SSimon J. Gerraty 	if (!sdata || !sig) {
3145fff9558SSimon J. Gerraty 		warnx("cannot verify %s", filename);
3155fff9558SSimon J. Gerraty 		goto oops;
3165fff9558SSimon J. Gerraty 	}
3175fff9558SSimon J. Gerraty 	if (!(sdata[0] & OPENPGP_TAG_ISTAG))
3185fff9558SSimon J. Gerraty 		sdata = ddata = dearmor((char *)sdata, sbytes, &sbytes);
3195fff9558SSimon J. Gerraty 	ptr = sdata;
3205fff9558SSimon J. Gerraty 	rc = decode_packet(2, &ptr, sbytes, (decoder_t)decode_sig, sig);
321*e5ec655dSSimon J. Gerraty 	DEBUG_PRINTF(2, ("rc=%d keyID=%s\n", rc, sig->key_id ? sig->key_id : "?"));
3225fff9558SSimon J. Gerraty 	if (rc == 0 && sig->key_id) {
3235fff9558SSimon J. Gerraty 		key = load_key_id(sig->key_id);
3245fff9558SSimon J. Gerraty 		if (!key) {
3255fff9558SSimon J. Gerraty 			warnx("cannot find key-id: %s", sig->key_id);
3265fff9558SSimon J. Gerraty 			rc = -1;
3275fff9558SSimon J. Gerraty 		} else if (!(hname = get_hname(sig->hash_alg))) {
3285fff9558SSimon J. Gerraty 			warnx("unsupported hash algorithm: %d", sig->hash_alg);
3295fff9558SSimon J. Gerraty 			rc = -1;
3305fff9558SSimon J. Gerraty 		} else {
3315fff9558SSimon J. Gerraty 			/*
3325fff9558SSimon J. Gerraty 			 * Hash fdata according to the OpenPGP recipe
3335fff9558SSimon J. Gerraty 			 *
3345fff9558SSimon J. Gerraty 			 * @sa rfc4880:5.2.4
3355fff9558SSimon J. Gerraty 			 */
3365fff9558SSimon J. Gerraty #ifdef USE_BEARSSL
3375fff9558SSimon J. Gerraty 			switch (sig->hash_alg) { /* see hash_algs above */
3385fff9558SSimon J. Gerraty 			case 2:			 /* sha1 */
3395fff9558SSimon J. Gerraty 				md = &br_sha1_vtable;
3405fff9558SSimon J. Gerraty 				mlen = br_sha1_SIZE;
3415fff9558SSimon J. Gerraty 				hash_oid = BR_HASH_OID_SHA1;
3425fff9558SSimon J. Gerraty 				break;
3435fff9558SSimon J. Gerraty 			case 8:			/* sha256 */
3445fff9558SSimon J. Gerraty 				md = &br_sha256_vtable;
3455fff9558SSimon J. Gerraty 				mlen = br_sha256_SIZE;
3465fff9558SSimon J. Gerraty 				hash_oid = BR_HASH_OID_SHA256;
3475fff9558SSimon J. Gerraty 				break;
3485fff9558SSimon J. Gerraty 			default:
3495fff9558SSimon J. Gerraty 				warnx("unsupported hash algorithm: %s", hname);
3505fff9558SSimon J. Gerraty 				goto oops;
3515fff9558SSimon J. Gerraty 			}
3525fff9558SSimon J. Gerraty 			md->init(&mctx.vtable);
3535fff9558SSimon J. Gerraty 			md->update(&mctx.vtable, fdata, fbytes);
3545fff9558SSimon J. Gerraty 			md->update(&mctx.vtable, sig->pgpbytes,
3555fff9558SSimon J. Gerraty 			    sig->pgpbytes_len);
3565fff9558SSimon J. Gerraty 			md->out(&mctx.vtable, mdata);
3575fff9558SSimon J. Gerraty 
3585fff9558SSimon J. Gerraty 			rc = verify_rsa_digest(key->key, hash_oid,
3595fff9558SSimon J. Gerraty 			    mdata, mlen, sig->sig, sig->sig_len);
3605fff9558SSimon J. Gerraty #else
3615fff9558SSimon J. Gerraty 			md = EVP_get_digestbyname(hname);
3625fff9558SSimon J. Gerraty 			EVP_DigestInit(&mctx, md);
3635fff9558SSimon J. Gerraty 			EVP_DigestUpdate(&mctx, fdata, fbytes);
3645fff9558SSimon J. Gerraty 			EVP_DigestUpdate(&mctx, sig->pgpbytes,
3655fff9558SSimon J. Gerraty 			    sig->pgpbytes_len);
3665fff9558SSimon J. Gerraty 			mlen = sizeof(mdata);
3675fff9558SSimon J. Gerraty 			EVP_DigestFinal(&mctx,mdata,(unsigned int *)&mlen);
3685fff9558SSimon J. Gerraty 
3695fff9558SSimon J. Gerraty 			rc = verify_digest(key->key, hname, mdata, mlen,
3705fff9558SSimon J. Gerraty 			    sig->sig, sig->sig_len);
3715fff9558SSimon J. Gerraty #endif
3725fff9558SSimon J. Gerraty 
3735fff9558SSimon J. Gerraty 			if (rc > 0) {
3745fff9558SSimon J. Gerraty 				if ((flags & 1))
3755fff9558SSimon J. Gerraty 					printf("Verified %s signed by %s\n",
3765fff9558SSimon J. Gerraty 					    filename,
3775fff9558SSimon J. Gerraty 					    key->user ? key->user->name : "someone");
3785fff9558SSimon J. Gerraty 				rc = 0;	/* success */
3795fff9558SSimon J. Gerraty 			} else if (rc == 0) {
3805fff9558SSimon J. Gerraty 				printf("Unverified %s: %s\n",
3815fff9558SSimon J. Gerraty 				    filename, get_error_string());
3825fff9558SSimon J. Gerraty 				rc = 1;
3835fff9558SSimon J. Gerraty 			} else {
3845fff9558SSimon J. Gerraty 				printf("Unverified %s\n", filename);
3855fff9558SSimon J. Gerraty 			}
3865fff9558SSimon J. Gerraty 		}
3875fff9558SSimon J. Gerraty 	} else {
3885fff9558SSimon J. Gerraty 		warnx("cannot decode signature for %s", filename);
3895fff9558SSimon J. Gerraty 		rc = -1;
3905fff9558SSimon J. Gerraty 	}
3915fff9558SSimon J. Gerraty oops:
3925fff9558SSimon J. Gerraty 	free(ddata);
3935fff9558SSimon J. Gerraty 	free(sig);
3945fff9558SSimon J. Gerraty 	return (rc);
3955fff9558SSimon J. Gerraty }
3965fff9558SSimon J. Gerraty 
3975fff9558SSimon J. Gerraty #ifndef _STANDALONE
3985fff9558SSimon J. Gerraty /**
3995fff9558SSimon J. Gerraty  * @brief list of extensions we handle
4005fff9558SSimon J. Gerraty  *
4015fff9558SSimon J. Gerraty  * ".asc" is preferred as it works seamlessly with openpgp
4025fff9558SSimon J. Gerraty  */
4035fff9558SSimon J. Gerraty static const char *sig_exts[] = {
4045fff9558SSimon J. Gerraty 	".asc",
4055fff9558SSimon J. Gerraty 	".pgp",
4065fff9558SSimon J. Gerraty 	".psig",
4075fff9558SSimon J. Gerraty 	NULL,
4085fff9558SSimon J. Gerraty };
4095fff9558SSimon J. Gerraty 
4105fff9558SSimon J. Gerraty /**
4115fff9558SSimon J. Gerraty  * @brief verify OpenPGP signed file
4125fff9558SSimon J. Gerraty  *
4135fff9558SSimon J. Gerraty  *
4145fff9558SSimon J. Gerraty  * @param[in] filename
4155fff9558SSimon J. Gerraty  *	used to determine the signature name
4165fff9558SSimon J. Gerraty  *
4175fff9558SSimon J. Gerraty  * @param[in] fdata
4185fff9558SSimon J. Gerraty  *	content of filename
4195fff9558SSimon J. Gerraty  *
4205fff9558SSimon J. Gerraty  * @param[in] nbytes
4215fff9558SSimon J. Gerraty  *	of fdata
4225fff9558SSimon J. Gerraty  *
4235fff9558SSimon J. Gerraty  * @return
4245fff9558SSimon J. Gerraty  */
4255fff9558SSimon J. Gerraty 
4265fff9558SSimon J. Gerraty int
4275fff9558SSimon J. Gerraty openpgp_verify_file(const char *filename, unsigned char *fdata, size_t nbytes)
4285fff9558SSimon J. Gerraty {
4295fff9558SSimon J. Gerraty 	char pbuf[MAXPATHLEN];
4305fff9558SSimon J. Gerraty 	unsigned char *sdata;
4315fff9558SSimon J. Gerraty 	const char *sname = NULL;
4325fff9558SSimon J. Gerraty 	const char **ep;
4335fff9558SSimon J. Gerraty 	size_t sz;
4345fff9558SSimon J. Gerraty 	int n;
4355fff9558SSimon J. Gerraty 
4365fff9558SSimon J. Gerraty 	for (ep = sig_exts; *ep; ep++) {
4375fff9558SSimon J. Gerraty 		n = snprintf(pbuf, sizeof(pbuf), "%s%s", filename, *ep);
4385fff9558SSimon J. Gerraty 		if (n >= (int)sizeof(pbuf)) {
4395fff9558SSimon J. Gerraty 			warnx("cannot form signature name for %s", filename);
4405fff9558SSimon J. Gerraty 			return (-1);
4415fff9558SSimon J. Gerraty 		}
4425fff9558SSimon J. Gerraty 		if (access(pbuf, R_OK) == 0) {
4435fff9558SSimon J. Gerraty 			sname = pbuf;
4445fff9558SSimon J. Gerraty 			break;
4455fff9558SSimon J. Gerraty 		}
4465fff9558SSimon J. Gerraty 	}
4475fff9558SSimon J. Gerraty 	if (!sname) {
4485fff9558SSimon J. Gerraty 		warnx("cannot find signature for %s", filename);
4495fff9558SSimon J. Gerraty 		return (-1);
4505fff9558SSimon J. Gerraty 	}
4515fff9558SSimon J. Gerraty 	sdata = read_file(sname, &sz);
4525fff9558SSimon J. Gerraty 	return (openpgp_verify(filename, fdata, nbytes, sdata, sz, 1));
4535fff9558SSimon J. Gerraty }
4545fff9558SSimon J. Gerraty #endif
4555fff9558SSimon J. Gerraty 
4565fff9558SSimon J. Gerraty /**
4575fff9558SSimon J. Gerraty  * @brief verify OpenPGP signature
4585fff9558SSimon J. Gerraty  *
4595fff9558SSimon J. Gerraty  * @return content of signed file
4605fff9558SSimon J. Gerraty  */
4615fff9558SSimon J. Gerraty unsigned char *
4625fff9558SSimon J. Gerraty verify_asc(const char *sigfile, int flags)
4635fff9558SSimon J. Gerraty {
4645fff9558SSimon J. Gerraty 	char pbuf[MAXPATHLEN];
4655fff9558SSimon J. Gerraty 	char *cp;
4665fff9558SSimon J. Gerraty 	size_t n;
4675fff9558SSimon J. Gerraty 	unsigned char *fdata, *sdata;
4685fff9558SSimon J. Gerraty 	size_t fbytes, sbytes;
4695fff9558SSimon J. Gerraty 
4705fff9558SSimon J. Gerraty 	if ((sdata = read_file(sigfile, &sbytes))) {
4715fff9558SSimon J. Gerraty 		n = strlcpy(pbuf, sigfile, sizeof(pbuf));
4725fff9558SSimon J. Gerraty 		if ((cp = strrchr(pbuf, '.')))
4735fff9558SSimon J. Gerraty 			*cp = '\0';
4745fff9558SSimon J. Gerraty 		if ((fdata = read_file(pbuf, &fbytes))) {
4755fff9558SSimon J. Gerraty 			if (openpgp_verify(pbuf, fdata, fbytes, sdata,
4765fff9558SSimon J. Gerraty 				sbytes, flags)) {
4775fff9558SSimon J. Gerraty 				free(fdata);
4785fff9558SSimon J. Gerraty 				fdata = NULL;
4795fff9558SSimon J. Gerraty 			}
4805fff9558SSimon J. Gerraty 		}
4815fff9558SSimon J. Gerraty 	} else
4825fff9558SSimon J. Gerraty 		fdata = NULL;
4835fff9558SSimon J. Gerraty 	free(sdata);
4845fff9558SSimon J. Gerraty 	return (fdata);
4855fff9558SSimon J. Gerraty }
486