b24a4c3e01
+ recognise signatures made by subkeys as well as by primary keys + print out the relevant key which signed the file, even if it's a subkey and not the primary key itself. + keep the same API as before with many thanks to Jonathan Perkin
298 lines
8.5 KiB
C
298 lines
8.5 KiB
C
/*-
|
|
* Copyright (c) 2012,2013,2014,2015 Alistair Crooks <agc@NetBSD.org>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#ifndef NETPGP_VERIFY_H_
|
|
#define NETPGP_VERIFY_H_ 20150205
|
|
|
|
#define NETPGPVERIFY_VERSION "netpgpverify portable 20150205"
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#ifndef PGPV_ARRAY
|
|
/* creates 2 unsigned vars called "name"c and "name"size in current scope */
|
|
/* also creates an array called "name"s in current scope */
|
|
#define PGPV_ARRAY(type, name) \
|
|
unsigned name##c; unsigned name##vsize; type *name##s
|
|
#endif
|
|
|
|
/* 64bit key ids */
|
|
#define PGPV_KEYID_LEN 8
|
|
#define PGPV_STR_KEYID_LEN (PGPV_KEYID_LEN + PGPV_KEYID_LEN + 1)
|
|
|
|
/* bignum structure */
|
|
typedef struct pgpv_bignum_t {
|
|
void *bn; /* hide the implementation details */
|
|
uint16_t bits; /* cached number of bits */
|
|
} pgpv_bignum_t;
|
|
|
|
/* right now, our max binary digest length is 20 bytes */
|
|
#define PGPV_MAX_HASH_LEN 64
|
|
|
|
/* fingerprint */
|
|
typedef struct pgpv_fingerprint_t {
|
|
uint8_t hashalg; /* algorithm for digest */
|
|
uint8_t v[PGPV_MAX_HASH_LEN]; /* the digest */
|
|
uint32_t len; /* its length */
|
|
} pgpv_fingerprint_t;
|
|
|
|
/* specify size for array of bignums */
|
|
#define PGPV_MAX_PUBKEY_BN 4
|
|
|
|
/* public key */
|
|
typedef struct pgpv_pubkey_t {
|
|
pgpv_fingerprint_t fingerprint; /* key fingerprint i.e. digest */
|
|
uint8_t keyid[PGPV_KEYID_LEN]; /* last 8 bytes of v4 keys */
|
|
int64_t birth; /* creation time */
|
|
int64_t expiry; /* expiry time */
|
|
pgpv_bignum_t bn[PGPV_MAX_PUBKEY_BN]; /* bignums */
|
|
uint8_t keyalg; /* key algorithm */
|
|
uint8_t hashalg; /* hash algorithm */
|
|
uint8_t version; /* key version */
|
|
} pgpv_pubkey_t;
|
|
|
|
#define PGPV_MAX_SESSKEY_BN 2
|
|
|
|
/* a (size, byte array) string */
|
|
typedef struct pgpv_string_t {
|
|
size_t size;
|
|
uint8_t *data;
|
|
} pgpv_string_t;
|
|
|
|
typedef struct pgpv_ref_t {
|
|
void *vp;
|
|
size_t offset;
|
|
unsigned mem;
|
|
} pgpv_ref_t;
|
|
|
|
#define PGPV_MAX_SECKEY_BN 4
|
|
|
|
typedef struct pgpv_compress_t {
|
|
pgpv_string_t s;
|
|
uint8_t compalg;
|
|
} pgpv_compress_t;
|
|
|
|
/* a packet dealing with trust */
|
|
typedef struct pgpv_trust_t {
|
|
uint8_t level;
|
|
uint8_t amount;
|
|
} pgpv_trust_t;
|
|
|
|
/* a signature sub packet */
|
|
typedef struct pgpv_sigsubpkt_t {
|
|
pgpv_string_t s;
|
|
uint8_t tag;
|
|
uint8_t critical;
|
|
} pgpv_sigsubpkt_t;
|
|
|
|
#define PGPV_MAX_SIG_BN 2
|
|
|
|
typedef struct pgpv_signature_t {
|
|
uint8_t *signer; /* key id of signer */
|
|
pgpv_ref_t hashstart;
|
|
uint8_t *hash2;
|
|
uint8_t *mpi;
|
|
int64_t birth;
|
|
int64_t keyexpiry;
|
|
int64_t expiry;
|
|
uint32_t hashlen;
|
|
uint8_t version;
|
|
uint8_t type;
|
|
uint8_t keyalg;
|
|
uint8_t hashalg;
|
|
uint8_t trustlevel;
|
|
uint8_t trustamount;
|
|
pgpv_bignum_t bn[PGPV_MAX_SIG_BN];
|
|
char *regexp;
|
|
char *pref_key_server;
|
|
char *policy;
|
|
char *features;
|
|
char *why_revoked;
|
|
uint8_t *revoke_fingerprint;
|
|
uint8_t revoke_alg;
|
|
uint8_t revoke_sensitive;
|
|
uint8_t trustsig;
|
|
uint8_t revocable;
|
|
uint8_t pref_symm_alg;
|
|
uint8_t pref_hash_alg;
|
|
uint8_t pref_compress_alg;
|
|
uint8_t key_server_modify;
|
|
uint8_t notation;
|
|
uint8_t type_key;
|
|
uint8_t primary_userid;
|
|
uint8_t revoked; /* subtract 1 to get real reason, 0 == not revoked */
|
|
} pgpv_signature_t;
|
|
|
|
/* a signature packet */
|
|
typedef struct pgpv_sigpkt_t {
|
|
pgpv_signature_t sig;
|
|
uint16_t subslen;
|
|
uint16_t unhashlen;
|
|
PGPV_ARRAY(pgpv_sigsubpkt_t, subpkts);
|
|
} pgpv_sigpkt_t;
|
|
|
|
/* a one-pass signature packet */
|
|
typedef struct pgpv_onepass_t {
|
|
uint8_t keyid[PGPV_KEYID_LEN];
|
|
uint8_t version;
|
|
uint8_t type;
|
|
uint8_t hashalg;
|
|
uint8_t keyalg;
|
|
uint8_t nested;
|
|
} pgpv_onepass_t;
|
|
|
|
/* a literal data packet */
|
|
typedef struct pgpv_litdata_t {
|
|
uint8_t *filename;
|
|
pgpv_string_t s;
|
|
uint32_t secs;
|
|
uint8_t namelen;
|
|
char format;
|
|
unsigned mem;
|
|
size_t offset;
|
|
size_t len;
|
|
} pgpv_litdata_t;
|
|
|
|
/* user attributes - images */
|
|
typedef struct pgpv_userattr_t {
|
|
size_t len;
|
|
PGPV_ARRAY(pgpv_string_t, subattrs);
|
|
} pgpv_userattr_t;
|
|
|
|
/* a general PGP packet */
|
|
typedef struct pgpv_pkt_t {
|
|
uint8_t tag;
|
|
uint8_t newfmt;
|
|
uint8_t allocated;
|
|
uint8_t mement;
|
|
size_t offset;
|
|
pgpv_string_t s;
|
|
union {
|
|
pgpv_sigpkt_t sigpkt;
|
|
pgpv_onepass_t onepass;
|
|
pgpv_litdata_t litdata;
|
|
pgpv_compress_t compressed;
|
|
pgpv_trust_t trust;
|
|
pgpv_pubkey_t pubkey;
|
|
pgpv_string_t userid;
|
|
pgpv_userattr_t userattr;
|
|
} u;
|
|
} pgpv_pkt_t;
|
|
|
|
/* a memory structure */
|
|
typedef struct pgpv_mem_t {
|
|
size_t size;
|
|
size_t cc;
|
|
uint8_t *mem;
|
|
FILE *fp;
|
|
uint8_t dealloc;
|
|
const char *allowed; /* the types of packet that are allowed */
|
|
} pgpv_mem_t;
|
|
|
|
/* packet parser */
|
|
|
|
typedef struct pgpv_signed_userid_t {
|
|
pgpv_string_t userid;
|
|
PGPV_ARRAY(pgpv_signature_t, sigs);
|
|
uint8_t primary_userid;
|
|
uint8_t revoked;
|
|
} pgpv_signed_userid_t;
|
|
|
|
typedef struct pgpv_signed_userattr_t {
|
|
pgpv_userattr_t userattr;
|
|
PGPV_ARRAY(pgpv_signature_t, sigs);
|
|
uint8_t revoked;
|
|
} pgpv_signed_userattr_t;
|
|
|
|
typedef struct pgpv_signed_subkey_t {
|
|
pgpv_pubkey_t subkey;
|
|
pgpv_signature_t revoc_self_sig;
|
|
PGPV_ARRAY(pgpv_signature_t, sigs);
|
|
} pgpv_signed_subkey_t;
|
|
|
|
typedef struct pgpv_primarykey_t {
|
|
pgpv_pubkey_t primary;
|
|
pgpv_signature_t revoc_self_sig;
|
|
PGPV_ARRAY(pgpv_signature_t, direct_sigs);
|
|
PGPV_ARRAY(pgpv_signed_userid_t, signed_userids);
|
|
PGPV_ARRAY(pgpv_signed_userattr_t, signed_userattrs);
|
|
PGPV_ARRAY(pgpv_signed_subkey_t, signed_subkeys);
|
|
size_t fmtsize;
|
|
uint8_t primary_userid;
|
|
} pgpv_primarykey_t;
|
|
|
|
/* everything stems from this structure */
|
|
typedef struct pgpv_t {
|
|
PGPV_ARRAY(pgpv_pkt_t, pkts); /* packet array */
|
|
PGPV_ARRAY(pgpv_primarykey_t, primaries); /* array of primary keys */
|
|
PGPV_ARRAY(pgpv_mem_t, areas); /* areas we read packets from */
|
|
PGPV_ARRAY(size_t, datastarts); /* starts of data packets */
|
|
size_t pkt; /* when parsing, current pkt number */
|
|
const char *op; /* the operation we're doing */
|
|
unsigned ssh; /* using ssh keys */
|
|
} pgpv_t;
|
|
|
|
#define PGPV_REASON_LEN 128
|
|
|
|
/* when searching, we define a cursor, and fill in an array of subscripts */
|
|
typedef struct pgpv_cursor_t {
|
|
pgpv_t *pgp; /* pointer to pgp tree */
|
|
char *field; /* field we're searching on */
|
|
char *op; /* operation we're doing */
|
|
char *value; /* value we're searching for */
|
|
void *ptr; /* for regexps etc */
|
|
PGPV_ARRAY(uint32_t, found); /* array of matched pimary key subscripts */
|
|
PGPV_ARRAY(size_t, datacookies); /* cookies to retrieve matched data */
|
|
int64_t sigtime; /* time of signature */
|
|
char why[PGPV_REASON_LEN]; /* reason for bad signature */
|
|
} pgpv_cursor_t;
|
|
|
|
#ifndef __BEGIN_DECLS
|
|
# if defined(__cplusplus)
|
|
# define __BEGIN_DECLS extern "C" {
|
|
# define __END_DECLS }
|
|
# else
|
|
# define __BEGIN_DECLS
|
|
# define __END_DECLS
|
|
# endif
|
|
#endif
|
|
|
|
__BEGIN_DECLS
|
|
|
|
int pgpv_read_pubring(pgpv_t */*pgp*/, const void */*keyringfile/mem*/, ssize_t /*size*/);
|
|
int pgpv_read_ssh_pubkeys(pgpv_t */*pgp*/, const void */*keyring*/, ssize_t /*size*/);
|
|
|
|
size_t pgpv_verify(pgpv_cursor_t */*cursor*/, pgpv_t */*pgp*/, const void */*mem/file*/, ssize_t /*size*/);
|
|
size_t pgpv_get_verified(pgpv_cursor_t */*cursor*/, size_t /*cookie*/, char **/*ret*/);
|
|
int pgpv_get_cursor_element(pgpv_cursor_t */*cursor*/, size_t /*element*/);
|
|
size_t pgpv_dump(pgpv_t */*pgp*/, char **/*data*/);
|
|
|
|
size_t pgpv_get_entry(pgpv_t */*pgp*/, unsigned /*ent*/, char **/*ret*/, const char */*modifiers*/);
|
|
|
|
int pgpv_close(pgpv_t */*pgp*/);
|
|
|
|
__END_DECLS
|
|
|
|
#endif
|