xref: /freebsd/lib/libsecureboot/openpgp/opgp_sig.c (revision dae4eb623e862789533dca8b644ea531502a088f)
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  *	This file is provided in the hope that it will
305fff9558SSimon J. Gerraty  *	be of use.  There is absolutely NO WARRANTY.
315fff9558SSimon J. Gerraty  *	Permission to copy, redistribute or otherwise
325fff9558SSimon J. Gerraty  *	use this file is hereby granted provided that
335fff9558SSimon J. Gerraty  *	the above copyright notice and this notice are
345fff9558SSimon J. Gerraty  *	left intact.
355fff9558SSimon J. Gerraty  *
365fff9558SSimon J. Gerraty  *	Please send copies of changes and bug-fixes to:
375fff9558SSimon J. Gerraty  *	sjg@crufty.net
385fff9558SSimon J. Gerraty  */
395fff9558SSimon J. Gerraty 
405fff9558SSimon J. Gerraty #include <sys/cdefs.h>
415fff9558SSimon J. Gerraty #include "../libsecureboot-priv.h"
425fff9558SSimon J. Gerraty #ifdef _STANDALONE
435fff9558SSimon J. Gerraty #define warnx printf
445fff9558SSimon J. Gerraty #else
455fff9558SSimon J. Gerraty 
465fff9558SSimon J. Gerraty #include <sys/param.h>
475fff9558SSimon J. Gerraty #include <sys/stat.h>
485fff9558SSimon J. Gerraty #include <unistd.h>
495fff9558SSimon J. Gerraty #include <stdio.h>
505fff9558SSimon J. Gerraty #include <fcntl.h>
515fff9558SSimon J. Gerraty #include <stdlib.h>
525fff9558SSimon J. Gerraty #include <string.h>
535fff9558SSimon J. Gerraty #include <err.h>
545fff9558SSimon J. Gerraty #endif
555fff9558SSimon J. Gerraty 
565fff9558SSimon J. Gerraty #include "decode.h"
575fff9558SSimon J. Gerraty #include "packet.h"
585fff9558SSimon J. Gerraty 
595fff9558SSimon J. Gerraty #ifdef USE_BEARSSL
605fff9558SSimon J. Gerraty 
615fff9558SSimon J. Gerraty #define get_error_string ve_error_get
625fff9558SSimon J. Gerraty 
635fff9558SSimon J. Gerraty void
initialize(void)645fff9558SSimon J. Gerraty initialize (void)
655fff9558SSimon J. Gerraty {
663ae2a848SSimon J. Gerraty 	openpgp_trust_init();
675fff9558SSimon J. Gerraty }
685fff9558SSimon J. Gerraty 
695fff9558SSimon J. Gerraty #else
705fff9558SSimon J. Gerraty 
715fff9558SSimon J. Gerraty #include <openssl/err.h>
725fff9558SSimon J. Gerraty 
735fff9558SSimon J. Gerraty /**
74cb25444cSElyes HAOUAS  * @brief initialize OpenSSL
755fff9558SSimon J. Gerraty  */
765fff9558SSimon J. Gerraty void
initialize(void)775fff9558SSimon J. Gerraty initialize(void)
785fff9558SSimon J. Gerraty {
795fff9558SSimon J. Gerraty 	static int once;
805fff9558SSimon J. Gerraty 
815fff9558SSimon J. Gerraty 	if (once)
825fff9558SSimon J. Gerraty 		return);
835fff9558SSimon J. Gerraty 	once = 1;
845fff9558SSimon J. Gerraty 	//CRYPTO_malloc_init();
855fff9558SSimon J. Gerraty 	ERR_load_crypto_strings();
865fff9558SSimon J. Gerraty 	OpenSSL_add_all_algorithms();
875fff9558SSimon J. Gerraty }
885fff9558SSimon J. Gerraty 
895fff9558SSimon J. Gerraty /**
905fff9558SSimon J. Gerraty  * @brief
915fff9558SSimon J. Gerraty  * last error from OpenSSL as a string
925fff9558SSimon J. Gerraty  */
935fff9558SSimon J. Gerraty char *
945fff9558SSimon J. Gerraty get_error_string(void)
955fff9558SSimon J. Gerraty {
965fff9558SSimon J. Gerraty 	initialize();
975fff9558SSimon J. Gerraty 	return (ERR_error_string(ERR_get_error(), NULL));
985fff9558SSimon J. Gerraty }
995fff9558SSimon J. Gerraty #endif
1005fff9558SSimon J. Gerraty 
1015fff9558SSimon J. Gerraty /**
1025fff9558SSimon J. Gerraty  * @brief decode a signature packet
1035fff9558SSimon J. Gerraty  *
1045fff9558SSimon J. Gerraty  * We only support RSA
1055fff9558SSimon J. Gerraty  *
1065fff9558SSimon J. Gerraty  * @sa rfc4880:5.2
1075fff9558SSimon J. Gerraty  */
1085fff9558SSimon J. Gerraty ssize_t
1095fff9558SSimon J. Gerraty decode_sig(int tag, unsigned char **pptr, size_t len, OpenPGP_sig *sig)
1105fff9558SSimon J. Gerraty {
1115fff9558SSimon J. Gerraty 	unsigned char *ptr;
1125fff9558SSimon J. Gerraty 	unsigned char *pgpbytes;
1135fff9558SSimon J. Gerraty 	unsigned char *sp;
1145fff9558SSimon J. Gerraty 	int version;
1155fff9558SSimon J. Gerraty 	int hcount = 0;
1165fff9558SSimon J. Gerraty 	int ucount = 0;
1175fff9558SSimon J. Gerraty 	int stag = 0;
1185fff9558SSimon J. Gerraty 	int n;
1195fff9558SSimon J. Gerraty 
1205fff9558SSimon J. Gerraty 	n = tag;			/* avoid unused */
1215fff9558SSimon J. Gerraty 
1225fff9558SSimon J. Gerraty 	/*
1235fff9558SSimon J. Gerraty 	 * We need to keep a reference to the packet bytes
1245fff9558SSimon J. Gerraty 	 * as these form part of the signature data.
1255fff9558SSimon J. Gerraty 	 *
1265fff9558SSimon J. Gerraty 	 * @sa rfc4880:5.2.4
1275fff9558SSimon J. Gerraty 	 */
1285fff9558SSimon J. Gerraty 	pgpbytes = ptr = *pptr;
1295fff9558SSimon J. Gerraty 	version = *ptr++;
1305fff9558SSimon J. Gerraty 	if (version == 3) {
1315fff9558SSimon J. Gerraty 		ptr++;
1325fff9558SSimon J. Gerraty 		sig->pgpbytes = malloc(5);
1335fff9558SSimon J. Gerraty 		if (!sig->pgpbytes)
1345fff9558SSimon J. Gerraty 			return (-1);
1355fff9558SSimon J. Gerraty 		memcpy(sig->pgpbytes, ptr, 5);
1365fff9558SSimon J. Gerraty 		sig->pgpbytes_len = 5;
1375fff9558SSimon J. Gerraty 		sig->sig_type = *ptr++;
1385fff9558SSimon J. Gerraty 		ptr += 4;
1395fff9558SSimon J. Gerraty 		sig->key_id = octets2hex(ptr, 8);
1405fff9558SSimon J. Gerraty 		ptr += 8;
1415fff9558SSimon J. Gerraty 		sig->sig_alg = *ptr++;
1425fff9558SSimon J. Gerraty 		sig->hash_alg = *ptr++;
1435fff9558SSimon J. Gerraty 	} else if (version == 4) {
1445fff9558SSimon J. Gerraty 		sig->sig_type = *ptr++;
1455fff9558SSimon J. Gerraty 		sig->sig_alg = *ptr++;
1465fff9558SSimon J. Gerraty 		sig->hash_alg = *ptr++;
1475fff9558SSimon J. Gerraty 		hcount = octets2i(ptr, 2);
1485fff9558SSimon J. Gerraty 		ptr += 2;
1495fff9558SSimon J. Gerraty 		sig->pgpbytes_len = (size_t)hcount + 6;
1505fff9558SSimon J. Gerraty 		sig->pgpbytes = malloc(sig->pgpbytes_len + 6);
1515fff9558SSimon J. Gerraty 		if (!sig->pgpbytes)
1525fff9558SSimon J. Gerraty 			return (-1);
1535fff9558SSimon J. Gerraty 		memcpy(sig->pgpbytes, pgpbytes, sig->pgpbytes_len);
1545fff9558SSimon J. Gerraty 		sp = &sig->pgpbytes[sig->pgpbytes_len];
1555fff9558SSimon J. Gerraty 		*sp++ = 4;
1565fff9558SSimon J. Gerraty 		*sp++ = 255;
1575fff9558SSimon J. Gerraty 		memcpy(sp, i2octets(4, (int)sig->pgpbytes_len), 4);
1585fff9558SSimon J. Gerraty 		sig->pgpbytes_len += 6;
1595fff9558SSimon J. Gerraty 
1605fff9558SSimon J. Gerraty 		while (hcount > 0) {
1615fff9558SSimon J. Gerraty 			sp = decode_subpacket(&ptr, &stag, &n);
1625fff9558SSimon J. Gerraty 			hcount -= n;
1635fff9558SSimon J. Gerraty 			/* can check stag to see if we care */
1645fff9558SSimon J. Gerraty 		}
1655fff9558SSimon J. Gerraty 		ucount = octets2i(ptr, 2);
1665fff9558SSimon J. Gerraty 		ptr += 2;
1675fff9558SSimon J. Gerraty 		while (ucount > 0) {
1685fff9558SSimon J. Gerraty 			sp = decode_subpacket(&ptr, &stag, &n);
1695fff9558SSimon J. Gerraty 			ucount -= n;
1705fff9558SSimon J. Gerraty 			/* can check stag to see if we care */
1715fff9558SSimon J. Gerraty 			if (stag == 16) {
1725fff9558SSimon J. Gerraty 				free(sig->key_id);
1735fff9558SSimon J. Gerraty 				sig->key_id = octets2hex(sp, 8);
1745fff9558SSimon J. Gerraty 			}
1755fff9558SSimon J. Gerraty 		}
1765fff9558SSimon J. Gerraty 	} else
1775fff9558SSimon J. Gerraty 		return (-1);
1785fff9558SSimon J. Gerraty 	ptr += 2;			/* skip hash16 */
1795fff9558SSimon J. Gerraty 	if (sig->sig_alg == 1) {	/* RSA */
1805fff9558SSimon J. Gerraty 		sig->sig = decode_mpi(&ptr, &sig->sig_len);
1815fff9558SSimon J. Gerraty 	}
1825fff9558SSimon J. Gerraty 	/* we are done */
1835fff9558SSimon J. Gerraty 	return ((ssize_t)len);
1845fff9558SSimon J. Gerraty }
1855fff9558SSimon J. Gerraty 
1865fff9558SSimon J. Gerraty /**
1875fff9558SSimon J. Gerraty  * @brief map OpenPGP hash algorithm id's to name
1885fff9558SSimon J. Gerraty  *
1895fff9558SSimon J. Gerraty  * @sa rfc4880:9.4
1905fff9558SSimon J. Gerraty  */
1915fff9558SSimon J. Gerraty static struct hash_alg_map {
1925fff9558SSimon J. Gerraty 	int halg;
1935fff9558SSimon J. Gerraty 	const char *hname;
1945fff9558SSimon J. Gerraty } hash_algs[] = {
1955fff9558SSimon J. Gerraty 	{1, "md5"},
1965fff9558SSimon J. Gerraty 	{2, "sha1"},
1975fff9558SSimon J. Gerraty 	{8, "sha256"},
1985fff9558SSimon J. Gerraty 	{9, "sha384"},
1995fff9558SSimon J. Gerraty 	{10, "sha512"},
2005fff9558SSimon J. Gerraty 	{11, "sha224"},
2015fff9558SSimon J. Gerraty 	{0, NULL},
2025fff9558SSimon J. Gerraty };
2035fff9558SSimon J. Gerraty 
2045fff9558SSimon J. Gerraty static const char *
2055fff9558SSimon J. Gerraty get_hname(int hash_alg)
2065fff9558SSimon J. Gerraty {
2075fff9558SSimon J. Gerraty 	struct hash_alg_map *hmp;
2085fff9558SSimon J. Gerraty 
2095fff9558SSimon J. Gerraty 	for (hmp = hash_algs; hmp->halg > 0; hmp++) {
2105fff9558SSimon J. Gerraty 		if (hmp->halg == hash_alg)
2115fff9558SSimon J. Gerraty 			return (hmp->hname);
2125fff9558SSimon J. Gerraty 	}
2135fff9558SSimon J. Gerraty 	return (NULL);
2145fff9558SSimon J. Gerraty }
2155fff9558SSimon J. Gerraty 
2165fff9558SSimon J. Gerraty /* lifted from signer.c */
2175fff9558SSimon J. Gerraty /**
2185fff9558SSimon J. Gerraty  * @brief verify a digest
2195fff9558SSimon J. Gerraty  *
2205fff9558SSimon J. Gerraty  * The public key, digest name, file and signature data.
2215fff9558SSimon J. Gerraty  *
2225fff9558SSimon J. Gerraty  * @return 1 on success 0 on failure, -1 on error
2235fff9558SSimon J. Gerraty  */
2245fff9558SSimon J. Gerraty #ifndef USE_BEARSSL
2255fff9558SSimon J. Gerraty static int
2265fff9558SSimon J. Gerraty verify_digest (EVP_PKEY *pkey,
2275fff9558SSimon J. Gerraty     const char *digest,
2285fff9558SSimon J. Gerraty     unsigned char *mdata, size_t mlen,
2295fff9558SSimon J. Gerraty     unsigned char *sdata, size_t slen)
2305fff9558SSimon J. Gerraty {
2315fff9558SSimon J. Gerraty 	EVP_MD_CTX ctx;
2325fff9558SSimon J. Gerraty 	const EVP_MD *md = NULL;
2335fff9558SSimon J. Gerraty 	EVP_PKEY_CTX *pctx = NULL;
2345fff9558SSimon J. Gerraty 	int rc = 0;
2355fff9558SSimon J. Gerraty 	int i = -1;
2365fff9558SSimon J. Gerraty 
2375fff9558SSimon J. Gerraty 	initialize();
2385fff9558SSimon J. Gerraty 	md = EVP_get_digestbyname(digest);
2395fff9558SSimon J. Gerraty 	EVP_DigestInit(&ctx, md);
2405fff9558SSimon J. Gerraty 
2415fff9558SSimon J. Gerraty 	pctx = EVP_PKEY_CTX_new(pkey, NULL);
2425fff9558SSimon J. Gerraty 	if (!pctx)
2435fff9558SSimon J. Gerraty 		goto fail;
2445fff9558SSimon J. Gerraty 	if (EVP_PKEY_verify_init(pctx) <= 0)
2455fff9558SSimon J. Gerraty 		goto fail;
2465fff9558SSimon J. Gerraty 	if (EVP_PKEY_CTX_set_signature_md(pctx, ctx.digest) <= 0)
2475fff9558SSimon J. Gerraty 		goto fail;
2485fff9558SSimon J. Gerraty 	i = EVP_PKEY_verify(pctx, sdata, slen, mdata, mlen);
2495fff9558SSimon J. Gerraty 	if (i >= 0)
2505fff9558SSimon J. Gerraty 		rc = i;
2515fff9558SSimon J. Gerraty fail:
2525fff9558SSimon J. Gerraty 	EVP_PKEY_CTX_free(pctx);
2535fff9558SSimon J. Gerraty 	return (rc);
2545fff9558SSimon J. Gerraty }
2555fff9558SSimon J. Gerraty #endif
2565fff9558SSimon J. Gerraty 
2575fff9558SSimon J. Gerraty 
2585fff9558SSimon J. Gerraty /**
2595fff9558SSimon J. Gerraty  * @brief verify OpenPGP signed file
2605fff9558SSimon J. Gerraty  *
2615fff9558SSimon J. Gerraty  *
2625fff9558SSimon J. Gerraty  * @param[in] filename
2635fff9558SSimon J. Gerraty  *	used to determine the signature name
2645fff9558SSimon J. Gerraty  *
2655fff9558SSimon J. Gerraty  * @param[in] fdata
2665fff9558SSimon J. Gerraty  *	content of filename
2675fff9558SSimon J. Gerraty  *
2685fff9558SSimon J. Gerraty  * @param[in] fbytes
2695fff9558SSimon J. Gerraty  *	of fdata
2705fff9558SSimon J. Gerraty  *
2715fff9558SSimon J. Gerraty  * @param[in] sdata
2725fff9558SSimon J. Gerraty  *	content of signature
2735fff9558SSimon J. Gerraty  *
2745fff9558SSimon J. Gerraty  * @param[in] sbytes
2755fff9558SSimon J. Gerraty  *	of sdata
2765fff9558SSimon J. Gerraty  *
2775fff9558SSimon J. Gerraty  * @param[in] flags
2785fff9558SSimon J. Gerraty  *
2795fff9558SSimon J. Gerraty  * @return 0 on success
2805fff9558SSimon J. Gerraty  */
2815fff9558SSimon J. Gerraty int
2825fff9558SSimon J. Gerraty openpgp_verify(const char *filename,
2835fff9558SSimon J. Gerraty     unsigned char *fdata, size_t fbytes,
2845fff9558SSimon J. Gerraty     unsigned char *sdata, size_t sbytes,
2855fff9558SSimon J. Gerraty     int flags)
2865fff9558SSimon J. Gerraty {
2875fff9558SSimon J. Gerraty 	OpenPGP_key *key;
2885fff9558SSimon J. Gerraty 	OpenPGP_sig *sig;
2895fff9558SSimon J. Gerraty #ifdef USE_BEARSSL
2905fff9558SSimon J. Gerraty 	const br_hash_class *md;
2915fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
2925fff9558SSimon J. Gerraty 	const unsigned char *hash_oid;
2935fff9558SSimon J. Gerraty #else
2945fff9558SSimon J. Gerraty 	const EVP_MD *md = NULL;
2955fff9558SSimon J. Gerraty 	EVP_MD_CTX mctx;
2965fff9558SSimon J. Gerraty #endif
2975fff9558SSimon J. Gerraty 	unsigned char mdata[64];
2985fff9558SSimon J. Gerraty 	unsigned char *ptr;
2995fff9558SSimon J. Gerraty 	unsigned char *ddata = NULL;
3005fff9558SSimon J. Gerraty 	const char *hname;
3015fff9558SSimon J. Gerraty 	size_t mlen;
3025fff9558SSimon J. Gerraty 	int rc = -1;
3035fff9558SSimon J. Gerraty 
3045fff9558SSimon J. Gerraty 	initialize();
3055fff9558SSimon J. Gerraty 
3065fff9558SSimon J. Gerraty 	sig = NEW(OpenPGP_sig);
3075fff9558SSimon J. Gerraty 	if (!sdata || !sig) {
3085fff9558SSimon J. Gerraty 		warnx("cannot verify %s", filename);
3095fff9558SSimon J. Gerraty 		goto oops;
3105fff9558SSimon J. Gerraty 	}
3115fff9558SSimon J. Gerraty 	if (!(sdata[0] & OPENPGP_TAG_ISTAG))
3125fff9558SSimon J. Gerraty 		sdata = ddata = dearmor((char *)sdata, sbytes, &sbytes);
3135fff9558SSimon J. Gerraty 	ptr = sdata;
3145fff9558SSimon J. Gerraty 	rc = decode_packet(2, &ptr, sbytes, (decoder_t)decode_sig, sig);
315e5ec655dSSimon J. Gerraty 	DEBUG_PRINTF(2, ("rc=%d keyID=%s\n", rc, sig->key_id ? sig->key_id : "?"));
3165fff9558SSimon J. Gerraty 	if (rc == 0 && sig->key_id) {
3175fff9558SSimon J. Gerraty 		key = load_key_id(sig->key_id);
3185fff9558SSimon J. Gerraty 		if (!key) {
3195fff9558SSimon J. Gerraty 			warnx("cannot find key-id: %s", sig->key_id);
3205fff9558SSimon J. Gerraty 			rc = -1;
3215fff9558SSimon J. Gerraty 		} else if (!(hname = get_hname(sig->hash_alg))) {
3225fff9558SSimon J. Gerraty 			warnx("unsupported hash algorithm: %d", sig->hash_alg);
3235fff9558SSimon J. Gerraty 			rc = -1;
3245fff9558SSimon J. Gerraty 		} else {
3255fff9558SSimon J. Gerraty 			/*
3265fff9558SSimon J. Gerraty 			 * Hash fdata according to the OpenPGP recipe
3275fff9558SSimon J. Gerraty 			 *
3285fff9558SSimon J. Gerraty 			 * @sa rfc4880:5.2.4
3295fff9558SSimon J. Gerraty 			 */
3305fff9558SSimon J. Gerraty #ifdef USE_BEARSSL
3315fff9558SSimon J. Gerraty 			switch (sig->hash_alg) { /* see hash_algs above */
3325fff9558SSimon J. Gerraty 			case 2:			 /* sha1 */
3335fff9558SSimon J. Gerraty 				md = &br_sha1_vtable;
3345fff9558SSimon J. Gerraty 				mlen = br_sha1_SIZE;
3355fff9558SSimon J. Gerraty 				hash_oid = BR_HASH_OID_SHA1;
3365fff9558SSimon J. Gerraty 				break;
3375fff9558SSimon J. Gerraty 			case 8:			/* sha256 */
3385fff9558SSimon J. Gerraty 				md = &br_sha256_vtable;
3395fff9558SSimon J. Gerraty 				mlen = br_sha256_SIZE;
3405fff9558SSimon J. Gerraty 				hash_oid = BR_HASH_OID_SHA256;
3415fff9558SSimon J. Gerraty 				break;
342*dae4eb62SSimon J. Gerraty 			case 9:			/* sha384 */
343*dae4eb62SSimon J. Gerraty 				md = &br_sha384_vtable;
344*dae4eb62SSimon J. Gerraty 				mlen = br_sha384_SIZE;
345*dae4eb62SSimon J. Gerraty 				hash_oid = BR_HASH_OID_SHA384;
346*dae4eb62SSimon J. Gerraty 				break;
347*dae4eb62SSimon J. Gerraty 			case 10:		/* sha512 */
348*dae4eb62SSimon J. Gerraty 				md = &br_sha512_vtable;
349*dae4eb62SSimon J. Gerraty 				mlen = br_sha512_SIZE;
350*dae4eb62SSimon J. Gerraty 				hash_oid = BR_HASH_OID_SHA512;
351*dae4eb62SSimon J. Gerraty 				break;
3525fff9558SSimon J. Gerraty 			default:
3535fff9558SSimon J. Gerraty 				warnx("unsupported hash algorithm: %s", hname);
354caaeab69SHuwyler 				rc = -1;
3555fff9558SSimon J. Gerraty 				goto oops;
3565fff9558SSimon J. Gerraty 			}
3575fff9558SSimon J. Gerraty 			md->init(&mctx.vtable);
3585fff9558SSimon J. Gerraty 			md->update(&mctx.vtable, fdata, fbytes);
3595fff9558SSimon J. Gerraty 			md->update(&mctx.vtable, sig->pgpbytes,
3605fff9558SSimon J. Gerraty 			    sig->pgpbytes_len);
3615fff9558SSimon J. Gerraty 			md->out(&mctx.vtable, mdata);
3625fff9558SSimon J. Gerraty 
3635fff9558SSimon J. Gerraty 			rc = verify_rsa_digest(key->key, hash_oid,
3645fff9558SSimon J. Gerraty 			    mdata, mlen, sig->sig, sig->sig_len);
3655fff9558SSimon J. Gerraty #else
3665fff9558SSimon J. Gerraty 			md = EVP_get_digestbyname(hname);
3675fff9558SSimon J. Gerraty 			EVP_DigestInit(&mctx, md);
3685fff9558SSimon J. Gerraty 			EVP_DigestUpdate(&mctx, fdata, fbytes);
3695fff9558SSimon J. Gerraty 			EVP_DigestUpdate(&mctx, sig->pgpbytes,
3705fff9558SSimon J. Gerraty 			    sig->pgpbytes_len);
3715fff9558SSimon J. Gerraty 			mlen = sizeof(mdata);
3725fff9558SSimon J. Gerraty 			EVP_DigestFinal(&mctx,mdata,(unsigned int *)&mlen);
3735fff9558SSimon J. Gerraty 
3745fff9558SSimon J. Gerraty 			rc = verify_digest(key->key, hname, mdata, mlen,
3755fff9558SSimon J. Gerraty 			    sig->sig, sig->sig_len);
3765fff9558SSimon J. Gerraty #endif
3775fff9558SSimon J. Gerraty 
3785fff9558SSimon J. Gerraty 			if (rc > 0) {
37966655411SSimon J. Gerraty 				if ((flags & VEF_VERBOSE))
3805fff9558SSimon J. Gerraty 					printf("Verified %s signed by %s\n",
3815fff9558SSimon J. Gerraty 					    filename,
3825fff9558SSimon J. Gerraty 					    key->user ? key->user->name : "someone");
3835fff9558SSimon J. Gerraty 				rc = 0;	/* success */
3845fff9558SSimon J. Gerraty 			} else if (rc == 0) {
3855fff9558SSimon J. Gerraty 				printf("Unverified %s: %s\n",
3865fff9558SSimon J. Gerraty 				    filename, get_error_string());
3875fff9558SSimon J. Gerraty 				rc = 1;
3885fff9558SSimon J. Gerraty 			} else {
3895fff9558SSimon J. Gerraty 				printf("Unverified %s\n", filename);
3905fff9558SSimon J. Gerraty 			}
3915fff9558SSimon J. Gerraty 		}
3925fff9558SSimon J. Gerraty 	} else {
3935fff9558SSimon J. Gerraty 		warnx("cannot decode signature for %s", filename);
3945fff9558SSimon J. Gerraty 		rc = -1;
3955fff9558SSimon J. Gerraty 	}
3965fff9558SSimon J. Gerraty oops:
3975fff9558SSimon J. Gerraty 	free(ddata);
3985fff9558SSimon J. Gerraty 	free(sig);
3995fff9558SSimon J. Gerraty 	return (rc);
4005fff9558SSimon J. Gerraty }
4015fff9558SSimon J. Gerraty 
4025fff9558SSimon J. Gerraty #ifndef _STANDALONE
4035fff9558SSimon J. Gerraty /**
4045fff9558SSimon J. Gerraty  * @brief list of extensions we handle
4055fff9558SSimon J. Gerraty  *
4065fff9558SSimon J. Gerraty  * ".asc" is preferred as it works seamlessly with openpgp
4075fff9558SSimon J. Gerraty  */
4085fff9558SSimon J. Gerraty static const char *sig_exts[] = {
4095fff9558SSimon J. Gerraty 	".asc",
4105fff9558SSimon J. Gerraty 	".pgp",
4115fff9558SSimon J. Gerraty 	".psig",
4125fff9558SSimon J. Gerraty 	NULL,
4135fff9558SSimon J. Gerraty };
4145fff9558SSimon J. Gerraty 
4155fff9558SSimon J. Gerraty /**
4165fff9558SSimon J. Gerraty  * @brief verify OpenPGP signed file
4175fff9558SSimon J. Gerraty  *
4185fff9558SSimon J. Gerraty  *
4195fff9558SSimon J. Gerraty  * @param[in] filename
4205fff9558SSimon J. Gerraty  *	used to determine the signature name
4215fff9558SSimon J. Gerraty  *
4225fff9558SSimon J. Gerraty  * @param[in] fdata
4235fff9558SSimon J. Gerraty  *	content of filename
4245fff9558SSimon J. Gerraty  *
4255fff9558SSimon J. Gerraty  * @param[in] nbytes
4265fff9558SSimon J. Gerraty  *	of fdata
4275fff9558SSimon J. Gerraty  *
4285fff9558SSimon J. Gerraty  * @return
4295fff9558SSimon J. Gerraty  */
4305fff9558SSimon J. Gerraty 
4315fff9558SSimon J. Gerraty int
4325fff9558SSimon J. Gerraty openpgp_verify_file(const char *filename, unsigned char *fdata, size_t nbytes)
4335fff9558SSimon J. Gerraty {
4345fff9558SSimon J. Gerraty 	char pbuf[MAXPATHLEN];
4355fff9558SSimon J. Gerraty 	unsigned char *sdata;
4365fff9558SSimon J. Gerraty 	const char *sname = NULL;
4375fff9558SSimon J. Gerraty 	const char **ep;
4385fff9558SSimon J. Gerraty 	size_t sz;
4395fff9558SSimon J. Gerraty 	int n;
4405fff9558SSimon J. Gerraty 
4415fff9558SSimon J. Gerraty 	for (ep = sig_exts; *ep; ep++) {
4425fff9558SSimon J. Gerraty 		n = snprintf(pbuf, sizeof(pbuf), "%s%s", filename, *ep);
4435fff9558SSimon J. Gerraty 		if (n >= (int)sizeof(pbuf)) {
4445fff9558SSimon J. Gerraty 			warnx("cannot form signature name for %s", filename);
4455fff9558SSimon J. Gerraty 			return (-1);
4465fff9558SSimon J. Gerraty 		}
4475fff9558SSimon J. Gerraty 		if (access(pbuf, R_OK) == 0) {
4485fff9558SSimon J. Gerraty 			sname = pbuf;
4495fff9558SSimon J. Gerraty 			break;
4505fff9558SSimon J. Gerraty 		}
4515fff9558SSimon J. Gerraty 	}
4525fff9558SSimon J. Gerraty 	if (!sname) {
4535fff9558SSimon J. Gerraty 		warnx("cannot find signature for %s", filename);
4545fff9558SSimon J. Gerraty 		return (-1);
4555fff9558SSimon J. Gerraty 	}
4565fff9558SSimon J. Gerraty 	sdata = read_file(sname, &sz);
45766655411SSimon J. Gerraty 	return (openpgp_verify(filename, fdata, nbytes, sdata, sz, VerifyFlags));
4585fff9558SSimon J. Gerraty }
4595fff9558SSimon J. Gerraty #endif
4605fff9558SSimon J. Gerraty 
4615fff9558SSimon J. Gerraty /**
4625fff9558SSimon J. Gerraty  * @brief verify OpenPGP signature
4635fff9558SSimon J. Gerraty  *
4645fff9558SSimon J. Gerraty  * @return content of signed file
4655fff9558SSimon J. Gerraty  */
4665fff9558SSimon J. Gerraty unsigned char *
4675fff9558SSimon J. Gerraty verify_asc(const char *sigfile, int flags)
4685fff9558SSimon J. Gerraty {
4695fff9558SSimon J. Gerraty 	char pbuf[MAXPATHLEN];
4705fff9558SSimon J. Gerraty 	char *cp;
4715fff9558SSimon J. Gerraty 	size_t n;
4725fff9558SSimon J. Gerraty 	unsigned char *fdata, *sdata;
4735fff9558SSimon J. Gerraty 	size_t fbytes, sbytes;
4745fff9558SSimon J. Gerraty 
47556f3f2d2SSimon J. Gerraty 	fdata = NULL;
4765fff9558SSimon J. Gerraty 	if ((sdata = read_file(sigfile, &sbytes))) {
4775fff9558SSimon J. Gerraty 		n = strlcpy(pbuf, sigfile, sizeof(pbuf));
47856f3f2d2SSimon J. Gerraty 		if (n < sizeof(pbuf)) {
4795fff9558SSimon J. Gerraty 			if ((cp = strrchr(pbuf, '.')))
4805fff9558SSimon J. Gerraty 				*cp = '\0';
4815fff9558SSimon J. Gerraty 			if ((fdata = read_file(pbuf, &fbytes))) {
4825fff9558SSimon J. Gerraty 				if (openpgp_verify(pbuf, fdata, fbytes, sdata,
4835fff9558SSimon J. Gerraty 					sbytes, flags)) {
4845fff9558SSimon J. Gerraty 					free(fdata);
4855fff9558SSimon J. Gerraty 					fdata = NULL;
4865fff9558SSimon J. Gerraty 				}
4875fff9558SSimon J. Gerraty 			}
48856f3f2d2SSimon J. Gerraty 		}
48956f3f2d2SSimon J. Gerraty 	}
4905fff9558SSimon J. Gerraty 	free(sdata);
4915fff9558SSimon J. Gerraty 	return (fdata);
4925fff9558SSimon J. Gerraty }
493