Added pgp_key_revoke. Fixed unencrypted secret key export. Fixed unwanted free compromizing keydata when decypting session key (openssl-crypto).

master
Edouard Tisserant 8 years ago
parent 84dfa75cd3
commit fda602171a

@ -301,154 +301,156 @@ write_seckey_body(const pgp_seckey_t *key,
if (!write_pubkey_body(&key->pubkey, output)) {
return 0;
}
if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) {
(void) fprintf(stderr, "write_seckey_body: s2k usage\n");
return 0;
}
if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) {
return 0;
}
if (key->s2k_usage != PGP_S2KU_NONE) {
if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) {
(void) fprintf(stderr, "write_seckey_body: s2k usage\n");
return 0;
}
if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) {
return 0;
}
if (key->alg != PGP_SA_CAST5) {
(void) fprintf(stderr, "write_seckey_body: algorithm\n");
return 0;
}
if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
return 0;
}
if (key->alg != PGP_SA_CAST5) {
(void) fprintf(stderr, "write_seckey_body: algorithm\n");
return 0;
}
if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
return 0;
}
if (key->s2k_specifier != PGP_S2KS_SIMPLE &&
key->s2k_specifier != PGP_S2KS_SALTED) {
/* = 1 \todo could also be iterated-and-salted */
(void) fprintf(stderr, "write_seckey_body: s2k spec\n");
return 0;
}
if (!pgp_write_scalar(output, (unsigned)key->s2k_specifier, 1)) {
return 0;
}
if (!pgp_write_scalar(output, (unsigned)key->hash_alg, 1)) {
return 0;
}
if (key->s2k_specifier != PGP_S2KS_SIMPLE &&
key->s2k_specifier != PGP_S2KS_SALTED) {
/* = 1 \todo could also be iterated-and-salted */
(void) fprintf(stderr, "write_seckey_body: s2k spec\n");
return 0;
}
if (!pgp_write_scalar(output, (unsigned)key->s2k_specifier, 1)) {
return 0;
}
if (!pgp_write_scalar(output, (unsigned)key->hash_alg, 1)) {
return 0;
}
switch (key->s2k_specifier) {
case PGP_S2KS_SIMPLE:
/* nothing more to do */
break;
switch (key->s2k_specifier) {
case PGP_S2KS_SIMPLE:
/* nothing more to do */
break;
case PGP_S2KS_SALTED:
/* 8-octet salt value */
pgp_random(__UNCONST(&key->salt[0]), PGP_SALT_SIZE);
if (!pgp_write(output, key->salt, PGP_SALT_SIZE)) {
return 0;
}
break;
case PGP_S2KS_SALTED:
/* 8-octet salt value */
pgp_random(__UNCONST(&key->salt[0]), PGP_SALT_SIZE);
if (!pgp_write(output, key->salt, PGP_SALT_SIZE)) {
return 0;
}
break;
/*
* \todo case PGP_S2KS_ITERATED_AND_SALTED: // 8-octet salt
* value // 1-octet count break;
*/
/*
* \todo case PGP_S2KS_ITERATED_AND_SALTED: // 8-octet salt
* value // 1-octet count break;
*/
default:
(void) fprintf(stderr,
"invalid/unsupported s2k specifier %d\n",
key->s2k_specifier);
return 0;
}
default:
(void) fprintf(stderr,
"invalid/unsupported s2k specifier %d\n",
key->s2k_specifier);
return 0;
}
if (!pgp_write(output, &key->iv[0], pgp_block_size(key->alg))) {
return 0;
}
if (!pgp_write(output, &key->iv[0], pgp_block_size(key->alg))) {
return 0;
}
/*
* create the session key for encrypting the algorithm-specific
* fields
*/
/*
* create the session key for encrypting the algorithm-specific
* fields
*/
switch (key->s2k_specifier) {
case PGP_S2KS_SIMPLE:
case PGP_S2KS_SALTED:
/* RFC4880: section 3.7.1.1 and 3.7.1.2 */
for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) {
unsigned hashsize;
unsigned j;
unsigned needed;
unsigned size;
uint8_t zero = 0;
/* Hard-coded SHA1 for session key */
pgp_hash_any(&hash, PGP_HASH_SHA1);
hashsize = pgp_hash_size(key->hash_alg);
needed = CAST_KEY_LENGTH - done;
size = MIN(needed, hashsize);
if ((hashed = calloc(1, hashsize)) == NULL) {
(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
return 0;
}
if (!hash.init(&hash)) {
(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
return 0;
}
switch (key->s2k_specifier) {
case PGP_S2KS_SIMPLE:
case PGP_S2KS_SALTED:
/* RFC4880: section 3.7.1.1 and 3.7.1.2 */
for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) {
unsigned hashsize;
unsigned j;
unsigned needed;
unsigned size;
uint8_t zero = 0;
/* Hard-coded SHA1 for session key */
pgp_hash_any(&hash, PGP_HASH_SHA1);
hashsize = pgp_hash_size(key->hash_alg);
needed = CAST_KEY_LENGTH - done;
size = MIN(needed, hashsize);
if ((hashed = calloc(1, hashsize)) == NULL) {
(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
return 0;
}
if (!hash.init(&hash)) {
(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
return 0;
}
/* preload if iterating */
for (j = 0; j < i; j++) {
/*
* Coverity shows a DEADCODE error on this
* line. This is expected since the hardcoded
* use of SHA1 and CAST5 means that it will
* not used. This will change however when
* other algorithms are supported.
*/
hash.add(&hash, &zero, 1);
}
/* preload if iterating */
for (j = 0; j < i; j++) {
/*
* Coverity shows a DEADCODE error on this
* line. This is expected since the hardcoded
* use of SHA1 and CAST5 means that it will
* not used. This will change however when
* other algorithms are supported.
*/
hash.add(&hash, &zero, 1);
}
if (key->s2k_specifier == PGP_S2KS_SALTED) {
hash.add(&hash, key->salt, PGP_SALT_SIZE);
}
hash.add(&hash, passphrase, (unsigned)pplen);
hash.finish(&hash, hashed);
/*
* if more in hash than is needed by session key, use
* the leftmost octets
*/
(void) memcpy(&sesskey[i * hashsize],
hashed, (unsigned)size);
done += (unsigned)size;
if (done > CAST_KEY_LENGTH) {
(void) fprintf(stderr,
"write_seckey_body: short add\n");
return 0;
}
}
if (key->s2k_specifier == PGP_S2KS_SALTED) {
hash.add(&hash, key->salt, PGP_SALT_SIZE);
}
hash.add(&hash, passphrase, (unsigned)pplen);
hash.finish(&hash, hashed);
/*
* if more in hash than is needed by session key, use
* the leftmost octets
*/
(void) memcpy(&sesskey[i * hashsize],
hashed, (unsigned)size);
done += (unsigned)size;
if (done > CAST_KEY_LENGTH) {
(void) fprintf(stderr,
"write_seckey_body: short add\n");
return 0;
}
}
break;
break;
/*
* \todo case PGP_S2KS_ITERATED_AND_SALTED: * 8-octet salt
* value * 1-octet count break;
*/
/*
* \todo case PGP_S2KS_ITERATED_AND_SALTED: * 8-octet salt
* value * 1-octet count break;
*/
default:
(void) fprintf(stderr,
"invalid/unsupported s2k specifier %d\n",
key->s2k_specifier);
return 0;
}
default:
(void) fprintf(stderr,
"invalid/unsupported s2k specifier %d\n",
key->s2k_specifier);
return 0;
}
/* use this session key to encrypt */
/* use this session key to encrypt */
pgp_crypt_any(&crypted, key->alg);
crypted.set_iv(&crypted, key->iv);
crypted.set_crypt_key(&crypted, sesskey);
pgp_encrypt_init(&crypted);
pgp_crypt_any(&crypted, key->alg);
crypted.set_iv(&crypted, key->iv);
crypted.set_crypt_key(&crypted, sesskey);
pgp_encrypt_init(&crypted);
if (pgp_get_debug_level(__FILE__)) {
hexdump(stderr, "writing: iv=", key->iv, pgp_block_size(key->alg));
hexdump(stderr, "key= ", sesskey, CAST_KEY_LENGTH);
(void) fprintf(stderr, "\nturning encryption on...\n");
}
pgp_push_enc_crypt(output, &crypted);
if (pgp_get_debug_level(__FILE__)) {
hexdump(stderr, "writing: iv=", key->iv, pgp_block_size(key->alg));
hexdump(stderr, "key= ", sesskey, CAST_KEY_LENGTH);
(void) fprintf(stderr, "\nturning encryption on...\n");
}
pgp_push_enc_crypt(output, &crypted);
}
switch (key->pubkey.alg) {
case PGP_PKA_RSA:
@ -477,7 +479,9 @@ write_seckey_body(const pgp_seckey_t *key,
return 0;
}
pgp_writer_pop(output);
if (key->s2k_usage != PGP_S2KU_NONE) {
pgp_writer_pop(output);
}
return 1;
}

@ -701,7 +701,7 @@ pgp_decrypt_and_validate_buf(pgp_io_t *io,
validation.mem = pgp_memory_new();
pgp_memory_init(validation.mem, 128);
/* setup for writing decrypted contents to given output file */
/* setup for writing decrypted contents */
pgp_setup_memory_write(&stream->cbinfo.output, &outmem, insize);
/* setup keyring and passphrase callback */

@ -862,6 +862,40 @@ pgp_add_selfsigned_userid(pgp_key_t *key, uint8_t *userid)
return 1;
}
unsigned
pgp_key_revoke(pgp_key_t *key, uint8_t code, const char *reason)
{
pgp_create_sig_t *sig;
pgp_subpacket_t sigpacket;
pgp_memory_t *mem_sig = NULL;
pgp_output_t *sigoutput = NULL;
sig = pgp_create_sig_new();
pgp_sig_start_key_rev(
sig, &key->key.seckey.pubkey,
PGP_SIG_REV_KEY);
pgp_add_time(sig, (int64_t)time(NULL), "birth");
pgp_add_issuer_keyid(sig, key->pubkeyid);
pgp_add_revocation_reason(sig, code, reason);
pgp_end_hashed_subpkts(sig);
pgp_setup_memory_write(&sigoutput, &mem_sig, 128);
pgp_write_sig(sigoutput, sig, &key->key.seckey.pubkey, &key->key.seckey);
sigpacket.length = pgp_mem_len(mem_sig);
sigpacket.raw = pgp_mem_data(mem_sig);
pgp_add_directsig(key, &sigpacket, &sig->sig.info);
/* cleanup */
pgp_create_sig_delete(sig);
pgp_output_delete(sigoutput);
pgp_memory_free(mem_sig);
return 1;
}
/**
\ingroup Core_Keys
\brief Initialise pgp_key_t

@ -221,4 +221,7 @@ pgp_key_find_uid_cond(
const pgp_key_rating_t pgp_key_get_rating(const pgp_key_t *key);
unsigned
pgp_key_revoke(pgp_key_t *key, uint8_t code, const char *reason);
#endif /* KEYRING_H_ */

@ -601,7 +601,7 @@ pgp_rsa_private_decrypt(uint8_t *out,
ERR_error_string(err, &errbuf[0]);
(void) fprintf(stderr, "openssl error : %s\n", errbuf);
}
keypair->n = keypair->d = keypair->p = keypair->q = NULL;
keypair->n = keypair->e = keypair->d = keypair->p = keypair->q = NULL;
RSA_free(keypair);
return n;
@ -712,10 +712,13 @@ pgp_rsa_generate_keypair(pgp_key_t *keydata,
seckey->pubkey.alg = PGP_PKA_RSA;
seckey->pubkey.key.rsa.n = BN_dup(rsa->n);
printf("RSA N %p %d\n", seckey->pubkey.key.rsa.n, BN_num_bits(seckey->pubkey.key.rsa.n));
seckey->pubkey.key.rsa.e = BN_dup(rsa->e);
printf("RSA E %p %d\n", seckey->pubkey.key.rsa.e, BN_num_bits(seckey->pubkey.key.rsa.e));
seckey->s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED;
seckey->s2k_specifier = PGP_S2KS_SALTED;
/* seckey->s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED; */
seckey->s2k_usage = PGP_S2KU_NONE;
/* seckey->s2k_specifier = PGP_S2KS_SALTED;*/
/* seckey->s2k_specifier=PGP_S2KS_SIMPLE; */
if ((seckey->hash_alg = pgp_str_to_hash_alg(hashalg)) == PGP_HASH_UNKNOWN) {
seckey->hash_alg = PGP_HASH_SHA1;
@ -775,19 +778,6 @@ pgp_rsa_generate_keypair(pgp_key_t *keydata,
/* should now have checksum in seckey struct */
/* add seckey raw packet */
output = NULL;
mem = NULL;
pgp_setup_memory_write(&output, &mem, 128);
if (!pgp_write_struct_seckey(seckey, passphrase, pplen, output)) {
return 0;
}
pgp_writer_close(output);
pgp_teardown_memory_write(output, mem);
/* test */
if (pgp_get_debug_level(__FILE__)) {
test_seckey(seckey);

@ -645,6 +645,22 @@ pgp_sig_start_key_sig(pgp_create_sig_t *sig,
start_sig_in_mem(sig);
}
void
pgp_sig_start_key_rev(pgp_create_sig_t *sig,
const pgp_pubkey_t *key,
pgp_sig_type_t type)
{
sig->output = pgp_output_new();
sig->sig.info.version = PGP_V4;
sig->sig.info.hash_alg = PGP_HASH_SHA1;
sig->sig.info.key_alg = key->alg;
sig->sig.info.type = type;
sig->hashlen = (unsigned)-1;
init_key_sig(&sig->hash, &sig->sig, key);
start_sig_in_mem(sig);
}
/**
* \ingroup Core_Signature
*
@ -873,6 +889,19 @@ pgp_add_primary_userid(pgp_create_sig_t *sig, unsigned primary)
pgp_write_scalar(sig->output, primary, 1);
}
unsigned
pgp_add_revocation_reason(
pgp_create_sig_t *sig,
uint8_t code, const char *reason)
{
size_t rlen = strlen(reason);
return pgp_write_ss_header(
sig->output, rlen + 1,
PGP_PTAG_SS_REVOCATION_REASON) &&
pgp_write_scalar(sig->output, code, 1) &&
pgp_write(sig->output, reason, rlen);
}
/**
* \ingroup Core_Signature
*

@ -172,4 +172,14 @@ struct pgp_create_sig_t {
unsigned unhashoff;
};
void
pgp_sig_start_key_rev(pgp_create_sig_t *sig,
const pgp_pubkey_t *key,
pgp_sig_type_t type);
unsigned
pgp_add_revocation_reason(
pgp_create_sig_t *sig,
uint8_t code, const char *reason);
#endif /* SIGNATURE_H_ */

Loading…
Cancel
Save