Browse Source

Added packet collection capability to on_valid callback. Added pgp_filter_keys_from_mem with stub key_filter_cb. To be continued.

master
Edouard Tisserant 7 years ago
parent
commit
a78a9dfa63
6 changed files with 215 additions and 83 deletions
  1. +8
    -5
      dist/src/lib/keyring.c
  2. +2
    -0
      dist/src/lib/keyring.h
  3. +14
    -20
      dist/src/lib/signature.c
  4. +4
    -8
      dist/src/lib/signature.h
  5. +173
    -45
      dist/src/lib/validate.c
  6. +14
    -5
      dist/src/lib/validate.h

+ 8
- 5
dist/src/lib/keyring.c View File

@ -160,6 +160,9 @@ pgp_keydata_free(pgp_key_t *keydata)
free(keydata);
}
/*
* TODO : rewrite
* */
int
pgp_keydata_dup(pgp_key_t *dst, pgp_key_t *src, unsigned make_public)
{
@ -495,14 +498,14 @@ copy_userid(uint8_t **dst, const uint8_t *src)
\param src Source packet
\note If dst already has a packet, it will be freed.
*/
static pgp_subpacket_t *
copy_packet(pgp_subpacket_t *dst, const pgp_subpacket_t *src)
pgp_subpacket_t *
pgp_copy_packet(pgp_subpacket_t *dst, const pgp_subpacket_t *src)
{
if (dst->raw) {
free(dst->raw);
}
if ((dst->raw = calloc(1, src->length)) == NULL) {
(void) fprintf(stderr, "copy_packet: bad alloc\n");
(void) fprintf(stderr, "pgp_copy_packet: bad alloc\n");
} else {
dst->length = src->length;
(void) memcpy(dst->raw, src->raw, src->length);
@ -550,7 +553,7 @@ pgp_add_subpacket(pgp_key_t *keydata, const pgp_subpacket_t *packet)
subpktp->length = 0;
subpktp->raw = NULL;
/* now copy it */
return copy_packet(subpktp, packet);
return pgp_copy_packet(subpktp, packet);
}
pgp_subpacket_t *
@ -564,7 +567,7 @@ pgp_replace_subpacket(
if (keydata->packetc > index) {
subpktp = &keydata->packets[index];
pgp_subpacket_free(subpktp);
return copy_packet(subpktp, packet);
return pgp_copy_packet(subpktp, packet);
}
return NULL;
}


+ 2
- 0
dist/src/lib/keyring.h View File

@ -168,4 +168,6 @@ int pgp_add_to_secring(pgp_keyring_t *, const pgp_seckey_t *);
int pgp_append_keyring(pgp_keyring_t *, pgp_keyring_t *);
pgp_subpacket_t * pgp_copy_packet(pgp_subpacket_t *, const pgp_subpacket_t *);
#endif /* KEYRING_H_ */

+ 14
- 20
dist/src/lib/signature.c View File

@ -380,12 +380,11 @@ init_key_sig(pgp_hash_t *hash, const pgp_sig_t *sig,
}
static void
hash_add_trailer(pgp_hash_t *hash, const pgp_sig_t *sig,
const uint8_t *raw_packet)
hash_add_trailer(pgp_hash_t *hash, const pgp_sig_t *sig)
{
if (sig->info.version == PGP_V4) {
if (raw_packet) {
hash->add(hash, raw_packet + sig->v4_hashstart,
if (sig->info.v4_hashlen) {
hash->add(hash, sig->info.v4_hashed,
(unsigned)sig->info.v4_hashlen);
}
pgp_hash_add_int(hash, (unsigned)sig->info.version, 1);
@ -452,10 +451,9 @@ hash_and_check_sig(pgp_hash_t *hash,
static unsigned
finalise_sig(pgp_hash_t *hash,
const pgp_sig_t *sig,
const pgp_pubkey_t *signer,
const uint8_t *raw_packet)
const pgp_pubkey_t *signer)
{
hash_add_trailer(hash, sig, raw_packet);
hash_add_trailer(hash, sig);
return hash_and_check_sig(hash, sig, signer);
}
@ -475,8 +473,7 @@ unsigned
pgp_check_useridcert_sig(const pgp_pubkey_t *key,
const uint8_t *id,
const pgp_sig_t *sig,
const pgp_pubkey_t *signer,
const uint8_t *raw_packet)
const pgp_pubkey_t *signer)
{
pgp_hash_t hash;
size_t userid_len;
@ -488,7 +485,7 @@ pgp_check_useridcert_sig(const pgp_pubkey_t *key,
pgp_hash_add_int(&hash, (unsigned)userid_len, 4);
}
hash.add(&hash, id, (unsigned)userid_len);
return finalise_sig(&hash, sig, signer, raw_packet);
return finalise_sig(&hash, sig, signer);
}
/**
@ -507,8 +504,7 @@ unsigned
pgp_check_userattrcert_sig(const pgp_pubkey_t *key,
const pgp_data_t *attribute,
const pgp_sig_t *sig,
const pgp_pubkey_t *signer,
const uint8_t *raw_packet)
const pgp_pubkey_t *signer)
{
pgp_hash_t hash;
@ -518,7 +514,7 @@ pgp_check_userattrcert_sig(const pgp_pubkey_t *key,
pgp_hash_add_int(&hash, (unsigned)attribute->len, 4);
}
hash.add(&hash, attribute->contents, (unsigned)attribute->len);
return finalise_sig(&hash, sig, signer, raw_packet);
return finalise_sig(&hash, sig, signer);
}
/**
@ -537,15 +533,14 @@ unsigned
pgp_check_subkey_sig(const pgp_pubkey_t *key,
const pgp_pubkey_t *subkey,
const pgp_sig_t *sig,
const pgp_pubkey_t *signer,
const uint8_t *raw_packet)
const pgp_pubkey_t *signer)
{
pgp_hash_t hash;
unsigned ret;
init_key_sig(&hash, sig, key);
hash_add_key(&hash, subkey);
ret = finalise_sig(&hash, sig, signer, raw_packet);
ret = finalise_sig(&hash, sig, signer);
return ret;
}
@ -563,14 +558,13 @@ pgp_check_subkey_sig(const pgp_pubkey_t *key,
unsigned
pgp_check_direct_sig(const pgp_pubkey_t *key,
const pgp_sig_t *sig,
const pgp_pubkey_t *signer,
const uint8_t *raw_packet)
const pgp_pubkey_t *signer)
{
pgp_hash_t hash;
unsigned ret;
init_key_sig(&hash, sig, key);
ret = finalise_sig(&hash, sig, signer, raw_packet);
ret = finalise_sig(&hash, sig, signer);
return ret;
}
@ -592,7 +586,7 @@ pgp_check_hash_sig(pgp_hash_t *hash,
const pgp_pubkey_t *signer)
{
return (sig->info.hash_alg == hash->alg) ?
finalise_sig(hash, sig, signer, NULL) :
finalise_sig(hash, sig, signer) :
0;
}


+ 4
- 8
dist/src/lib/signature.h View File

@ -69,22 +69,18 @@ void pgp_create_sig_delete(pgp_create_sig_t *);
unsigned pgp_check_useridcert_sig(const pgp_pubkey_t *,
const uint8_t *,
const pgp_sig_t *,
const pgp_pubkey_t *,
const uint8_t *);
const pgp_pubkey_t *);
unsigned pgp_check_userattrcert_sig(const pgp_pubkey_t *,
const pgp_data_t *,
const pgp_sig_t *,
const pgp_pubkey_t *,
const uint8_t *);
const pgp_pubkey_t *);
unsigned pgp_check_subkey_sig(const pgp_pubkey_t *,
const pgp_pubkey_t *,
const pgp_sig_t *,
const pgp_pubkey_t *,
const uint8_t *);
const pgp_pubkey_t *);
unsigned pgp_check_direct_sig(const pgp_pubkey_t *,
const pgp_sig_t *,
const pgp_pubkey_t *,
const uint8_t *);
const pgp_pubkey_t *);
unsigned pgp_check_hash_sig(pgp_hash_t *,
const pgp_sig_t *,
const pgp_pubkey_t *);


+ 173
- 45
dist/src/lib/validate.c View File

@ -125,10 +125,15 @@ keydata_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **er
return (int)length;
}
void pgp_free_sig_info(pgp_sig_info_t *sig)
{
free(sig->v4_hashed);
}
static void
free_sig_info(pgp_sig_info_t *sig)
{
free(sig->v4_hashed);
pgp_free_sig_info(sig);
free(sig);
}
@ -250,6 +255,13 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
}
vdata = pgp_callback_arg(cbinfo);
errors = pgp_callback_errors(cbinfo);
/* forget packet post-processing requests if packet is not
* passed in call immediately following tag where it was requested
* Parser shouldn't allow this, though */
vdata->store_pkt &= pkt->tag == PGP_PARSER_PACKET_END;
vdata->sig_is_valid &= pkt->tag == PGP_PARSER_PACKET_END;
switch (pkt->tag) {
case PGP_PTAG_CT_PUBLIC_KEY:
if (vdata->pubkey.version != 0) {
@ -262,6 +274,8 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
&vdata->pubkey, PGP_HASH_SHA1); /* TODO v3*/
vdata->last_seen = PRIMARYKEY;
vdata->store_pkt = 1;
vdata->not_commited = 1;
return PGP_KEEP_MEMORY;
case PGP_PTAG_CT_PUBLIC_SUBKEY:
@ -272,6 +286,7 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
}
vdata->subkey = content->pubkey;
vdata->last_seen = SUBKEY;
vdata->store_pkt = 1;
return PGP_KEEP_MEMORY;
}else{
(void) fprintf(io->errs,
@ -288,6 +303,7 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
}
vdata->userid = content->userid;
vdata->last_seen = ID;
vdata->store_pkt = 1;
return PGP_KEEP_MEMORY;
}else{
(void) fprintf(io->errs,
@ -311,6 +327,7 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
}
vdata->userattr = content->userattr;
vdata->last_seen = ATTRIBUTE;
vdata->store_pkt = 1;
return PGP_KEEP_MEMORY;
}else{
(void) fprintf(io->errs,
@ -360,21 +377,12 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
valid = pgp_check_useridcert_sig(&vdata->pubkey,
vdata->userid,
&content->sig,
sigkey,
vdata->reader->key->packets[
vdata->reader->packet].raw);
/* XXX TODO if valid : pgp_update_key_userid
* - id expiration
* - revocation
* - is primary
* */
sigkey);
} else if(vdata->last_seen == ATTRIBUTE) {
valid = pgp_check_userattrcert_sig(&vdata->pubkey,
&vdata->userattr,
&content->sig,
sigkey,
vdata->reader->key->packets[
vdata->reader->packet].raw);
sigkey);
}
break;
@ -390,11 +398,7 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
valid = pgp_check_subkey_sig(&vdata->pubkey,
&vdata->subkey,
&content->sig,
&vdata->pubkey,
vdata->reader->key->packets[
vdata->reader->packet].raw);
/* XXX TODO if valid : pgp_update_key_subkey
* with expiration and flags from sig info */
&vdata->pubkey);
}
break;
@ -402,11 +406,7 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
if(vdata->last_seen == PRIMARYKEY){
valid = pgp_check_direct_sig(&vdata->pubkey,
&content->sig,
sigkey,
vdata->reader->key->packets[
vdata->reader->packet].raw);
/* XXX TODO if valid : pgp_update_key
* with expiration and flags from sig info */
sigkey);
}
break;
@ -434,11 +434,11 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
&vdata->result->valid_sigs,
&vdata->result->validc)) {
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s",
"Can't add good sig to list\n");
"Can't add valid sig to list\n");
}
if(vdata->on_valid){
return vdata->on_valid(vdata,&content->sig);
}
vdata->sig_is_valid = 1;
copy_sig_info(&vdata->valid_sig_info,
&content->sig.info);
} else {
PGP_ERROR_1(errors, PGP_E_V_BAD_SIGNATURE, "%s",
"Bad Sig");
@ -446,15 +446,31 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
&vdata->result->invalid_sigs,
&vdata->result->invalidc)) {
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s",
"Can't add good sig to list\n");
"Can't add invalid sig to list\n");
}
}
break;
/* ignore these */
case PGP_PARSER_PACKET_END:
/* Store packet so that on_valid callback still
* can access it once valid signture is parsed */
if(vdata->store_pkt){
pgp_copy_packet(&vdata->last_pkt, &content->packet);
vdata->store_pkt = 0;
}else if(vdata->sig_is_valid){
pgp_cb_ret_t ret = PGP_KEEP_MEMORY;
if(vdata->on_valid){
ret = vdata->on_valid(vdata, &content->packet);
}
vdata->sig_is_valid = 0;
vdata->not_commited = 0;
return ret;
}
return PGP_KEEP_MEMORY;
/* ignore these */
case PGP_PARSER_PTAG:
case PGP_PTAG_CT_SIGNATURE_HEADER:
case PGP_PARSER_PACKET_END:
break;
case PGP_GET_PASSPHRASE:
@ -727,6 +743,118 @@ validate_result_status(FILE *errs, const char *f, pgp_validation_t *val)
return val->validc && !val->invalidc && !val->unknownc;
}
static void printtime(time_t t)
{
struct tm *tm;
tm = gmtime(&t);
(void) printf("%04d-%02d-%02d\n",
tm->tm_year + 1900,
tm->tm_mon + 1,
tm->tm_mday);
}
static pgp_cb_ret_t key_filter_cb (
validate_key_cb_t *vdata,
const pgp_subpacket_t *sigpkt)
{
if(vdata->not_commited){
printf("New key ************************************** \n");
/*hexdump(stdout, "signer ID", vdata->valid_sig_info.signer_id,
sizeof(vdata->valid_sig_info.signer_id));*/
hexdump(stdout, "pubkey ID", vdata->pubkeyid,
sizeof(vdata->pubkeyid));
}
switch(vdata->last_seen){
case ATTRIBUTE:
printf("ATTRIBUTE\n");
break;
case ID:
printf("ID %s\n", vdata->userid);
/* XXX TODO add/update userid
* - id expiration
* - revocation
* - is primary
* */
break;
case SUBKEY:
printf("SUBKEY\n");
{
uint8_t subkeyid[PGP_KEY_ID_SIZE];
pgp_keyid(subkeyid, PGP_KEY_ID_SIZE,
&vdata->subkey, PGP_HASH_SHA1);
hexdump(stdout, "subkey ID", subkeyid,
sizeof(subkeyid));
/* XXX TODO add/update subkey
* with expiration and flags from sig info */
}
break;
case PRIMARYKEY:
printf("PRIMARYKEY\n");
/* XXX TODO direct key signature pgp_update_key
* with expiration and flags from sig info */
break;
default:
printf("no_last_seen\n");
break;
}
printtime(vdata->valid_sig_info.birthtime);
return PGP_RELEASE_MEMORY;
}
unsigned
pgp_filter_keys_from_mem(pgp_io_t *io,
pgp_keyring_t *destring,
pgp_keyring_t *certring,
const unsigned armour,
pgp_memory_t *mem)
{
pgp_validation_t vresult;
pgp_stream_t *stream;
const unsigned noaccum = 0;
validate_key_cb_t vdata;
const int printerrors = 1;
unsigned res;
(void) memset(&vresult, 0x0, sizeof(vresult));
(void) memset(&vdata, 0x0, sizeof(vdata));
vdata.result = &vresult;
vdata.getpassphrase = NULL;
stream = pgp_new(sizeof(*stream));
pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED);
pgp_setup_memory_read(io, &stream, mem, &vdata, pgp_validate_key_cb,
noaccum);
if (armour) {
pgp_reader_push_dearmour(stream);
}
vdata.keyring = certring;
vdata.on_valid = &key_filter_cb;
vdata.on_valid_args = NULL;
stream->readinfo.accumulate = 1;
res = pgp_parse(stream, !printerrors);
pgp_pubkey_free(&vdata.pubkey);
if (vdata.subkey.version) {
pgp_pubkey_free(&vdata.subkey);
}
pgp_userid_free(&vdata.userid);
pgp_data_free(&vdata.userattr);
pgp_subpacket_free(&vdata.last_pkt);
pgp_free_sig_info(&vdata.valid_sig_info);
if (armour) {
pgp_reader_pop_dearmour(stream);
}
/* don't call teardown_memory_read because memory was passed in */
pgp_stream_delete(stream);
return res;
}
/**
* \ingroup HighLevel_Verify
* \brief Validate all signatures on a single key against the given keyring
@ -747,37 +875,37 @@ pgp_validate_key_sigs(pgp_validation_t *result,
)
{
pgp_stream_t *stream;
validate_key_cb_t keysigs;
validate_key_cb_t vdata;
const int printerrors = 1;
(void) memset(&keysigs, 0x0, sizeof(keysigs));
keysigs.result = result;
keysigs.getpassphrase = cb_get_passphrase;
(void) memset(&vdata, 0x0, sizeof(vdata));
vdata.result = result;
vdata.getpassphrase = cb_get_passphrase;
stream = pgp_new(sizeof(*stream));
/* pgp_parse_options(&opt,PGP_PTAG_CT_SIGNATURE,PGP_PARSE_PARSED); */
keysigs.keyring = keyring;
keysigs.on_valid = NULL;
keysigs.on_valid_args = NULL;
vdata.keyring = keyring;
pgp_set_callback(stream, pgp_validate_key_cb, &keysigs);
pgp_set_callback(stream, pgp_validate_key_cb, &vdata);
stream->readinfo.accumulate = 1;
pgp_keydata_reader_set(stream, key);
/* Note: Coverity incorrectly reports an error that keysigs.reader */
/* Note: Coverity incorrectly reports an error that vdata.reader */
/* is never used. */
keysigs.reader = stream->readinfo.arg;
vdata.reader = stream->readinfo.arg;
pgp_parse(stream, !printerrors);
pgp_pubkey_free(&keysigs.pubkey);
if (keysigs.subkey.version) {
pgp_pubkey_free(&keysigs.subkey);
pgp_pubkey_free(&vdata.pubkey);
if (vdata.subkey.version) {
pgp_pubkey_free(&vdata.subkey);
}
pgp_userid_free(&keysigs.userid);
pgp_data_free(&keysigs.userattr);
pgp_userid_free(&vdata.userid);
pgp_data_free(&vdata.userattr);
pgp_subpacket_free(&vdata.last_pkt);
pgp_free_sig_info(&vdata.valid_sig_info);
pgp_stream_delete(stream);


+ 14
- 5
dist/src/lib/validate.h View File

@ -56,7 +56,7 @@ typedef struct {
} validate_reader_t;
/** Struct used with the validate_key_cb callback */
typedef struct validate_key_cb_s{
typedef struct validate_key_cb_t{
pgp_pubkey_t pubkey;
pgp_pubkey_t subkey;
uint8_t pubkeyid[PGP_KEY_ID_SIZE];
@ -66,6 +66,7 @@ typedef struct validate_key_cb_s{
SUBKEY,
PRIMARYKEY
} last_seen;
uint8_t *userid;
pgp_data_t userattr;
uint8_t hash[PGP_MAX_HASH_SIZE];
@ -74,10 +75,17 @@ typedef struct validate_key_cb_s{
pgp_validation_t *result;
pgp_cb_ret_t(*getpassphrase) (const pgp_packet_t *,
pgp_cbdata_t *);
pgp_cb_ret_t(*on_valid) (
struct validate_key_cb_s *,
const pgp_sig_t *);
void *on_valid_args;
pgp_subpacket_t last_pkt; /* last non-signature packet met */
unsigned store_pkt; /* request to store packet at packet end */
unsigned not_commited; /* tells on_valid it is first commit of that key */
pgp_sig_info_t valid_sig_info; /* store last valid sig info */
unsigned sig_is_valid; /* condition to call on_valid at packet end */
pgp_cb_ret_t(*on_valid) ( /* callback for action on valid sig */
struct validate_key_cb_t *, /* this struct */
const pgp_subpacket_t *); /* sig packet */
void *on_valid_args; /* pointer to argument for on_valid callback */
} validate_key_cb_t;
/** Struct use with the validate_data_cb callback */
@ -130,5 +138,6 @@ unsigned pgp_validate_mem_detached(pgp_io_t *,
pgp_memory_t *);
pgp_cb_ret_t validate_data_cb(const pgp_packet_t *, pgp_cbdata_t *);
void pgp_free_sig_info(pgp_sig_info_t *);
#endif /* !VALIDATE_H_ */

Loading…
Cancel
Save