From adf0debc88cdf09c29cebe47730f8db35f883e22 Mon Sep 17 00:00:00 2001 From: Nickolay Olshevsky Date: Fri, 20 Dec 2024 17:58:43 +0200 Subject: [PATCH] Further refactor crypto code to use rnp::secure_vector instead of raw pointers/sizes. --- src/lib/crypto/ecdh.cpp | 107 ++++++++--------- src/lib/crypto/ecdh.h | 55 ++++----- src/lib/crypto/ecdh_ossl.cpp | 196 ++++++++++++++------------------ src/lib/crypto/ecdh_utils.cpp | 53 ++++----- src/lib/crypto/ecdh_utils.h | 16 ++- src/lib/crypto/elgamal.cpp | 14 ++- src/lib/crypto/elgamal.h | 15 ++- src/lib/crypto/elgamal_ossl.cpp | 50 ++++---- src/lib/crypto/ossl_utils.hpp | 10 ++ src/lib/crypto/rsa.cpp | 22 ++-- src/lib/crypto/rsa.h | 15 ++- src/lib/crypto/rsa_ossl.cpp | 20 ++-- src/lib/crypto/sm2.cpp | 97 ++++++++-------- src/lib/crypto/sm2.h | 57 +++++----- src/lib/key_material.cpp | 95 +++++++--------- src/lib/key_material.hpp | 42 +++---- src/lib/types.h | 11 +- src/librepgp/stream-dump.cpp | 9 +- src/librepgp/stream-packet.cpp | 6 +- src/librepgp/stream-parse.cpp | 9 +- src/librepgp/stream-write.cpp | 5 +- src/tests/cipher.cpp | 171 +++++++++++++--------------- 22 files changed, 502 insertions(+), 573 deletions(-) diff --git a/src/lib/crypto/ecdh.cpp b/src/lib/crypto/ecdh.cpp index 386791595..11e009eae 100644 --- a/src/lib/crypto/ecdh.cpp +++ b/src/lib/crypto/ecdh.cpp @@ -37,13 +37,15 @@ #include "utils.h" #include "mem.h" +namespace pgp { +namespace ecdh { // Produces kek of size kek_len which corresponds to length of wrapping key static bool compute_kek(uint8_t * kek, size_t kek_len, const std::vector &other_info, - const pgp::ec::Curve * curve_desc, - const pgp::mpi & ec_pubkey, + const ec::Curve * curve_desc, + const mpi & ec_pubkey, const rnp::botan::Privkey & ec_prvkey, const pgp_hash_alg_t hash_alg) { @@ -74,9 +76,9 @@ compute_kek(uint8_t * kek, } static bool -ecdh_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &key) +load_public_key(rnp::botan::Pubkey &pubkey, const ec::Key &key) { - auto curve = pgp::ec::Curve::get(key.curve); + auto curve = ec::Curve::get(key.curve); if (!curve) { RNP_LOG("unknown curve"); return false; @@ -112,9 +114,9 @@ ecdh_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &key) } static bool -ecdh_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &key) +load_secret_key(rnp::botan::Privkey &seckey, const ec::Key &key) { - auto curve = pgp::ec::Curve::get(key.curve); + auto curve = ec::Curve::get(key.curve); if (!curve) { return false; } @@ -137,16 +139,15 @@ ecdh_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &key) } rnp_result_t -ecdh_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) +validate_key(rnp::RNG &rng, const ec::Key &key, bool secret) { - auto curve_desc = pgp::ec::Curve::get(key.curve); + auto curve_desc = ec::Curve::get(key.curve); if (!curve_desc) { return RNP_ERROR_NOT_SUPPORTED; } rnp::botan::Pubkey bpkey; - if (!ecdh_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) { @@ -154,7 +155,7 @@ ecdh_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } rnp::botan::Privkey bskey; - if (!ecdh_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; } @@ -162,19 +163,16 @@ ecdh_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } rnp_result_t -ecdh_encrypt_pkcs5(rnp::RNG & rng, - pgp_ecdh_encrypted_t & out, - const uint8_t *const in, - size_t in_len, - const pgp::ec::Key & key, - const pgp_fingerprint_t &fingerprint) +encrypt_pkcs5(rnp::RNG & rng, + Encrypted & out, + const rnp::secure_bytes & in, + const ec::Key & key, + const std::vector &fp) { - // 'm' is padded to the 8-byte granularity - uint8_t m[MAX_SESSION_KEY_SIZE]; - if (!in || (in_len > sizeof(m))) { + if (in.size() > MAX_SESSION_KEY_SIZE) { return RNP_ERROR_BAD_PARAMETERS; } - const size_t m_padded_len = ((in_len / 8) + 1) * 8; + const size_t m_padded_len = ((in.size() / 8) + 1) * 8; // +8 because of AES-wrap adds 8 bytes if (ECDH_WRAPPED_KEY_SIZE < (m_padded_len + 8)) { return RNP_ERROR_BAD_PARAMETERS; @@ -186,7 +184,7 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, return RNP_ERROR_NOT_IMPLEMENTED; } #endif - auto curve_desc = pgp::ec::Curve::get(key.curve); + auto curve_desc = ec::Curve::get(key.curve); if (!curve_desc) { RNP_LOG("unsupported curve"); return RNP_ERROR_NOT_SUPPORTED; @@ -195,7 +193,7 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, // See 13.5 of RFC 4880 for definition of other_info size const size_t kek_len = pgp_key_size(key.key_wrap_alg); auto other_info = - kdf_other_info_serialize(curve_desc, fingerprint, key.kdf_hash_alg, key.key_wrap_alg); + kdf_other_info_serialize(*curve_desc, fp, key.kdf_hash_alg, key.key_wrap_alg); assert(other_info.size() == curve_desc->OID.size() + 46); rnp::botan::Privkey eph_prv_key; @@ -217,22 +215,22 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, return RNP_ERROR_GENERIC; } - memcpy(m, in, in_len); - if (!pad_pkcs7(m, m_padded_len, in_len)) { - // Should never happen - return RNP_ERROR_GENERIC; - } + // 'm' is padded to the 8-byte granularity + rnp::secure_bytes m = in; + pad_pkcs7(m, m_padded_len - m.size()); - out.mlen = sizeof(out.m); + size_t mlen = ECDH_WRAPPED_KEY_SIZE; + out.m.resize(ECDH_WRAPPED_KEY_SIZE); #if defined(CRYPTO_BACKEND_BOTAN3) char name[16]; snprintf(name, sizeof(name), "AES-%zu", 8 * kek_len); - if (botan_nist_kw_enc(name, 0, m, m_padded_len, kek, kek_len, out.m, &out.mlen)) { + if (botan_nist_kw_enc(name, 0, m.data(), m.size(), kek, kek_len, out.m.data(), &mlen)) { #else - if (botan_key_wrap3394(m, m_padded_len, kek, kek_len, out.m, &out.mlen)) { + if (botan_key_wrap3394(m.data(), m.size(), kek, kek_len, out.m.data(), &mlen)) { #endif return RNP_ERROR_GENERIC; } + out.m.resize(mlen); /* we need to prepend 0x40 for the x25519 */ if (key.curve == PGP_CURVE_25519) { @@ -255,17 +253,16 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, } rnp_result_t -ecdh_decrypt_pkcs5(uint8_t * out, - size_t * out_len, - const pgp_ecdh_encrypted_t &in, - const pgp::ec::Key & key, - const pgp_fingerprint_t & fingerprint) +decrypt_pkcs5(rnp::secure_bytes & out, + const Encrypted & in, + const ec::Key & key, + const std::vector &fp) { - if (!out || !out_len || !key.x.bytes()) { + if (!key.x.bytes()) { return RNP_ERROR_BAD_PARAMETERS; } - auto curve_desc = pgp::ec::Curve::get(key.curve); + auto curve_desc = ec::Curve::get(key.curve); if (!curve_desc) { RNP_LOG("unknown curve"); return RNP_ERROR_NOT_SUPPORTED; @@ -274,28 +271,23 @@ ecdh_decrypt_pkcs5(uint8_t * out, auto wrap_alg = key.key_wrap_alg; auto kdf_hash = key.kdf_hash_alg; /* Ensure that AES is used for wrapping */ - if ((wrap_alg != PGP_SA_AES_128) && (wrap_alg != PGP_SA_AES_192) && - (wrap_alg != PGP_SA_AES_256)) { + if (!pgp_is_sa_aes(wrap_alg)) { RNP_LOG("non-aes wrap algorithm"); return RNP_ERROR_NOT_SUPPORTED; } // See 13.5 of RFC 4880 for definition of other_info_size - auto other_info = kdf_other_info_serialize(curve_desc, fingerprint, kdf_hash, wrap_alg); + auto other_info = kdf_other_info_serialize(*curve_desc, fp, kdf_hash, wrap_alg); assert(other_info.size() == curve_desc->OID.size() + 46); rnp::botan::Privkey prv_key; - if (!ecdh_load_secret_key(prv_key, key)) { + if (!load_secret_key(prv_key, key)) { RNP_LOG("failed to load ecdh secret key"); return RNP_ERROR_GENERIC; } // Size of SHA-256 or smaller - rnp::secure_array kek; - rnp::secure_array deckey; - - size_t deckey_len = deckey.size(); - size_t offset = 0; + rnp::secure_array kek; /* Security: Always return same error code in case compute_kek, * botan_key_unwrap3394 or unpad_pkcs7 fails @@ -305,30 +297,29 @@ ecdh_decrypt_pkcs5(uint8_t * out, return RNP_ERROR_GENERIC; } + size_t deckey_len = MAX_SESSION_KEY_SIZE; + out.resize(deckey_len); #if defined(CRYPTO_BACKEND_BOTAN3) char name[16]; snprintf(name, sizeof(name), "AES-%zu", 8 * kek_len); if (botan_nist_kw_dec( - name, 0, in.m, in.mlen, kek.data(), kek_len, deckey.data(), &deckey_len)) { + name, 0, in.m.data(), in.m.size(), kek.data(), kek_len, out.data(), &deckey_len)) { #else - if (botan_key_unwrap3394(in.m, in.mlen, kek.data(), kek_len, deckey.data(), &deckey_len)) { + if (botan_key_unwrap3394( + in.m.data(), in.m.size(), kek.data(), kek_len, out.data(), &deckey_len)) { #endif return RNP_ERROR_GENERIC; } - - if (!unpad_pkcs7(deckey.data(), deckey_len, &offset)) { + out.resize(deckey_len); + if (!unpad_pkcs7(out)) { return RNP_ERROR_GENERIC; } - - if (*out_len < offset) { - return RNP_ERROR_SHORT_BUFFER; - } - - *out_len = offset; - memcpy(out, deckey.data(), *out_len); return RNP_SUCCESS; } +} // namespace ecdh +} // namespace pgp + #if defined(ENABLE_CRYPTO_REFRESH) || defined(ENABLE_PQC) rnp_result_t ecdh_kem_gen_keypair_native(rnp::RNG * rng, diff --git a/src/lib/crypto/ecdh.h b/src/lib/crypto/ecdh.h index 7d0d8b944..63d409e7d 100644 --- a/src/lib/crypto/ecdh.h +++ b/src/lib/crypto/ecdh.h @@ -38,16 +38,17 @@ #define ECDH_WRAPPED_KEY_SIZE 48 /* Forward declarations */ -typedef struct pgp_fingerprint_t pgp_fingerprint_t; -typedef struct pgp_ecdh_encrypted_t { - pgp::mpi p; - uint8_t m[ECDH_WRAPPED_KEY_SIZE]; - size_t mlen; - const pgp_fingerprint_t *fp; -} pgp_ecdh_encrypted_t; +namespace pgp { +namespace ecdh { +class Encrypted { + public: + mpi p{}; + std::vector m; + std::vector fp; +}; -rnp_result_t ecdh_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret); +rnp_result_t validate_key(rnp::RNG &rng, const ec::Key &key, bool secret); /* * @brief Sets hash algorithm and key wrapping algo @@ -58,24 +59,18 @@ rnp_result_t ecdh_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secr * * @returns false if curve is not supported, otherwise true */ -bool ecdh_set_params(pgp::ec::Key &key, pgp_curve_t curve_id); +bool set_params(ec::Key &key, pgp_curve_t curve_id); /* * Encrypts session key with a KEK agreed during ECDH as specified in * RFC 4880 bis 01, 13.5 * * @param rng initialized rnp::RNG object - * @param session_key key to be encrypted - * @param session_key_len length of the key buffer - * @param wrapped_key [out] resulting key wrapped in by some AES + * @param out [out] resulting key wrapped in by some AES * as specified in RFC 3394 - * @param wrapped_key_len [out] length of the `wrapped_key' buffer - * Current implementation always produces 48 bytes as key - * is padded with PKCS-5/7 - * @param ephemeral_key [out] public ephemeral ECDH key used for key - * agreement (private part). Must be initialized - * @param pubkey public key to be used for encryption - * @param fingerprint fingerprint of the pubkey + * @param in data to be encrypted + * @param key public key to be used for encryption + * @param fp fingerprint of the encrypting key * * @return RNP_SUCCESS on success and output parameters are populated * @return RNP_ERROR_NOT_SUPPORTED unknown curve @@ -83,12 +78,11 @@ bool ecdh_set_params(pgp::ec::Key &key, pgp_curve_t curve_id); * @return RNP_ERROR_SHORT_BUFFER `wrapped_key_len' to small to store result * @return RNP_ERROR_GENERIC implementation error */ -rnp_result_t ecdh_encrypt_pkcs5(rnp::RNG & rng, - pgp_ecdh_encrypted_t & out, - const uint8_t *const in, - size_t in_len, - const pgp::ec::Key & key, - const pgp_fingerprint_t &fingerprint); +rnp_result_t encrypt_pkcs5(rnp::RNG & rng, + Encrypted & out, + const rnp::secure_bytes & in, + const ec::Key & key, + const std::vector &fp); /* * Decrypts session key with a KEK agreed during ECDH as specified in @@ -110,11 +104,12 @@ rnp_result_t ecdh_encrypt_pkcs5(rnp::RNG & rng, * @return RNP_ERROR_SHORT_BUFFER `session_key_len' to small to store result * @return RNP_ERROR_GENERIC decryption failed or implementation error */ -rnp_result_t ecdh_decrypt_pkcs5(uint8_t * out, - size_t * out_len, - const pgp_ecdh_encrypted_t &in, - const pgp::ec::Key & key, - const pgp_fingerprint_t & fingerprint); +rnp_result_t decrypt_pkcs5(rnp::secure_bytes & out, + const Encrypted & in, + const ec::Key & key, + const std::vector &fp); +} // namespace ecdh +} // namespace pgp #if defined(ENABLE_CRYPTO_REFRESH) || defined(ENABLE_PQC) /* Generate an ECDH key pair in "native" format, i.e., diff --git a/src/lib/crypto/ecdh_ossl.cpp b/src/lib/crypto/ecdh_ossl.cpp index db1c32713..a57e23226 100644 --- a/src/lib/crypto/ecdh_ossl.cpp +++ b/src/lib/crypto/ecdh_ossl.cpp @@ -38,6 +38,9 @@ #include #include +namespace pgp { +namespace ecdh { + static const struct ecdh_wrap_alg_map_t { pgp_symm_alg_t alg; const char * name; @@ -46,20 +49,18 @@ static const struct ecdh_wrap_alg_map_t { {PGP_SA_AES_256, "aes256-wrap"}}; rnp_result_t -ecdh_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); } static rnp_result_t -ecdh_derive_kek(uint8_t * x, - size_t xlen, - const pgp::ec::Key & key, - const pgp_fingerprint_t &fingerprint, - uint8_t * kek, - const size_t kek_len) +derive_kek(rnp::secure_bytes & x, + const ec::Key & key, + const std::vector &fp, + rnp::secure_bytes & kek) { - auto curve_desc = pgp::ec::Curve::get(key.curve); + auto curve_desc = ec::Curve::get(key.curve); if (!curve_desc) { RNP_LOG("unsupported curve"); return RNP_ERROR_NOT_SUPPORTED; @@ -75,13 +76,13 @@ ecdh_derive_kek(uint8_t * x, /* LCOV_EXCL_END */ } auto other_info = - kdf_other_info_serialize(curve_desc, fingerprint, key.kdf_hash_alg, key.key_wrap_alg); + kdf_other_info_serialize(*curve_desc, fp, key.kdf_hash_alg, key.key_wrap_alg); // Self-check assert(other_info.size() == curve_desc->OID.size() + 46); // Derive KEK, using the KDF from SP800-56A rnp::secure_array dgst; assert(hash_len <= PGP_MAX_HASH_SIZE); - size_t reps = (kek_len + hash_len - 1) / hash_len; + size_t reps = (kek.size() + hash_len - 1) / hash_len; // As we use AES & SHA2 we should not get more then 2 iterations if (reps > 2) { /* LCOV_EXCL_START */ @@ -93,21 +94,21 @@ ecdh_derive_kek(uint8_t * x, for (size_t i = 1; i <= reps; i++) { auto hash = rnp::Hash::create(key.kdf_hash_alg); hash->add(i); - hash->add(x, xlen); + hash->add(x.data(), x.size()); hash->add(other_info); hash->finish(dgst.data()); - size_t bytes = std::min(hash_len, kek_len - have); - memcpy(kek + have, dgst.data(), bytes); + size_t bytes = std::min(hash_len, kek.size() - have); + memcpy(kek.data() + have, dgst.data(), bytes); have += bytes; } return RNP_SUCCESS; } static rnp_result_t -ecdh_rfc3394_wrap_ctx(EVP_CIPHER_CTX **ctx, - pgp_symm_alg_t wrap_alg, - const uint8_t * key, - bool decrypt) +rfc3394_wrap_ctx(rnp::ossl::evp::CipherCtx &ctx, + pgp_symm_alg_t wrap_alg, + const rnp::secure_bytes & key, + bool decrypt) { /* get OpenSSL EVP cipher for key wrap */ const char *cipher_name = NULL; @@ -125,21 +126,20 @@ ecdh_rfc3394_wrap_ctx(EVP_CIPHER_CTX **ctx, return RNP_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_END */ } - *ctx = EVP_CIPHER_CTX_new(); + ctx.reset(EVP_CIPHER_CTX_new()); if (!ctx) { /* LCOV_EXCL_START */ RNP_LOG("Context allocation failed : %lu", ERR_peek_last_error()); return RNP_ERROR_OUT_OF_MEMORY; /* LCOV_EXCL_END */ } - EVP_CIPHER_CTX_set_flags(*ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); - int res = decrypt ? EVP_DecryptInit_ex(*ctx, cipher, NULL, key, NULL) : - EVP_EncryptInit_ex(*ctx, cipher, NULL, key, NULL); + EVP_CIPHER_CTX_set_flags(ctx.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + int res = decrypt ? EVP_DecryptInit_ex(ctx.get(), cipher, NULL, key.data(), NULL) : + EVP_EncryptInit_ex(ctx.get(), cipher, NULL, key.data(), NULL); if (res <= 0) { /* LCOV_EXCL_START */ RNP_LOG("Failed to initialize cipher : %lu", ERR_peek_last_error()); - EVP_CIPHER_CTX_free(*ctx); - *ctx = NULL; + ctx.reset(); return RNP_ERROR_GENERIC; /* LCOV_EXCL_END */ } @@ -147,70 +147,61 @@ ecdh_rfc3394_wrap_ctx(EVP_CIPHER_CTX **ctx, } static rnp_result_t -ecdh_rfc3394_wrap(uint8_t * out, - size_t * out_len, - const uint8_t *const in, - size_t in_len, - const uint8_t * key, - pgp_symm_alg_t wrap_alg) +rfc3394_wrap(std::vector & out, + const rnp::secure_bytes &in, + const rnp::secure_bytes &key, + pgp_symm_alg_t wrap_alg) { - EVP_CIPHER_CTX *ctx = NULL; - rnp_result_t ret = ecdh_rfc3394_wrap_ctx(&ctx, wrap_alg, key, false); + rnp::ossl::evp::CipherCtx ctx; + rnp_result_t ret = rfc3394_wrap_ctx(ctx, wrap_alg, key, false); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Wrap context initialization failed."); return ret; /* LCOV_EXCL_END */ } - int intlen = *out_len; + int intlen = out.size(); /* encrypts in one pass, no final is needed */ - int res = EVP_EncryptUpdate(ctx, out, &intlen, in, in_len); + int res = EVP_EncryptUpdate(ctx.get(), out.data(), &intlen, in.data(), in.size()); if (res <= 0) { RNP_LOG("Failed to encrypt data : %lu", ERR_peek_last_error()); // LCOV_EXCL_LINE - } else { - *out_len = intlen; + return RNP_ERROR_GENERIC; } - EVP_CIPHER_CTX_free(ctx); - return res > 0 ? RNP_SUCCESS : RNP_ERROR_GENERIC; + out.resize(intlen); + return RNP_SUCCESS; } static rnp_result_t -ecdh_rfc3394_unwrap(uint8_t * out, - size_t * out_len, - const uint8_t *const in, - size_t in_len, - const uint8_t * key, - pgp_symm_alg_t wrap_alg) +rfc3394_unwrap(rnp::secure_bytes & out, + const std::vector &in, + const rnp::secure_bytes & key, + pgp_symm_alg_t wrap_alg) { - if ((in_len < 16) || (in_len % 8)) { + if ((in.size() < 16) || (in.size() % 8)) { RNP_LOG("Invalid wrapped key size."); return RNP_ERROR_GENERIC; } - EVP_CIPHER_CTX *ctx = NULL; - rnp_result_t ret = ecdh_rfc3394_wrap_ctx(&ctx, wrap_alg, key, true); + rnp::ossl::evp::CipherCtx ctx; + rnp_result_t ret = rfc3394_wrap_ctx(ctx, wrap_alg, key, true); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Unwrap context initialization failed."); return ret; /* LCOV_EXCL_END */ } - int intlen = *out_len; + int intlen = out.size(); /* decrypts in one pass, no final is needed */ - int res = EVP_DecryptUpdate(ctx, out, &intlen, in, in_len); + int res = EVP_DecryptUpdate(ctx.get(), out.data(), &intlen, in.data(), in.size()); if (res <= 0) { RNP_LOG("Failed to decrypt data : %lu", ERR_peek_last_error()); - } else { - *out_len = intlen; + return RNP_ERROR_GENERIC; } - EVP_CIPHER_CTX_free(ctx); - return res > 0 ? RNP_SUCCESS : RNP_ERROR_GENERIC; + out.resize(intlen); + return RNP_SUCCESS; } static bool -ecdh_derive_secret(rnp::ossl::evp::PKey &sec, - rnp::ossl::evp::PKey &peer, - uint8_t * x, - size_t * xlen) +derive_secret(rnp::ossl::evp::PKey &sec, rnp::ossl::evp::PKey &peer, rnp::secure_bytes &x) { rnp::ossl::evp::PKeyCtx ctx(EVP_PKEY_CTX_new(sec.get(), NULL)); if (!ctx) { @@ -231,12 +222,15 @@ ecdh_derive_secret(rnp::ossl::evp::PKey &sec, return false; /* LCOV_EXCL_END */ } - if (EVP_PKEY_derive(ctx.get(), x, xlen) <= 0) { + x.resize(MAX_CURVE_BYTELEN + 1); + size_t xlen = x.size(); + if (EVP_PKEY_derive(ctx.get(), x.data(), &xlen) <= 0) { /* LCOV_EXCL_START */ RNP_LOG("Failed to obtain shared secret size: %lu", ERR_peek_last_error()); return false; /* LCOV_EXCL_END */ } + x.resize(xlen); return true; } @@ -254,14 +248,13 @@ ecdh_kek_len(pgp_symm_alg_t wrap_alg) } rnp_result_t -ecdh_encrypt_pkcs5(rnp::RNG & rng, - pgp_ecdh_encrypted_t & out, - const uint8_t *const in, - size_t in_len, - const pgp::ec::Key & key, - const pgp_fingerprint_t &fingerprint) +encrypt_pkcs5(rnp::RNG & rng, + Encrypted & out, + const rnp::secure_bytes & in, + const ec::Key & key, + const std::vector &fp) { - if (!in || (in_len > MAX_SESSION_KEY_SIZE)) { + if (in.size() > MAX_SESSION_KEY_SIZE) { return RNP_ERROR_BAD_PARAMETERS; } #if !defined(ENABLE_SM2) @@ -279,20 +272,16 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, /* LCOV_EXCL_END */ } /* load our public key */ - auto pkey = pgp::ec::load_key(key.p, NULL, key.curve); + auto pkey = ec::load_key(key.p, NULL, key.curve); if (!pkey) { /* LCOV_EXCL_START */ RNP_LOG("Failed to load public key."); return RNP_ERROR_BAD_PARAMETERS; /* LCOV_EXCL_END */ } - rnp::secure_bytes sec(MAX_CURVE_BYTELEN + 1, 0); - rnp::secure_array kek; - rnp::secure_array mpad; - size_t seclen = sec.size(); /* generate ephemeral key */ - auto ephkey = pgp::ec::generate_pkey(PGP_PKA_ECDH, key.curve); + auto ephkey = ec::generate_pkey(PGP_PKA_ECDH, key.curve); if (!ephkey) { /* LCOV_EXCL_START */ RNP_LOG("Failed to generate ephemeral key."); @@ -300,14 +289,16 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, /* LCOV_EXCL_END */ } /* do ECDH derivation */ - if (!ecdh_derive_secret(ephkey, pkey, sec.data(), &seclen)) { + rnp::secure_bytes sec; + if (!derive_secret(ephkey, pkey, sec)) { /* LCOV_EXCL_START */ RNP_LOG("ECDH derivation failed."); return RNP_ERROR_GENERIC; /* LCOV_EXCL_END */ } /* here we got x value in sec, deriving kek */ - auto ret = ecdh_derive_kek(sec.data(), seclen, key, fingerprint, kek.data(), keklen); + rnp::secure_bytes kek(keklen, 0); + auto ret = derive_kek(sec, key, fp, kek); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Failed to derive KEK."); @@ -315,19 +306,12 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, /* LCOV_EXCL_END */ } /* add PKCS#7 padding */ - size_t m_padded_len = ((in_len / 8) + 1) * 8; - memcpy(mpad.data(), in, in_len); - if (!pad_pkcs7(mpad.data(), m_padded_len, in_len)) { - /* LCOV_EXCL_START */ - RNP_LOG("Failed to add PKCS #7 padding."); - return RNP_ERROR_GENERIC; - /* LCOV_EXCL_END */ - } + size_t m_padded_len = ((in.size() / 8) + 1) * 8; + rnp::secure_bytes mpad(in.begin(), in.end()); + pad_pkcs7(mpad, m_padded_len - in.size()); /* do RFC 3394 AES key wrap */ - static_assert(sizeof(out.m) == ECDH_WRAPPED_KEY_SIZE, "Wrong ECDH wrapped key size."); - out.mlen = ECDH_WRAPPED_KEY_SIZE; - ret = ecdh_rfc3394_wrap( - out.m, &out.mlen, mpad.data(), m_padded_len, kek.data(), key.key_wrap_alg); + out.m.resize(ECDH_WRAPPED_KEY_SIZE); + ret = rfc3394_wrap(out.m, mpad, kek, key.key_wrap_alg); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Failed to wrap key."); @@ -335,7 +319,7 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, /* LCOV_EXCL_END */ } /* write ephemeral public key */ - if (!pgp::ec::write_pubkey(ephkey, out.p, key.curve)) { + if (!ec::write_pubkey(ephkey, out.p, key.curve)) { /* LCOV_EXCL_START */ RNP_LOG("Failed to write ec key."); return RNP_ERROR_GENERIC; @@ -345,13 +329,12 @@ ecdh_encrypt_pkcs5(rnp::RNG & rng, } rnp_result_t -ecdh_decrypt_pkcs5(uint8_t * out, - size_t * out_len, - const pgp_ecdh_encrypted_t &in, - const pgp::ec::Key & key, - const pgp_fingerprint_t & fingerprint) +decrypt_pkcs5(rnp::secure_bytes & out, + const Encrypted & in, + const ec::Key & key, + const std::vector &fp) { - if (!out || !out_len || !key.x.bytes()) { + if (!key.x.bytes()) { return RNP_ERROR_BAD_PARAMETERS; } @@ -362,19 +345,13 @@ ecdh_decrypt_pkcs5(uint8_t * out, return RNP_ERROR_NOT_SUPPORTED; } /* load ephemeral public key */ - auto ephkey = pgp::ec::load_key(in.p, NULL, key.curve); + auto ephkey = ec::load_key(in.p, nullptr, key.curve); if (!ephkey) { RNP_LOG("Failed to load ephemeral public key."); return RNP_ERROR_BAD_PARAMETERS; } /* load our secret key */ - rnp::secure_array sec; - rnp::secure_array kek; - rnp::secure_array mpad; - - size_t seclen = sec.size(); - size_t mpadlen = mpad.size(); - auto pkey = pgp::ec::load_key(key.p, &key.x, key.curve); + auto pkey = ec::load_key(key.p, &key.x, key.curve); if (!pkey) { /* LCOV_EXCL_START */ RNP_LOG("Failed to load secret key."); @@ -382,14 +359,16 @@ ecdh_decrypt_pkcs5(uint8_t * out, /* LCOV_EXCL_END */ } /* do ECDH derivation */ - if (!ecdh_derive_secret(pkey, ephkey, sec.data(), &seclen)) { + rnp::secure_bytes sec; + if (!derive_secret(pkey, ephkey, sec)) { /* LCOV_EXCL_START */ RNP_LOG("ECDH derivation failed."); return RNP_ERROR_GENERIC; /* LCOV_EXCL_END */ } /* here we got x value in sec, deriving kek */ - auto ret = ecdh_derive_kek(sec.data(), seclen, key, fingerprint, kek.data(), keklen); + rnp::secure_bytes kek(keklen, 0); + auto ret = derive_kek(sec, key, fp, kek); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Failed to derive KEK."); @@ -397,8 +376,8 @@ ecdh_decrypt_pkcs5(uint8_t * out, /* LCOV_EXCL_END */ } /* do RFC 3394 AES key unwrap */ - ret = - ecdh_rfc3394_unwrap(mpad.data(), &mpadlen, in.m, in.mlen, kek.data(), key.key_wrap_alg); + rnp::secure_bytes mpad(MAX_SESSION_KEY_SIZE, 0); + ret = rfc3394_unwrap(mpad, in.m, kek, key.key_wrap_alg); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Failed to unwrap key."); @@ -406,14 +385,15 @@ ecdh_decrypt_pkcs5(uint8_t * out, /* LCOV_EXCL_END */ } /* remove PKCS#7 padding */ - if (!unpad_pkcs7(mpad.data(), mpadlen, &mpadlen)) { + if (!unpad_pkcs7(mpad)) { /* LCOV_EXCL_START */ RNP_LOG("Failed to unpad key."); return RNP_ERROR_GENERIC; /* LCOV_EXCL_END */ } - assert(mpadlen <= *out_len); - *out_len = mpadlen; - memcpy(out, mpad.data(), mpadlen); + out.assign(mpad.begin(), mpad.end()); return RNP_SUCCESS; } + +} // namespace ecdh +} // namespace pgp diff --git a/src/lib/crypto/ecdh_utils.cpp b/src/lib/crypto/ecdh_utils.cpp index 9c7a66404..f36cbde51 100644 --- a/src/lib/crypto/ecdh_utils.cpp +++ b/src/lib/crypto/ecdh_utils.cpp @@ -29,6 +29,8 @@ #include "utils.h" #include +namespace pgp { +namespace ecdh { /* Used by ECDH keys. Specifies which hash and wrapping algorithm * to be used (see point 15. of RFC 4880). * @@ -51,18 +53,18 @@ static const struct ecdh_params_t { // returns size of data written to other_info std::vector -kdf_other_info_serialize(const pgp::ec::Curve * curve, - const pgp_fingerprint_t &fp, - const pgp_hash_alg_t kdf_hash, - const pgp_symm_alg_t wrap_alg) +kdf_other_info_serialize(const pgp::ec::Curve & curve, + const std::vector &fp, + const pgp_hash_alg_t kdf_hash, + const pgp_symm_alg_t wrap_alg) { - assert(fp.length >= 20); + assert(fp.size() >= 20); /* KDF-OtherInfo: AlgorithmID * Current implementation will always use SHA-512 and AES-256 for KEK wrapping */ std::vector buf; - buf.push_back(static_cast(curve->OID.size())); - buf.insert(buf.end(), curve->OID.begin(), curve->OID.end()); + buf.push_back(static_cast(curve.OID.size())); + buf.insert(buf.end(), curve.OID.begin(), curve.OID.end()); buf.push_back(PGP_PKA_ECDH); // size of following 3 params (each 1 byte) buf.push_back(0x03); @@ -81,49 +83,41 @@ kdf_other_info_serialize(const pgp::ec::Curve * curve, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20}; buf.insert(buf.end(), anonymous.begin(), anonymous.end()); // keep 20, as per spec - buf.insert(buf.end(), fp.fingerprint, fp.fingerprint + fp.length); + buf.insert(buf.end(), fp.begin(), fp.end()); return buf; } -bool -pad_pkcs7(uint8_t *buf, size_t buf_len, size_t offset) +void +pad_pkcs7(rnp::secure_bytes &buf, uint8_t padding) { - if (buf_len <= offset) { - // Must have at least 1 byte of padding - return false; - } - - const uint8_t pad_byte = buf_len - offset; - memset(buf + offset, pad_byte, pad_byte); - return true; + buf.insert(buf.end(), padding, padding); } bool -unpad_pkcs7(uint8_t *buf, size_t buf_len, size_t *offset) +unpad_pkcs7(rnp::secure_bytes &buf) { - if (!buf || !offset || !buf_len) { + if (buf.empty()) { return false; } - uint8_t err = 0; - const uint8_t pad_byte = buf[buf_len - 1]; - const uint32_t pad_begin = buf_len - pad_byte; + uint8_t err = 0; + const uint8_t pad_byte = buf.back(); + const size_t pad_begin = buf.size() - pad_byte; // TODO: Still >, <, and <=,== are not constant time (maybe?) - err |= (pad_byte > buf_len); + err |= (pad_byte > buf.size()); err |= (pad_byte == 0); /* Check if padding is OK */ - for (size_t c = 0; c < buf_len; c++) { + for (size_t c = 0; c < buf.size(); c++) { err |= (buf[c] ^ pad_byte) * (pad_begin <= c); } - - *offset = pad_begin; + buf.resize(pad_begin); return (err == 0); } bool -ecdh_set_params(pgp::ec::Key &key, pgp_curve_t curve_id) +set_params(pgp::ec::Key &key, pgp_curve_t curve_id) { for (size_t i = 0; i < ARRAY_SIZE(ecdh_params); i++) { if (ecdh_params[i].curve == curve_id) { @@ -136,6 +130,9 @@ ecdh_set_params(pgp::ec::Key &key, pgp_curve_t curve_id) return false; } +} // namespace ecdh +} // namespace pgp + bool x25519_tweak_bits(pgp::ec::Key &key) { diff --git a/src/lib/crypto/ecdh_utils.h b/src/lib/crypto/ecdh_utils.h index a763fdab8..c03831385 100644 --- a/src/lib/crypto/ecdh_utils.h +++ b/src/lib/crypto/ecdh_utils.h @@ -33,13 +33,17 @@ #define MAX_SESSION_KEY_SIZE 40 #define MAX_AES_KEY_SIZE 32 -std::vector kdf_other_info_serialize(const pgp::ec::Curve * curve, - const pgp_fingerprint_t &fp, - const pgp_hash_alg_t kdf_hash, - const pgp_symm_alg_t wrap_alg); +namespace pgp { +namespace ecdh { +std::vector kdf_other_info_serialize(const pgp::ec::Curve & curve, + const std::vector &fp, + const pgp_hash_alg_t kdf_hash, + const pgp_symm_alg_t wrap_alg); -bool pad_pkcs7(uint8_t *buf, size_t buf_len, size_t offset); +void pad_pkcs7(rnp::secure_bytes &buf, uint8_t padding); -bool unpad_pkcs7(uint8_t *buf, size_t buf_len, size_t *offset); +bool unpad_pkcs7(rnp::secure_bytes &buf); +} // namespace ecdh +} // namespace pgp #endif // ECDH_UTILS_H_ diff --git a/src/lib/crypto/elgamal.cpp b/src/lib/crypto/elgamal.cpp index c4a0d798f..0605c929a 100644 --- a/src/lib/crypto/elgamal.cpp +++ b/src/lib/crypto/elgamal.cpp @@ -124,7 +124,7 @@ Key::validate(bool secret) const noexcept } rnp_result_t -Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const uint8_t *in, size_t in_len) const +Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const rnp::secure_bytes &in) const { rnp::botan::Pubkey b_key; if (!load_public_key(b_key, *this)) { @@ -143,7 +143,8 @@ Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const uint8_t *in, size_t in_l rnp::botan::op::Encrypt op_ctx; if (botan_pk_op_encrypt_create(&op_ctx.get(), b_key.get(), "PKCS1v15", 0) || - botan_pk_op_encrypt(op_ctx.get(), rng.handle(), enc_buf.data(), &p_len, in, in_len)) { + botan_pk_op_encrypt( + op_ctx.get(), rng.handle(), enc_buf.data(), &p_len, in.data(), in.size())) { RNP_LOG("Failed to create operation context"); return RNP_ERROR_BAD_PARAMETERS; } @@ -168,7 +169,7 @@ Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const uint8_t *in, size_t in_l } rnp_result_t -Key::decrypt_pkcs1(rnp::RNG &rng, uint8_t *out, size_t *out_len, const Encrypted &in) const +Key::decrypt_pkcs1(rnp::RNG &rng, rnp::secure_bytes &out, const Encrypted &in) const { if (!x.bytes()) { RNP_LOG("empty secret key"); @@ -198,13 +199,16 @@ Key::decrypt_pkcs1(rnp::RNG &rng, uint8_t *out, size_t *out_len, const Encrypted memcpy(&enc_buf[p_len - g_len], in.g.mpi, g_len); memcpy(&enc_buf[2 * p_len - m_len], in.m.mpi, m_len); - *out_len = p_len; + out.resize(p_len); + size_t out_len = out.size(); rnp::botan::op::Decrypt op_ctx; if (botan_pk_op_decrypt_create(&op_ctx.get(), b_key.get(), "PKCS1v15", 0) || - botan_pk_op_decrypt(op_ctx.get(), out, out_len, enc_buf.data(), 2 * p_len)) { + botan_pk_op_decrypt(op_ctx.get(), out.data(), &out_len, enc_buf.data(), 2 * p_len)) { + out.resize(0); RNP_LOG("Decryption failed"); return RNP_ERROR_BAD_PARAMETERS; } + out.resize(out_len); return RNP_SUCCESS; } diff --git a/src/lib/crypto/elgamal.h b/src/lib/crypto/elgamal.h index 259b2c59b..56878b636 100644 --- a/src/lib/crypto/elgamal.h +++ b/src/lib/crypto/elgamal.h @@ -30,6 +30,7 @@ #include #include "crypto/rng.h" #include "crypto/mpi.h" +#include "mem.h" namespace pgp { namespace eg { @@ -86,10 +87,9 @@ class Key { * RNP_ERROR_OUT_OF_MEMORY allocation failure * RNP_ERROR_BAD_PARAMETERS wrong input provided */ - rnp_result_t encrypt_pkcs1(rnp::RNG & rng, - Encrypted & out, - const uint8_t *in, - size_t in_len) const; + rnp_result_t encrypt_pkcs1(rnp::RNG & rng, + Encrypted & out, + const rnp::secure_bytes &in) const; /* * Performs ElGamal decryption @@ -109,10 +109,9 @@ class Key { * RNP_ERROR_OUT_OF_MEMORY allocation failure * RNP_ERROR_BAD_PARAMETERS wrong input provided */ - rnp_result_t decrypt_pkcs1(rnp::RNG & rng, - uint8_t * out, - size_t * out_len, - const Encrypted &in) const; + rnp_result_t decrypt_pkcs1(rnp::RNG & rng, + rnp::secure_bytes &out, + const Encrypted & in) const; /* * Generates ElGamal key diff --git a/src/lib/crypto/elgamal_ossl.cpp b/src/lib/crypto/elgamal_ossl.cpp index ac9ca34fc..60f2834b2 100644 --- a/src/lib/crypto/elgamal_ossl.cpp +++ b/src/lib/crypto/elgamal_ossl.cpp @@ -115,64 +115,61 @@ Key::validate(bool secret) const noexcept } static bool -pkcs1v15_pad(uint8_t *out, size_t out_len, const uint8_t *in, size_t in_len) +pkcs1v15_pad(mpi &out, size_t psize, const rnp::secure_bytes &in) { - assert(out && in); - if (out_len < in_len + 11) { - return false; - } - out[0] = 0x00; - out[1] = 0x02; - size_t rnd = out_len - in_len - 3; - out[2 + rnd] = 0x00; - if (RAND_bytes(&out[2], rnd) != 1) { + assert(psize >= in.size() + 11); + out.mpi[0] = 0x00; + out.mpi[1] = 0x02; + size_t rnd = psize - in.size() - 3; + out.mpi[2 + rnd] = 0x00; + if (RAND_bytes(&out.mpi[2], rnd) != 1) { return false; } for (size_t i = 2; i < 2 + rnd; i++) { /* we need non-zero bytes */ size_t cntr = 16; - while (!out[i] && (cntr--) && (RAND_bytes(&out[i], 1) == 1)) { + while (!out.mpi[i] && (cntr--) && (RAND_bytes(&out.mpi[i], 1) == 1)) { } - if (!out[i]) { + if (!out.mpi[i]) { /* LCOV_EXCL_START */ RNP_LOG("Something is wrong with RNG."); return false; /* LCOV_EXCL_END */ } } - memcpy(out + rnd + 3, in, in_len); + memcpy(out.mpi + rnd + 3, in.data(), in.size()); + out.len = psize; return true; } static bool -pkcs1v15_unpad(size_t *padlen, const uint8_t *in, size_t in_len, bool skip0) +pkcs1v15_unpad(const mpi &in, rnp::secure_bytes &out, bool skip0) { - if (in_len <= (size_t)(11 - skip0)) { + if (in.len <= (size_t)(11 - skip0)) { return false; } - if (!skip0 && in[0]) { + if (!skip0 && in.mpi[0]) { return false; } - if (in[1 - skip0] != 0x02) { + if (in.mpi[1 - skip0] != 0x02) { return false; } size_t pad = 2 - skip0; - while ((pad < in_len) && in[pad]) { + while ((pad < in.len) && in.mpi[pad]) { pad++; } - if (pad >= in_len) { + if (pad >= in.len) { return false; } - *padlen = pad + 1; + out.assign(in.mpi + pad + 1, in.mpi + in.len); return true; } rnp_result_t -Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const uint8_t *in, size_t in_len) const +Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const rnp::secure_bytes &in) const { mpi mm{}; - mm.len = p.len; - if (!pkcs1v15_pad(mm.mpi, mm.len, in, in_len)) { + if (!pkcs1v15_pad(mm, p.len, in)) { /* LCOV_EXCL_START */ RNP_LOG("Failed to add PKCS1 v1.5 padding."); return RNP_ERROR_BAD_PARAMETERS; @@ -251,7 +248,7 @@ Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const uint8_t *in, size_t in_l } rnp_result_t -Key::decrypt_pkcs1(rnp::RNG &rng, uint8_t *out, size_t *out_len, const Encrypted &in) const +Key::decrypt_pkcs1(rnp::RNG &rng, rnp::secure_bytes &out, const Encrypted &in) const { if (!x.bytes()) { RNP_LOG("Secret key not set."); @@ -316,13 +313,10 @@ Key::decrypt_pkcs1(rnp::RNG &rng, uint8_t *out, size_t *out_len, const Encrypted return RNP_ERROR_OUT_OF_MEMORY; // LCOV_EXCL_LINE } /* unpad, handling skipped leftmost 0 case */ - size_t padlen = 0; - if (!pkcs1v15_unpad(&padlen, mm.mpi, mm.len, mm.len == p.len - 1)) { + if (!pkcs1v15_unpad(mm, out, mm.len == p.len - 1)) { RNP_LOG("Unpad failed."); return RNP_ERROR_GENERIC; } - *out_len = mm.len - padlen; - memcpy(out, &mm.mpi[padlen], *out_len); secure_clear(mm.mpi, PGP_MPINT_SIZE); return RNP_SUCCESS; } diff --git a/src/lib/crypto/ossl_utils.hpp b/src/lib/crypto/ossl_utils.hpp index aff6ae9d1..761efd911 100644 --- a/src/lib/crypto/ossl_utils.hpp +++ b/src/lib/crypto/ossl_utils.hpp @@ -227,6 +227,16 @@ struct PKeyCtxDeleter { using PKeyCtx = std::unique_ptr; +struct CipherCtxDeleter { + void + operator()(EVP_CIPHER_CTX *ptr) const + { + EVP_CIPHER_CTX_free(ptr); + } +}; + +using CipherCtx = std::unique_ptr; + struct MDCtxDeleter { void operator()(EVP_MD_CTX *ptr) const diff --git a/src/lib/crypto/rsa.cpp b/src/lib/crypto/rsa.cpp index 6fc049d6b..4065fd950 100644 --- a/src/lib/crypto/rsa.cpp +++ b/src/lib/crypto/rsa.cpp @@ -87,10 +87,7 @@ Key::validate(rnp::RNG &rng, bool secret) const noexcept } rnp_result_t -Key::encrypt_pkcs1(rnp::RNG & rng, - Encrypted & out, - const uint8_t *in, - size_t in_len) const noexcept +Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const rnp::secure_bytes &in) const noexcept { rnp::botan::Pubkey rsa_key; if (!load_public_key(rsa_key, *this)) { @@ -101,7 +98,8 @@ Key::encrypt_pkcs1(rnp::RNG & rng, out.m.len = PGP_MPINT_SIZE; rnp::botan::op::Encrypt enc_op; if (botan_pk_op_encrypt_create(&enc_op.get(), rsa_key.get(), "PKCS1v15", 0) || - botan_pk_op_encrypt(enc_op.get(), rng.handle(), out.m.mpi, &out.m.len, in, in_len)) { + botan_pk_op_encrypt( + enc_op.get(), rng.handle(), out.m.mpi, &out.m.len, in.data(), in.size())) { out.m.len = 0; return RNP_ERROR_GENERIC; } @@ -167,10 +165,7 @@ Key::sign_pkcs1(rnp::RNG & rng, } rnp_result_t -Key::decrypt_pkcs1(rnp::RNG & rng, - uint8_t * out, - size_t & out_len, - const Encrypted &in) const noexcept +Key::decrypt_pkcs1(rnp::RNG &rng, rnp::secure_bytes &out, const Encrypted &in) const noexcept { if (!q.bytes()) { RNP_LOG("private key not set"); @@ -187,16 +182,19 @@ Key::decrypt_pkcs1(rnp::RNG & rng, if (botan_pk_op_decrypt_create(&decrypt_op.get(), rsa_key.get(), "PKCS1v15", 0)) { return RNP_ERROR_GENERIC; } - /* Skip trailing zeroes if any as Botan3 doesn't like m.len > e.len */ + /* Skip trailing zeroes if any as Botan3 doesn't like m.len > n.len */ size_t skip = 0; while ((in.m.len - skip > e.len) && !in.m.mpi[skip]) { skip++; } - out_len = PGP_MPINT_SIZE; + out.resize(n.len); + size_t out_len = out.size(); if (botan_pk_op_decrypt( - decrypt_op.get(), out, &out_len, in.m.mpi + skip, in.m.len - skip)) { + decrypt_op.get(), out.data(), &out_len, in.m.mpi + skip, in.m.len - skip)) { + out.resize(0); return RNP_ERROR_GENERIC; } + out.resize(out_len); return RNP_SUCCESS; } diff --git a/src/lib/crypto/rsa.h b/src/lib/crypto/rsa.h index 02a4239bc..a8ce7686d 100644 --- a/src/lib/crypto/rsa.h +++ b/src/lib/crypto/rsa.h @@ -31,6 +31,7 @@ #include #include "crypto/rng.h" #include "crypto/mpi.h" +#include "mem.h" namespace pgp { namespace rsa { @@ -73,15 +74,13 @@ class Key { rnp_result_t generate(rnp::RNG &rng, size_t numbits) noexcept; - rnp_result_t encrypt_pkcs1(rnp::RNG & rng, - Encrypted & out, - const uint8_t *in, - size_t in_len) const noexcept; + rnp_result_t encrypt_pkcs1(rnp::RNG & rng, + Encrypted & out, + const rnp::secure_bytes &in) const noexcept; - rnp_result_t decrypt_pkcs1(rnp::RNG & rng, - uint8_t * out, - size_t & out_len, - const Encrypted &in) const noexcept; + rnp_result_t decrypt_pkcs1(rnp::RNG & rng, + rnp::secure_bytes &out, + const Encrypted & in) const noexcept; rnp_result_t verify_pkcs1(const Signature &sig, pgp_hash_alg_t hash_alg, diff --git a/src/lib/crypto/rsa_ossl.cpp b/src/lib/crypto/rsa_ossl.cpp index bb456dca9..6aa7f36e1 100644 --- a/src/lib/crypto/rsa_ossl.cpp +++ b/src/lib/crypto/rsa_ossl.cpp @@ -352,10 +352,7 @@ setup_signature_hash(rnp::ossl::evp::PKeyCtx &ctx, } rnp_result_t -Key::encrypt_pkcs1(rnp::RNG & rng, - Encrypted & out, - const uint8_t *in, - size_t in_len) const noexcept +Key::encrypt_pkcs1(rnp::RNG &rng, Encrypted &out, const rnp::secure_bytes &in) const noexcept { auto ctx = init_context(*this, false); if (!ctx) { @@ -371,7 +368,7 @@ Key::encrypt_pkcs1(rnp::RNG & rng, return RNP_ERROR_GENERIC; // LCOV_EXCL_LINE } out.m.len = PGP_MPINT_SIZE; - if (EVP_PKEY_encrypt(ctx.get(), out.m.mpi, &out.m.len, in, in_len) <= 0) { + if (EVP_PKEY_encrypt(ctx.get(), out.m.mpi, &out.m.len, in.data(), in.size()) <= 0) { RNP_LOG("Encryption failed: %lu", ERR_peek_last_error()); out.m.len = 0; return RNP_ERROR_GENERIC; @@ -475,10 +472,7 @@ Key::sign_pkcs1(rnp::RNG & rng, } rnp_result_t -Key::decrypt_pkcs1(rnp::RNG & rng, - uint8_t * out, - size_t & out_len, - const Encrypted &in) const noexcept +Key::decrypt_pkcs1(rnp::RNG &rng, rnp::secure_bytes &out, const Encrypted &in) const noexcept { if (!q.bytes()) { /* LCOV_EXCL_START */ @@ -499,14 +493,16 @@ Key::decrypt_pkcs1(rnp::RNG & rng, if (!setup_context(ctx)) { return RNP_ERROR_GENERIC; // LCOV_EXCL_LINE } - out_len = PGP_MPINT_SIZE; - if (EVP_PKEY_decrypt(ctx.get(), out, &out_len, in.m.mpi, in.m.len) <= 0) { + out.resize(n.len); + size_t out_len = out.size(); + if (EVP_PKEY_decrypt(ctx.get(), out.data(), &out_len, in.m.mpi, in.m.len) <= 0) { /* LCOV_EXCL_START */ RNP_LOG("Encryption failed: %lu", ERR_peek_last_error()); - out_len = 0; + out.resize(0); return RNP_ERROR_GENERIC; /* LCOV_EXCL_END */ } + out.resize(out_len); return RNP_SUCCESS; } diff --git a/src/lib/crypto/sm2.cpp b/src/lib/crypto/sm2.cpp index 19bda33e9..9a96df40f 100644 --- a/src/lib/crypto/sm2.cpp +++ b/src/lib/crypto/sm2.cpp @@ -32,10 +32,13 @@ #include "sm2.h" #include "utils.h" +namespace pgp { +namespace sm2 { + static bool -sm2_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) +load_public_key(rnp::botan::Pubkey &pubkey, const ec::Key &keydata) { - auto curve = pgp::ec::Curve::get(keydata.curve); + auto curve = ec::Curve::get(keydata.curve); if (!curve) { return false; } @@ -56,9 +59,9 @@ sm2_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) } static bool -sm2_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) +load_secret_key(rnp::botan::Privkey &seckey, const ec::Key &keydata) { - auto curve = pgp::ec::Curve::get(keydata.curve); + auto curve = ec::Curve::get(keydata.curve); if (!curve) { return false; } @@ -72,10 +75,10 @@ sm2_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) } rnp_result_t -sm2_compute_za(const pgp::ec::Key &key, rnp::Hash &hash, const char *ident_field) +compute_za(const ec::Key &key, rnp::Hash &hash, const char *ident_field) { rnp::botan::Pubkey sm2_key; - if (!sm2_load_public_key(sm2_key, key)) { + if (!load_public_key(sm2_key, key)) { RNP_LOG("Failed to load SM2 key"); return RNP_ERROR_GENERIC; } @@ -94,16 +97,15 @@ sm2_compute_za(const pgp::ec::Key &key, rnp::Hash &hash, const char *ident_field RNP_LOG("compute_za failed %d", rc); return RNP_ERROR_GENERIC; } - hash.add(digest_buf.data(), digest_len); + hash.add(digest_buf); return RNP_SUCCESS; } rnp_result_t -sm2_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) +validate_key(rnp::RNG &rng, const ec::Key &key, bool secret) { rnp::botan::Pubkey bpkey; - if (!sm2_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; } @@ -112,7 +114,7 @@ sm2_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } rnp::botan::Privkey bskey; - if (!sm2_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; } @@ -120,36 +122,35 @@ sm2_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) } rnp_result_t -sm2_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 (botan_ffi_supports_api(20180713)) { RNP_LOG("SM2 signatures requires Botan 2.8 or higher"); return RNP_ERROR_NOT_SUPPORTED; } - if (hash_len != rnp::Hash::size(hash_alg)) { + if (hash.size() != rnp::Hash::size(hash_alg)) { return RNP_ERROR_BAD_PARAMETERS; } - auto curve = pgp::ec::Curve::get(key.curve); + auto curve = ec::Curve::get(key.curve); if (!curve) { return RNP_ERROR_BAD_PARAMETERS; } rnp::botan::Privkey b_key; - if (!sm2_load_secret_key(b_key, key)) { + if (!load_secret_key(b_key, key)) { RNP_LOG("Can't load private key"); return RNP_ERROR_BAD_PARAMETERS; } rnp::botan::op::Sign signer; if (botan_pk_op_sign_create(&signer.get(), b_key.get(), ",Raw", 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_SIGNING_FAILED; } @@ -171,22 +172,21 @@ sm2_sign(rnp::RNG & rng, } rnp_result_t -sm2_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) { if (botan_ffi_supports_api(20180713) != 0) { RNP_LOG("SM2 signatures requires Botan 2.8 or higher"); return RNP_ERROR_NOT_SUPPORTED; } - if (hash_len != rnp::Hash::size(hash_alg)) { + if (hash.size() != rnp::Hash::size(hash_alg)) { return RNP_ERROR_BAD_PARAMETERS; } - auto curve = pgp::ec::Curve::get(key.curve); + auto curve = ec::Curve::get(key.curve); if (!curve) { return RNP_ERROR_BAD_PARAMETERS; } @@ -201,14 +201,14 @@ sm2_verify(const pgp::ec::Signature &sig, } rnp::botan::Pubkey pub; - if (!sm2_load_public_key(pub, key)) { + if (!load_public_key(pub, key)) { RNP_LOG("Failed to load public key"); return RNP_ERROR_SIGNATURE_INVALID; } rnp::botan::op::Verify verifier; if (botan_pk_op_verify_create(&verifier.get(), pub.get(), ",Raw", 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; } @@ -223,14 +223,13 @@ sm2_verify(const pgp::ec::Signature &sig, } rnp_result_t -sm2_encrypt(rnp::RNG & rng, - pgp_sm2_encrypted_t &out, - const uint8_t * in, - size_t in_len, - pgp_hash_alg_t hash_algo, - const pgp::ec::Key & key) +encrypt(rnp::RNG & rng, + Encrypted & out, + const rnp::secure_bytes &in, + pgp_hash_alg_t hash_algo, + const ec::Key & key) { - auto curve = pgp::ec::Curve::get(key.curve); + auto curve = ec::Curve::get(key.curve); if (!curve) { return RNP_ERROR_GENERIC; } @@ -246,14 +245,14 @@ sm2_encrypt(rnp::RNG & rng, * the masked ciphertext (out_len) plus a hash. */ size_t point_len = curve->bytes(); - size_t ctext_len = (2 * point_len + 1) + in_len + hash_alg_len; + size_t ctext_len = (2 * point_len + 1) + in.size() + hash_alg_len; if (ctext_len > PGP_MPINT_SIZE) { RNP_LOG("too large output for SM2 encryption"); return RNP_ERROR_GENERIC; } rnp::botan::Pubkey sm2_key; - if (!sm2_load_public_key(sm2_key, key)) { + if (!load_public_key(sm2_key, key)) { RNP_LOG("Failed to load public key"); return RNP_ERROR_GENERIC; } @@ -270,7 +269,8 @@ sm2_encrypt(rnp::RNG & rng, } out.m.len = sizeof(out.m.mpi); - if (botan_pk_op_encrypt(enc_op.get(), rng.handle(), out.m.mpi, &out.m.len, in, in_len)) { + if (botan_pk_op_encrypt( + enc_op.get(), rng.handle(), out.m.mpi, &out.m.len, in.data(), in.size())) { return RNP_ERROR_GENERIC; } out.m.mpi[out.m.len++] = hash_algo; @@ -278,12 +278,9 @@ sm2_encrypt(rnp::RNG & rng, } rnp_result_t -sm2_decrypt(uint8_t * out, - size_t * out_len, - const pgp_sm2_encrypted_t &in, - const pgp::ec::Key & key) +decrypt(rnp::secure_bytes &out, const Encrypted &in, const ec::Key &key) { - auto curve = pgp::ec::Curve::get(key.curve); + auto curve = ec::Curve::get(key.curve); size_t in_len = in.m.bytes(); if (!curve || in_len < 64) { return RNP_ERROR_GENERIC; @@ -297,15 +294,21 @@ sm2_decrypt(uint8_t * out, } rnp::botan::Privkey b_key; - if (!sm2_load_secret_key(b_key, key)) { + if (!load_secret_key(b_key, key)) { RNP_LOG("Can't load private key"); return RNP_ERROR_GENERIC; } + out.resize(in_len - 1); + size_t out_size = out.size(); rnp::botan::op::Decrypt decrypt_op; if (botan_pk_op_decrypt_create(&decrypt_op.get(), b_key.get(), hash_name, 0) || - botan_pk_op_decrypt(decrypt_op.get(), out, out_len, in.m.mpi, in_len - 1)) { + botan_pk_op_decrypt(decrypt_op.get(), out.data(), &out_size, in.m.mpi, in_len - 1)) { return RNP_ERROR_GENERIC; } + out.resize(out_size); return RNP_SUCCESS; } + +} // namespace sm2 +} // namespace pgp diff --git a/src/lib/crypto/sm2.h b/src/lib/crypto/sm2.h index d48e3eac6..c70d78564 100644 --- a/src/lib/crypto/sm2.h +++ b/src/lib/crypto/sm2.h @@ -30,50 +30,49 @@ #include "config.h" #include "ec.h" -typedef struct pgp_sm2_encrypted_t { - pgp::mpi m; -} pgp_sm2_encrypted_t; - namespace rnp { class Hash; } // namespace rnp +namespace pgp { +namespace sm2 { +class Encrypted { + public: + mpi m; +}; + #if defined(ENABLE_SM2) -rnp_result_t sm2_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret); +rnp_result_t validate_key(rnp::RNG &rng, const ec::Key &key, bool secret); /** * Compute the SM2 "ZA" field, and add it to the hash object * * If ident_field is null, uses the default value */ -rnp_result_t sm2_compute_za(const pgp::ec::Key &key, - rnp::Hash & hash, - const char * ident_field = NULL); +rnp_result_t compute_za(const pgp::ec::Key &key, + rnp::Hash & hash, + const char * ident_field = NULL); -rnp_result_t sm2_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 pgp::ec::Key & key); -rnp_result_t sm2_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); -rnp_result_t sm2_encrypt(rnp::RNG & rng, - pgp_sm2_encrypted_t &out, - const uint8_t * in, - size_t in_len, - pgp_hash_alg_t hash_algo, - const pgp::ec::Key & key); +rnp_result_t encrypt(rnp::RNG & rng, + Encrypted & out, + const rnp::secure_bytes &in, + pgp_hash_alg_t hash_algo, + const ec::Key & key); -rnp_result_t sm2_decrypt(uint8_t * out, - size_t * out_len, - const pgp_sm2_encrypted_t &in, - const pgp::ec::Key & key); +rnp_result_t decrypt(rnp::secure_bytes &out, const Encrypted &in, const ec::Key &key); #endif // defined(ENABLE_SM2) +} // namespace sm2 +} // namespace pgp #endif // SM2_H_ diff --git a/src/lib/key_material.cpp b/src/lib/key_material.cpp index 595908ea7..a6df9a390 100644 --- a/src/lib/key_material.cpp +++ b/src/lib/key_material.cpp @@ -324,16 +324,14 @@ KeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) rnp_result_t KeyMaterial::encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const + const rnp::secure_bytes & data) const { return RNP_ERROR_NOT_SUPPORTED; } rnp_result_t KeyMaterial::decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const { return RNP_ERROR_NOT_SUPPORTED; @@ -566,23 +564,17 @@ RSAKeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) rnp_result_t RSAKeyMaterial::encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const + const rnp::secure_bytes & data) const { - return key_.encrypt_pkcs1(ctx.rng, out.rsa, data, len); + return key_.encrypt_pkcs1(ctx.rng, out.rsa, data); } rnp_result_t RSAKeyMaterial::decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const { - if ((alg() != PGP_PKA_RSA) && (alg() != PGP_PKA_RSA_ENCRYPT_ONLY)) { - RNP_LOG("Non-encrypting RSA algorithm: %d\n", alg()); - return RNP_ERROR_BAD_PARAMETERS; - } - return key_.decrypt_pkcs1(ctx.rng, out, out_len, in.rsa); + return key_.decrypt_pkcs1(ctx.rng, out, in.rsa); } rnp_result_t @@ -902,19 +894,17 @@ EGKeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) rnp_result_t EGKeyMaterial::encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const + const rnp::secure_bytes & data) const { - return key_.encrypt_pkcs1(ctx.rng, out.eg, data, len); + return key_.encrypt_pkcs1(ctx.rng, out.eg, data); } rnp_result_t EGKeyMaterial::decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const { - return key_.decrypt_pkcs1(ctx.rng, out, &out_len, in.eg); + return key_.decrypt_pkcs1(ctx.rng, out, in.eg); } rnp_result_t @@ -1147,7 +1137,7 @@ ECDHKeyMaterial::validate_material(rnp::SecurityContext &ctx, bool reset) RNP_LOG("ECDH validate: curve %d is not supported.", key_.curve); return true; } - return !ecdh_validate_key(ctx.rng, key_, secret_); + return !ecdh::validate_key(ctx.rng, key_, secret_); } std::unique_ptr @@ -1193,7 +1183,7 @@ bool ECDHKeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) { auto &ecc = dynamic_cast(params); - if (!ecdh_set_params(key_, ecc.curve())) { + if (!ecdh::set_params(key_, ecc.curve())) { RNP_LOG("Unsupported curve [ID=%d]", ecc.curve()); return false; } @@ -1213,21 +1203,18 @@ ECDHKeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) rnp_result_t ECDHKeyMaterial::encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const + const rnp::secure_bytes & data) const { if (!ec::Curve::is_supported(key_.curve)) { RNP_LOG("ECDH encrypt: curve %d is not supported.", key_.curve); return RNP_ERROR_NOT_SUPPORTED; } - assert(out.ecdh.fp); - return ecdh_encrypt_pkcs5(ctx.rng, out.ecdh, data, len, key_, *out.ecdh.fp); + return ecdh::encrypt_pkcs5(ctx.rng, out.ecdh, data, key_, out.ecdh.fp); } rnp_result_t ECDHKeyMaterial::decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const { if (!ec::Curve::is_supported(key_.curve)) { @@ -1237,7 +1224,7 @@ ECDHKeyMaterial::decrypt(rnp::SecurityContext & ctx, if ((key_.curve == PGP_CURVE_25519) && !x25519_bits_tweaked()) { RNP_LOG("Warning: bits of 25519 secret key are not tweaked."); } - return ecdh_decrypt_pkcs5(out, &out_len, in.ecdh, key_, *in.ecdh.fp); + return ecdh::decrypt_pkcs5(out, in.ecdh, key_, in.ecdh.fp); } pgp_hash_alg_t @@ -1306,7 +1293,7 @@ bool SM2KeyMaterial::validate_material(rnp::SecurityContext &ctx, bool reset) { #if defined(ENABLE_SM2) - return !sm2_validate_key(ctx.rng, key_, secret_); + return !pgp::sm2::validate_key(ctx.rng, key_, secret_); #else RNP_LOG("SM2 key validation is not available."); return false; @@ -1322,11 +1309,10 @@ SM2KeyMaterial::clone() rnp_result_t SM2KeyMaterial::encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const + const rnp::secure_bytes & data) const { #if defined(ENABLE_SM2) - return sm2_encrypt(ctx.rng, out.sm2, data, len, PGP_HASH_SM3, key_); + return pgp::sm2::encrypt(ctx.rng, out.sm2, data, PGP_HASH_SM3, key_); #else RNP_LOG("sm2_encrypt is not available"); return RNP_ERROR_NOT_IMPLEMENTED; @@ -1335,12 +1321,11 @@ SM2KeyMaterial::encrypt(rnp::SecurityContext & ctx, rnp_result_t SM2KeyMaterial::decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const { #if defined(ENABLE_SM2) - return sm2_decrypt(out, &out_len, in.sm2, key_); + return pgp::sm2::decrypt(out, in.sm2, key_); #else RNP_LOG("SM2 decryption is not available."); return RNP_ERROR_NOT_IMPLEMENTED; @@ -1353,7 +1338,7 @@ SM2KeyMaterial::verify(const rnp::SecurityContext & ctx, const rnp::secure_bytes & hash) const { #if defined(ENABLE_SM2) - return sm2_verify(sig.ecc, sig.halg, hash.data(), hash.size(), key_); + return pgp::sm2::verify(sig.ecc, sig.halg, hash, key_); #else RNP_LOG("SM2 verification is not available."); return RNP_ERROR_NOT_IMPLEMENTED; @@ -1370,7 +1355,7 @@ SM2KeyMaterial::sign(rnp::SecurityContext & ctx, if (ret) { return ret; } - return sm2_sign(ctx.rng, sig.ecc, sig.halg, hash.data(), hash.size(), key_); + return pgp::sm2::sign(ctx.rng, sig.ecc, sig.halg, hash, key_); #else RNP_LOG("SM2 signing is not available."); return RNP_ERROR_NOT_IMPLEMENTED; @@ -1381,7 +1366,7 @@ void SM2KeyMaterial::compute_za(rnp::Hash &hash) const { #if defined(ENABLE_SM2) - auto res = sm2_compute_za(key_, hash); + auto res = pgp::sm2::compute_za(key_, hash); if (res) { RNP_LOG("failed to compute SM2 ZA field"); throw rnp::rnp_exception(res); @@ -1608,19 +1593,23 @@ X25519KeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) rnp_result_t X25519KeyMaterial::encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const + const rnp::secure_bytes & data) const { - return x25519_native_encrypt(&ctx.rng, key_.pub, data, len, &out.x25519); + return x25519_native_encrypt(&ctx.rng, key_.pub, data.data(), data.size(), &out.x25519); } rnp_result_t X25519KeyMaterial::decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const { - return x25519_native_decrypt(&ctx.rng, key_, &in.x25519, out, &out_len); + out.resize(PGP_MPINT_SIZE); + size_t out_size = out.size(); + auto ret = x25519_native_decrypt(&ctx.rng, key_, &in.x25519, out.data(), &out_size); + if (!ret) { + out.resize(out_size); + } + return ret; } size_t @@ -1735,19 +1724,23 @@ MlkemEcdhKeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶m rnp_result_t MlkemEcdhKeyMaterial::encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const + const rnp::secure_bytes & data) const { - return key_.pub.encrypt(&ctx.rng, &out.kyber_ecdh, data, len); + return key_.pub.encrypt(&ctx.rng, &out.kyber_ecdh, data.data(), data.size()); } rnp_result_t MlkemEcdhKeyMaterial::decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const { - return key_.priv.decrypt(&ctx.rng, out, &out_len, &in.kyber_ecdh); + out.resize(PGP_MPINT_SIZE); + size_t out_size = out.size(); + auto ret = key_.priv.decrypt(&ctx.rng, out.data(), &out_size, &in.kyber_ecdh); + if (!ret) { + out.resize(out_size); + } + return ret; } size_t diff --git a/src/lib/key_material.hpp b/src/lib/key_material.hpp index 3fc346da1..67628e4b3 100644 --- a/src/lib/key_material.hpp +++ b/src/lib/key_material.hpp @@ -209,11 +209,9 @@ class KeyMaterial { virtual bool generate(rnp::SecurityContext &ctx, const KeyParams ¶ms); virtual rnp_result_t encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const; + const rnp::secure_bytes & data) const; virtual rnp_result_t decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const; virtual rnp_result_t verify(const rnp::SecurityContext & ctx, const pgp_signature_material_t &sig, @@ -258,11 +256,9 @@ class RSAKeyMaterial : public KeyMaterial { bool generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) override; rnp_result_t encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const override; + const rnp::secure_bytes & data) const override; rnp_result_t decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const override; rnp_result_t verify(const rnp::SecurityContext & ctx, const pgp_signature_material_t &sig, @@ -342,11 +338,9 @@ class EGKeyMaterial : public KeyMaterial { bool generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) override; rnp_result_t encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const override; + const rnp::secure_bytes & data) const override; rnp_result_t decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const override; rnp_result_t verify(const rnp::SecurityContext & ctx, const pgp_signature_material_t &sig, @@ -422,11 +416,9 @@ class ECDHKeyMaterial : public ECKeyMaterial { bool generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) override; rnp_result_t encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const override; + const rnp::secure_bytes & data) const override; rnp_result_t decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const override; pgp_hash_alg_t kdf_hash_alg() const noexcept; @@ -466,11 +458,9 @@ class SM2KeyMaterial : public ECKeyMaterial { rnp_result_t encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const override; + const rnp::secure_bytes & data) const override; rnp_result_t decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const override; rnp_result_t verify(const rnp::SecurityContext & ctx, const pgp_signature_material_t &sig, @@ -533,11 +523,9 @@ class X25519KeyMaterial : public KeyMaterial { bool generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) override; rnp_result_t encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const override; + const rnp::secure_bytes & data) const override; rnp_result_t decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const override; size_t bits() const noexcept override; pgp_curve_t curve() const noexcept override; @@ -568,11 +556,9 @@ class MlkemEcdhKeyMaterial : public KeyMaterial { bool generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) override; rnp_result_t encrypt(rnp::SecurityContext & ctx, pgp_encrypted_material_t &out, - const uint8_t * data, - size_t len) const override; + const rnp::secure_bytes & data) const override; rnp_result_t decrypt(rnp::SecurityContext & ctx, - uint8_t * out, - size_t & out_len, + rnp::secure_bytes & out, const pgp_encrypted_material_t &in) const override; size_t bits() const noexcept override; diff --git a/src/lib/types.h b/src/lib/types.h index d819e6df0..0cc618a4c 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -191,12 +191,11 @@ typedef struct pgp_signature_material_t { * Type to keep pk-encrypted data without any openpgp-dependent data. */ typedef struct pgp_encrypted_material_t { - union { - pgp::rsa::Encrypted rsa; - pgp::eg::Encrypted eg; - pgp_sm2_encrypted_t sm2; - pgp_ecdh_encrypted_t ecdh; - }; + /* Temporary: will be replaced by class */ + pgp::rsa::Encrypted rsa; + pgp::eg::Encrypted eg; + pgp::sm2::Encrypted sm2; + pgp::ecdh::Encrypted ecdh; #if defined(ENABLE_CRYPTO_REFRESH) pgp_x25519_encrypted_t x25519; // non-trivial type cannot be member in union #endif diff --git a/src/librepgp/stream-dump.cpp b/src/librepgp/stream-dump.cpp index 93d5f43e7..c51820e2d 100644 --- a/src/librepgp/stream-dump.cpp +++ b/src/librepgp/stream-dump.cpp @@ -1211,9 +1211,9 @@ stream_dump_pk_session_key(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *d case PGP_PKA_ECDH: dst_print_mpi(dst, "ecdh p", material.ecdh.p, ctx->dump_mpi); if (ctx->dump_mpi) { - dst_print_hex(dst, "ecdh m", material.ecdh.m, material.ecdh.mlen, true); + dst_print_hex(dst, "ecdh m", material.ecdh.m.data(), material.ecdh.m.size(), true); } else { - dst_printf(dst, "ecdh m: %d bytes\n", (int) material.ecdh.mlen); + dst_printf(dst, "ecdh m: %zu bytes\n", material.ecdh.m.size()); } break; #if defined(ENABLE_CRYPTO_REFRESH) @@ -2392,11 +2392,10 @@ stream_dump_pk_session_key_json(rnp_dump_ctx_t *ctx, pgp_source_t *src, json_obj break; case PGP_PKA_ECDH: if (!obj_add_mpi_json(material, "p", pkmaterial.ecdh.p, ctx->dump_mpi) || - !json_add(material, "m.bytes", (int) pkmaterial.ecdh.mlen)) { + !json_add(material, "m.bytes", (int) pkmaterial.ecdh.m.size())) { return RNP_ERROR_OUT_OF_MEMORY; // LCOV_EXCL_LINE } - if (ctx->dump_mpi && - !json_add_hex(material, "m", pkmaterial.ecdh.m, pkmaterial.ecdh.mlen)) { + if (ctx->dump_mpi && !json_add_hex(material, "m", pkmaterial.ecdh.m)) { return RNP_ERROR_OUT_OF_MEMORY; // LCOV_EXCL_LINE } break; diff --git a/src/librepgp/stream-packet.cpp b/src/librepgp/stream-packet.cpp index 6e84d133e..384249d72 100644 --- a/src/librepgp/stream-packet.cpp +++ b/src/librepgp/stream-packet.cpp @@ -1235,7 +1235,7 @@ pgp_pk_sesskey_t::parse_material(pgp_encrypted_material_t &material) RNP_LOG("wrong ecdh m len"); return false; } - material.ecdh.mlen = bt; + material.ecdh.m.resize(bt); if (!pkt.get(material.ecdh.m, bt)) { RNP_LOG("failed to get ecdh m len"); return false; @@ -1342,8 +1342,8 @@ pgp_pk_sesskey_t::write_material(const pgp_encrypted_material_t &material) break; case PGP_PKA_ECDH: pktbody.add(material.ecdh.p); - pktbody.add_byte(material.ecdh.mlen); - pktbody.add(material.ecdh.m, material.ecdh.mlen); + pktbody.add_byte(material.ecdh.m.size()); + pktbody.add(material.ecdh.m); break; case PGP_PKA_ELGAMAL: pktbody.add(material.eg.g); diff --git a/src/librepgp/stream-parse.cpp b/src/librepgp/stream-parse.cpp index c11a50770..97d929a23 100644 --- a/src/librepgp/stream-parse.cpp +++ b/src/librepgp/stream-parse.cpp @@ -1607,18 +1607,15 @@ encrypted_try_key(pgp_source_encrypted_param_t *param, } #endif - rnp::secure_bytes decbuf(PGP_MPINT_SIZE, 0); /* Decrypting session key value */ - size_t declen = decbuf.size(); - + rnp::secure_bytes decbuf(PGP_MPINT_SIZE, 0); if (sesskey.alg == PGP_PKA_ECDH) { - encmaterial.ecdh.fp = &seckey.fp(); + encmaterial.ecdh.fp = seckey.fp().vec(); } - auto err = seckey.pkt().material->decrypt(ctx, decbuf.data(), declen, encmaterial); + auto err = seckey.pkt().material->decrypt(ctx, decbuf, encmaterial); if (err) { return false; } - decbuf.resize(declen); /* This is always true for non-experimental pqc/crypto refresh */ if (do_encrypt_pkesk_v3_alg_id(sesskey.alg)) { diff --git a/src/librepgp/stream-write.cpp b/src/librepgp/stream-write.cpp index 1502337c9..b8423af23 100644 --- a/src/librepgp/stream-write.cpp +++ b/src/librepgp/stream-write.cpp @@ -642,10 +642,9 @@ encrypted_add_recipient(pgp_write_handler_t *handler, pgp_encrypted_material_t material; if (userkey->alg() == PGP_PKA_ECDH) { - material.ecdh.fp = &userkey->fp(); + material.ecdh.fp = userkey->fp().vec(); } - auto ret = userkey->pkt().material->encrypt( - *handler->ctx->ctx, material, enckey.data(), enckey.size()); + auto ret = userkey->pkt().material->encrypt(*handler->ctx->ctx, material, enckey); if (ret) { return ret; } diff --git a/src/tests/cipher.cpp b/src/tests/cipher.cpp index 0653ccb28..428e5b9fa 100644 --- a/src/tests/cipher.cpp +++ b/src/tests/cipher.cpp @@ -115,8 +115,8 @@ TEST_F(rnp_tests, cipher_test_success) TEST_F(rnp_tests, pkcs1_rsa_test_success) { - uint8_t ptext[1024 / 8] = {'a', 'b', 'c', 0}; - uint8_t dec[1024 / 8]; + rnp::secure_bytes ptext({'a', 'b', 'c'}); + rnp::secure_bytes dec; rnp::KeygenParams keygen(PGP_PKA_RSA, global_ctx); auto & rsa = dynamic_cast(keygen.key_params()); @@ -126,14 +126,12 @@ TEST_F(rnp_tests, pkcs1_rsa_test_success) assert_true(keygen.generate(seckey, true)); pgp_encrypted_material_t enc; - assert_rnp_success(seckey.material->encrypt(global_ctx, enc, ptext, 3)); + assert_rnp_success(seckey.material->encrypt(global_ctx, enc, ptext)); assert_int_equal(enc.rsa.m.len, 1024 / 8); - memset(dec, 0, sizeof(dec)); - size_t dec_size = 0; - assert_rnp_success(seckey.material->decrypt(global_ctx, dec, dec_size, enc)); - assert_true(bin_eq_hex(dec, 3, "616263")); - assert_int_equal(dec_size, 3); + assert_rnp_success(seckey.material->decrypt(global_ctx, dec, enc)); + assert_int_equal(dec.size(), 3); + assert_true(bin_eq_hex(dec.data(), 3, "616263")); } TEST_F(rnp_tests, rnp_test_eddsa) @@ -177,47 +175,47 @@ TEST_F(rnp_tests, rnp_test_x25519) /* encrypt */ pgp_fingerprint_t fp = {}; assert_rnp_success(pgp_fingerprint(fp, seckey)); - uint8_t in[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + rnp::secure_bytes in({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}); pgp_encrypted_material_t enc = {}; - enc.ecdh.fp = &fp; - assert_rnp_success(seckey.material->encrypt(global_ctx, enc, in, sizeof(in))); - assert_true(enc.ecdh.mlen > 16); + enc.ecdh.fp = fp.vec(); + assert_rnp_success(seckey.material->encrypt(global_ctx, enc, in)); + assert_true(enc.ecdh.m.size() > 16); assert_int_equal(enc.ecdh.p.mpi[0], 0x40); assert_int_equal(enc.ecdh.p.len, 33); /* decrypt */ - uint8_t out[16] = {}; - size_t outlen = sizeof(out); - assert_rnp_success(seckey.material->decrypt(global_ctx, out, outlen, enc)); - assert_int_equal(outlen, 16); - assert_int_equal(memcmp(in, out, 16), 0); + rnp::secure_bytes out; + assert_rnp_success(seckey.material->decrypt(global_ctx, out, enc)); + assert_int_equal(out.size(), 16); + assert_int_equal(memcmp(in.data(), out.data(), 16), 0); /* negative cases */ enc.ecdh.p.mpi[16] ^= 0xff; - assert_rnp_failure(seckey.material->decrypt(global_ctx, out, outlen, enc)); + assert_rnp_failure(seckey.material->decrypt(global_ctx, out, enc)); enc.ecdh.p.mpi[16] ^= 0xff; enc.ecdh.p.mpi[0] = 0x04; - assert_rnp_failure(seckey.material->decrypt(global_ctx, out, outlen, enc)); + assert_rnp_failure(seckey.material->decrypt(global_ctx, out, enc)); enc.ecdh.p.mpi[0] = 0x40; - enc.ecdh.mlen--; - assert_rnp_failure(seckey.material->decrypt(global_ctx, out, outlen, enc)); + uint8_t back = enc.ecdh.m.back(); + enc.ecdh.m.pop_back(); + assert_rnp_failure(seckey.material->decrypt(global_ctx, out, enc)); - enc.ecdh.mlen += 2; - assert_rnp_failure(seckey.material->decrypt(global_ctx, out, outlen, enc)); + enc.ecdh.m.push_back(back); + enc.ecdh.m.push_back(0); + assert_rnp_failure(seckey.material->decrypt(global_ctx, out, enc)); } static void elgamal_roundtrip(const pgp::eg::Key &key, rnp::RNG &rng) { - const uint8_t in_b[] = {0x01, 0x02, 0x03, 0x04, 0x17}; + rnp::secure_bytes in_b({0x01, 0x02, 0x03, 0x04, 0x17}); pgp::eg::Encrypted enc = {{{0}}}; - uint8_t res[1024]; - size_t res_len = 0; + rnp::secure_bytes res; - assert_rnp_success(key.encrypt_pkcs1(rng, enc, in_b, sizeof(in_b))); - assert_rnp_success(key.decrypt_pkcs1(rng, res, &res_len, enc)); - assert_int_equal(res_len, sizeof(in_b)); - assert_true(bin_eq_hex(res, res_len, "0102030417")); + assert_rnp_success(key.encrypt_pkcs1(rng, enc, in_b)); + assert_rnp_success(key.decrypt_pkcs1(rng, res, enc)); + assert_int_equal(res.size(), in_b.size()); + assert_true(bin_eq_hex(res.data(), res.size(), "0102030417")); } TEST_F(rnp_tests, raw_elgamal_random_key_test_success) @@ -277,8 +275,8 @@ TEST_F(rnp_tests, ecdh_roundtrip) } curves[] = { {PGP_CURVE_NIST_P_256, 32}, {PGP_CURVE_NIST_P_384, 48}, {PGP_CURVE_NIST_P_521, 66}}; - uint8_t in[32] = {1, 2, 3}; - size_t in_len = sizeof(in); + rnp::secure_bytes in({1, 2, 3}); + in.insert(in.end(), 32 - in.size(), 0); for (size_t i = 0; i < ARRAY_SIZE(curves); i++) { rnp::KeygenParams keygen(PGP_PKA_ECDH, global_ctx); @@ -293,15 +291,14 @@ TEST_F(rnp_tests, ecdh_roundtrip) assert_rnp_success(pgp_fingerprint(ecdh_key1_fpr, ecdh_key1)); pgp_encrypted_material_t enc{}; - enc.ecdh.fp = &ecdh_key1_fpr; - assert_rnp_success(ecdh_key1.material->encrypt(global_ctx, enc, in, in_len)); + enc.ecdh.fp = ecdh_key1_fpr.vec(); + assert_rnp_success(ecdh_key1.material->encrypt(global_ctx, enc, in)); - uint8_t res[40] = {0}; - size_t res_len = sizeof(res); - assert_rnp_success(ecdh_key1.material->decrypt(global_ctx, res, res_len, enc)); + rnp::secure_bytes res; + assert_rnp_success(ecdh_key1.material->decrypt(global_ctx, res, enc)); - assert_int_equal(in_len, res_len); - assert_int_equal(memcmp(in, res, res_len), 0); + assert_int_equal(in.size(), res.size()); + assert_true(in == res); } } @@ -328,10 +325,9 @@ class ECDHTestKeyMaterial : public ECDHKeyMaterial { TEST_F(rnp_tests, ecdh_decryptionNegativeCases) { - uint8_t in[32] = {1, 2, 3, 4}; - size_t in_len = sizeof(in); - uint8_t res[36] = {0}; - size_t res_len = sizeof(res); + rnp::secure_bytes in({1, 2, 3, 4}); + in.insert(in.end(), 32 - in.size(), 0); + rnp::secure_bytes res; rnp::KeygenParams keygen(PGP_PKA_ECDH, global_ctx); keygen.set_hash(PGP_HASH_SHA512); @@ -345,25 +341,20 @@ TEST_F(rnp_tests, ecdh_decryptionNegativeCases) assert_rnp_success(pgp_fingerprint(ecdh_key1_fpr, ecdh_key1)); pgp_encrypted_material_t enc; - enc.ecdh.fp = &ecdh_key1_fpr; - assert_rnp_success(ecdh_key1.material->encrypt(global_ctx, enc, in, in_len)); + enc.ecdh.fp = ecdh_key1_fpr.vec(); + assert_rnp_success(ecdh_key1.material->encrypt(global_ctx, enc, in)); - assert_int_equal(ecdh_key1.material->decrypt(global_ctx, nullptr, res_len, enc), - RNP_ERROR_BAD_PARAMETERS); + auto m = enc.ecdh.m; + enc.ecdh.m.resize(0); + assert_int_equal(ecdh_key1.material->decrypt(global_ctx, res, enc), RNP_ERROR_GENERIC); - size_t mlen = enc.ecdh.mlen; - enc.ecdh.mlen = 0; - assert_int_equal(ecdh_key1.material->decrypt(global_ctx, res, res_len, enc), - RNP_ERROR_GENERIC); - - enc.ecdh.mlen = mlen - 1; - assert_int_equal(ecdh_key1.material->decrypt(global_ctx, res, res_len, enc), - RNP_ERROR_GENERIC); + enc.ecdh.m.assign(m.begin(), m.end() - 1); + assert_int_equal(ecdh_key1.material->decrypt(global_ctx, res, enc), RNP_ERROR_GENERIC); pgp::ECDHTestKeyMaterial key1_mod( dynamic_cast(*ecdh_key1.material)); key1_mod.set_key_wrap_alg(PGP_SA_IDEA); - assert_int_equal(key1_mod.decrypt(global_ctx, res, res_len, enc), RNP_ERROR_NOT_SUPPORTED); + assert_int_equal(key1_mod.decrypt(global_ctx, res, enc), RNP_ERROR_NOT_SUPPORTED); } #if defined(ENABLE_SM2) @@ -372,8 +363,8 @@ TEST_F(rnp_tests, sm2_roundtrip) rnp::KeygenParams keygen(PGP_PKA_SM2, global_ctx); keygen.set_hash(PGP_HASH_SM3); - uint8_t key[27] = {0}; - global_ctx.rng.get(key, sizeof(key)); + rnp::secure_bytes key(27, 0); + global_ctx.rng.get(key.data(), key.size()); pgp_key_pkt_t seckey; assert_true(keygen.generate(seckey, true)); @@ -384,15 +375,14 @@ TEST_F(rnp_tests, sm2_roundtrip) pgp_encrypted_material_t enc; for (size_t i = 0; i < ARRAY_SIZE(hashes); ++i) { - auto ret = eckey.encrypt(global_ctx, enc, key, sizeof(key)); + auto ret = eckey.encrypt(global_ctx, enc, key); assert_int_equal(ret, RNP_SUCCESS); - uint8_t dec[32] = {0}; - size_t dec_size = sizeof(dec); - ret = eckey.decrypt(global_ctx, dec, dec_size, enc); + rnp::secure_bytes dec(32, 0); + ret = eckey.decrypt(global_ctx, dec, enc); assert_int_equal(ret, RNP_SUCCESS); - assert_int_equal(dec_size, sizeof(key)); - assert_int_equal(memcmp(key, dec, dec_size), 0); + assert_int_equal(dec.size(), key.size()); + assert_true(dec == key); } } #endif @@ -408,8 +398,6 @@ TEST_F(rnp_tests, sm2_sm3_signature_test) pgp_hash_alg_t hash_alg = PGP_HASH_SM3; const size_t hash_len = rnp::Hash::size(hash_alg); - uint8_t digest[PGP_MAX_HASH_SIZE]; - sm2_key.curve = PGP_CURVE_NIST_P_256; hex2mpi(&sm2_key.p, @@ -417,29 +405,30 @@ TEST_F(rnp_tests, sm2_sm3_signature_test) "c82f49ee0a5b11df22cb0c3c6d9d5526d9e24d02ff8c83c06a859c26565f1"); hex2mpi(&sm2_key.x, "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC"); - assert_rnp_success(sm2_validate_key(global_ctx.rng, sm2_key, true)); + assert_rnp_success(pgp::sm2::validate_key(global_ctx.rng, sm2_key, true)); auto hash = rnp::Hash::create(hash_alg); - assert_rnp_success(sm2_compute_za(sm2_key, *hash, "sm2_p256_test@example.com")); + assert_rnp_success(pgp::sm2::compute_za(sm2_key, *hash, "sm2_p256_test@example.com")); hash->add(msg, strlen(msg)); - assert_int_equal(hash->finish(digest), hash_len); + rnp::secure_bytes digest(hash_len, 0); + assert_int_equal(hash->finish(digest.data()), hash_len); // First generate a signature, then verify it - assert_rnp_success(sm2_sign(global_ctx.rng, sig, hash_alg, digest, hash_len, sm2_key)); - assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); + assert_rnp_success(pgp::sm2::sign(global_ctx.rng, sig, hash_alg, digest, sm2_key)); + assert_rnp_success(pgp::sm2::verify(sig, hash_alg, digest, sm2_key)); // Check that invalid signatures are rejected digest[0] ^= 1; - assert_rnp_failure(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); + assert_rnp_failure(pgp::sm2::verify(sig, hash_alg, digest, sm2_key)); digest[0] ^= 1; - assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); + assert_rnp_success(pgp::sm2::verify(sig, hash_alg, digest, sm2_key)); // Now verify a known good signature for this key/message (generated by GmSSL) hex2mpi(&sig.r, "96AA39A0C4A5C454653F394E86386F2E38BE14C57D0E555F3A27A5CEF30E51BD"); hex2mpi(&sig.s, "62372BE4AC97DBE725AC0B279BB8FD15883858D814FD792DDB0A401DCC988E70"); - assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); + assert_rnp_success(pgp::sm2::verify(sig, hash_alg, digest, sm2_key)); } #endif @@ -451,7 +440,6 @@ TEST_F(rnp_tests, sm2_sha256_signature_test) pgp::ec::Signature sig; pgp_hash_alg_t hash_alg = PGP_HASH_SHA256; const size_t hash_len = rnp::Hash::size(hash_alg); - uint8_t digest[PGP_MAX_HASH_SIZE]; sm2_key.curve = PGP_CURVE_SM2_P_256; hex2mpi(&sm2_key.p, @@ -459,28 +447,29 @@ TEST_F(rnp_tests, sm2_sha256_signature_test) "05e6213eee145b748e36e274e5f101dc10d7bbc9dab9a04022e73b76e02cd"); hex2mpi(&sm2_key.x, "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC"); - assert_rnp_success(sm2_validate_key(global_ctx.rng, sm2_key, true)); + assert_rnp_success(pgp::sm2::validate_key(global_ctx.rng, sm2_key, true)); auto hash = rnp::Hash::create(hash_alg); - assert_rnp_success(sm2_compute_za(sm2_key, *hash, "sm2test@example.com")); + assert_rnp_success(pgp::sm2::compute_za(sm2_key, *hash, "sm2test@example.com")); hash->add(msg, strlen(msg)); - assert_int_equal(hash->finish(digest), hash_len); + rnp::secure_bytes digest(hash_len, 0); + assert_int_equal(hash->finish(digest.data()), hash_len); // First generate a signature, then verify it - assert_rnp_success(sm2_sign(global_ctx.rng, sig, hash_alg, digest, hash_len, sm2_key)); - assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); + assert_rnp_success(pgp::sm2::sign(global_ctx.rng, sig, hash_alg, digest, sm2_key)); + assert_rnp_success(pgp::sm2::verify(sig, hash_alg, digest, sm2_key)); // Check that invalid signatures are rejected digest[0] ^= 1; - assert_rnp_failure(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); + assert_rnp_failure(pgp::sm2::verify(sig, hash_alg, digest, sm2_key)); digest[0] ^= 1; - assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); + assert_rnp_success(pgp::sm2::verify(sig, hash_alg, digest, sm2_key)); // Now verify a known good signature for this key/message (generated by GmSSL) hex2mpi(&sig.r, "94DA20EA69E4FC70692158BF3D30F87682A4B2F84DF4A4829A1EFC5D9C979D3F"); hex2mpi(&sig.s, "EE15AF8D455B728AB80E592FCB654BF5B05620B2F4D25749D263D5C01FAD365F"); - assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); + assert_rnp_success(pgp::sm2::verify(sig, hash_alg, digest, sm2_key)); } #endif @@ -572,12 +561,10 @@ TEST_F(rnp_tests, kyber_ecdh_roundtrip) PGP_PKA_KYBER768_BP256, PGP_PKA_KYBER1024_BP384}; - uint8_t in[32] = {0}; - size_t in_len = sizeof(in); - uint8_t res[36] = {0}; - size_t res_len = sizeof(res); + rnp::secure_bytes in(32, 0); + rnp::secure_bytes res(36); - for (size_t i = 0; i < in_len; i++) { + for (size_t i = 0; i < in.size(); i++) { in[i] = i; // assures that we do not have a special case with all-zeroes } @@ -589,11 +576,11 @@ TEST_F(rnp_tests, kyber_ecdh_roundtrip) assert_true(keygen.generate(key_pkt, true)); pgp_encrypted_material_t enc; - assert_rnp_success(key_pkt.material->encrypt(global_ctx, enc, in, in_len)); - assert_rnp_success(key_pkt.material->decrypt(global_ctx, res, res_len, enc)); + assert_rnp_success(key_pkt.material->encrypt(global_ctx, enc, in)); + assert_rnp_success(key_pkt.material->decrypt(global_ctx, res, enc)); - assert_int_equal(in_len, res_len); - assert_int_equal(memcmp(in, res, res_len), 0); + assert_int_equal(in.size(), res.size()); + assert_true(in == res); } }