diff --git a/dist/src/lib/keyring.c b/dist/src/lib/keyring.c index bc383bb..a062da9 100644 --- a/dist/src/lib/keyring.c +++ b/dist/src/lib/keyring.c @@ -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; } diff --git a/dist/src/lib/keyring.h b/dist/src/lib/keyring.h index c40794f..9330a4d 100644 --- a/dist/src/lib/keyring.h +++ b/dist/src/lib/keyring.h @@ -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_ */ diff --git a/dist/src/lib/signature.c b/dist/src/lib/signature.c index 06cb600..ebb2c2d 100644 --- a/dist/src/lib/signature.c +++ b/dist/src/lib/signature.c @@ -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; } diff --git a/dist/src/lib/signature.h b/dist/src/lib/signature.h index 9e691dd..f8a4242 100644 --- a/dist/src/lib/signature.h +++ b/dist/src/lib/signature.h @@ -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 *); diff --git a/dist/src/lib/validate.c b/dist/src/lib/validate.c index 3779d88..fc85668 100644 --- a/dist/src/lib/validate.c +++ b/dist/src/lib/validate.c @@ -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); diff --git a/dist/src/lib/validate.h b/dist/src/lib/validate.h index e5b56b0..b608dc4 100644 --- a/dist/src/lib/validate.h +++ b/dist/src/lib/validate.h @@ -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_ */