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