From 16137d36a74c326e7dab797bb705b0ae28d11eba Mon Sep 17 00:00:00 2001 From: Nickolay Olshevsky Date: Mon, 23 Dec 2024 18:29:33 +0200 Subject: [PATCH] Use rnp::secure_bytes for hash parameter in crypto. --- src/lib/crypto/dsa.cpp | 12 +++--- src/lib/crypto/dsa.h | 8 ++-- src/lib/crypto/dsa_common.cpp | 7 +++- src/lib/crypto/dsa_ossl.cpp | 8 ++-- src/lib/crypto/ecdsa.cpp | 52 +++++++++++++------------- src/lib/crypto/ecdsa.h | 31 +++++++++------- src/lib/crypto/ecdsa_ossl.cpp | 55 ++++++++++++++-------------- src/lib/crypto/eddsa.cpp | 40 ++++++++++---------- src/lib/crypto/eddsa.h | 25 +++++++------ src/lib/crypto/eddsa_ossl.cpp | 27 +++++++------- src/lib/crypto/exdsa_ecdhkem.cpp | 4 +- src/lib/crypto/ossl_utils.hpp | 11 ++++++ src/lib/crypto/rsa.cpp | 20 +++++----- src/lib/crypto/rsa.h | 18 ++++----- src/lib/crypto/rsa_ossl.cpp | 63 +++++++++++++++----------------- src/lib/key_material.cpp | 26 ++++++------- 16 files changed, 209 insertions(+), 198 deletions(-) diff --git a/src/lib/crypto/dsa.cpp b/src/lib/crypto/dsa.cpp index d5725ab3a..c7eb551e0 100644 --- a/src/lib/crypto/dsa.cpp +++ b/src/lib/crypto/dsa.cpp @@ -75,7 +75,7 @@ Key::validate(rnp::RNG &rng, bool secret) const noexcept } rnp_result_t -Key::sign(rnp::RNG &rng, Signature &sig, const uint8_t *hash, size_t hash_len) const +Key::sign(rnp::RNG &rng, Signature &sig, const rnp::secure_bytes &hash) const { sig = {}; size_t q_order = q.bytes(); @@ -85,7 +85,7 @@ Key::sign(rnp::RNG &rng, Signature &sig, const uint8_t *hash, size_t hash_len) c } // As 'Raw' is used we need to reduce hash size (as per FIPS-186-4, 4.6) - size_t z_len = hash_len < q_order ? hash_len : q_order; + size_t z_len = std::min(hash.size(), q_order); rnp::bn bp(p); rnp::bn bq(q); @@ -108,7 +108,7 @@ Key::sign(rnp::RNG &rng, Signature &sig, const uint8_t *hash, size_t hash_len) c return RNP_ERROR_SIGNING_FAILED; } - if (botan_pk_op_sign_update(sign_op.get(), hash, z_len)) { + if (botan_pk_op_sign_update(sign_op.get(), hash.data(), z_len)) { return RNP_ERROR_SIGNING_FAILED; } @@ -128,14 +128,14 @@ Key::sign(rnp::RNG &rng, Signature &sig, const uint8_t *hash, size_t hash_len) c } rnp_result_t -Key::verify(const Signature &sig, const uint8_t *hash, size_t hash_len) const +Key::verify(const Signature &sig, const rnp::secure_bytes &hash) const { size_t q_order = q.bytes(); if (q_order > BITS_TO_BYTES(DSA_MAX_Q_BITLEN)) { return RNP_ERROR_BAD_PARAMETERS; } - size_t z_len = hash_len < q_order ? hash_len : q_order; + size_t z_len = std::min(hash.size(), q_order); size_t r_blen = sig.r.bytes(); size_t s_blen = sig.s.bytes(); if ((r_blen > q_order) || (s_blen > q_order)) { @@ -169,7 +169,7 @@ Key::verify(const Signature &sig, const uint8_t *hash, size_t hash_len) const return RNP_ERROR_GENERIC; } - if (botan_pk_op_verify_update(verify_op.get(), hash, z_len)) { + if (botan_pk_op_verify_update(verify_op.get(), hash.data(), z_len)) { return RNP_ERROR_GENERIC; } diff --git a/src/lib/crypto/dsa.h b/src/lib/crypto/dsa.h index 1f3c671bb..ee2c37016 100644 --- a/src/lib/crypto/dsa.h +++ b/src/lib/crypto/dsa.h @@ -31,6 +31,7 @@ #include #include "crypto/rng.h" #include "crypto/mpi.h" +#include "crypto/mem.h" #define DSA_MAX_Q_BITLEN 256 @@ -85,10 +86,7 @@ class Key { * RNP_ERROR_BAD_PARAMETERS wrong input provided * RNP_ERROR_SIGNING_FAILED internal error */ - rnp_result_t sign(rnp::RNG & rng, - Signature & sig, - const uint8_t *hash, - size_t hash_len) const; + rnp_result_t sign(rnp::RNG &rng, Signature &sig, const rnp::secure_bytes &hash) const; /* * @brief Performs DSA verification @@ -102,7 +100,7 @@ class Key { * RNP_ERROR_GENERIC internal error * RNP_ERROR_SIGNATURE_INVALID signature is invalid */ - rnp_result_t verify(const Signature &sig, const uint8_t *hash, size_t hash_len) const; + rnp_result_t verify(const Signature &sig, const rnp::secure_bytes &hash) const; /* * @brief Performs DSA key generation diff --git a/src/lib/crypto/dsa_common.cpp b/src/lib/crypto/dsa_common.cpp index 9f321d4c2..83579c436 100644 --- a/src/lib/crypto/dsa_common.cpp +++ b/src/lib/crypto/dsa_common.cpp @@ -62,10 +62,10 @@ Key::choose_qsize(size_t psize) } } // namespace dsa -} // namespace pgp +namespace ecdsa { pgp_hash_alg_t -ecdsa_get_min_hash(pgp_curve_t curve) +get_min_hash(pgp_curve_t curve) { switch (curve) { case PGP_CURVE_NIST_P_256: @@ -82,3 +82,6 @@ ecdsa_get_min_hash(pgp_curve_t curve) return PGP_HASH_UNKNOWN; } } +} // namespace ecdsa + +} // namespace pgp diff --git a/src/lib/crypto/dsa_ossl.cpp b/src/lib/crypto/dsa_ossl.cpp index b97798cba..33367bbdc 100644 --- a/src/lib/crypto/dsa_ossl.cpp +++ b/src/lib/crypto/dsa_ossl.cpp @@ -184,7 +184,7 @@ Key::validate(rnp::RNG &rng, bool secret) const noexcept } rnp_result_t -Key::sign(rnp::RNG &rng, Signature &sig, const uint8_t *hash, size_t hash_len) const +Key::sign(rnp::RNG &rng, Signature &sig, const rnp::secure_bytes &hash) const { if (!x.bytes()) { RNP_LOG("private key not set"); @@ -211,7 +211,7 @@ Key::sign(rnp::RNG &rng, Signature &sig, const uint8_t *hash, size_t hash_len) c return RNP_ERROR_GENERIC; } sig.s.len = PGP_MPINT_SIZE; - if (EVP_PKEY_sign(ctx.get(), sig.s.mpi, &sig.s.len, hash, hash_len) <= 0) { + if (EVP_PKEY_sign(ctx.get(), sig.s.mpi, &sig.s.len, hash.data(), hash.size()) <= 0) { RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); sig.s.len = 0; return RNP_ERROR_GENERIC; @@ -224,7 +224,7 @@ Key::sign(rnp::RNG &rng, Signature &sig, const uint8_t *hash, size_t hash_len) c } rnp_result_t -Key::verify(const Signature &sig, const uint8_t *hash, size_t hash_len) const +Key::verify(const Signature &sig, const rnp::secure_bytes &hash) const { /* Load secret key to EVP key */ auto evpkey = load_key(*this, false); @@ -249,7 +249,7 @@ Key::verify(const Signature &sig, const uint8_t *hash, size_t hash_len) const if (!encode_sig(sigbuf.mpi, &sigbuf.len, sig)) { return RNP_ERROR_GENERIC; } - if (EVP_PKEY_verify(ctx.get(), sigbuf.mpi, sigbuf.len, hash, hash_len) <= 0) { + if (EVP_PKEY_verify(ctx.get(), sigbuf.mpi, sigbuf.len, hash.data(), hash.size()) <= 0) { return RNP_ERROR_SIGNATURE_INVALID; } return RNP_SUCCESS; diff --git a/src/lib/crypto/ecdsa.cpp b/src/lib/crypto/ecdsa.cpp index 24da6678c..fddd80025 100644 --- a/src/lib/crypto/ecdsa.cpp +++ b/src/lib/crypto/ecdsa.cpp @@ -30,8 +30,11 @@ #include #include "botan_utils.hpp" +namespace pgp { +namespace ecdsa { + static bool -ecdsa_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) +load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) { auto curve = pgp::ec::Curve::get(keydata.curve); if (!curve) { @@ -59,7 +62,7 @@ ecdsa_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) } static bool -ecdsa_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) +load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) { auto curve = pgp::ec::Curve::get(keydata.curve); if (!curve) { @@ -79,11 +82,10 @@ ecdsa_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) } rnp_result_t -ecdsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) +validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { rnp::botan::Pubkey bpkey; - if (!ecdsa_load_public_key(bpkey, key) || - botan_pubkey_check_key(bpkey.get(), rng.handle(), 0)) { + if (!load_public_key(bpkey, key) || botan_pubkey_check_key(bpkey.get(), rng.handle(), 0)) { return RNP_ERROR_BAD_PARAMETERS; } if (!secret) { @@ -91,7 +93,7 @@ ecdsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } rnp::botan::Privkey bskey; - if (!ecdsa_load_secret_key(bskey, key) || + if (!load_secret_key(bskey, key) || botan_privkey_check_key(bskey.get(), rng.handle(), 0)) { return RNP_ERROR_BAD_PARAMETERS; } @@ -99,7 +101,7 @@ ecdsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } const char * -ecdsa_padding_str_for(pgp_hash_alg_t hash_alg) +padding_str_for(pgp_hash_alg_t hash_alg) { switch (hash_alg) { case PGP_HASH_MD5: @@ -108,7 +110,6 @@ ecdsa_padding_str_for(pgp_hash_alg_t hash_alg) return "Raw(SHA-1)"; case PGP_HASH_RIPEMD: return "Raw(RIPEMD-160)"; - case PGP_HASH_SHA256: return "Raw(SHA-256)"; case PGP_HASH_SHA384: @@ -121,7 +122,6 @@ ecdsa_padding_str_for(pgp_hash_alg_t hash_alg) return "Raw(SHA-3(256))"; case PGP_HASH_SHA3_512: return "Raw(SHA-3(512))"; - case PGP_HASH_SM3: return "Raw(SM3)"; default: @@ -130,12 +130,11 @@ ecdsa_padding_str_for(pgp_hash_alg_t hash_alg) } rnp_result_t -ecdsa_sign(rnp::RNG & rng, - pgp::ec::Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key &key) +sign(rnp::RNG & rng, + pgp::ec::Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash, + const pgp::ec::Key & key) { auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { @@ -143,15 +142,15 @@ ecdsa_sign(rnp::RNG & rng, } rnp::botan::Privkey b_key; - if (!ecdsa_load_secret_key(b_key, key)) { + if (!load_secret_key(b_key, key)) { RNP_LOG("Can't load private key"); return RNP_ERROR_GENERIC; } rnp::botan::op::Sign signer; - auto pad = ecdsa_padding_str_for(hash_alg); + auto pad = padding_str_for(hash_alg); if (botan_pk_op_sign_create(&signer.get(), b_key.get(), pad, 0) || - botan_pk_op_sign_update(signer.get(), hash, hash_len)) { + botan_pk_op_sign_update(signer.get(), hash.data(), hash.size())) { return RNP_ERROR_GENERIC; } @@ -173,11 +172,10 @@ ecdsa_sign(rnp::RNG & rng, } rnp_result_t -ecdsa_verify(const pgp::ec::Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key & key) +verify(const pgp::ec::Signature &sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes & hash, + const pgp::ec::Key & key) { auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { @@ -194,14 +192,14 @@ ecdsa_verify(const pgp::ec::Signature &sig, } rnp::botan::Pubkey pub; - if (!ecdsa_load_public_key(pub, key)) { + if (!load_public_key(pub, key)) { return RNP_ERROR_SIGNATURE_INVALID; } rnp::botan::op::Verify verifier; - auto pad = ecdsa_padding_str_for(hash_alg); + auto pad = padding_str_for(hash_alg); if (botan_pk_op_verify_create(&verifier.get(), pub.get(), pad, 0) || - botan_pk_op_verify_update(verifier.get(), hash, hash_len)) { + botan_pk_op_verify_update(verifier.get(), hash.data(), hash.size())) { return RNP_ERROR_SIGNATURE_INVALID; } @@ -215,3 +213,5 @@ ecdsa_verify(const pgp::ec::Signature &sig, } return RNP_SUCCESS; } +} // namespace ecdsa +} // namespace pgp diff --git a/src/lib/crypto/ecdsa.h b/src/lib/crypto/ecdsa.h index c7ccbdcca..98f8bb644 100644 --- a/src/lib/crypto/ecdsa.h +++ b/src/lib/crypto/ecdsa.h @@ -29,22 +29,22 @@ #include "crypto/ec.h" -rnp_result_t ecdsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret); +namespace pgp { +namespace ecdsa { +rnp_result_t validate_key(rnp::RNG &rng, const ec::Key &key, bool secret); -rnp_result_t ecdsa_sign(rnp::RNG & rng, - pgp::ec::Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key &key); +rnp_result_t sign(rnp::RNG & rng, + ec::Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash, + const ec::Key & key); -rnp_result_t ecdsa_verify(const pgp::ec::Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key & key); +rnp_result_t verify(const ec::Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash, + const ec::Key & key); -const char *ecdsa_padding_str_for(pgp_hash_alg_t hash_alg); +const char *padding_str_for(pgp_hash_alg_t hash_alg); /* * @brief Returns hash which should be used with the curve @@ -54,6 +54,9 @@ const char *ecdsa_padding_str_for(pgp_hash_alg_t hash_alg); * @returns Either ID of the hash algorithm, or PGP_HASH_UNKNOWN * if not found */ -pgp_hash_alg_t ecdsa_get_min_hash(pgp_curve_t curve); +pgp_hash_alg_t get_min_hash(pgp_curve_t curve); + +} // namespace ecdsa +} // namespace pgp #endif // ECDSA_H_ diff --git a/src/lib/crypto/ecdsa_ossl.cpp b/src/lib/crypto/ecdsa_ossl.cpp index 5179b59a8..bac506164 100644 --- a/src/lib/crypto/ecdsa_ossl.cpp +++ b/src/lib/crypto/ecdsa_ossl.cpp @@ -32,24 +32,26 @@ #include #include +namespace pgp { +namespace ecdsa { + static bool -ecdsa_decode_sig(const uint8_t *data, size_t len, pgp::ec::Signature &sig) +decode_sig(const uint8_t *data, size_t len, ec::Signature &sig) { - ECDSA_SIG *esig = d2i_ECDSA_SIG(NULL, &data, len); - if (!esig) { + rnp::ossl::ECDSASig esig(d2i_ECDSA_SIG(NULL, &data, len)); + if (!esig.get()) { RNP_LOG("Failed to parse ECDSA sig: %lu", ERR_peek_last_error()); return false; } rnp::bn r, s; - ECDSA_SIG_get0(esig, r.cptr(), s.cptr()); + ECDSA_SIG_get0(esig.get(), r.cptr(), s.cptr()); r.mpi(sig.r); s.mpi(sig.s); - ECDSA_SIG_free(esig); return true; } static bool -ecdsa_encode_sig(uint8_t *data, size_t *len, const pgp::ec::Signature &sig) +encode_sig(uint8_t *data, size_t *len, const ec::Signature &sig) { ECDSA_SIG *dsig = ECDSA_SIG_new(); rnp::bn r(sig.r); @@ -71,18 +73,17 @@ ecdsa_encode_sig(uint8_t *data, size_t *len, const pgp::ec::Signature &sig) } rnp_result_t -ecdsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) +validate_key(rnp::RNG &rng, const ec::Key &key, bool secret) { - return pgp::ec::validate_key(key, secret); + return ec::validate_key(key, secret); } rnp_result_t -ecdsa_sign(rnp::RNG & rng, - pgp::ec::Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key &key) +sign(rnp::RNG & rng, + ec::Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash, + const ec::Key & key) { if (!key.x.bytes()) { RNP_LOG("private key not set"); @@ -90,7 +91,7 @@ ecdsa_sign(rnp::RNG & rng, } /* Load secret key to DSA structure*/ - auto evpkey = pgp::ec::load_key(key.p, &key.x, key.curve); + auto evpkey = ec::load_key(key.p, &key.x, key.curve); if (!evpkey) { RNP_LOG("Failed to load key"); return RNP_ERROR_BAD_PARAMETERS; @@ -107,12 +108,11 @@ ecdsa_sign(rnp::RNG & rng, return RNP_ERROR_GENERIC; } sig.s.len = PGP_MPINT_SIZE; - if (EVP_PKEY_sign(ctx.get(), sig.s.mpi, &sig.s.len, hash, hash_len) <= 0) { + if (EVP_PKEY_sign(ctx.get(), sig.s.mpi, &sig.s.len, hash.data(), hash.size()) <= 0) { RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); - sig.s.len = 0; return RNP_ERROR_GENERIC; } - if (!ecdsa_decode_sig(sig.s.mpi, sig.s.len, sig)) { + if (!decode_sig(sig.s.mpi, sig.s.len, sig)) { RNP_LOG("Failed to parse ECDSA sig: %lu", ERR_peek_last_error()); return RNP_ERROR_GENERIC; } @@ -120,14 +120,13 @@ ecdsa_sign(rnp::RNG & rng, } rnp_result_t -ecdsa_verify(const pgp::ec::Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key & key) +verify(const ec::Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash, + const ec::Key & key) { /* Load secret key to DSA structure*/ - auto evpkey = pgp::ec::load_key(key.p, NULL, key.curve); + auto evpkey = ec::load_key(key.p, NULL, key.curve); if (!evpkey) { RNP_LOG("Failed to load key"); return RNP_ERROR_BAD_PARAMETERS; @@ -142,12 +141,14 @@ ecdsa_verify(const pgp::ec::Signature &sig, RNP_LOG("Failed to initialize verify: %lu", ERR_peek_last_error()); return RNP_ERROR_SIGNATURE_INVALID; } - pgp::mpi sigbuf; - if (!ecdsa_encode_sig(sigbuf.mpi, &sigbuf.len, sig)) { + mpi sigbuf; + if (!encode_sig(sigbuf.mpi, &sigbuf.len, sig)) { return RNP_ERROR_SIGNATURE_INVALID; } - if (EVP_PKEY_verify(ctx.get(), sigbuf.mpi, sigbuf.len, hash, hash_len) < 1) { + if (EVP_PKEY_verify(ctx.get(), sigbuf.mpi, sigbuf.len, hash.data(), hash.size()) < 1) { return RNP_ERROR_SIGNATURE_INVALID; } return RNP_SUCCESS; } +} // namespace ecdsa +} // namespace pgp diff --git a/src/lib/crypto/eddsa.cpp b/src/lib/crypto/eddsa.cpp index 9104d864a..d59bae741 100644 --- a/src/lib/crypto/eddsa.cpp +++ b/src/lib/crypto/eddsa.cpp @@ -31,8 +31,11 @@ #include "utils.h" #include "botan_utils.hpp" +namespace pgp { +namespace eddsa { + static bool -eddsa_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) +load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) { if (keydata.curve != PGP_CURVE_ED25519) { return false; @@ -50,7 +53,7 @@ eddsa_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) } static bool -eddsa_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) +load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) { if (keydata.curve != PGP_CURVE_ED25519) { return false; @@ -69,11 +72,10 @@ eddsa_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) } rnp_result_t -eddsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) +validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { rnp::botan::Pubkey bpkey; - if (!eddsa_load_public_key(bpkey, key) || - botan_pubkey_check_key(bpkey.get(), rng.handle(), 0)) { + if (!load_public_key(bpkey, key) || botan_pubkey_check_key(bpkey.get(), rng.handle(), 0)) { return RNP_ERROR_BAD_PARAMETERS; } @@ -82,7 +84,7 @@ eddsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } rnp::botan::Privkey bskey; - if (!eddsa_load_secret_key(bskey, key) || + if (!load_secret_key(bskey, key) || botan_privkey_check_key(bskey.get(), rng.handle(), 0)) { return RNP_ERROR_BAD_PARAMETERS; } @@ -90,7 +92,7 @@ eddsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } rnp_result_t -eddsa_generate(rnp::RNG &rng, pgp::ec::Key &key) +generate(rnp::RNG &rng, pgp::ec::Key &key) { rnp::botan::Privkey eddsa; if (botan_privkey_create(&eddsa.get(), "Ed25519", NULL, rng.handle())) { @@ -113,10 +115,7 @@ eddsa_generate(rnp::RNG &rng, pgp::ec::Key &key) } rnp_result_t -eddsa_verify(const pgp::ec::Signature &sig, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key & key) +verify(const pgp::ec::Signature &sig, const rnp::secure_bytes &hash, const pgp::ec::Key &key) { // Unexpected size for Ed25519 signature if ((sig.r.bytes() > 32) || (sig.s.bytes() > 32)) { @@ -124,13 +123,13 @@ eddsa_verify(const pgp::ec::Signature &sig, } rnp::botan::Pubkey eddsa; - if (!eddsa_load_public_key(eddsa, key)) { + if (!load_public_key(eddsa, key)) { return RNP_ERROR_BAD_PARAMETERS; } rnp::botan::op::Verify verify_op; if (botan_pk_op_verify_create(&verify_op.get(), eddsa.get(), "Pure", 0) || - botan_pk_op_verify_update(verify_op.get(), hash, hash_len)) { + botan_pk_op_verify_update(verify_op.get(), hash.data(), hash.size())) { return RNP_ERROR_SIGNATURE_INVALID; } @@ -145,20 +144,19 @@ eddsa_verify(const pgp::ec::Signature &sig, } rnp_result_t -eddsa_sign(rnp::RNG & rng, - pgp::ec::Signature &sig, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key &key) +sign(rnp::RNG & rng, + pgp::ec::Signature & sig, + const rnp::secure_bytes &hash, + const pgp::ec::Key & key) { rnp::botan::Privkey eddsa; - if (!eddsa_load_secret_key(eddsa, key)) { + if (!load_secret_key(eddsa, key)) { return RNP_ERROR_BAD_PARAMETERS; } rnp::botan::op::Sign sign_op; if (botan_pk_op_sign_create(&sign_op.get(), eddsa.get(), "Pure", 0) || - botan_pk_op_sign_update(sign_op.get(), hash, hash_len)) { + botan_pk_op_sign_update(sign_op.get(), hash.data(), hash.size())) { return RNP_ERROR_SIGNING_FAILED; } @@ -173,3 +171,5 @@ eddsa_sign(rnp::RNG & rng, sig.s.from_mem(bn_buf + 32, 32); return RNP_SUCCESS; } +} // namespace eddsa +} // namespace pgp diff --git a/src/lib/crypto/eddsa.h b/src/lib/crypto/eddsa.h index f347f5892..cea5bde12 100644 --- a/src/lib/crypto/eddsa.h +++ b/src/lib/crypto/eddsa.h @@ -29,22 +29,25 @@ #include "ec.h" -rnp_result_t eddsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret); +namespace pgp { +namespace eddsa { + +rnp_result_t validate_key(rnp::RNG &rng, const ec::Key &key, bool secret); /* * curve_len must be 255 currently (for Ed25519) * If Ed448 was supported in the future curve_len=448 would also be allowed. */ -rnp_result_t eddsa_generate(rnp::RNG &rng, pgp::ec::Key &key); +rnp_result_t generate(rnp::RNG &rng, ec::Key &key); -rnp_result_t eddsa_verify(const pgp::ec::Signature &sig, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key & key); +rnp_result_t verify(const ec::Signature & sig, + const rnp::secure_bytes &hash, + const ec::Key & key); -rnp_result_t eddsa_sign(rnp::RNG & rng, - pgp::ec::Signature &sig, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key &key); +rnp_result_t sign(rnp::RNG & rng, + ec::Signature & sig, + const rnp::secure_bytes &hash, + const ec::Key & key); +} // namespace eddsa +} // namespace pgp #endif diff --git a/src/lib/crypto/eddsa_ossl.cpp b/src/lib/crypto/eddsa_ossl.cpp index 863fa5371..275414521 100644 --- a/src/lib/crypto/eddsa_ossl.cpp +++ b/src/lib/crypto/eddsa_ossl.cpp @@ -36,8 +36,11 @@ #include #include +namespace pgp { +namespace eddsa { + rnp_result_t -eddsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) +validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { /* Not implemented in the OpenSSL, so just do basic size checks. */ if ((key.p.bytes() != 33) || (key.p.mpi[0] != 0x40)) { @@ -50,7 +53,7 @@ eddsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } rnp_result_t -eddsa_generate(rnp::RNG &rng, pgp::ec::Key &key) +generate(rnp::RNG &rng, pgp::ec::Key &key) { rnp_result_t ret = key.generate(rng, PGP_PKA_EDDSA, PGP_CURVE_ED25519); if (!ret) { @@ -60,10 +63,7 @@ eddsa_generate(rnp::RNG &rng, pgp::ec::Key &key) } rnp_result_t -eddsa_verify(const pgp::ec::Signature &sig, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key & key) +verify(const pgp::ec::Signature &sig, const rnp::secure_bytes &hash, const pgp::ec::Key &key) { if ((sig.r.bytes() > 32) || (sig.s.bytes() > 32)) { RNP_LOG("Invalid EdDSA signature."); @@ -96,18 +96,17 @@ eddsa_verify(const pgp::ec::Signature &sig, sig.r.to_mem(&sigbuf[32 - sig.r.bytes()]); sig.s.to_mem(&sigbuf[64 - sig.s.bytes()]); - if (EVP_DigestVerify(md.get(), sigbuf, 64, hash, hash_len) < 1) { + if (EVP_DigestVerify(md.get(), sigbuf, 64, hash.data(), hash.size()) < 1) { return RNP_ERROR_SIGNATURE_INVALID; } return RNP_SUCCESS; } rnp_result_t -eddsa_sign(rnp::RNG & rng, - pgp::ec::Signature &sig, - const uint8_t * hash, - size_t hash_len, - const pgp::ec::Key &key) +sign(rnp::RNG & rng, + pgp::ec::Signature & sig, + const rnp::secure_bytes &hash, + const pgp::ec::Key & key) { if (!key.x.bytes()) { RNP_LOG("private key not set"); @@ -134,7 +133,7 @@ eddsa_sign(rnp::RNG & rng, static_assert((sizeof(sig.r.mpi) == PGP_MPINT_SIZE) && (PGP_MPINT_SIZE >= 64), "invalid mpi type/size"); sig.r.len = PGP_MPINT_SIZE; - if (EVP_DigestSign(md.get(), sig.r.mpi, &sig.r.len, hash, hash_len) <= 0) { + if (EVP_DigestSign(md.get(), sig.r.mpi, &sig.r.len, hash.data(), hash.size()) <= 0) { RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); sig.r.len = 0; return RNP_ERROR_GENERIC; @@ -145,3 +144,5 @@ eddsa_sign(rnp::RNG & rng, memcpy(sig.s.mpi, &sig.r.mpi[32], 32); return RNP_SUCCESS; } +} // namespace eddsa +} // namespace pgp diff --git a/src/lib/crypto/exdsa_ecdhkem.cpp b/src/lib/crypto/exdsa_ecdhkem.cpp index 464a8e4ee..a4895f91e 100644 --- a/src/lib/crypto/exdsa_ecdhkem.cpp +++ b/src/lib/crypto/exdsa_ecdhkem.cpp @@ -242,7 +242,7 @@ exdsa_private_key_t::sign(rnp::RNG * rng, } else { Botan::ECDSA_PrivateKey priv_key = botan_key(rng); auto signer = - Botan::PK_Signer(priv_key, *(rng->obj()), ecdsa_padding_str_for(hash_alg)); + Botan::PK_Signer(priv_key, *(rng->obj()), pgp::ecdsa::padding_str_for(hash_alg)); sig_out = signer.sign_message(hash, hash_len, *(rng->obj())); } return RNP_SUCCESS; @@ -258,7 +258,7 @@ exdsa_public_key_t::verify(const std::vector &sig, return ed25519_verify_native(sig, key_, hash, hash_len); } else { Botan::ECDSA_PublicKey pub_key = botan_key(); - auto verifier = Botan::PK_Verifier(pub_key, ecdsa_padding_str_for(hash_alg)); + auto verifier = Botan::PK_Verifier(pub_key, pgp::ecdsa::padding_str_for(hash_alg)); if (verifier.verify_message(hash, hash_len, sig.data(), sig.size())) { return RNP_SUCCESS; } diff --git a/src/lib/crypto/ossl_utils.hpp b/src/lib/crypto/ossl_utils.hpp index 761efd911..053978281 100644 --- a/src/lib/crypto/ossl_utils.hpp +++ b/src/lib/crypto/ossl_utils.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #if defined(CRYPTO_BACKEND_OPENSSL3) #include #include @@ -258,6 +259,16 @@ struct DSASigDeleter { using DSASig = std::unique_ptr; +struct ECDSASigDeleter { + void + operator()(::ECDSA_SIG *ptr) const + { + ECDSA_SIG_free(ptr); + } +}; + +using ECDSASig = std::unique_ptr<::ECDSA_SIG, ECDSASigDeleter>; + #if !defined(CRYPTO_BACKEND_OPENSSL3) struct RSADeleter { void diff --git a/src/lib/crypto/rsa.cpp b/src/lib/crypto/rsa.cpp index 4065fd950..a0fd1ec11 100644 --- a/src/lib/crypto/rsa.cpp +++ b/src/lib/crypto/rsa.cpp @@ -107,10 +107,9 @@ Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const rnp::secure_bytes &in) c } rnp_result_t -Key::verify_pkcs1(const Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len) const noexcept +Key::verify_pkcs1(const Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash) const noexcept { rnp::botan::Pubkey rsa_key; if (!load_public_key(rsa_key, *this)) { @@ -124,7 +123,7 @@ Key::verify_pkcs1(const Signature &sig, rnp::botan::op::Verify verify_op; if (botan_pk_op_verify_create(&verify_op.get(), rsa_key.get(), pad, 0) || - botan_pk_op_verify_update(verify_op.get(), hash, hash_len) || + botan_pk_op_verify_update(verify_op.get(), hash.data(), hash.size()) || botan_pk_op_verify_finish(verify_op.get(), sig.s.mpi, sig.s.len)) { return RNP_ERROR_SIGNATURE_INVALID; } @@ -132,11 +131,10 @@ Key::verify_pkcs1(const Signature &sig, } rnp_result_t -Key::sign_pkcs1(rnp::RNG & rng, - Signature & sig, - pgp_hash_alg_t hash_alg, - const uint8_t *hash, - size_t hash_len) const noexcept +Key::sign_pkcs1(rnp::RNG & rng, + Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash) const noexcept { if (!q.bytes()) { RNP_LOG("private key not set"); @@ -156,7 +154,7 @@ Key::sign_pkcs1(rnp::RNG & rng, sig.s.len = PGP_MPINT_SIZE; rnp::botan::op::Sign sign_op; if (botan_pk_op_sign_create(&sign_op.get(), rsa_key.get(), pad, 0) || - botan_pk_op_sign_update(sign_op.get(), hash, hash_len) || + botan_pk_op_sign_update(sign_op.get(), hash.data(), hash.size()) || botan_pk_op_sign_finish(sign_op.get(), rng.handle(), sig.s.mpi, &sig.s.len)) { sig.s.len = 0; return RNP_ERROR_GENERIC; diff --git a/src/lib/crypto/rsa.h b/src/lib/crypto/rsa.h index a8ce7686d..644925ba0 100644 --- a/src/lib/crypto/rsa.h +++ b/src/lib/crypto/rsa.h @@ -82,16 +82,14 @@ class Key { rnp::secure_bytes &out, const Encrypted & in) const noexcept; - rnp_result_t verify_pkcs1(const Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len) const noexcept; - - rnp_result_t sign_pkcs1(rnp::RNG & rng, - Signature & sig, - pgp_hash_alg_t hash_alg, - const uint8_t *hash, - size_t hash_len) const noexcept; + rnp_result_t verify_pkcs1(const Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash) const noexcept; + + rnp_result_t sign_pkcs1(rnp::RNG & rng, + Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash) const noexcept; }; } // namespace rsa diff --git a/src/lib/crypto/rsa_ossl.cpp b/src/lib/crypto/rsa_ossl.cpp index 6aa7f36e1..6990aa032 100644 --- a/src/lib/crypto/rsa_ossl.cpp +++ b/src/lib/crypto/rsa_ossl.cpp @@ -322,8 +322,7 @@ static const uint8_t PKCS1_SHA1_ENCODING[15] = { static bool setup_signature_hash(rnp::ossl::evp::PKeyCtx &ctx, pgp_hash_alg_t hash_alg, - const uint8_t *& enc, - size_t & enc_size) + rnp::secure_bytes & enc) { auto hash_name = rnp::Hash_OpenSSL::name(hash_alg); if (!hash_name) { @@ -342,11 +341,9 @@ setup_signature_hash(rnp::ossl::evp::PKeyCtx &ctx, RNP_LOG("Failed to set digest %s: %s", hash_name, rnp::ossl::latest_err()); return false; } - enc = &PKCS1_SHA1_ENCODING[0]; - enc_size = sizeof(PKCS1_SHA1_ENCODING); + enc.assign(PKCS1_SHA1_ENCODING, PKCS1_SHA1_ENCODING + sizeof(PKCS1_SHA1_ENCODING)); } else { - enc = NULL; - enc_size = 0; + enc.resize(0); } return true; } @@ -377,10 +374,9 @@ Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const rnp::secure_bytes &in) c } rnp_result_t -Key::verify_pkcs1(const Signature &sig, - pgp_hash_alg_t hash_alg, - const uint8_t * hash, - size_t hash_len) const noexcept +Key::verify_pkcs1(const Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash) const noexcept { auto ctx = init_context(*this, false); if (!ctx) { @@ -394,27 +390,27 @@ Key::verify_pkcs1(const Signature &sig, /* LCOV_EXCL_END */ } - const uint8_t *hash_enc = NULL; - size_t hash_enc_size = 0; - if (!setup_context(ctx) || !setup_signature_hash(ctx, hash_alg, hash_enc, hash_enc_size)) { + rnp::secure_bytes hash_enc; + if (!setup_context(ctx) || !setup_signature_hash(ctx, hash_alg, hash_enc)) { return RNP_ERROR_SIGNATURE_INVALID; // LCOV_EXCL_LINE } /* Check whether we need to workaround on unsupported SHA1 for RSA signature verification */ - std::vector hash_buf(hash_enc, hash_enc + hash_enc_size); - if (hash_enc_size) { - hash_buf.insert(hash_buf.end(), hash, hash + hash_len); - hash = hash_buf.data(); - hash_len = hash_buf.size(); + auto hptr = hash.data(); + auto hsize = hash.size(); + if (!hash_enc.empty()) { + hash_enc.insert(hash_enc.end(), hash.begin(), hash.end()); + hptr = hash_enc.data(); + hsize = hash_enc.size(); } int res = 0; if (sig.s.len < n.len) { /* OpenSSL doesn't like signatures smaller then N */ std::vector sn(n.len - sig.s.len, 0); sn.insert(sn.end(), sig.s.mpi, sig.s.mpi + sig.s.len); - res = EVP_PKEY_verify(ctx.get(), sn.data(), sn.size(), hash, hash_len); + res = EVP_PKEY_verify(ctx.get(), sn.data(), sn.size(), hptr, hsize); } else { - res = EVP_PKEY_verify(ctx.get(), sig.s.mpi, sig.s.len, hash, hash_len); + res = EVP_PKEY_verify(ctx.get(), sig.s.mpi, sig.s.len, hptr, hsize); } if (res <= 0) { RNP_LOG("RSA verification failure: %s", rnp::ossl::latest_err()); @@ -424,11 +420,10 @@ Key::verify_pkcs1(const Signature &sig, } rnp_result_t -Key::sign_pkcs1(rnp::RNG & rng, - Signature & sig, - pgp_hash_alg_t hash_alg, - const uint8_t *hash, - size_t hash_len) const noexcept +Key::sign_pkcs1(rnp::RNG & rng, + Signature & sig, + pgp_hash_alg_t hash_alg, + const rnp::secure_bytes &hash) const noexcept { if (!q.bytes()) { /* LCOV_EXCL_START */ @@ -447,21 +442,21 @@ Key::sign_pkcs1(rnp::RNG & rng, return RNP_ERROR_GENERIC; /* LCOV_EXCL_END */ } - const uint8_t *hash_enc = NULL; - size_t hash_enc_size = 0; - if (!setup_context(ctx) || !setup_signature_hash(ctx, hash_alg, hash_enc, hash_enc_size)) { + rnp::secure_bytes hash_enc; + if (!setup_context(ctx) || !setup_signature_hash(ctx, hash_alg, hash_enc)) { return RNP_ERROR_GENERIC; // LCOV_EXCL_LINE } /* Check whether we need to workaround on unsupported SHA1 for RSA signature verification */ - std::vector hash_buf(hash_enc, hash_enc + hash_enc_size); - if (hash_enc_size) { - hash_buf.insert(hash_buf.end(), hash, hash + hash_len); - hash = hash_buf.data(); - hash_len = hash_buf.size(); + auto hptr = hash.data(); + auto hsize = hash.size(); + if (!hash_enc.empty()) { + hash_enc.insert(hash_enc.end(), hash.begin(), hash.end()); + hptr = hash_enc.data(); + hsize = hash_enc.size(); } sig.s.len = PGP_MPINT_SIZE; - if (EVP_PKEY_sign(ctx.get(), sig.s.mpi, &sig.s.len, hash, hash_len) <= 0) { + if (EVP_PKEY_sign(ctx.get(), sig.s.mpi, &sig.s.len, hptr, hsize) <= 0) { /* LCOV_EXCL_START */ RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); sig.s.len = 0; diff --git a/src/lib/key_material.cpp b/src/lib/key_material.cpp index a6df9a390..b5cfc7aaf 100644 --- a/src/lib/key_material.cpp +++ b/src/lib/key_material.cpp @@ -215,7 +215,7 @@ ECCKeyParams::bits() const noexcept pgp_hash_alg_t ECDSAKeyParams::min_hash() const noexcept { - return ecdsa_get_min_hash(curve()); + return ecdsa::get_min_hash(curve()); } #if defined(ENABLE_PQC) @@ -586,7 +586,7 @@ RSAKeyMaterial::verify(const rnp::SecurityContext & ctx, RNP_LOG("RSA encrypt-only signature considered as invalid."); return RNP_ERROR_SIGNATURE_INVALID; } - return key_.verify_pkcs1(sig.rsa, sig.halg, hash.data(), hash.size()); + return key_.verify_pkcs1(sig.rsa, sig.halg, hash); } rnp_result_t @@ -594,7 +594,7 @@ RSAKeyMaterial::sign(rnp::SecurityContext & ctx, pgp_signature_material_t &sig, const rnp::secure_bytes & hash) const { - return key_.sign_pkcs1(ctx.rng, sig.rsa, sig.halg, hash.data(), hash.size()); + return key_.sign_pkcs1(ctx.rng, sig.rsa, sig.halg, hash); } void @@ -737,7 +737,7 @@ DSAKeyMaterial::verify(const rnp::SecurityContext & ctx, const pgp_signature_material_t &sig, const rnp::secure_bytes & hash) const { - return key_.verify(sig.dsa, hash.data(), hash.size()); + return key_.verify(sig.dsa, hash); } rnp_result_t @@ -745,7 +745,7 @@ DSAKeyMaterial::sign(rnp::SecurityContext & ctx, pgp_signature_material_t &sig, const rnp::secure_bytes & hash) const { - return key_.sign(ctx.rng, sig.dsa, hash.data(), hash.size()); + return key_.sign(ctx.rng, sig.dsa, hash); } pgp_hash_alg_t @@ -1086,7 +1086,7 @@ ECDSAKeyMaterial::validate_material(rnp::SecurityContext &ctx, bool reset) RNP_LOG("ECDSA validate: curve %d is not supported.", key_.curve); return true; } - return !ecdsa_validate_key(ctx.rng, key_, secret_); + return !ecdsa::validate_key(ctx.rng, key_, secret_); } std::unique_ptr @@ -1104,7 +1104,7 @@ ECDSAKeyMaterial::verify(const rnp::SecurityContext & ctx, RNP_LOG("Curve %d is not supported.", key_.curve); return RNP_ERROR_NOT_SUPPORTED; } - return ecdsa_verify(sig.ecc, sig.halg, hash.data(), hash.size(), key_); + return ecdsa::verify(sig.ecc, sig.halg, hash, key_); } rnp_result_t @@ -1116,13 +1116,13 @@ ECDSAKeyMaterial::sign(rnp::SecurityContext & ctx, if (ret) { return ret; } - return ecdsa_sign(ctx.rng, sig.ecc, sig.halg, hash.data(), hash.size(), key_); + return ecdsa::sign(ctx.rng, sig.ecc, sig.halg, hash, key_); } pgp_hash_alg_t ECDSAKeyMaterial::adjust_hash(pgp_hash_alg_t hash) const { - pgp_hash_alg_t hash_min = ecdsa_get_min_hash(key_.curve); + pgp_hash_alg_t hash_min = ecdsa::get_min_hash(key_.curve); if (rnp::Hash::size(hash) < rnp::Hash::size(hash_min)) { return hash_min; } @@ -1254,7 +1254,7 @@ ECDHKeyMaterial::x25519_tweak_bits() noexcept bool EDDSAKeyMaterial::validate_material(rnp::SecurityContext &ctx, bool reset) { - return !eddsa_validate_key(ctx.rng, key_, secret_); + return !eddsa::validate_key(ctx.rng, key_, secret_); } std::unique_ptr @@ -1266,7 +1266,7 @@ EDDSAKeyMaterial::clone() bool EDDSAKeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) { - if (eddsa_generate(ctx.rng, key_)) { + if (eddsa::generate(ctx.rng, key_)) { RNP_LOG("failed to generate EDDSA key"); return false; } @@ -1278,7 +1278,7 @@ EDDSAKeyMaterial::verify(const rnp::SecurityContext & ctx, const pgp_signature_material_t &sig, const rnp::secure_bytes & hash) const { - return eddsa_verify(sig.ecc, hash.data(), hash.size(), key_); + return eddsa::verify(sig.ecc, hash, key_); } rnp_result_t @@ -1286,7 +1286,7 @@ EDDSAKeyMaterial::sign(rnp::SecurityContext & ctx, pgp_signature_material_t &sig, const rnp::secure_bytes & hash) const { - return eddsa_sign(ctx.rng, sig.ecc, hash.data(), hash.size(), key_); + return eddsa::sign(ctx.rng, sig.ecc, hash, key_); } bool