mirror of
https://github.com/deltachat/deltachat-core.git
synced 2025-10-05 02:29:28 +02:00
Add subkey-binding packet to secret keys so that the correct subkey is selected for decryption.
This commit is contained in:
parent
e573b27b53
commit
b90a503325
4 changed files with 126 additions and 12 deletions
|
@ -86,6 +86,7 @@ unsigned pgp_check_hash_sig(pgp_hash_t *,
|
||||||
const pgp_pubkey_t *);
|
const pgp_pubkey_t *);
|
||||||
void pgp_sig_start_key_sig(pgp_create_sig_t *,
|
void pgp_sig_start_key_sig(pgp_create_sig_t *,
|
||||||
const pgp_pubkey_t *,
|
const pgp_pubkey_t *,
|
||||||
|
const pgp_pubkey_t * subkey, // parameter added by Delta Chat to allow subkey binding signatures, EDIT BY MR (bp)
|
||||||
const uint8_t *,
|
const uint8_t *,
|
||||||
pgp_sig_type_t);
|
pgp_sig_type_t);
|
||||||
void pgp_start_sig(pgp_create_sig_t *,
|
void pgp_start_sig(pgp_create_sig_t *,
|
||||||
|
|
|
@ -842,6 +842,7 @@ void print_packet_hex(const pgp_subpacket_t *pkt);
|
||||||
\param userid Self-signed User ID to add
|
\param userid Self-signed User ID to add
|
||||||
\return 1 if OK; else 0
|
\return 1 if OK; else 0
|
||||||
*/
|
*/
|
||||||
|
#if 0 //////
|
||||||
unsigned
|
unsigned
|
||||||
pgp_add_selfsigned_userid(pgp_key_t *skey, pgp_key_t *pkey, const uint8_t *userid, time_t key_expiry)
|
pgp_add_selfsigned_userid(pgp_key_t *skey, pgp_key_t *pkey, const uint8_t *userid, time_t key_expiry)
|
||||||
{
|
{
|
||||||
|
@ -862,7 +863,7 @@ pgp_add_selfsigned_userid(pgp_key_t *skey, pgp_key_t *pkey, const uint8_t *useri
|
||||||
pgp_add_key_expiration_time(sig, key_expiry);
|
pgp_add_key_expiration_time(sig, key_expiry);
|
||||||
pgp_add_issuer_keyid(sig, skey->pubkeyid);
|
pgp_add_issuer_keyid(sig, skey->pubkeyid);
|
||||||
pgp_add_primary_userid(sig, 1);
|
pgp_add_primary_userid(sig, 1);
|
||||||
pgp_add_key_flags(sig, PGP_KEYFLAG_SIGN_DATA|PGP_KEYFLAG_CERT_KEYS); // Edit for Autocrypt/Delta Chat: our primary key should be able to SIGN+CERTIFY (original was SIGN+ENC_COMM) (maybe we should create a copy of this functions to be future-save on netpgp-updates)
|
pgp_add_key_flags(sig, PGP_KEYFLAG_SIGN_DATA|PGP_KEYFLAG_ENC_COMM);
|
||||||
pgp_add_key_prefs(sig);
|
pgp_add_key_prefs(sig);
|
||||||
pgp_add_key_features(sig);
|
pgp_add_key_features(sig);
|
||||||
|
|
||||||
|
@ -887,6 +888,7 @@ pgp_add_selfsigned_userid(pgp_key_t *skey, pgp_key_t *pkey, const uint8_t *useri
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif //////
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
pgp_key_revoke(pgp_key_t *skey, pgp_key_t *pkey, uint8_t code, const char *reason)
|
pgp_key_revoke(pgp_key_t *skey, pgp_key_t *pkey, uint8_t code, const char *reason)
|
||||||
|
|
|
@ -629,6 +629,7 @@ start_sig_in_mem(pgp_create_sig_t *sig)
|
||||||
void
|
void
|
||||||
pgp_sig_start_key_sig(pgp_create_sig_t *sig,
|
pgp_sig_start_key_sig(pgp_create_sig_t *sig,
|
||||||
const pgp_pubkey_t *key,
|
const pgp_pubkey_t *key,
|
||||||
|
const pgp_pubkey_t *subkey, // added by Delta Chat to allow subkey binding signatures, EDIT BY MR (bp)
|
||||||
const uint8_t *id,
|
const uint8_t *id,
|
||||||
pgp_sig_type_t type)
|
pgp_sig_type_t type)
|
||||||
{
|
{
|
||||||
|
@ -643,9 +644,14 @@ pgp_sig_start_key_sig(pgp_create_sig_t *sig,
|
||||||
sig->sig.info.type = type;
|
sig->sig.info.type = type;
|
||||||
sig->hashlen = (unsigned)-1;
|
sig->hashlen = (unsigned)-1;
|
||||||
init_key_sig(&sig->hash, &sig->sig, key);
|
init_key_sig(&sig->hash, &sig->sig, key);
|
||||||
pgp_hash_add_int(&sig->hash, 0xb4, 1);
|
if( subkey ) {
|
||||||
pgp_hash_add_int(&sig->hash, (unsigned)strlen((const char *) id), 4);
|
hash_add_key(&sig->hash, subkey); // added by Delta Chat to allow subkey binding signatures, EDIT BY MR (bp)
|
||||||
sig->hash.add(&sig->hash, id, (unsigned)strlen((const char *) id));
|
}
|
||||||
|
if( id ) { // condition added by Delta Chat to allow subkey binding signatures, EDIT BY MR (bp)
|
||||||
|
pgp_hash_add_int(&sig->hash, 0xb4, 1);
|
||||||
|
pgp_hash_add_int(&sig->hash, (unsigned)strlen((const char *) id), 4);
|
||||||
|
sig->hash.add(&sig->hash, id, (unsigned)strlen((const char *) id));
|
||||||
|
}
|
||||||
start_sig_in_mem(sig);
|
start_sig_in_mem(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,87 @@ void mre2ee_driver_exit(mrmailbox_t* mailbox)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Key generatation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
static void add_selfsigned_userid(pgp_key_t *skey, pgp_key_t *pkey, const uint8_t *userid, time_t key_expiry)
|
||||||
|
{
|
||||||
|
/* close to pgp_add_selfsigned_userid() which, however, uses different key flags */
|
||||||
|
pgp_create_sig_t *sig;
|
||||||
|
pgp_subpacket_t sigpacket;
|
||||||
|
pgp_memory_t *mem_sig = NULL;
|
||||||
|
pgp_output_t *sigoutput = NULL;
|
||||||
|
|
||||||
|
/* create sig for this pkt */
|
||||||
|
sig = pgp_create_sig_new();
|
||||||
|
pgp_sig_start_key_sig(sig, &skey->key.seckey.pubkey, NULL, userid, PGP_CERT_POSITIVE);
|
||||||
|
|
||||||
|
pgp_add_creation_time(sig, time(NULL));
|
||||||
|
pgp_add_key_expiration_time(sig, key_expiry);
|
||||||
|
pgp_add_issuer_keyid(sig, skey->pubkeyid);
|
||||||
|
pgp_add_primary_userid(sig, 1);
|
||||||
|
pgp_add_key_flags(sig, PGP_KEYFLAG_SIGN_DATA|PGP_KEYFLAG_CERT_KEYS);
|
||||||
|
pgp_add_key_prefs(sig);
|
||||||
|
pgp_add_key_features(sig);
|
||||||
|
|
||||||
|
pgp_end_hashed_subpkts(sig);
|
||||||
|
|
||||||
|
pgp_setup_memory_write(&sigoutput, &mem_sig, 128);
|
||||||
|
pgp_write_sig(sigoutput, sig, &skey->key.seckey.pubkey, &skey->key.seckey);
|
||||||
|
|
||||||
|
/* add this packet to key */
|
||||||
|
sigpacket.length = pgp_mem_len(mem_sig);
|
||||||
|
sigpacket.raw = pgp_mem_data(mem_sig);
|
||||||
|
|
||||||
|
/* add user id and signature to key */
|
||||||
|
pgp_update_userid(skey, userid, &sigpacket, &sig->sig.info);
|
||||||
|
if(pkey) {
|
||||||
|
pgp_update_userid(pkey, userid, &sigpacket, &sig->sig.info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
pgp_create_sig_delete(sig);
|
||||||
|
pgp_output_delete(sigoutput);
|
||||||
|
pgp_memory_free(mem_sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void add_subkey_binding_structure(pgp_subkeysig_t* p, pgp_key_t* primarykey, pgp_key_t* subkey, pgp_key_t* seckey)
|
||||||
|
{
|
||||||
|
//pgp_subkeysig_t* p = &pubkey.subkeysigs[pubkey.subkeysigc++];
|
||||||
|
pgp_create_sig_t* sig;
|
||||||
|
pgp_output_t* sigoutput = NULL;
|
||||||
|
pgp_memory_t* mem_sig = NULL;
|
||||||
|
|
||||||
|
sig = pgp_create_sig_new();
|
||||||
|
pgp_sig_start_key_sig(sig, &primarykey->key.pubkey, &subkey->key.pubkey, NULL, PGP_SIG_SUBKEY);
|
||||||
|
|
||||||
|
pgp_add_creation_time(sig, time(NULL));
|
||||||
|
pgp_add_key_expiration_time(sig, 0);
|
||||||
|
pgp_add_issuer_keyid(sig, seckey->pubkeyid);
|
||||||
|
//pgp_add_primary_userid(sig, 1); // seems not be needed for "Subkey Binding Signature"
|
||||||
|
pgp_add_key_flags(sig, PGP_KEYFLAG_ENC_STORAGE|PGP_KEYFLAG_ENC_COMM);
|
||||||
|
pgp_add_key_prefs(sig); // algo/hash/compression preferences seems not to be required for subkeys, however, skipping this results in a bad structure
|
||||||
|
//pgp_add_key_features(sig); // will add 0x01 - modification detection, not needed for subkeys
|
||||||
|
|
||||||
|
pgp_end_hashed_subpkts(sig);
|
||||||
|
|
||||||
|
pgp_setup_memory_write(&sigoutput, &mem_sig, 128);
|
||||||
|
pgp_write_sig(sigoutput, sig, &seckey->key.seckey.pubkey, &seckey->key.seckey);
|
||||||
|
|
||||||
|
p->subkey = primarykey->subkeyc-1; /* index of subkey in array */
|
||||||
|
p->packet.length = mem_sig->length;
|
||||||
|
p->packet.raw = mem_sig->buf; mem_sig->buf = NULL; /* move ownership to packet */
|
||||||
|
copy_sig_info(&p->siginfo, &sig->sig.info); /* not sure, if this is okay, however, siginfo should be set up, otherwise we get "bad info-type" errors */
|
||||||
|
|
||||||
|
pgp_create_sig_delete(sig);
|
||||||
|
pgp_output_delete(sigoutput);
|
||||||
|
free(mem_sig); /* do not use pgp_memory_free() as this would also free mem_sig->buf which is owned by the packet */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t* ret_public_key, mrkey_t* ret_private_key)
|
int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t* ret_public_key, mrkey_t* ret_private_key)
|
||||||
{
|
{
|
||||||
int success = 0;
|
int success = 0;
|
||||||
|
@ -133,12 +214,15 @@ int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make a public key out of generated secret key */
|
|
||||||
|
/* Create public key
|
||||||
|
------------------------------------------------------------------------ */
|
||||||
|
|
||||||
pubkey.type = PGP_PTAG_CT_PUBLIC_KEY;
|
pubkey.type = PGP_PTAG_CT_PUBLIC_KEY;
|
||||||
pgp_pubkey_dup(&pubkey.key.pubkey, &seckey.key.pubkey);
|
pgp_pubkey_dup(&pubkey.key.pubkey, &seckey.key.pubkey);
|
||||||
memcpy(pubkey.pubkeyid, seckey.pubkeyid, PGP_KEY_ID_SIZE);
|
memcpy(pubkey.pubkeyid, seckey.pubkeyid, PGP_KEY_ID_SIZE);
|
||||||
pgp_fingerprint(&pubkey.pubkeyfpr, &seckey.key.pubkey, 0);
|
pgp_fingerprint(&pubkey.pubkeyfpr, &seckey.key.pubkey, 0);
|
||||||
pgp_add_selfsigned_userid(&seckey, &pubkey, (const uint8_t*)user_id, 0/*never expire*/);
|
add_selfsigned_userid(&seckey, &pubkey, (const uint8_t*)user_id, 0/*never expire*/);
|
||||||
|
|
||||||
/* add subkey to public key and sign it (cmp. pgp_update_subkey()) */
|
/* add subkey to public key and sign it (cmp. pgp_update_subkey()) */
|
||||||
EXPAND_ARRAY((&pubkey), subkey);
|
EXPAND_ARRAY((&pubkey), subkey);
|
||||||
|
@ -151,6 +235,8 @@ int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t
|
||||||
|
|
||||||
// add "0x18: Subkey Binding Signature" packet, PGP_SIG_SUBKEY, see also pgp_update_subkey()
|
// add "0x18: Subkey Binding Signature" packet, PGP_SIG_SUBKEY, see also pgp_update_subkey()
|
||||||
EXPAND_ARRAY((&pubkey), subkeysig);
|
EXPAND_ARRAY((&pubkey), subkeysig);
|
||||||
|
add_subkey_binding_structure(&pubkey.subkeysigs[pubkey.subkeysigc++], &pubkey, &subkey, &seckey);
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
pgp_subkeysig_t* p = &pubkey.subkeysigs[pubkey.subkeysigc++];
|
pgp_subkeysig_t* p = &pubkey.subkeysigs[pubkey.subkeysigc++];
|
||||||
pgp_create_sig_t* sig;
|
pgp_create_sig_t* sig;
|
||||||
|
@ -158,15 +244,15 @@ int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t
|
||||||
pgp_memory_t* mem_sig = NULL;
|
pgp_memory_t* mem_sig = NULL;
|
||||||
|
|
||||||
sig = pgp_create_sig_new();
|
sig = pgp_create_sig_new();
|
||||||
pgp_sig_start_key_sig(sig, &subkey.key.pubkey, user_id, PGP_SIG_SUBKEY);
|
pgp_sig_start_key_sig(sig, &pubkey.key.pubkey, &subkey.key.pubkey, NULL, PGP_SIG_SUBKEY);
|
||||||
|
|
||||||
pgp_add_creation_time(sig, time(NULL));
|
pgp_add_creation_time(sig, time(NULL));
|
||||||
pgp_add_key_expiration_time(sig, 0);
|
pgp_add_key_expiration_time(sig, 0);
|
||||||
pgp_add_issuer_keyid(sig, seckey.pubkeyid);
|
pgp_add_issuer_keyid(sig, seckey.pubkeyid);
|
||||||
//pgp_add_primary_userid(sig, 1); -- seems not be needed for "ubkey Binding Signature"
|
//pgp_add_primary_userid(sig, 1); // seems not be needed for "Subkey Binding Signature"
|
||||||
pgp_add_key_flags(sig, PGP_KEYFLAG_ENC_STORAGE|PGP_KEYFLAG_ENC_COMM);
|
pgp_add_key_flags(sig, PGP_KEYFLAG_ENC_STORAGE|PGP_KEYFLAG_ENC_COMM);
|
||||||
//pgp_add_key_prefs(sig); -- algo/hash/compression preferences seems not to be required for subkeys
|
pgp_add_key_prefs(sig); // algo/hash/compression preferences seems not to be required for subkeys, however, skipping this results in a bad structure
|
||||||
pgp_add_key_features(sig);
|
//pgp_add_key_features(sig); // will add 0x01 - modification detection, not needed for subkeys
|
||||||
|
|
||||||
pgp_end_hashed_subpkts(sig);
|
pgp_end_hashed_subpkts(sig);
|
||||||
|
|
||||||
|
@ -182,8 +268,12 @@ int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t
|
||||||
pgp_output_delete(sigoutput);
|
pgp_output_delete(sigoutput);
|
||||||
free(mem_sig); /* do not use pgp_memory_free() as this would also free mem_sig->buf which is owned by the packet */
|
free(mem_sig); /* do not use pgp_memory_free() as this would also free mem_sig->buf which is owned by the packet */
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Create secret key
|
||||||
|
------------------------------------------------------------------------ */
|
||||||
|
|
||||||
/* add subkey to private key */
|
|
||||||
EXPAND_ARRAY((&seckey), subkey);
|
EXPAND_ARRAY((&seckey), subkey);
|
||||||
{
|
{
|
||||||
pgp_subkey_t* p = &seckey.subkeys[seckey.subkeyc++];
|
pgp_subkey_t* p = &seckey.subkeys[seckey.subkeyc++];
|
||||||
|
@ -192,7 +282,12 @@ int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t
|
||||||
memcpy(p->id, subkeyid, PGP_KEY_ID_SIZE);
|
memcpy(p->id, subkeyid, PGP_KEY_ID_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return keys */
|
EXPAND_ARRAY((&seckey), subkeysig);
|
||||||
|
add_subkey_binding_structure(&seckey.subkeysigs[seckey.subkeysigc++], &seckey, &subkey, &seckey);
|
||||||
|
|
||||||
|
/* Done with key generation, write binary keys to memory
|
||||||
|
------------------------------------------------------------------------ */
|
||||||
|
|
||||||
pgp_writer_set_memory(pubout, pubmem);
|
pgp_writer_set_memory(pubout, pubmem);
|
||||||
if( !pgp_write_xfer_key(pubout, &pubkey, 0/*armored*/)
|
if( !pgp_write_xfer_key(pubout, &pubkey, 0/*armored*/)
|
||||||
|| pubmem->buf == NULL || pubmem->length <= 0 ) {
|
|| pubmem->buf == NULL || pubmem->length <= 0 ) {
|
||||||
|
@ -223,6 +318,11 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Check keys
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
int mre2ee_driver_is_valid_key(mrmailbox_t* mailbox, const mrkey_t* raw_key)
|
int mre2ee_driver_is_valid_key(mrmailbox_t* mailbox, const mrkey_t* raw_key)
|
||||||
{
|
{
|
||||||
int key_is_valid = 0;
|
int key_is_valid = 0;
|
||||||
|
@ -255,6 +355,11 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Encrypt/Decrypt
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
int mre2ee_driver_encrypt( mrmailbox_t* mailbox,
|
int mre2ee_driver_encrypt( mrmailbox_t* mailbox,
|
||||||
const void* plain, size_t plain_bytes,
|
const void* plain, size_t plain_bytes,
|
||||||
const mrkeyring_t* raw_keys, int use_armor,
|
const mrkeyring_t* raw_keys, int use_armor,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue