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