Skip to content

Commit

Permalink
Use pgp::KeyMaterial instead of pgp_key_material_t.
Browse files Browse the repository at this point in the history
  • Loading branch information
ni4 committed Jul 22, 2024
1 parent 7307c18 commit 79bde7e
Show file tree
Hide file tree
Showing 27 changed files with 1,057 additions and 2,294 deletions.
278 changes: 7 additions & 271 deletions src/lib/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,286 +95,22 @@ pgp_generate_seckey(const rnp_keygen_crypto_params_t &crypto,
#endif
seckey.creation_time = crypto.ctx->time();
seckey.alg = crypto.key_alg;
seckey.material.alg = crypto.key_alg;
seckey.material = pgp::KeyMaterial::create(crypto.key_alg);
if (!seckey.material) {
RNP_LOG("Unsupported key algorithm: %d", crypto.key_alg);
return false;
}
seckey.tag = primary ? PGP_PKT_SECRET_KEY : PGP_PKT_SECRET_SUBKEY;

switch (seckey.alg) {
case PGP_PKA_RSA:
if (rsa_generate(&crypto.ctx->rng, &seckey.material.rsa, crypto.rsa.modulus_bit_len)) {
RNP_LOG("failed to generate RSA key");
return false;
}
break;
case PGP_PKA_DSA:
if (dsa_generate(&crypto.ctx->rng,
&seckey.material.dsa,
crypto.dsa.p_bitlen,
crypto.dsa.q_bitlen)) {
RNP_LOG("failed to generate DSA key");
return false;
}
break;
case PGP_PKA_EDDSA:
if (eddsa_generate(&crypto.ctx->rng, &seckey.material.ec)) {
RNP_LOG("failed to generate EDDSA key");
return false;
}
break;
case PGP_PKA_ECDH:
if (!ecdh_set_params(&seckey.material.ec, crypto.ecc.curve)) {
RNP_LOG("Unsupported curve [ID=%d]", crypto.ecc.curve);
return false;
}
if (crypto.ecc.curve == PGP_CURVE_25519) {
if (x25519_generate(&crypto.ctx->rng, &seckey.material.ec)) {
RNP_LOG("failed to generate x25519 key");
return false;
}
seckey.material.ec.curve = crypto.ecc.curve;
break;
}
FALLTHROUGH_STATEMENT;
case PGP_PKA_ECDSA:
case PGP_PKA_SM2:
if (!curve_supported(crypto.ecc.curve)) {
RNP_LOG("EC generate: curve %d is not supported.", (int) crypto.ecc.curve);
return false;
}
if (ec_generate(&crypto.ctx->rng, &seckey.material.ec, seckey.alg, crypto.ecc.curve)) {
RNP_LOG("failed to generate EC key");
return false;
}
seckey.material.ec.curve = crypto.ecc.curve;
break;
case PGP_PKA_ELGAMAL:
if (elgamal_generate(
&crypto.ctx->rng, &seckey.material.eg, crypto.elgamal.key_bitlen)) {
RNP_LOG("failed to generate ElGamal key");
return false;
}
break;
#if defined(ENABLE_CRYPTO_REFRESH)
case PGP_PKA_ED25519:
if (generate_ed25519_native(&crypto.ctx->rng,
seckey.material.ed25519.priv,
seckey.material.ed25519.pub) != RNP_SUCCESS) {
RNP_LOG("failed to generate ED25519 key");
return false;
}
break;
case PGP_PKA_X25519:
if (generate_x25519_native(&crypto.ctx->rng,
seckey.material.x25519.priv,
seckey.material.x25519.pub) != RNP_SUCCESS) {
RNP_LOG("failed to generate X25519 key");
return false;
}
break;
#endif
#if defined(ENABLE_PQC)
case PGP_PKA_KYBER768_X25519:
FALLTHROUGH_STATEMENT;
// TODO add case PGP_PKA_KYBER1024_X448: FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER768_P256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER1024_P384:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER768_BP256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER1024_BP384:
if (pgp_kyber_ecdh_composite_key_t::gen_keypair(
&crypto.ctx->rng, &seckey.material.kyber_ecdh, seckey.alg)) {
RNP_LOG("failed to generate MLKEM-ECDH-composite key for PK alg %d", seckey.alg);
return false;
}
break;
case PGP_PKA_DILITHIUM3_ED25519:
FALLTHROUGH_STATEMENT;
// TODO: add case PGP_PKA_DILITHIUM5_ED448: FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_P256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_P384:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_BP256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_BP384:
if (pgp_dilithium_exdsa_composite_key_t::gen_keypair(
&crypto.ctx->rng, &seckey.material.dilithium_exdsa, seckey.alg)) {
RNP_LOG("failed to generate mldsa-ecdsa/eddsa-composite key for PK alg %d",
seckey.alg);
return false;
}
break;
case PGP_PKA_SPHINCSPLUS_SHA2:
FALLTHROUGH_STATEMENT;
case PGP_PKA_SPHINCSPLUS_SHAKE:
if (pgp_sphincsplus_generate(&crypto.ctx->rng,
&seckey.material.sphincsplus,
crypto.sphincsplus.param,
seckey.alg)) {
RNP_LOG("failed to generate SLH-DSA key for PK alg %d", seckey.alg);
return false;
}
break;
#endif
default:
RNP_LOG("key generation not implemented for PK alg: %d", seckey.alg);
if (!seckey.material->generate(crypto)) {
return false;
}

seckey.sec_protection.s2k.usage = PGP_S2KU_NONE;
seckey.material.secret = true;
seckey.material.validity.mark_valid();
/* fill the sec_data/sec_len */
if (encrypt_secret_key(&seckey, NULL, crypto.ctx->rng)) {
RNP_LOG("failed to fill sec_data");
return false;
}
return true;
}

bool
key_material_equal(const pgp_key_material_t *key1, const pgp_key_material_t *key2)
{
if (key1->alg != key2->alg) {
return false;
}

switch (key1->alg) {
case PGP_PKA_RSA:
case PGP_PKA_RSA_ENCRYPT_ONLY:
case PGP_PKA_RSA_SIGN_ONLY:
return (key1->rsa.n == key2->rsa.n) && (key1->rsa.e == key2->rsa.e);
case PGP_PKA_DSA:
return (key1->dsa.p == key2->dsa.p) && (key1->dsa.q == key2->dsa.q) &&
(key1->dsa.g == key2->dsa.g) && (key1->dsa.y == key2->dsa.y);
case PGP_PKA_ELGAMAL:
case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
return (key1->eg.p == key2->eg.p) && (key1->eg.g == key2->eg.g) &&
(key1->eg.y == key2->eg.y);
case PGP_PKA_EDDSA:
case PGP_PKA_ECDH:
case PGP_PKA_ECDSA:
case PGP_PKA_SM2:
return (key1->ec.curve == key2->ec.curve) && (key1->ec.p == key2->ec.p);
#if defined(ENABLE_CRYPTO_REFRESH)
case PGP_PKA_ED25519:
return (key1->ed25519.pub == key2->ed25519.pub);
case PGP_PKA_X25519:
return (key1->x25519.pub == key2->x25519.pub);
#endif
#if defined(ENABLE_PQC)
case PGP_PKA_KYBER768_X25519:
FALLTHROUGH_STATEMENT;
// TODO add case PGP_PKA_KYBER1024_X448: FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER768_P256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER1024_P384:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER768_BP256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER1024_BP384:
return (key1->kyber_ecdh.pub == key2->kyber_ecdh.pub);
case PGP_PKA_DILITHIUM3_ED25519:
FALLTHROUGH_STATEMENT;
// TODO: add case PGP_PKA_DILITHIUM5_ED448: FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_P256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_P384:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_BP256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_BP384:
return (key1->dilithium_exdsa.pub == key2->dilithium_exdsa.pub);
case PGP_PKA_SPHINCSPLUS_SHA2:
FALLTHROUGH_STATEMENT;
case PGP_PKA_SPHINCSPLUS_SHAKE:
return (key1->sphincsplus.pub == key2->sphincsplus.pub);
#endif
default:
RNP_LOG("unknown public key algorithm: %d", (int) key1->alg);
return false;
}
}

rnp_result_t
validate_pgp_key_material(const pgp_key_material_t *material, rnp::RNG *rng)
{
#ifdef FUZZERS_ENABLED
/* do not timeout on large keys during fuzzing */
return RNP_SUCCESS;
#else
switch (material->alg) {
case PGP_PKA_RSA:
case PGP_PKA_RSA_ENCRYPT_ONLY:
case PGP_PKA_RSA_SIGN_ONLY:
return rsa_validate_key(rng, &material->rsa, material->secret);
case PGP_PKA_DSA:
return dsa_validate_key(rng, &material->dsa, material->secret);
case PGP_PKA_EDDSA:
return eddsa_validate_key(rng, &material->ec, material->secret);
case PGP_PKA_ECDH:
if (!curve_supported(material->ec.curve)) {
/* allow to import key if curve is not supported */
RNP_LOG("ECDH validate: curve %d is not supported.", (int) material->ec.curve);
return RNP_SUCCESS;
}
return ecdh_validate_key(rng, &material->ec, material->secret);
case PGP_PKA_ECDSA:
if (!curve_supported(material->ec.curve)) {
/* allow to import key if curve is not supported */
RNP_LOG("ECDH validate: curve %d is not supported.", (int) material->ec.curve);
return RNP_SUCCESS;
}
return ecdsa_validate_key(rng, &material->ec, material->secret);
case PGP_PKA_SM2:
#if defined(ENABLE_SM2)
return sm2_validate_key(rng, &material->ec, material->secret);
#else
RNP_LOG("SM2 key validation is not available.");
return RNP_ERROR_NOT_IMPLEMENTED;
#endif
case PGP_PKA_ELGAMAL:
case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
return elgamal_validate_key(&material->eg, material->secret) ? RNP_SUCCESS :
RNP_ERROR_GENERIC;
#if defined(ENABLE_CRYPTO_REFRESH)
case PGP_PKA_ED25519:
return ed25519_validate_key_native(rng, &material->ed25519, material->secret);
case PGP_PKA_X25519:
return x25519_validate_key_native(rng, &material->x25519, material->secret);
#endif
#if defined(ENABLE_PQC)
case PGP_PKA_KYBER768_X25519:
FALLTHROUGH_STATEMENT;
// TODO add case PGP_PKA_KYBER1024_X448: FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER768_P256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER1024_P384:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER768_BP256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_KYBER1024_BP384:
return kyber_ecdh_validate_key(rng, &material->kyber_ecdh, material->secret);
case PGP_PKA_DILITHIUM3_ED25519:
FALLTHROUGH_STATEMENT;
// TODO: add case PGP_PKA_DILITHIUM5_ED448: FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_P256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_P384:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_BP256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_BP384:
return dilithium_exdsa_validate_key(rng, &material->dilithium_exdsa, material->secret);
case PGP_PKA_SPHINCSPLUS_SHA2:
FALLTHROUGH_STATEMENT;
case PGP_PKA_SPHINCSPLUS_SHAKE:
return sphincsplus_validate_key(rng, &material->sphincsplus, material->secret);
#endif
default:
RNP_LOG("unknown public key algorithm: %d", (int) material->alg);
}

return RNP_ERROR_BAD_PARAMETERS;
#endif
}
12 changes: 0 additions & 12 deletions src/lib/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,4 @@ bool pgp_generate_subkey(rnp_keygen_subkey_desc_t & desc,
const pgp_password_provider_t &password_provider,
pgp_key_store_format_t secformat);

/**
* @brief Check two key material for equality. Only public part is checked, so this can be
* called on public/secret key material
*
* @param key1 first key material
* @param key2 second key material
* @return true if both key materials are equal or false otherwise
*/
bool key_material_equal(const pgp_key_material_t *key1, const pgp_key_material_t *key2);

rnp_result_t validate_pgp_key_material(const pgp_key_material_t *material, rnp::RNG *rng);

#endif /* CRYPTO_H_ */
11 changes: 11 additions & 0 deletions src/lib/crypto/dsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ typedef struct pgp_dsa_key_t {
pgp::mpi y;
/* secret mpi */
pgp::mpi x;

void
clear_secret()
{
x.forget();
}

~pgp_dsa_key_t()
{
clear_secret();
}
} pgp_dsa_key_t;

typedef struct pgp_dsa_signature_t {
Expand Down
36 changes: 36 additions & 0 deletions src/lib/crypto/ec.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <repgp/repgp_def.h>
#include "crypto/rng.h"
#include "crypto/mpi.h"
#include "crypto/mem.h"
#include <vector>

#define MAX_CURVE_BIT_SIZE 521 // secp521r1
Expand Down Expand Up @@ -83,6 +84,17 @@ typedef struct pgp_ec_key_t {
/* ecdh params */
pgp_hash_alg_t kdf_hash_alg; /* Hash used by kdf */
pgp_symm_alg_t key_wrap_alg; /* Symmetric algorithm used to wrap KEK*/

void
clear_secret()
{
x.forget();
}

~pgp_ec_key_t()
{
clear_secret();
}
} pgp_ec_key_t;

typedef struct pgp_ec_signature_t {
Expand All @@ -94,6 +106,18 @@ typedef struct pgp_ec_signature_t {
typedef struct pgp_ed25519_key_t {
std::vector<uint8_t> pub; // \ native encoding
std::vector<uint8_t> priv; // /

void
clear_secret()
{
secure_clear(priv.data(), priv.size());
priv.resize(0);
}

~pgp_ed25519_key_t()
{
clear_secret();
}
} pgp_ed25519_key_t;

typedef struct pgp_ed25519_signature_t {
Expand All @@ -103,6 +127,18 @@ typedef struct pgp_ed25519_signature_t {
typedef struct pgp_x25519_key_t {
std::vector<uint8_t> pub; // \ native encoding
std::vector<uint8_t> priv; // /

void
clear_secret()
{
secure_clear(priv.data(), priv.size());
priv.resize(0);
}

~pgp_x25519_key_t()
{
clear_secret();
}
} pgp_x25519_key_t;

typedef struct pgp_x25519_encrypted_t {
Expand Down
Loading

0 comments on commit 79bde7e

Please sign in to comment.