void pgp_build_pubkey(pgp_memory_t *out, const pgp_pubkey_t *key, unsigned make_packet) { pgp_output_t *output; output = pgp_output_new(); pgp_memory_init(out, 128); pgp_writer_set_memory(output, out); write_pubkey_body(key, output); if (make_packet) { pgp_memory_make_packet(out, PGP_PTAG_CT_PUBLIC_KEY); } pgp_output_delete(output); }
int dc_pgp_split_key(dc_context_t* context, const dc_key_t* private_in, dc_key_t* ret_public_key) { int success = 0; pgp_keyring_t* public_keys = calloc(1, sizeof(pgp_keyring_t)); pgp_keyring_t* private_keys = calloc(1, sizeof(pgp_keyring_t)); pgp_memory_t* keysmem = pgp_memory_new(); pgp_memory_t* pubmem = pgp_memory_new(); pgp_output_t* pubout = pgp_output_new(); if (context==NULL || private_in==NULL || ret_public_key==NULL || public_keys==NULL || private_keys==NULL || keysmem==NULL || pubmem==NULL || pubout==NULL) { goto cleanup; } pgp_memory_add(keysmem, private_in->binary, private_in->bytes); pgp_filter_keys_from_mem(&s_io, public_keys, private_keys, NULL, 0, keysmem); if (private_in->type!=DC_KEY_PRIVATE || private_keys->keyc <= 0) { dc_log_warning(context, 0, "Split key: Given key is no private key."); goto cleanup; } if (public_keys->keyc <= 0) { dc_log_warning(context, 0, "Split key: Given key does not contain a public key."); goto cleanup; } pgp_writer_set_memory(pubout, pubmem); if (!pgp_write_xfer_key(pubout, &public_keys->keys[0], 0/*armored*/) || pubmem->buf==NULL || pubmem->length <= 0) { goto cleanup; } dc_key_set_from_binary(ret_public_key, pubmem->buf, pubmem->length, DC_KEY_PUBLIC); success = 1; cleanup: if (pubout) { pgp_output_delete(pubout); } if (pubmem) { pgp_memory_free(pubmem); } if (keysmem) { pgp_memory_free(keysmem); } if (public_keys) { pgp_keyring_purge(public_keys); free(public_keys); } /*pgp_keyring_free() frees the content, not the pointer itself*/ if (private_keys) { pgp_keyring_purge(private_keys); free(private_keys); } return success; }
static void start_sig_in_mem(pgp_create_sig_t *sig) { /* since this has subpackets and stuff, we have to buffer the whole */ /* thing to get counts before writing. */ sig->mem = pgp_memory_new(); pgp_memory_init(sig->mem, 100); pgp_writer_set_memory(sig->output, sig->mem); /* write nearly up to the first subpacket */ pgp_write_scalar(sig->output, (unsigned)sig->sig.info.version, 1); pgp_write_scalar(sig->output, (unsigned)sig->sig.info.type, 1); pgp_write_scalar(sig->output, (unsigned)sig->sig.info.key_alg, 1); pgp_write_scalar(sig->output, (unsigned)sig->sig.info.hash_alg, 1); /* dummy hashed subpacket count */ sig->hashoff = (unsigned)pgp_mem_len(sig->mem); pgp_write_scalar(sig->output, 0, 2); }
int dc_pgp_create_keypair(dc_context_t* context, const char* addr, dc_key_t* ret_public_key, dc_key_t* ret_private_key) { int success = 0; pgp_key_t seckey; pgp_key_t pubkey; pgp_key_t subkey; uint8_t subkeyid[PGP_KEY_ID_SIZE]; uint8_t* user_id = NULL; pgp_memory_t* pubmem = pgp_memory_new(); pgp_memory_t* secmem = pgp_memory_new(); pgp_output_t* pubout = pgp_output_new(); pgp_output_t* secout = pgp_output_new(); memset(&seckey, 0, sizeof(pgp_key_t)); memset(&pubkey, 0, sizeof(pgp_key_t)); memset(&subkey, 0, sizeof(pgp_key_t)); if (context==NULL || addr==NULL || ret_public_key==NULL || ret_private_key==NULL || pubmem==NULL || secmem==NULL || pubout==NULL || secout==NULL) { goto cleanup; } /* Generate User ID. By convention, this is the e-mail-address in angle brackets. As the user-id is only decorative in Autocrypt and not needed for Delta Chat, so we _could_ just use sth. that looks like an e-mail-address. This would protect the user's privacy if someone else uploads the keys to keyservers. However, as eg. Enigmail displayes the user-id in "Good signature from <user-id>, for now, we decided to leave the address in the user-id */ #if 0 user_id = (uint8_t*)dc_mprintf("<%08X@%08X.org>", (int)random(), (int)random()); #else user_id = (uint8_t*)dc_mprintf("<%s>", addr); #endif /* generate two keypairs */ if (!pgp_rsa_generate_keypair(&seckey, DC_KEYGEN_BITS, DC_KEYGEN_E, NULL, NULL, NULL, 0) || !pgp_rsa_generate_keypair(&subkey, DC_KEYGEN_BITS, DC_KEYGEN_E, NULL, NULL, NULL, 0)) { goto cleanup; } /* Create public key, bind public subkey to public key ------------------------------------------------------------------------ */ pubkey.type = PGP_PTAG_CT_PUBLIC_KEY; pgp_pubkey_dup(&pubkey.key.pubkey, &seckey.key.pubkey); memcpy(pubkey.pubkeyid, seckey.pubkeyid, PGP_KEY_ID_SIZE); pgp_fingerprint(&pubkey.pubkeyfpr, &seckey.key.pubkey, 0); add_selfsigned_userid(&seckey, &pubkey, (const uint8_t*)user_id, 0/*never expire*/); EXPAND_ARRAY((&pubkey), subkey); { pgp_subkey_t* p = &pubkey.subkeys[pubkey.subkeyc++]; pgp_pubkey_dup(&p->key.pubkey, &subkey.key.pubkey); pgp_keyid(subkeyid, PGP_KEY_ID_SIZE, &pubkey.key.pubkey, PGP_HASH_SHA1); memcpy(p->id, subkeyid, PGP_KEY_ID_SIZE); } EXPAND_ARRAY((&pubkey), subkeysig); add_subkey_binding_signature(&pubkey.subkeysigs[pubkey.subkeysigc++], &pubkey, &subkey, &seckey); /* Create secret key, bind secret subkey to secret key ------------------------------------------------------------------------ */ EXPAND_ARRAY((&seckey), subkey); { pgp_subkey_t* p = &seckey.subkeys[seckey.subkeyc++]; pgp_seckey_dup(&p->key.seckey, &subkey.key.seckey); pgp_keyid(subkeyid, PGP_KEY_ID_SIZE, &seckey.key.pubkey, PGP_HASH_SHA1); memcpy(p->id, subkeyid, PGP_KEY_ID_SIZE); } EXPAND_ARRAY((&seckey), subkeysig); add_subkey_binding_signature(&seckey.subkeysigs[seckey.subkeysigc++], &seckey, &subkey, &seckey); /* Done with key generation, write binary keys to memory ------------------------------------------------------------------------ */ pgp_writer_set_memory(pubout, pubmem); if (!pgp_write_xfer_key(pubout, &pubkey, 0/*armored*/) || pubmem->buf==NULL || pubmem->length <= 0) { goto cleanup; } pgp_writer_set_memory(secout, secmem); if (!pgp_write_xfer_key(secout, &seckey, 0/*armored*/) || secmem->buf==NULL || secmem->length <= 0) { goto cleanup; } dc_key_set_from_binary(ret_public_key, pubmem->buf, pubmem->length, DC_KEY_PUBLIC); dc_key_set_from_binary(ret_private_key, secmem->buf, secmem->length, DC_KEY_PRIVATE); success = 1; cleanup: if (pubout) { pgp_output_delete(pubout); } if (secout) { pgp_output_delete(secout); } if (pubmem) { pgp_memory_free(pubmem); } if (secmem) { pgp_memory_free(secmem); } pgp_key_free(&seckey); /* not: pgp_keydata_free() which will also free the pointer itself (we created it on the stack) */ pgp_key_free(&pubkey); pgp_key_free(&subkey); free(user_id); return success; }