|
|
@ -564,13 +564,17 @@ pgp_rsa_private_check(const pgp_seckey_t *seckey) |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
int pgp_dsa_private_check(const pgp_dsa_seckey_t *secdsa) |
|
|
|
int pgp_eddsa_private_check(const pgp_seckey_t *seckey) |
|
|
|
{ |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
int pgp_dsa_private_check(const pgp_seckey_t *seckey) |
|
|
|
{ |
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int pgp_elgamal_private_check(const pgp_elgamal_seckey_t *seckey) |
|
|
|
int pgp_elgamal_private_check(const pgp_seckey_t *seckey) |
|
|
|
{ |
|
|
|
return 1; |
|
|
|
} |
|
|
@ -784,30 +788,10 @@ pgp_rsa_generate_keypair(pgp_key_t *keydata, |
|
|
|
|
|
|
|
pgp_push_checksum_writer(output, seckey); |
|
|
|
|
|
|
|
switch (seckey->pubkey.alg) { |
|
|
|
case PGP_PKA_DSA: |
|
|
|
return pgp_write_mpi(output, seckey->key.dsa.x); |
|
|
|
case PGP_PKA_RSA: |
|
|
|
case PGP_PKA_RSA_ENCRYPT_ONLY: |
|
|
|
case PGP_PKA_RSA_SIGN_ONLY: |
|
|
|
if (!pgp_write_mpi(output, seckey->key.rsa.d) || |
|
|
|
!pgp_write_mpi(output, seckey->key.rsa.p) || |
|
|
|
!pgp_write_mpi(output, seckey->key.rsa.q) || |
|
|
|
!pgp_write_mpi(output, seckey->key.rsa.u)) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
break; |
|
|
|
case PGP_PKA_ELGAMAL: |
|
|
|
return pgp_write_mpi(output, seckey->key.elgamal.x); |
|
|
|
|
|
|
|
case PGP_PKA_EDDSA: |
|
|
|
case PGP_PKA_ECDH: |
|
|
|
// TODO |
|
|
|
printf("%s:%d, %s: Elliptic curves pub(%d)\n",__FILE__,__LINE__,__FUNCTION__,seckey->pubkey.alg); |
|
|
|
return 0; |
|
|
|
|
|
|
|
default: |
|
|
|
(void) fprintf(stderr, "Bad seckey->pubkey.alg\n"); |
|
|
|
if (!pgp_write_mpi(output, seckey->key.rsa.d) || |
|
|
|
!pgp_write_mpi(output, seckey->key.rsa.p) || |
|
|
|
!pgp_write_mpi(output, seckey->key.rsa.q) || |
|
|
|
!pgp_write_mpi(output, seckey->key.rsa.u)) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
@ -825,7 +809,382 @@ pgp_rsa_generate_keypair(pgp_key_t *keydata, |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
pgp_dsa_sig_t * |
|
|
|
/** |
|
|
|
\ingroup HighLevel_KeyGenerate |
|
|
|
\brief Generates an DSA keypair |
|
|
|
\param numbits Modulus size |
|
|
|
\param e Public Exponent |
|
|
|
\param keydata Pointer to keydata struct to hold new key |
|
|
|
\return 1 if key generated successfully; otherwise 0 |
|
|
|
\note It is the caller's responsibility to call pgp_keydata_free(keydata) |
|
|
|
*/ |
|
|
|
unsigned |
|
|
|
pgp_dsa_generate_keypair(pgp_key_t *keydata, |
|
|
|
const char *hashalg, |
|
|
|
const char *cipher, |
|
|
|
const uint8_t *passphrase, |
|
|
|
const size_t pplen) |
|
|
|
{ |
|
|
|
pgp_seckey_t *seckey; |
|
|
|
DSA *dsa; |
|
|
|
BN_CTX *ctx; |
|
|
|
pgp_output_t *output; |
|
|
|
pgp_memory_t *mem; |
|
|
|
int res; |
|
|
|
|
|
|
|
ctx = BN_CTX_new(); |
|
|
|
pgp_keydata_init(keydata, PGP_PTAG_CT_SECRET_KEY); |
|
|
|
seckey = pgp_get_writable_seckey(keydata); |
|
|
|
|
|
|
|
/* generate the key pair */ |
|
|
|
dsa = DSA_new(); |
|
|
|
res = DSA_generate_key(dsa); |
|
|
|
|
|
|
|
if (!res){ |
|
|
|
DSA_free(dsa); |
|
|
|
return 0; |
|
|
|
}; |
|
|
|
|
|
|
|
/* populate pgp key from ssl key */ |
|
|
|
seckey->pubkey.version = PGP_V4; |
|
|
|
seckey->pubkey.birthtime = time(NULL); |
|
|
|
seckey->pubkey.days_valid = 0; |
|
|
|
seckey->pubkey.alg = PGP_PKA_DSA; |
|
|
|
|
|
|
|
seckey->pubkey.key.dsa.p = (BIGNUM *)DSA_get0_p(dsa); |
|
|
|
seckey->pubkey.key.dsa.q = (BIGNUM *)DSA_get0_q(dsa); |
|
|
|
seckey->pubkey.key.dsa.g = (BIGNUM *)DSA_get0_g(dsa); |
|
|
|
seckey->pubkey.key.dsa.y = (BIGNUM *)DSA_get0_pub_key(dsa); |
|
|
|
|
|
|
|
/* 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; |
|
|
|
} |
|
|
|
seckey->alg = pgp_str_to_cipher(cipher); |
|
|
|
seckey->octetc = 0; |
|
|
|
seckey->checksum = 0; |
|
|
|
|
|
|
|
seckey->key.dsa.x = (BIGNUM *)DSA_get0_priv_key(dsa); |
|
|
|
|
|
|
|
BN_CTX_free(ctx); |
|
|
|
|
|
|
|
DSA_free(dsa); |
|
|
|
|
|
|
|
pgp_keyid(keydata->pubkeyid, PGP_KEY_ID_SIZE, &keydata->key.seckey.pubkey, seckey->hash_alg); |
|
|
|
pgp_fingerprint(&keydata->pubkeyfpr, &keydata->key.seckey.pubkey, seckey->hash_alg); |
|
|
|
|
|
|
|
/* Generate checksum */ |
|
|
|
|
|
|
|
output = NULL; |
|
|
|
mem = NULL; |
|
|
|
|
|
|
|
pgp_setup_memory_write(&output, &mem, 128); |
|
|
|
|
|
|
|
pgp_push_checksum_writer(output, seckey); |
|
|
|
|
|
|
|
if(!pgp_write_mpi(output, seckey->key.dsa.x)) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* close rather than pop, since its the only one on the stack */ |
|
|
|
pgp_writer_close(output); |
|
|
|
pgp_teardown_memory_write(output, mem); |
|
|
|
|
|
|
|
/* should now have checksum in seckey struct */ |
|
|
|
|
|
|
|
/* test */ |
|
|
|
if (pgp_get_debug_level(__FILE__)) { |
|
|
|
pgp_dsa_private_check(seckey); |
|
|
|
} |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
\ingroup HighLevel_KeyGenerate |
|
|
|
\brief Generates an ElGamal keypair |
|
|
|
\param numbits Modulus size |
|
|
|
\param e Public Exponent |
|
|
|
\param keydata Pointer to keydata struct to hold new key |
|
|
|
\return 1 if key generated successfully; otherwise 0 |
|
|
|
\note It is the caller's responsibility to call pgp_keydata_free(keydata) |
|
|
|
*/ |
|
|
|
unsigned |
|
|
|
pgp_elgamal_generate_keypair(pgp_key_t *keydata, |
|
|
|
const int numbits, |
|
|
|
const unsigned long e, |
|
|
|
const char *hashalg, |
|
|
|
const char *cipher, |
|
|
|
const uint8_t *passphrase, |
|
|
|
const size_t pplen) |
|
|
|
{ |
|
|
|
pgp_seckey_t *seckey; |
|
|
|
DH *dh; |
|
|
|
BN_CTX *ctx; |
|
|
|
pgp_output_t *output; |
|
|
|
pgp_memory_t *mem; |
|
|
|
int res; |
|
|
|
|
|
|
|
ctx = BN_CTX_new(); |
|
|
|
pgp_keydata_init(keydata, PGP_PTAG_CT_SECRET_KEY); |
|
|
|
seckey = pgp_get_writable_seckey(keydata); |
|
|
|
|
|
|
|
/* generate the key pair */ |
|
|
|
dh = DH_new(); |
|
|
|
res = DH_generate_key(dh); |
|
|
|
|
|
|
|
if (!res){ |
|
|
|
DH_free(dh); |
|
|
|
return 0; |
|
|
|
}; |
|
|
|
|
|
|
|
/* populate pgp key from ssl key */ |
|
|
|
seckey->pubkey.version = PGP_V4; |
|
|
|
seckey->pubkey.birthtime = time(NULL); |
|
|
|
seckey->pubkey.days_valid = 0; |
|
|
|
seckey->pubkey.alg = PGP_PKA_ELGAMAL; |
|
|
|
|
|
|
|
seckey->pubkey.key.elgamal.p = (BIGNUM *)DH_get0_p(dh); |
|
|
|
seckey->pubkey.key.elgamal.g = (BIGNUM *)DH_get0_g(dh); |
|
|
|
seckey->pubkey.key.elgamal.y = (BIGNUM *)DH_get0_pub_key(dh); |
|
|
|
|
|
|
|
/* 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; |
|
|
|
} |
|
|
|
seckey->alg = pgp_str_to_cipher(cipher); |
|
|
|
seckey->octetc = 0; |
|
|
|
seckey->checksum = 0; |
|
|
|
|
|
|
|
seckey->key.elgamal.x = (BIGNUM *)DH_get0_priv_key(dh); |
|
|
|
BN_CTX_free(ctx); |
|
|
|
DH_free(dh); |
|
|
|
|
|
|
|
pgp_keyid(keydata->pubkeyid, PGP_KEY_ID_SIZE, &keydata->key.seckey.pubkey, seckey->hash_alg); |
|
|
|
pgp_fingerprint(&keydata->pubkeyfpr, &keydata->key.seckey.pubkey, seckey->hash_alg); |
|
|
|
|
|
|
|
/* Generate checksum */ |
|
|
|
|
|
|
|
output = NULL; |
|
|
|
mem = NULL; |
|
|
|
|
|
|
|
pgp_setup_memory_write(&output, &mem, 128); |
|
|
|
|
|
|
|
pgp_push_checksum_writer(output, seckey); |
|
|
|
|
|
|
|
if(! pgp_write_mpi(output, seckey->key.elgamal.x) ) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* close rather than pop, since its the only one on the stack */ |
|
|
|
pgp_writer_close(output); |
|
|
|
pgp_teardown_memory_write(output, mem); |
|
|
|
|
|
|
|
/* should now have checksum in seckey struct */ |
|
|
|
|
|
|
|
/* test */ |
|
|
|
if (pgp_get_debug_level(__FILE__)) { |
|
|
|
pgp_elgamal_private_check(seckey); |
|
|
|
} |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
\ingroup HighLevel_KeyGenerate |
|
|
|
\brief Generates an ECDH keypair |
|
|
|
\param numbits Modulus size |
|
|
|
\param keydata Pointer to keydata struct to hold new key |
|
|
|
\return 1 if key generated successfully; otherwise 0 |
|
|
|
\note It is the caller's responsibility to call pgp_keydata_free(keydata) |
|
|
|
\RFC: https://datatracker.ietf.org/doc/html/rfc6637 |
|
|
|
*/ |
|
|
|
unsigned |
|
|
|
pgp_ecdh_generate_keypair(pgp_key_t *keydata, |
|
|
|
const int numbits, |
|
|
|
const char *hashalg, |
|
|
|
const char *cipher, |
|
|
|
const uint8_t *passphrase, |
|
|
|
const size_t pplen) |
|
|
|
{ |
|
|
|
pgp_seckey_t *seckey; |
|
|
|
DH *dh; |
|
|
|
BN_CTX *ctx; |
|
|
|
pgp_output_t *output; |
|
|
|
pgp_memory_t *mem; |
|
|
|
int res; |
|
|
|
|
|
|
|
ctx = BN_CTX_new(); |
|
|
|
pgp_keydata_init(keydata, PGP_PTAG_CT_SECRET_KEY); |
|
|
|
seckey = pgp_get_writable_seckey(keydata); |
|
|
|
|
|
|
|
/* generate the key pair */ |
|
|
|
dh = DH_new(); |
|
|
|
res = DH_generate_key(dh); |
|
|
|
|
|
|
|
if (!res){ |
|
|
|
DH_free(dh); |
|
|
|
return 0; |
|
|
|
}; |
|
|
|
|
|
|
|
/* populate pgp key from ssl key */ |
|
|
|
seckey->pubkey.version = PGP_V4; |
|
|
|
seckey->pubkey.birthtime = time(NULL); |
|
|
|
seckey->pubkey.days_valid = 0; |
|
|
|
seckey->pubkey.alg = PGP_PKA_ECDH; |
|
|
|
|
|
|
|
seckey->pubkey.key.elgamal.p = (BIGNUM *)DH_get0_p(dh); |
|
|
|
seckey->pubkey.key.elgamal.g = (BIGNUM *)DH_get0_g(dh); |
|
|
|
seckey->pubkey.key.elgamal.y = (BIGNUM *)DH_get0_pub_key(dh); |
|
|
|
|
|
|
|
/* 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; |
|
|
|
} |
|
|
|
seckey->alg = pgp_str_to_cipher(cipher); |
|
|
|
seckey->octetc = 0; |
|
|
|
seckey->checksum = 0; |
|
|
|
|
|
|
|
seckey->key.elgamal.x = (BIGNUM *)DH_get0_priv_key(dh); |
|
|
|
BN_CTX_free(ctx); |
|
|
|
DH_free(dh); |
|
|
|
|
|
|
|
pgp_keyid(keydata->pubkeyid, PGP_KEY_ID_SIZE, &keydata->key.seckey.pubkey, seckey->hash_alg); |
|
|
|
pgp_fingerprint(&keydata->pubkeyfpr, &keydata->key.seckey.pubkey, seckey->hash_alg); |
|
|
|
|
|
|
|
/* Generate checksum */ |
|
|
|
|
|
|
|
output = NULL; |
|
|
|
mem = NULL; |
|
|
|
|
|
|
|
pgp_setup_memory_write(&output, &mem, 128); |
|
|
|
|
|
|
|
pgp_push_checksum_writer(output, seckey); |
|
|
|
|
|
|
|
//if(! pgp_write_mpi(output, seckey->key.ecdh.x) ) { |
|
|
|
// return 0; |
|
|
|
//} |
|
|
|
// TODO |
|
|
|
printf("%s:%d, %s: Elliptic curves pub(%d)\n",__FILE__,__LINE__,__FUNCTION__,seckey->pubkey.alg); |
|
|
|
|
|
|
|
/* close rather than pop, since its the only one on the stack */ |
|
|
|
pgp_writer_close(output); |
|
|
|
pgp_teardown_memory_write(output, mem); |
|
|
|
|
|
|
|
/* should now have checksum in seckey struct */ |
|
|
|
|
|
|
|
/* test */ |
|
|
|
if (pgp_get_debug_level(__FILE__)) { |
|
|
|
pgp_eddsa_private_check(seckey); |
|
|
|
} |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
\ingroup HighLevel_KeyGenerate |
|
|
|
\brief Generates an EdDSA keypair |
|
|
|
\param numbits Modulus size |
|
|
|
\param keydata Pointer to keydata struct to hold new key |
|
|
|
\return 1 if key generated successfully; otherwise 0 |
|
|
|
\note It is the caller's responsibility to call pgp_keydata_free(keydata) |
|
|
|
\RFC: https://datatracker.ietf.org/doc/html/rfc8032 |
|
|
|
*/ |
|
|
|
unsigned |
|
|
|
pgp_eddsa_generate_keypair(pgp_key_t *keydata, |
|
|
|
const int numbits, |
|
|
|
const char *hashalg, |
|
|
|
const char *cipher, |
|
|
|
const uint8_t *passphrase, |
|
|
|
const size_t pplen) |
|
|
|
{ |
|
|
|
pgp_seckey_t *seckey; |
|
|
|
DH *dh; |
|
|
|
BN_CTX *ctx; |
|
|
|
pgp_output_t *output; |
|
|
|
pgp_memory_t *mem; |
|
|
|
int res; |
|
|
|
|
|
|
|
ctx = BN_CTX_new(); |
|
|
|
pgp_keydata_init(keydata, PGP_PTAG_CT_SECRET_KEY); |
|
|
|
seckey = pgp_get_writable_seckey(keydata); |
|
|
|
|
|
|
|
/* generate the key pair */ |
|
|
|
dh = DH_new(); |
|
|
|
res = DH_generate_key(dh); |
|
|
|
|
|
|
|
if (!res){ |
|
|
|
DH_free(dh); |
|
|
|
return 0; |
|
|
|
}; |
|
|
|
|
|
|
|
/* populate pgp key from ssl key */ |
|
|
|
seckey->pubkey.version = PGP_V4; |
|
|
|
seckey->pubkey.birthtime = time(NULL); |
|
|
|
seckey->pubkey.days_valid = 0; |
|
|
|
seckey->pubkey.alg = PGP_PKA_EDDSA; |
|
|
|
|
|
|
|
seckey->pubkey.key.elgamal.p = (BIGNUM *)DH_get0_p(dh); |
|
|
|
seckey->pubkey.key.elgamal.g = (BIGNUM *)DH_get0_g(dh); |
|
|
|
seckey->pubkey.key.elgamal.y = (BIGNUM *)DH_get0_pub_key(dh); |
|
|
|
|
|
|
|
/* 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; |
|
|
|
} |
|
|
|
seckey->alg = pgp_str_to_cipher(cipher); |
|
|
|
seckey->octetc = 0; |
|
|
|
seckey->checksum = 0; |
|
|
|
|
|
|
|
seckey->key.elgamal.x = (BIGNUM *)DH_get0_priv_key(dh); |
|
|
|
BN_CTX_free(ctx); |
|
|
|
DH_free(dh); |
|
|
|
|
|
|
|
pgp_keyid(keydata->pubkeyid, PGP_KEY_ID_SIZE, &keydata->key.seckey.pubkey, seckey->hash_alg); |
|
|
|
pgp_fingerprint(&keydata->pubkeyfpr, &keydata->key.seckey.pubkey, seckey->hash_alg); |
|
|
|
|
|
|
|
/* Generate checksum */ |
|
|
|
|
|
|
|
output = NULL; |
|
|
|
mem = NULL; |
|
|
|
|
|
|
|
pgp_setup_memory_write(&output, &mem, 128); |
|
|
|
|
|
|
|
pgp_push_checksum_writer(output, seckey); |
|
|
|
|
|
|
|
//if(! pgp_write_mpi(output, seckey->key.ecdh.x) ) { |
|
|
|
// return 0; |
|
|
|
//} |
|
|
|
// TODO |
|
|
|
printf("%s:%d, %s: Elliptic curves pub(%d)\n",__FILE__,__LINE__,__FUNCTION__,seckey->pubkey.alg); |
|
|
|
|
|
|
|
/* close rather than pop, since its the only one on the stack */ |
|
|
|
pgp_writer_close(output); |
|
|
|
pgp_teardown_memory_write(output, mem); |
|
|
|
|
|
|
|
/* should now have checksum in seckey struct */ |
|
|
|
|
|
|
|
/* test */ |
|
|
|
if (pgp_get_debug_level(__FILE__)) { |
|
|
|
pgp_eddsa_private_check(seckey); |
|
|
|
} |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
pgp_dsa_sig_t * |
|
|
|
pgp_dsa_sign(uint8_t *hashbuf, |
|
|
|
unsigned hashsize, |
|
|
|
const pgp_dsa_seckey_t *secdsa, |
|
|
|