diff --git a/src/lib/crypto/botan_utils.hpp b/src/lib/crypto/botan_utils.hpp index 4f54acf1d..cc8aae59f 100644 --- a/src/lib/crypto/botan_utils.hpp +++ b/src/lib/crypto/botan_utils.hpp @@ -41,15 +41,17 @@ class bn { botan_mp_init(&bn_); } - bn(const pgp::mpi &val) + bn(const uint8_t *val, size_t len) { botan_mp_init(&bn_); - if (bn_ && botan_mp_from_bin(bn_, val.mpi, val.len)) { + if (bn_ && botan_mp_from_bin(bn_, val, len)) { botan_mp_destroy(bn_); bn_ = NULL; } } + bn(const pgp::mpi &val) : bn(val.mpi, val.len){}; + ~bn() { botan_mp_destroy(bn_); @@ -75,7 +77,13 @@ class bn { val.len = 0; return false; } - return botan_mp_to_bin(bn_, val.mpi) == 0; + return !botan_mp_to_bin(bn_, val.mpi); + } + + bool + bin(uint8_t *b) const noexcept + { + return b ? !botan_mp_to_bin(bn_, b) : false; } size_t @@ -121,6 +129,12 @@ class Privkey { { return key_; }; + + const botan_privkey_t & + get() const noexcept + { + return key_; + }; }; namespace op { @@ -188,6 +202,22 @@ class Sign { }; }; +class KeyAgreement { + botan_pk_op_ka_t op_; + + public: + KeyAgreement() : op_(NULL){}; + ~KeyAgreement() + { + botan_pk_op_key_agreement_destroy(op_); + } + botan_pk_op_ka_t & + get() noexcept + { + return op_; + }; +}; + } // namespace op } // namespace botan } // namespace rnp diff --git a/src/lib/crypto/ec.cpp b/src/lib/crypto/ec.cpp index ba3ef30c3..e4353e2dd 100644 --- a/src/lib/crypto/ec.cpp +++ b/src/lib/crypto/ec.cpp @@ -32,14 +32,19 @@ #include "utils.h" #include "mem.h" #include "bn.h" +#include "botan_utils.hpp" #if defined(ENABLE_CRYPTO_REFRESH) || defined(ENABLE_PQC) #include "x25519.h" #include "ed25519.h" +#include "botan_utils.hpp" #include "botan/bigint.h" #include "botan/ecdh.h" #include #endif +namespace pgp { +namespace ec { + static id_str_pair ec_algo_to_botan[] = { {PGP_PKA_ECDH, "ECDH"}, {PGP_PKA_ECDSA, "ECDSA"}, @@ -48,53 +53,42 @@ static id_str_pair ec_algo_to_botan[] = { }; rnp_result_t -x25519_generate(rnp::RNG *rng, pgp_ec_key_t *key) +Key::generate_x25519(rnp::RNG &rng) { - botan_privkey_t pr_key = NULL; - botan_pubkey_t pu_key = NULL; - rnp_result_t ret = RNP_ERROR_KEY_GENERATION; - - rnp::secure_array keyle; - - if (botan_privkey_create(&pr_key, "Curve25519", "", rng->handle())) { - goto end; + rnp::botan::Privkey pr_key; + if (botan_privkey_create(&pr_key.get(), "Curve25519", "", rng.handle())) { + return RNP_ERROR_KEY_GENERATION; } - if (botan_privkey_export_pubkey(&pu_key, pr_key)) { - goto end; + rnp::botan::Pubkey pu_key; + if (botan_privkey_export_pubkey(&pu_key.get(), pr_key.get())) { + return RNP_ERROR_KEY_GENERATION; } /* botan returns key in little-endian, while mpi is big-endian */ - if (botan_privkey_x25519_get_privkey(pr_key, keyle.data())) { - goto end; + rnp::secure_array keyle; + if (botan_privkey_x25519_get_privkey(pr_key.get(), keyle.data())) { + return RNP_ERROR_KEY_GENERATION; } for (int i = 0; i < 32; i++) { - key->x.mpi[31 - i] = keyle[i]; + x.mpi[31 - i] = keyle[i]; } - key->x.len = 32; + x.len = 32; /* botan doesn't tweak secret key bits, so we should do that here */ - if (!x25519_tweak_bits(*key)) { - goto end; + if (!x25519_tweak_bits(*this)) { + return RNP_ERROR_KEY_GENERATION; } - if (botan_pubkey_x25519_get_pubkey(pu_key, &key->p.mpi[1])) { - goto end; + if (botan_pubkey_x25519_get_pubkey(pu_key.get(), &p.mpi[1])) { + return RNP_ERROR_KEY_GENERATION; } - key->p.len = 33; - key->p.mpi[0] = 0x40; - - ret = RNP_SUCCESS; -end: - botan_privkey_destroy(pr_key); - botan_pubkey_destroy(pu_key); - return ret; + p.len = 33; + p.mpi[0] = 0x40; + return RNP_SUCCESS; } rnp_result_t -ec_generate(rnp::RNG * rng, - pgp_ec_key_t * key, - const pgp_pubkey_alg_t alg_id, - const pgp_curve_t curve) +Key::generate(rnp::RNG &rng, const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve) { /** * Keeps "0x04 || x || y" @@ -102,69 +96,48 @@ ec_generate(rnp::RNG * rng, * * P-521 is biggest supported curve */ - botan_privkey_t pr_key = NULL; - botan_pubkey_t pu_key = NULL; - bignum_t * px = NULL; - bignum_t * py = NULL; - bignum_t * x = NULL; - rnp_result_t ret = RNP_ERROR_KEY_GENERATION; - size_t filed_byte_size = 0; - - if (!alg_allows_curve(alg_id, curve)) { + if (!Curve::alg_allows(alg_id, curve)) { return RNP_ERROR_BAD_PARAMETERS; } const char *ec_algo = id_str_pair::lookup(ec_algo_to_botan, alg_id, NULL); assert(ec_algo); - auto ec_desc = get_curve_desc(curve); + auto ec_desc = Curve::get(curve); if (!ec_desc) { - ret = RNP_ERROR_BAD_PARAMETERS; - goto end; + return RNP_ERROR_BAD_PARAMETERS; } - filed_byte_size = BITS_TO_BYTES(ec_desc->bitlen); // at this point it must succeed - if (botan_privkey_create(&pr_key, ec_algo, ec_desc->botan_name, rng->handle())) { - goto end; + rnp::botan::Privkey pr_key; + if (botan_privkey_create(&pr_key.get(), ec_algo, ec_desc->botan_name, rng.handle())) { + return RNP_ERROR_KEY_GENERATION; } - if (botan_privkey_export_pubkey(&pu_key, pr_key)) { - goto end; + rnp::botan::Pubkey pu_key; + if (botan_privkey_export_pubkey(&pu_key.get(), pr_key.get())) { + return RNP_ERROR_KEY_GENERATION; } - // Crash if seckey is null. It's clean and easy to debug design - px = bn_new(); - py = bn_new(); - x = bn_new(); + rnp::bn px; + rnp::bn py; + rnp::bn bx; - if (!px || !py || !x) { + if (!px || !py || !bx) { RNP_LOG("Allocation failed"); - ret = RNP_ERROR_OUT_OF_MEMORY; - goto end; + return RNP_ERROR_OUT_OF_MEMORY; } - if (botan_pubkey_get_field(BN_HANDLE_PTR(px), pu_key, "public_x")) { - goto end; + if (botan_pubkey_get_field(px.get(), pu_key.get(), "public_x") || + botan_pubkey_get_field(py.get(), pu_key.get(), "public_y") || + botan_privkey_get_field(bx.get(), pr_key.get(), "x")) { + return RNP_ERROR_KEY_GENERATION; } - if (botan_pubkey_get_field(BN_HANDLE_PTR(py), pu_key, "public_y")) { - goto end; - } - - if (botan_privkey_get_field(BN_HANDLE_PTR(x), pr_key, "x")) { - goto end; - } - - size_t x_bytes; - size_t y_bytes; - x_bytes = bn_num_bytes(*px); - y_bytes = bn_num_bytes(*py); - // Safety check - if ((x_bytes > filed_byte_size) || (y_bytes > filed_byte_size)) { + size_t field_size = ec_desc->bytes(); + if ((px.bytes() > field_size) || (py.bytes() > field_size)) { RNP_LOG("Key generation failed"); - ret = RNP_ERROR_BAD_PARAMETERS; - goto end; + return RNP_ERROR_BAD_PARAMETERS; } /* @@ -176,23 +149,19 @@ ec_generate(rnp::RNG * rng, * Note: Generated pk/sk may not always have exact number of bytes * which is important when converting to octet-string */ - memset(key->p.mpi, 0, sizeof(key->p.mpi)); - key->p.mpi[0] = 0x04; - bn_bn2bin(px, &key->p.mpi[1 + filed_byte_size - x_bytes]); - bn_bn2bin(py, &key->p.mpi[1 + filed_byte_size + (filed_byte_size - y_bytes)]); - key->p.len = 2 * filed_byte_size + 1; + memset(p.mpi, 0, sizeof(p.mpi)); + p.mpi[0] = 0x04; + px.bin(&p.mpi[1 + field_size - px.bytes()]); + py.bin(&p.mpi[1 + 2 * field_size - py.bytes()]); + p.len = 2 * field_size + 1; /* secret key value */ - bn2mpi(x, &key->x); - ret = RNP_SUCCESS; -end: - botan_privkey_destroy(pr_key); - botan_pubkey_destroy(pu_key); - bn_free(px); - bn_free(py); - bn_free(x); - return ret; + bx.mpi(x); + return RNP_SUCCESS; } +} // namespace ec +} // namespace pgp + #if defined(ENABLE_CRYPTO_REFRESH) || defined(ENABLE_PQC) static bool is_generic_prime_curve(pgp_curve_t curve) @@ -229,8 +198,8 @@ ec_generate_generic_native(rnp::RNG * rng, return RNP_ERROR_BAD_PARAMETERS; } - auto ec_desc = get_curve_desc(curve); - const size_t curve_order = BITS_TO_BYTES(ec_desc->bitlen); + auto ec_desc = pgp::ec::Curve::get(curve); + const size_t curve_order = ec_desc->bytes(); Botan::ECDH_PrivateKey privkey_botan(*(rng->obj()), Botan::EC_Group(ec_desc->botan_name)); Botan::BigInt pub_x = privkey_botan.public_point().get_affine_x(); diff --git a/src/lib/crypto/ec.h b/src/lib/crypto/ec.h index ae541814f..eba765ff4 100644 --- a/src/lib/crypto/ec.h +++ b/src/lib/crypto/ec.h @@ -1,11 +1,7 @@ -/* - * Copyright (c) 2017-2020 [Ribose Inc](https://www.ribose.com). +/*- + * Copyright (c) 2017-2024 Ribose Inc. * All rights reserved. * - * This code is originally derived from software contributed to - * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and - * carried further by Ribose Inc (https://www.ribose.com). - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,16 +32,20 @@ #include "crypto/rng.h" #include "crypto/mpi.h" #include "crypto/mem.h" +#include "utils.h" #include #define MAX_CURVE_BIT_SIZE 521 // secp521r1 /* Maximal byte size of elliptic curve order (NIST P-521) */ #define MAX_CURVE_BYTELEN ((MAX_CURVE_BIT_SIZE + 7) / 8) +namespace pgp { +namespace ec { /** * Structure holds description of elliptic curve */ -typedef struct ec_curve_desc_t { +class Curve { + public: const pgp_curve_t rnp_curve_id; const size_t bitlen; const std::vector OID; @@ -66,9 +66,52 @@ typedef struct ec_curve_desc_t { const char *gx; const char *gy; const char *h; -} ec_curve_desc_t; -typedef struct pgp_ec_key_t { + /** + * @brief Finds curve ID by hex representation of OID + * @param oid buffer with OID in hex + * @returns success curve ID + * failure PGP_CURVE_MAX is returned + * @remarks see RFC 4880 bis 01 - 9.2 ECC Curve OID + */ + static pgp_curve_t by_OID(const std::vector &oid); + + static pgp_curve_t by_name(const char *name); + + /** + * @brief Returns pointer to the curve descriptor + * + * @param Valid curve ID + * + * @returns NULL if wrong ID provided, otherwise descriptor + * + */ + static const Curve *get(const pgp_curve_t curve_id); + + static bool alg_allows(pgp_pubkey_alg_t alg, pgp_curve_t curve); + + /** + * @brief Check whether curve is supported for operations. + * All available curves are supported for reading/parsing key data, however some of + * them may be disabled for use, i.e. for key generation/signing/encryption. + */ + static bool is_supported(pgp_curve_t curve); + + size_t + bytes() const noexcept + { + return BITS_TO_BYTES(bitlen); + } +}; + +class Signature { + public: + pgp::mpi r; + pgp::mpi s; +}; + +class Key { + public: pgp_curve_t curve; pgp::mpi p; /* secret mpi */ @@ -83,16 +126,58 @@ typedef struct pgp_ec_key_t { x.forget(); } - ~pgp_ec_key_t() + ~Key() { clear_secret(); } -} pgp_ec_key_t; -typedef struct pgp_ec_signature_t { - pgp::mpi r; - pgp::mpi s; -} pgp_ec_signature_t; + /** + * @brief Generates EC key in uncompressed format + * + * @param rng initialized rnp::RNG context + * @param alg_id ID of EC algorithm + * @param curve underlying ECC curve ID + * + * @pre alg_id MUST be supported algorithm + * + * @returns RNP_ERROR_BAD_PARAMETERS unknown curve_id + * @returns RNP_ERROR_OUT_OF_MEMORY memory allocation failed + * @returns RNP_ERROR_KEY_GENERATION implementation error + */ + rnp_result_t generate(rnp::RNG & rng, + const pgp_pubkey_alg_t alg_id, + const pgp_curve_t curve); + + /** + * @brief Generates x25519 ECDH key in x25519-specific format + * + * @param rng initialized rnp::RNG context* + * + * @returns RNP_ERROR_KEY_GENERATION implementation error + */ + rnp_result_t generate_x25519(rnp::RNG &rng); +}; + +} // namespace ec +} // namespace pgp + +/** + * @brief Set least significant/most significant bits of the 25519 secret key as per + * specification. + * + * @param key secret key. + * @return true on success or false otherwise. + */ +bool x25519_tweak_bits(pgp::ec::Key &key); + +/** + * @brief Check whether least significant/most significant bits of 25519 secret key are + * correctly tweaked. + * + * @param key secret key. + * @return true if bits are set correctly, and false otherwise. + */ +bool x25519_bits_tweaked(const pgp::ec::Key &key); #if defined(ENABLE_CRYPTO_REFRESH) || defined(ENABLE_PQC) typedef struct pgp_ed25519_key_t { @@ -137,84 +222,6 @@ typedef struct pgp_x25519_encrypted_t { std::vector eph_key; std::vector enc_sess_key; } pgp_x25519_encrypted_t; -#endif - -/* - * @brief Finds curve ID by hex representation of OID - * @param oid buffer with OID in hex - * @returns success curve ID - * failure PGP_CURVE_MAX is returned - * @remarks see RFC 4880 bis 01 - 9.2 ECC Curve OID - */ -pgp_curve_t find_curve_by_OID(const std::vector &oid); - -pgp_curve_t find_curve_by_name(const char *name); - -/* - * @brief Returns pointer to the curve descriptor - * - * @param Valid curve ID - * - * @returns NULL if wrong ID provided, otherwise descriptor - * - */ -const ec_curve_desc_t *get_curve_desc(const pgp_curve_t curve_id); - -bool alg_allows_curve(pgp_pubkey_alg_t alg, pgp_curve_t curve); - -/** - * @brief Check whether curve is supported for operations. - * All available curves are supported for reading/parsing key data, however some of them - * may be disabled for use, i.e. for key generation/signing/encryption. - */ -bool curve_supported(pgp_curve_t curve); - -/* - * @brief Generates EC key in uncompressed format - * - * @param rng initialized rnp::RNG context* - * @param key key data to be generated - * @param alg_id ID of EC algorithm - * @param curve underlying ECC curve ID - * - * @pre alg_id MUST be supported algorithm - * - * @returns RNP_ERROR_BAD_PARAMETERS unknown curve_id - * @returns RNP_ERROR_OUT_OF_MEMORY memory allocation failed - * @returns RNP_ERROR_KEY_GENERATION implementation error - */ -rnp_result_t ec_generate(rnp::RNG * rng, - pgp_ec_key_t * key, - const pgp_pubkey_alg_t alg_id, - const pgp_curve_t curve); - -/* - * @brief Generates x25519 ECDH key in x25519-specific format - * - * @param rng initialized rnp::RNG context* - * @param key key data to be generated - * - * @returns RNP_ERROR_KEY_GENERATION implementation error - */ -rnp_result_t x25519_generate(rnp::RNG *rng, pgp_ec_key_t *key); - -/** - * @brief Set least significant/most significant bits of the 25519 secret key as per - * specification. - * - * @param key secret key. - * @return true on success or false otherwise. - */ -bool x25519_tweak_bits(pgp_ec_key_t &key); - -/** - * @brief Check whether least significant/most significant bits of 25519 secret key are - * correctly tweaked. - * - * @param key secret key. - * @return true if bits are set correctly, and false otherwise. - */ -bool x25519_bits_tweaked(const pgp_ec_key_t &key); /* * @brief Generates EC keys in "native" or SEC1-encoded uncompressed format @@ -233,3 +240,5 @@ rnp_result_t ec_generate_native(rnp::RNG * rng, pgp_curve_t curve, pgp_pubkey_alg_t alg); #endif + +#endif diff --git a/src/lib/crypto/ec_curves.cpp b/src/lib/crypto/ec_curves.cpp index 41f97c46d..379a6f938 100644 --- a/src/lib/crypto/ec_curves.cpp +++ b/src/lib/crypto/ec_curves.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2021-2024, [Ribose Inc](https://www.ribose.com). * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,6 +30,8 @@ #include "utils.h" #include "str-utils.h" +namespace pgp { +namespace ec { /** * EC Curves definition used by implementation * @@ -38,7 +40,7 @@ * Order of the elements in this array corresponds to * values in pgp_curve_t enum. */ -static const ec_curve_desc_t ec_curves[] = { +static const Curve ec_curves[] = { {PGP_CURVE_UNKNOWN, 0, {0}, NULL, NULL}, {PGP_CURVE_NIST_P_256, @@ -256,7 +258,7 @@ static const ec_curve_desc_t ec_curves[] = { }; pgp_curve_t -find_curve_by_OID(const std::vector &oid) +Curve::by_OID(const std::vector &oid) { for (size_t i = 0; i < PGP_CURVE_MAX; i++) { if (oid == ec_curves[i].OID) { @@ -267,7 +269,7 @@ find_curve_by_OID(const std::vector &oid) } pgp_curve_t -find_curve_by_name(const char *name) +Curve::by_name(const char *name) { for (size_t i = 1; i < PGP_CURVE_MAX; i++) { if (rnp::str_case_eq(ec_curves[i].pgp_name, name)) { @@ -278,14 +280,14 @@ find_curve_by_name(const char *name) return PGP_CURVE_MAX; } -const ec_curve_desc_t * -get_curve_desc(const pgp_curve_t curve_id) +const Curve * +Curve::get(const pgp_curve_t curve_id) { return (curve_id < PGP_CURVE_MAX && curve_id > 0) ? &ec_curves[curve_id] : NULL; } bool -alg_allows_curve(pgp_pubkey_alg_t alg, pgp_curve_t curve) +Curve::alg_allows(pgp_pubkey_alg_t alg, pgp_curve_t curve) { /* SM2 curve is only for SM2 algo */ if ((alg == PGP_PKA_SM2) || (curve == PGP_CURVE_SM2_P_256)) { @@ -304,8 +306,11 @@ alg_allows_curve(pgp_pubkey_alg_t alg, pgp_curve_t curve) } bool -curve_supported(pgp_curve_t curve) +Curve::is_supported(pgp_curve_t curve) { - auto info = get_curve_desc(curve); + auto info = Curve::get(curve); return info && info->supported; } + +} // namespace ec +} // namespace pgp diff --git a/src/lib/crypto/ec_ossl.cpp b/src/lib/crypto/ec_ossl.cpp index 61cf0176a..dd2be418b 100644 --- a/src/lib/crypto/ec_ossl.cpp +++ b/src/lib/crypto/ec_ossl.cpp @@ -41,25 +41,28 @@ #include #endif +namespace pgp { +namespace ec { + static bool -ec_is_raw_key(const pgp_curve_t curve) +is_raw_key(const pgp_curve_t curve) { return (curve == PGP_CURVE_ED25519) || (curve == PGP_CURVE_25519); } rnp_result_t -x25519_generate(rnp::RNG *rng, pgp_ec_key_t *key) +Key::generate_x25519(rnp::RNG &rng) { - return ec_generate(rng, key, PGP_PKA_ECDH, PGP_CURVE_25519); + return generate(rng, PGP_PKA_ECDH, PGP_CURVE_25519); } EVP_PKEY * -ec_generate_pkey(const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve) +generate_pkey(const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve) { - if (!alg_allows_curve(alg_id, curve)) { + if (!Curve::alg_allows(alg_id, curve)) { return NULL; } - auto ec_desc = get_curve_desc(curve); + auto ec_desc = Curve::get(curve); if (!ec_desc) { return NULL; } @@ -70,7 +73,7 @@ ec_generate_pkey(const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve) return NULL; /* LCOV_EXCL_END */ } - bool raw = ec_is_raw_key(curve); + bool raw = is_raw_key(curve); EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(raw ? nid : EVP_PKEY_EC, NULL); if (!ctx) { /* LCOV_EXCL_START */ @@ -100,29 +103,29 @@ ec_generate_pkey(const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve) } static bool -ec_write_raw_seckey(EVP_PKEY *pkey, pgp_ec_key_t *key) +write_raw_seckey(EVP_PKEY *pkey, pgp::ec::Key &key) { /* EdDSA and X25519 keys are saved in a different way */ - static_assert(sizeof(key->x.mpi) > 32, "mpi is too small."); - key->x.len = sizeof(key->x.mpi); - if (EVP_PKEY_get_raw_private_key(pkey, key->x.mpi, &key->x.len) <= 0) { + static_assert(sizeof(key.x.mpi) > 32, "mpi is too small."); + key.x.len = sizeof(key.x.mpi); + if (EVP_PKEY_get_raw_private_key(pkey, key.x.mpi, &key.x.len) <= 0) { /* LCOV_EXCL_START */ RNP_LOG("Failed get raw private key: %lu", ERR_peek_last_error()); return false; /* LCOV_EXCL_END */ } - assert(key->x.len == 32); + assert(key.x.len == 32); if (EVP_PKEY_id(pkey) == EVP_PKEY_X25519) { /* in OpenSSL private key is exported as little-endian, while MPI is big-endian */ for (size_t i = 0; i < 16; i++) { - std::swap(key->x.mpi[i], key->x.mpi[31 - i]); + std::swap(key.x.mpi[i], key.x.mpi[31 - i]); } } return true; } static bool -ec_write_seckey(EVP_PKEY *pkey, pgp::mpi &key) +write_seckey(EVP_PKEY *pkey, pgp::mpi &key) { #if defined(CRYPTO_BACKEND_OPENSSL3) rnp::bn x; @@ -146,30 +149,27 @@ ec_write_seckey(EVP_PKEY *pkey, pgp::mpi &key) } rnp_result_t -ec_generate(rnp::RNG * rng, - pgp_ec_key_t * key, - const pgp_pubkey_alg_t alg_id, - const pgp_curve_t curve) +Key::generate(rnp::RNG &rng, const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve) { - EVP_PKEY *pkey = ec_generate_pkey(alg_id, curve); + EVP_PKEY *pkey = generate_pkey(alg_id, curve); if (!pkey) { return RNP_ERROR_BAD_PARAMETERS; } rnp_result_t ret = RNP_ERROR_GENERIC; - if (ec_is_raw_key(curve)) { - if (ec_write_pubkey(pkey, key->p, curve) && ec_write_raw_seckey(pkey, key)) { + if (is_raw_key(curve)) { + if (write_pubkey(pkey, p, curve) && write_raw_seckey(pkey, *this)) { ret = RNP_SUCCESS; } EVP_PKEY_free(pkey); return ret; } - if (!ec_write_pubkey(pkey, key->p, curve)) { + if (!write_pubkey(pkey, p, curve)) { /* LCOV_EXCL_START */ RNP_LOG("Failed to write pubkey."); goto done; /* LCOV_EXCL_END */ } - if (!ec_write_seckey(pkey, key->x)) { + if (!write_seckey(pkey, x)) { /* LCOV_EXCL_START */ RNP_LOG("Failed to write seckey."); goto done; @@ -182,7 +182,7 @@ ec_generate(rnp::RNG * rng, } static EVP_PKEY * -ec_load_raw_key(const pgp::mpi &keyp, const pgp::mpi *keyx, int nid) +load_raw_key(const pgp::mpi &keyp, const pgp::mpi *keyx, int nid) { if (!keyx) { /* as per RFC, EdDSA & 25519 keys must use 0x40 byte for encoding */ @@ -229,7 +229,7 @@ ec_load_raw_key(const pgp::mpi &keyp, const pgp::mpi *keyx, int nid) #if defined(CRYPTO_BACKEND_OPENSSL3) static OSSL_PARAM * -ec_build_params(const pgp::mpi &p, bignum_t *x, const char *curve) +build_params(const pgp::mpi &p, bignum_t *x, const char *curve) { OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); if (!bld) { @@ -249,12 +249,10 @@ ec_build_params(const pgp::mpi &p, bignum_t *x, const char *curve) } static EVP_PKEY * -ec_load_key_openssl3(const pgp::mpi & keyp, - const pgp::mpi * keyx, - const ec_curve_desc_t *curv_desc) +load_key_openssl3(const pgp::mpi &keyp, const pgp::mpi *keyx, const Curve &curv_desc) { rnp::bn x(keyx ? mpi2bn(keyx) : NULL); - OSSL_PARAM *params = ec_build_params(keyp, x.get(), curv_desc->openssl_name); + OSSL_PARAM *params = build_params(keyp, x.get(), curv_desc.openssl_name); if (!params) { /* LCOV_EXCL_START */ RNP_LOG("failed to build ec params"); @@ -286,14 +284,14 @@ ec_load_key_openssl3(const pgp::mpi & keyp, #endif EVP_PKEY * -ec_load_key(const pgp::mpi &keyp, const pgp::mpi *keyx, pgp_curve_t curve) +load_key(const pgp::mpi &keyp, const pgp::mpi *keyx, pgp_curve_t curve) { - auto curv_desc = get_curve_desc(curve); + auto curv_desc = Curve::get(curve); if (!curv_desc) { RNP_LOG("unknown curve"); return NULL; } - if (!curve_supported(curve)) { + if (!Curve::is_supported(curve)) { RNP_LOG("Curve %s is not supported.", curv_desc->pgp_name); return NULL; } @@ -305,11 +303,11 @@ ec_load_key(const pgp::mpi &keyp, const pgp::mpi *keyx, pgp_curve_t curve) /* LCOV_EXCL_END */ } /* EdDSA and X25519 keys are loaded in a different way */ - if (ec_is_raw_key(curve)) { - return ec_load_raw_key(keyp, keyx, nid); + if (is_raw_key(curve)) { + return load_raw_key(keyp, keyx, nid); } #if defined(CRYPTO_BACKEND_OPENSSL3) - return ec_load_key_openssl3(keyp, keyx, curv_desc); + return load_key_openssl3(keyp, keyx, *curv_desc); #else EC_KEY *ec = EC_KEY_new_by_curve_name(nid); if (!ec) { @@ -387,7 +385,7 @@ ec_load_key(const pgp::mpi &keyp, const pgp::mpi *keyx, pgp_curve_t curve) } rnp_result_t -ec_validate_key(const pgp_ec_key_t &key, bool secret) +validate_key(const Key &key, bool secret) { if (key.curve == PGP_CURVE_25519) { /* No key check implementation for x25519 in the OpenSSL yet, so just basic size checks @@ -400,7 +398,7 @@ ec_validate_key(const pgp_ec_key_t &key, bool secret) } return RNP_SUCCESS; } - EVP_PKEY *evpkey = ec_load_key(key.p, secret ? &key.x : NULL, key.curve); + EVP_PKEY *evpkey = load_key(key.p, secret ? &key.x : NULL, key.curve); if (!evpkey) { return RNP_ERROR_BAD_PARAMETERS; } @@ -430,9 +428,9 @@ ec_validate_key(const pgp_ec_key_t &key, bool secret) } bool -ec_write_pubkey(EVP_PKEY *pkey, pgp::mpi &mpi, pgp_curve_t curve) +write_pubkey(EVP_PKEY *pkey, pgp::mpi &mpi, pgp_curve_t curve) { - if (ec_is_raw_key(curve)) { + if (is_raw_key(curve)) { /* EdDSA and X25519 keys are saved in a different way */ mpi.len = sizeof(mpi.mpi) - 1; if (EVP_PKEY_get_raw_public_key(pkey, &mpi.mpi[1], &mpi.len) <= 0) { @@ -447,11 +445,11 @@ ec_write_pubkey(EVP_PKEY *pkey, pgp::mpi &mpi, pgp_curve_t curve) return true; } #if defined(CRYPTO_BACKEND_OPENSSL3) - auto ec_desc = get_curve_desc(curve); + auto ec_desc = Curve::get(curve); if (!ec_desc) { return false; } - size_t flen = BITS_TO_BYTES(ec_desc->bitlen); + size_t flen = ec_desc->bytes(); rnp::bn qx; rnp::bn qy; @@ -494,3 +492,6 @@ ec_write_pubkey(EVP_PKEY *pkey, pgp::mpi &mpi, pgp_curve_t curve) return mpi.len; #endif } + +} // namespace ec +} // namespace pgp diff --git a/src/lib/crypto/ec_ossl.h b/src/lib/crypto/ec_ossl.h index 121d89b77..72ab82217 100644 --- a/src/lib/crypto/ec_ossl.h +++ b/src/lib/crypto/ec_ossl.h @@ -31,12 +31,18 @@ #include "ec.h" #include -EVP_PKEY *ec_load_key(const pgp::mpi &keyp, const pgp::mpi *keyx, pgp_curve_t curve); +namespace pgp { +namespace ec { -rnp_result_t ec_validate_key(const pgp_ec_key_t &key, bool secret); +EVP_PKEY *load_key(const pgp::mpi &keyp, const pgp::mpi *keyx, pgp_curve_t curve); -EVP_PKEY *ec_generate_pkey(const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve); +rnp_result_t validate_key(const pgp::ec::Key &key, bool secret); -bool ec_write_pubkey(EVP_PKEY *key, pgp::mpi &mpi, pgp_curve_t curve); +EVP_PKEY *generate_pkey(const pgp_pubkey_alg_t alg_id, const pgp_curve_t curve); + +bool write_pubkey(EVP_PKEY *key, pgp::mpi &mpi, pgp_curve_t curve); + +} // namespace ec +} // namespace pgp #endif diff --git a/src/lib/crypto/ecdh.cpp b/src/lib/crypto/ecdh.cpp index 66e5f8d1d..2d52382e0 100644 --- a/src/lib/crypto/ecdh.cpp +++ b/src/lib/crypto/ecdh.cpp @@ -28,6 +28,7 @@ #include #include #include "hash_botan.hpp" +#include "botan_utils.hpp" #include "ecdh.h" #include "ec.h" #include "ecdh_utils.h" @@ -42,13 +43,13 @@ static bool compute_kek(uint8_t * kek, size_t kek_len, const std::vector &other_info, - const ec_curve_desc_t * curve_desc, - const pgp::mpi * ec_pubkey, - const botan_privkey_t ec_prvkey, + const pgp::ec::Curve * curve_desc, + const pgp::mpi & ec_pubkey, + const rnp::botan::Privkey & ec_prvkey, const pgp_hash_alg_t hash_alg) { - const uint8_t *p = ec_pubkey->mpi; - uint8_t p_len = ec_pubkey->len; + const uint8_t *p = ec_pubkey.mpi; + uint8_t p_len = ec_pubkey.len; if (curve_desc->rnp_curve_id == PGP_CURVE_25519) { if ((p_len != 33) || (p[0] != 0x40)) { @@ -59,248 +60,220 @@ compute_kek(uint8_t * kek, } rnp::secure_array s; - - botan_pk_op_ka_t op_key_agreement = NULL; - bool ret = false; - char kdf_name[32] = {0}; - size_t s_len = s.size(); - - if (botan_pk_op_key_agreement_create(&op_key_agreement, ec_prvkey, "Raw", 0) || - botan_pk_op_key_agreement(op_key_agreement, s.data(), &s_len, p, p_len, NULL, 0)) { - goto end; + size_t s_len = s.size(); + rnp::botan::op::KeyAgreement op; + if (botan_pk_op_key_agreement_create(&op.get(), ec_prvkey.get(), "Raw", 0) || + botan_pk_op_key_agreement(op.get(), s.data(), &s_len, p, p_len, NULL, 0)) { + return false; } + char kdf_name[32] = {0}; snprintf( kdf_name, sizeof(kdf_name), "SP800-56A(%s)", rnp::Hash_Botan::name_backend(hash_alg)); - ret = !botan_kdf( + return !botan_kdf( kdf_name, kek, kek_len, s.data(), s_len, NULL, 0, other_info.data(), other_info.size()); -end: - return ret && !botan_pk_op_key_agreement_destroy(op_key_agreement); } static bool -ecdh_load_public_key(botan_pubkey_t *pubkey, const pgp_ec_key_t *key) +ecdh_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &key) { - bool res = false; - - auto curve = get_curve_desc(key->curve); + auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { RNP_LOG("unknown curve"); return false; } if (curve->rnp_curve_id == PGP_CURVE_25519) { - if ((key->p.len != 33) || (key->p.mpi[0] != 0x40)) { + if ((key.p.len != 33) || (key.p.mpi[0] != 0x40)) { return false; } rnp::secure_array pkey; - memcpy(pkey.data(), key->p.mpi + 1, 32); - return !botan_pubkey_load_x25519(pubkey, pkey.data()); + memcpy(pkey.data(), key.p.mpi + 1, 32); + return !botan_pubkey_load_x25519(&pubkey.get(), pkey.data()); } - if (!key->p.bytes() || (key->p.mpi[0] != 0x04)) { + if (!key.p.bytes() || (key.p.mpi[0] != 0x04)) { RNP_LOG("Failed to load public key"); return false; } - botan_mp_t px = NULL; - botan_mp_t py = NULL; - const size_t curve_order = BITS_TO_BYTES(curve->bitlen); + const size_t curve_order = curve->bytes(); + rnp::bn px(&key.p.mpi[1], curve_order); + rnp::bn py(&key.p.mpi[1 + curve_order], curve_order); - if (botan_mp_init(&px) || botan_mp_init(&py) || - botan_mp_from_bin(px, &key->p.mpi[1], curve_order) || - botan_mp_from_bin(py, &key->p.mpi[1 + curve_order], curve_order)) { - goto end; + if (!px || !py) { + return false; } - if (!(res = !botan_pubkey_load_ecdh(pubkey, px, py, curve->botan_name))) { - RNP_LOG("failed to load ecdh public key"); + if (!botan_pubkey_load_ecdh(&pubkey.get(), px.get(), py.get(), curve->botan_name)) { + return true; } -end: - botan_mp_destroy(px); - botan_mp_destroy(py); - return res; + RNP_LOG("failed to load ecdh public key"); + return false; } static bool -ecdh_load_secret_key(botan_privkey_t *seckey, const pgp_ec_key_t *key) +ecdh_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &key) { - auto curve = get_curve_desc(key->curve); + auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { return false; } if (curve->rnp_curve_id == PGP_CURVE_25519) { - if (key->x.len != 32) { + if (key.x.len != 32) { RNP_LOG("wrong x25519 key"); return false; } /* need to reverse byte order since in mpi we have big-endian */ rnp::secure_array prkey; for (int i = 0; i < 32; i++) { - prkey[i] = key->x.mpi[31 - i]; + prkey[i] = key.x.mpi[31 - i]; } - return !botan_privkey_load_x25519(seckey, prkey.data()); + return !botan_privkey_load_x25519(&seckey.get(), prkey.data()); } - bignum_t *x = NULL; - if (!(x = mpi2bn(&key->x))) { - return false; - } - bool res = !botan_privkey_load_ecdh(seckey, BN_HANDLE_PTR(x), curve->botan_name); - bn_free(x); - return res; + rnp::bn bx(key.x); + return bx && !botan_privkey_load_ecdh(&seckey.get(), bx.get(), curve->botan_name); } rnp_result_t -ecdh_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +ecdh_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { - botan_pubkey_t bpkey = NULL; - botan_privkey_t bskey = NULL; - rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; - - auto curve_desc = get_curve_desc(key->curve); + auto curve_desc = pgp::ec::Curve::get(key.curve); if (!curve_desc) { return RNP_ERROR_NOT_SUPPORTED; } - if (!ecdh_load_public_key(&bpkey, key) || - botan_pubkey_check_key(bpkey, rng->handle(), 0)) { - goto done; + rnp::botan::Pubkey bpkey; + if (!ecdh_load_public_key(bpkey, key) || + botan_pubkey_check_key(bpkey.get(), rng.handle(), 0)) { + return RNP_ERROR_BAD_PARAMETERS; } if (!secret) { - ret = RNP_SUCCESS; - goto done; + return RNP_SUCCESS; } - if (!ecdh_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng->handle(), 0)) { - goto done; + rnp::botan::Privkey bskey; + if (!ecdh_load_secret_key(bskey, key) || + botan_privkey_check_key(bskey.get(), rng.handle(), 0)) { + return RNP_ERROR_BAD_PARAMETERS; } - ret = RNP_SUCCESS; -done: - botan_privkey_destroy(bskey); - botan_pubkey_destroy(bpkey); - return ret; + return RNP_SUCCESS; } rnp_result_t -ecdh_encrypt_pkcs5(rnp::RNG * rng, - pgp_ecdh_encrypted_t * out, +ecdh_encrypt_pkcs5(rnp::RNG & rng, + pgp_ecdh_encrypted_t & out, const uint8_t *const in, size_t in_len, - const pgp_ec_key_t * key, + const pgp::ec::Key & key, const pgp_fingerprint_t &fingerprint) { - botan_privkey_t eph_prv_key = NULL; - rnp_result_t ret = RNP_ERROR_GENERIC; - uint8_t kek[32] = {0}; // Size of SHA-256 or smaller // 'm' is padded to the 8-byte granularity - uint8_t m[MAX_SESSION_KEY_SIZE]; + uint8_t m[MAX_SESSION_KEY_SIZE]; + if (!in || (in_len > sizeof(m))) { + return RNP_ERROR_BAD_PARAMETERS; + } const size_t m_padded_len = ((in_len / 8) + 1) * 8; - - if (!key || !out || !in || (in_len > sizeof(m))) { + // +8 because of AES-wrap adds 8 bytes + if (ECDH_WRAPPED_KEY_SIZE < (m_padded_len + 8)) { return RNP_ERROR_BAD_PARAMETERS; } + #if !defined(ENABLE_SM2) - if (key->curve == PGP_CURVE_SM2_P_256) { + if (key.curve == PGP_CURVE_SM2_P_256) { RNP_LOG("SM2 curve support is disabled."); return RNP_ERROR_NOT_IMPLEMENTED; } #endif - auto curve_desc = get_curve_desc(key->curve); + auto curve_desc = pgp::ec::Curve::get(key.curve); if (!curve_desc) { RNP_LOG("unsupported curve"); return RNP_ERROR_NOT_SUPPORTED; } - // +8 because of AES-wrap adds 8 bytes - if (ECDH_WRAPPED_KEY_SIZE < (m_padded_len + 8)) { - return RNP_ERROR_BAD_PARAMETERS; - } - // See 13.5 of RFC 4880 for definition of other_info size - const size_t kek_len = pgp_key_size(key->key_wrap_alg); + 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, fingerprint, key.kdf_hash_alg, key.key_wrap_alg); assert(other_info.size() == curve_desc->OID.size() + 46); + rnp::botan::Privkey eph_prv_key; + int res = 0; if (!strcmp(curve_desc->botan_name, "curve25519")) { - if (botan_privkey_create(&eph_prv_key, "Curve25519", "", rng->handle())) { - goto end; - } + res = botan_privkey_create(&eph_prv_key.get(), "Curve25519", "", rng.handle()); } else { - if (botan_privkey_create( - &eph_prv_key, "ECDH", curve_desc->botan_name, rng->handle())) { - goto end; - } + res = botan_privkey_create( + &eph_prv_key.get(), "ECDH", curve_desc->botan_name, rng.handle()); + } + if (res) { + return RNP_ERROR_GENERIC; } + uint8_t kek[32] = {0}; // Size of SHA-256 or smaller if (!compute_kek( - kek, kek_len, other_info, curve_desc, &key->p, eph_prv_key, key->kdf_hash_alg)) { + kek, kek_len, other_info, curve_desc, key.p, eph_prv_key, key.kdf_hash_alg)) { RNP_LOG("KEK computation failed"); - goto end; + return RNP_ERROR_GENERIC; } memcpy(m, in, in_len); if (!pad_pkcs7(m, m_padded_len, in_len)) { // Should never happen - goto end; + return RNP_ERROR_GENERIC; } - out->mlen = sizeof(out->m); + out.mlen = sizeof(out.m); #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, m_padded_len, kek, kek_len, out.m, &out.mlen)) { #else - if (botan_key_wrap3394(m, m_padded_len, kek, kek_len, out->m, &out->mlen)) { + if (botan_key_wrap3394(m, m_padded_len, kek, kek_len, out.m, &out.mlen)) { #endif - goto end; + return RNP_ERROR_GENERIC; } /* we need to prepend 0x40 for the x25519 */ - if (key->curve == PGP_CURVE_25519) { - out->p.len = sizeof(out->p.mpi) - 1; + if (key.curve == PGP_CURVE_25519) { + out.p.len = sizeof(out.p.mpi) - 1; if (botan_pk_op_key_agreement_export_public( - eph_prv_key, out->p.mpi + 1, &out->p.len)) { - goto end; + eph_prv_key.get(), out.p.mpi + 1, &out.p.len)) { + return RNP_ERROR_GENERIC; } - out->p.mpi[0] = 0x40; - out->p.len++; + out.p.mpi[0] = 0x40; + out.p.len++; } else { - out->p.len = sizeof(out->p.mpi); - if (botan_pk_op_key_agreement_export_public(eph_prv_key, out->p.mpi, &out->p.len)) { - goto end; + out.p.len = sizeof(out.p.mpi); + if (botan_pk_op_key_agreement_export_public( + eph_prv_key.get(), out.p.mpi, &out.p.len)) { + return RNP_ERROR_GENERIC; } } - // All OK - ret = RNP_SUCCESS; -end: - botan_privkey_destroy(eph_prv_key); - return ret; + return RNP_SUCCESS; } rnp_result_t ecdh_decrypt_pkcs5(uint8_t * out, size_t * out_len, - const pgp_ecdh_encrypted_t *in, - const pgp_ec_key_t * key, + const pgp_ecdh_encrypted_t &in, + const pgp::ec::Key & key, const pgp_fingerprint_t & fingerprint) { - if (!out || !out_len || !in || !key || !key->x.bytes()) { + if (!out || !out_len || !key.x.bytes()) { return RNP_ERROR_BAD_PARAMETERS; } - auto curve_desc = get_curve_desc(key->curve); + auto curve_desc = pgp::ec::Curve::get(key.curve); if (!curve_desc) { RNP_LOG("unknown curve"); return RNP_ERROR_NOT_SUPPORTED; } - const pgp_symm_alg_t wrap_alg = key->key_wrap_alg; - const pgp_hash_alg_t kdf_hash = key->kdf_hash_alg; + 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)) { @@ -312,8 +285,8 @@ ecdh_decrypt_pkcs5(uint8_t * out, auto other_info = kdf_other_info_serialize(curve_desc, fingerprint, kdf_hash, wrap_alg); assert(other_info.size() == curve_desc->OID.size() + 46); - botan_privkey_t prv_key = NULL; - if (!ecdh_load_secret_key(&prv_key, key)) { + rnp::botan::Privkey prv_key; + if (!ecdh_load_secret_key(prv_key, key)) { RNP_LOG("failed to load ecdh secret key"); return RNP_ERROR_GENERIC; } @@ -322,45 +295,39 @@ ecdh_decrypt_pkcs5(uint8_t * out, rnp::secure_array kek; rnp::secure_array deckey; - size_t deckey_len = deckey.size(); - size_t offset = 0; - rnp_result_t ret = RNP_ERROR_GENERIC; + size_t deckey_len = deckey.size(); + size_t offset = 0; /* Security: Always return same error code in case compute_kek, * botan_key_unwrap3394 or unpad_pkcs7 fails */ size_t kek_len = pgp_key_size(wrap_alg); - if (!compute_kek(kek.data(), kek_len, other_info, curve_desc, &in->p, prv_key, kdf_hash)) { - goto end; + if (!compute_kek(kek.data(), kek_len, other_info, curve_desc, in.p, prv_key, kdf_hash)) { + return RNP_ERROR_GENERIC; } #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, in.mlen, kek.data(), kek_len, deckey.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, in.mlen, kek.data(), kek_len, deckey.data(), &deckey_len)) { #endif - goto end; + return RNP_ERROR_GENERIC; } if (!unpad_pkcs7(deckey.data(), deckey_len, &offset)) { - goto end; + return RNP_ERROR_GENERIC; } if (*out_len < offset) { - ret = RNP_ERROR_SHORT_BUFFER; - goto end; + return RNP_ERROR_SHORT_BUFFER; } *out_len = offset; memcpy(out, deckey.data(), *out_len); - ret = RNP_SUCCESS; -end: - botan_privkey_destroy(prv_key); - return ret; + return RNP_SUCCESS; } #if defined(ENABLE_CRYPTO_REFRESH) || defined(ENABLE_PQC) diff --git a/src/lib/crypto/ecdh.h b/src/lib/crypto/ecdh.h index ef9a00d7f..7d0d8b944 100644 --- a/src/lib/crypto/ecdh.h +++ b/src/lib/crypto/ecdh.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017 Ribose Inc. + * Copyright (c) 2017-2024 Ribose Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ typedef struct pgp_ecdh_encrypted_t { const pgp_fingerprint_t *fp; } pgp_ecdh_encrypted_t; -rnp_result_t ecdh_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret); +rnp_result_t ecdh_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret); /* * @brief Sets hash algorithm and key wrapping algo @@ -58,7 +58,7 @@ rnp_result_t ecdh_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secr * * @returns false if curve is not supported, otherwise true */ -bool ecdh_set_params(pgp_ec_key_t *key, pgp_curve_t curve_id); +bool ecdh_set_params(pgp::ec::Key &key, pgp_curve_t curve_id); /* * Encrypts session key with a KEK agreed during ECDH as specified in @@ -83,11 +83,11 @@ bool ecdh_set_params(pgp_ec_key_t *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, +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_t * key, + const pgp::ec::Key & key, const pgp_fingerprint_t &fingerprint); /* @@ -112,8 +112,8 @@ rnp_result_t 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_t * key, + const pgp_ecdh_encrypted_t &in, + const pgp::ec::Key & key, const pgp_fingerprint_t & fingerprint); #if defined(ENABLE_CRYPTO_REFRESH) || defined(ENABLE_PQC) diff --git a/src/lib/crypto/ecdh_ossl.cpp b/src/lib/crypto/ecdh_ossl.cpp index da47775fe..bb9947bb7 100644 --- a/src/lib/crypto/ecdh_ossl.cpp +++ b/src/lib/crypto/ecdh_ossl.cpp @@ -46,20 +46,20 @@ 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_t *key, bool secret) +ecdh_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { - return ec_validate_key(*key, secret); + return pgp::ec::validate_key(key, secret); } static rnp_result_t ecdh_derive_kek(uint8_t * x, size_t xlen, - const pgp_ec_key_t & key, + const pgp::ec::Key & key, const pgp_fingerprint_t &fingerprint, uint8_t * kek, const size_t kek_len) { - auto curve_desc = get_curve_desc(key.curve); + auto curve_desc = pgp::ec::Curve::get(key.curve); if (!curve_desc) { RNP_LOG("unsupported curve"); return RNP_ERROR_NOT_SUPPORTED; @@ -255,32 +255,32 @@ ecdh_kek_len(pgp_symm_alg_t wrap_alg) } rnp_result_t -ecdh_encrypt_pkcs5(rnp::RNG * rng, - pgp_ecdh_encrypted_t * out, +ecdh_encrypt_pkcs5(rnp::RNG & rng, + pgp_ecdh_encrypted_t & out, const uint8_t *const in, size_t in_len, - const pgp_ec_key_t * key, + const pgp::ec::Key & key, const pgp_fingerprint_t &fingerprint) { - if (!key || !out || !in || (in_len > MAX_SESSION_KEY_SIZE)) { + if (!in || (in_len > MAX_SESSION_KEY_SIZE)) { return RNP_ERROR_BAD_PARAMETERS; } #if !defined(ENABLE_SM2) - if (key->curve == PGP_CURVE_SM2_P_256) { + if (key.curve == PGP_CURVE_SM2_P_256) { RNP_LOG("SM2 curve support is disabled."); return RNP_ERROR_NOT_IMPLEMENTED; } #endif /* check whether we have valid wrap_alg before doing heavy operations */ - size_t keklen = ecdh_kek_len(key->key_wrap_alg); + size_t keklen = ecdh_kek_len(key.key_wrap_alg); if (!keklen) { /* LCOV_EXCL_START */ - RNP_LOG("Unsupported key wrap algorithm: %d", (int) key->key_wrap_alg); + RNP_LOG("Unsupported key wrap algorithm: %d", (int) key.key_wrap_alg); return RNP_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_END */ } /* load our public key */ - EVP_PKEY *pkey = ec_load_key(key->p, NULL, key->curve); + EVP_PKEY *pkey = pgp::ec::load_key(key.p, NULL, key.curve); if (!pkey) { /* LCOV_EXCL_START */ RNP_LOG("Failed to load public key."); @@ -294,7 +294,7 @@ ecdh_encrypt_pkcs5(rnp::RNG * rng, size_t seclen = sec.size(); rnp_result_t ret = RNP_ERROR_GENERIC; /* generate ephemeral key */ - EVP_PKEY *ephkey = ec_generate_pkey(PGP_PKA_ECDH, key->curve); + EVP_PKEY *ephkey = pgp::ec::generate_pkey(PGP_PKA_ECDH, key.curve); if (!ephkey) { /* LCOV_EXCL_START */ RNP_LOG("Failed to generate ephemeral key."); @@ -310,7 +310,7 @@ ecdh_encrypt_pkcs5(rnp::RNG * rng, /* LCOV_EXCL_END */ } /* here we got x value in sec, deriving kek */ - ret = ecdh_derive_kek(sec.data(), seclen, *key, fingerprint, kek.data(), keklen); + ret = ecdh_derive_kek(sec.data(), seclen, key, fingerprint, kek.data(), keklen); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Failed to derive KEK."); @@ -328,10 +328,10 @@ ecdh_encrypt_pkcs5(rnp::RNG * rng, /* LCOV_EXCL_END */ } /* 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; + 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, &out.mlen, mpad.data(), m_padded_len, kek.data(), key.key_wrap_alg); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Failed to wrap key."); @@ -339,7 +339,7 @@ ecdh_encrypt_pkcs5(rnp::RNG * rng, /* LCOV_EXCL_END */ } /* write ephemeral public key */ - if (!ec_write_pubkey(ephkey, out->p, key->curve)) { + if (!pgp::ec::write_pubkey(ephkey, out.p, key.curve)) { /* LCOV_EXCL_START */ RNP_LOG("Failed to write ec key."); goto done; @@ -355,22 +355,22 @@ 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_t * key, + const pgp_ecdh_encrypted_t &in, + const pgp::ec::Key & key, const pgp_fingerprint_t & fingerprint) { - if (!out || !out_len || !in || !key || !key->x.bytes()) { + if (!out || !out_len || !key.x.bytes()) { return RNP_ERROR_BAD_PARAMETERS; } /* check whether we have valid wrap_alg before doing heavy operations */ - size_t keklen = ecdh_kek_len(key->key_wrap_alg); + size_t keklen = ecdh_kek_len(key.key_wrap_alg); if (!keklen) { - RNP_LOG("Unsupported key wrap algorithm: %d", (int) key->key_wrap_alg); + RNP_LOG("Unsupported key wrap algorithm: %d", (int) key.key_wrap_alg); return RNP_ERROR_NOT_SUPPORTED; } /* load ephemeral public key */ - EVP_PKEY *ephkey = ec_load_key(in->p, NULL, key->curve); + EVP_PKEY *ephkey = pgp::ec::load_key(in.p, NULL, key.curve); if (!ephkey) { RNP_LOG("Failed to load ephemeral public key."); return RNP_ERROR_BAD_PARAMETERS; @@ -383,7 +383,7 @@ ecdh_decrypt_pkcs5(uint8_t * out, size_t seclen = sec.size(); size_t mpadlen = mpad.size(); rnp_result_t ret = RNP_ERROR_GENERIC; - EVP_PKEY * pkey = ec_load_key(key->p, &key->x, key->curve); + EVP_PKEY * pkey = pgp::ec::load_key(key.p, &key.x, key.curve); if (!pkey) { /* LCOV_EXCL_START */ RNP_LOG("Failed to load secret key."); @@ -399,7 +399,7 @@ ecdh_decrypt_pkcs5(uint8_t * out, /* LCOV_EXCL_END */ } /* here we got x value in sec, deriving kek */ - ret = ecdh_derive_kek(sec.data(), seclen, *key, fingerprint, kek.data(), keklen); + ret = ecdh_derive_kek(sec.data(), seclen, key, fingerprint, kek.data(), keklen); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Failed to derive KEK."); @@ -407,8 +407,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); + ret = + ecdh_rfc3394_unwrap(mpad.data(), &mpadlen, in.m, in.mlen, kek.data(), key.key_wrap_alg); if (ret) { /* LCOV_EXCL_START */ RNP_LOG("Failed to unwrap key."); diff --git a/src/lib/crypto/ecdh_utils.cpp b/src/lib/crypto/ecdh_utils.cpp index d9e643731..9c7a66404 100644 --- a/src/lib/crypto/ecdh_utils.cpp +++ b/src/lib/crypto/ecdh_utils.cpp @@ -51,7 +51,7 @@ static const struct ecdh_params_t { // returns size of data written to other_info std::vector -kdf_other_info_serialize(const ec_curve_desc_t * ec_curve, +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) @@ -61,8 +61,8 @@ kdf_other_info_serialize(const ec_curve_desc_t * ec_curve, * Current implementation will always use SHA-512 and AES-256 for KEK wrapping */ std::vector buf; - buf.push_back(static_cast(ec_curve->OID.size())); - buf.insert(buf.end(), ec_curve->OID.begin(), ec_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); @@ -123,12 +123,12 @@ unpad_pkcs7(uint8_t *buf, size_t buf_len, size_t *offset) } bool -ecdh_set_params(pgp_ec_key_t *key, pgp_curve_t curve_id) +ecdh_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) { - key->kdf_hash_alg = ecdh_params[i].hash; - key->key_wrap_alg = ecdh_params[i].wrap_alg; + key.kdf_hash_alg = ecdh_params[i].hash; + key.key_wrap_alg = ecdh_params[i].wrap_alg; return true; } } @@ -137,7 +137,7 @@ ecdh_set_params(pgp_ec_key_t *key, pgp_curve_t curve_id) } bool -x25519_tweak_bits(pgp_ec_key_t &key) +x25519_tweak_bits(pgp::ec::Key &key) { if (key.x.len != 32) { return false; @@ -150,7 +150,7 @@ x25519_tweak_bits(pgp_ec_key_t &key) } bool -x25519_bits_tweaked(const pgp_ec_key_t &key) +x25519_bits_tweaked(const pgp::ec::Key &key) { if (key.x.len != 32) { return false; diff --git a/src/lib/crypto/ecdh_utils.h b/src/lib/crypto/ecdh_utils.h index 866055ac9..a763fdab8 100644 --- a/src/lib/crypto/ecdh_utils.h +++ b/src/lib/crypto/ecdh_utils.h @@ -33,7 +33,7 @@ #define MAX_SESSION_KEY_SIZE 40 #define MAX_AES_KEY_SIZE 32 -std::vector kdf_other_info_serialize(const ec_curve_desc_t * ec_curve, +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); diff --git a/src/lib/crypto/ecdsa.cpp b/src/lib/crypto/ecdsa.cpp index 9072f4b4f..2e95d0dd5 100644 --- a/src/lib/crypto/ecdsa.cpp +++ b/src/lib/crypto/ecdsa.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2017-2024, [Ribose Inc](https://www.ribose.com). * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,87 +29,74 @@ #include #include #include "bn.h" +#include "botan_utils.hpp" static bool -ecdsa_load_public_key(botan_pubkey_t *pubkey, const pgp_ec_key_t *keydata) +ecdsa_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) { - botan_mp_t px = NULL; - botan_mp_t py = NULL; - bool res = false; - - auto curve = get_curve_desc(keydata->curve); + auto curve = pgp::ec::Curve::get(keydata.curve); if (!curve) { RNP_LOG("unknown curve"); return false; } - const size_t curve_order = BITS_TO_BYTES(curve->bitlen); - - if (!keydata->p.bytes() || (keydata->p.mpi[0] != 0x04)) { - RNP_LOG("Failed to load public key: %zu, %02x", keydata->p.bytes(), keydata->p.mpi[0]); + if (!keydata.p.bytes() || (keydata.p.mpi[0] != 0x04)) { + RNP_LOG("Failed to load public key: %02x", keydata.p.mpi[0]); return false; } - if (botan_mp_init(&px) || botan_mp_init(&py) || - botan_mp_from_bin(px, &keydata->p.mpi[1], curve_order) || - botan_mp_from_bin(py, &keydata->p.mpi[1 + curve_order], curve_order)) { - goto end; + const size_t curve_order = curve->bytes(); + rnp::bn px(keydata.p.mpi + 1, curve_order); + rnp::bn py(keydata.p.mpi + 1 + curve_order, curve_order); + + if (!px || !py) { + return false; } - if (!(res = !botan_pubkey_load_ecdsa(pubkey, px, py, curve->botan_name))) { + bool res = !botan_pubkey_load_ecdsa(&pubkey.get(), px.get(), py.get(), curve->botan_name); + if (!res) { RNP_LOG("failed to load ecdsa public key"); } -end: - botan_mp_destroy(px); - botan_mp_destroy(py); return res; } static bool -ecdsa_load_secret_key(botan_privkey_t *seckey, const pgp_ec_key_t *keydata) +ecdsa_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) { - auto curve = get_curve_desc(keydata->curve); + auto curve = pgp::ec::Curve::get(keydata.curve); if (!curve) { return false; } - bignum_t *x = mpi2bn(&keydata->x); + rnp::bn x(keydata.x); if (!x) { return false; } - bool res = false; - if (!(res = !botan_privkey_load_ecdsa(seckey, BN_HANDLE_PTR(x), curve->botan_name))) { + bool res = !botan_privkey_load_ecdsa(&seckey.get(), x.get(), curve->botan_name); + if (!res) { RNP_LOG("Can't load private key"); } - bn_free(x); return res; } rnp_result_t -ecdsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +ecdsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { - botan_pubkey_t bpkey = NULL; - botan_privkey_t bskey = NULL; - rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; - - if (!ecdsa_load_public_key(&bpkey, key) || - botan_pubkey_check_key(bpkey, rng->handle(), 0)) { - goto done; + rnp::botan::Pubkey bpkey; + if (!ecdsa_load_public_key(bpkey, key) || + botan_pubkey_check_key(bpkey.get(), rng.handle(), 0)) { + return RNP_ERROR_BAD_PARAMETERS; } if (!secret) { - ret = RNP_SUCCESS; - goto done; + return RNP_SUCCESS; } - if (!ecdsa_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng->handle(), 0)) { - goto done; + rnp::botan::Privkey bskey; + if (!ecdsa_load_secret_key(bskey, key) || + botan_privkey_check_key(bskey.get(), rng.handle(), 0)) { + return RNP_ERROR_BAD_PARAMETERS; } - ret = RNP_SUCCESS; -done: - botan_privkey_destroy(bskey); - botan_pubkey_destroy(bpkey); - return ret; + return RNP_SUCCESS; } const char * @@ -144,105 +131,88 @@ ecdsa_padding_str_for(pgp_hash_alg_t hash_alg) } rnp_result_t -ecdsa_sign(rnp::RNG * rng, - pgp_ec_signature_t *sig, +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_t *key) + const pgp::ec::Key &key) { - botan_pk_op_sign_t signer = NULL; - botan_privkey_t b_key = NULL; - rnp_result_t ret = RNP_ERROR_GENERIC; - uint8_t out_buf[2 * MAX_CURVE_BYTELEN] = {0}; - auto curve = get_curve_desc(key->curve); - const char * padding_str = ecdsa_padding_str_for(hash_alg); - + auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { return RNP_ERROR_BAD_PARAMETERS; } - const size_t curve_order = BITS_TO_BYTES(curve->bitlen); - size_t sig_len = 2 * curve_order; - if (!ecdsa_load_secret_key(&b_key, key)) { + rnp::botan::Privkey b_key; + if (!ecdsa_load_secret_key(b_key, key)) { RNP_LOG("Can't load private key"); - goto end; + return RNP_ERROR_GENERIC; } - if (botan_pk_op_sign_create(&signer, b_key, padding_str, 0)) { - goto end; + rnp::botan::op::Sign signer; + auto pad = ecdsa_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)) { + return RNP_ERROR_GENERIC; } - if (botan_pk_op_sign_update(signer, hash, hash_len)) { - goto end; - } + const size_t curve_order = curve->bytes(); + size_t sig_len = 2 * curve_order; + std::vector out_buf(sig_len); - if (botan_pk_op_sign_finish(signer, rng->handle(), out_buf, &sig_len)) { + if (botan_pk_op_sign_finish(signer.get(), rng.handle(), out_buf.data(), &sig_len)) { RNP_LOG("Signing failed"); - goto end; + return RNP_ERROR_GENERIC; } // Allocate memory and copy results - if (sig->r.from_mem(out_buf, curve_order) && - sig->s.from_mem(out_buf + curve_order, curve_order)) { - ret = RNP_SUCCESS; - } -end: - botan_privkey_destroy(b_key); - botan_pk_op_sign_destroy(signer); - return ret; + if (!sig.r.from_mem(out_buf.data(), curve_order) || + !sig.s.from_mem(out_buf.data() + curve_order, curve_order)) { + return RNP_ERROR_GENERIC; + } + return RNP_SUCCESS; } rnp_result_t -ecdsa_verify(const pgp_ec_signature_t *sig, +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_t * key) + const pgp::ec::Key & key) { - botan_pubkey_t pub = NULL; - botan_pk_op_verify_t verifier = NULL; - rnp_result_t ret = RNP_ERROR_SIGNATURE_INVALID; - uint8_t sign_buf[2 * MAX_CURVE_BYTELEN] = {0}; - size_t r_blen, s_blen; - const char * padding_str = ecdsa_padding_str_for(hash_alg); - - auto curve = get_curve_desc(key->curve); + auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { RNP_LOG("unknown curve"); return RNP_ERROR_BAD_PARAMETERS; } - const size_t curve_order = BITS_TO_BYTES(curve->bitlen); - - if (!ecdsa_load_public_key(&pub, key)) { - goto end; - } - if (botan_pk_op_verify_create(&verifier, pub, padding_str, 0)) { - goto end; + size_t curve_order = curve->bytes(); + size_t r_blen = sig.r.bytes(); + size_t s_blen = sig.s.bytes(); + if ((r_blen > curve_order) || (s_blen > curve_order) || + (curve_order > MAX_CURVE_BYTELEN)) { + return RNP_ERROR_BAD_PARAMETERS; } - if (botan_pk_op_verify_update(verifier, hash, hash_len)) { - goto end; + rnp::botan::Pubkey pub; + if (!ecdsa_load_public_key(pub, key)) { + return RNP_ERROR_SIGNATURE_INVALID; } - r_blen = sig->r.bytes(); - s_blen = sig->s.bytes(); - if ((r_blen > curve_order) || (s_blen > curve_order) || - (curve_order > MAX_CURVE_BYTELEN)) { - ret = RNP_ERROR_BAD_PARAMETERS; - goto end; + rnp::botan::op::Verify verifier; + auto pad = ecdsa_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)) { + return RNP_ERROR_SIGNATURE_INVALID; } + std::vector sign_buf(2 * curve_order, 0); // Both can't fail - sig->r.to_mem(&sign_buf[curve_order - r_blen]); - sig->s.to_mem(&sign_buf[curve_order + curve_order - s_blen]); + sig.r.to_mem(sign_buf.data() + curve_order - r_blen); + sig.s.to_mem(sign_buf.data() + 2 * curve_order - s_blen); - if (!botan_pk_op_verify_finish(verifier, sign_buf, curve_order * 2)) { - ret = RNP_SUCCESS; + if (botan_pk_op_verify_finish(verifier.get(), sign_buf.data(), sign_buf.size())) { + return RNP_ERROR_SIGNATURE_INVALID; } -end: - botan_pubkey_destroy(pub); - botan_pk_op_verify_destroy(verifier); - return ret; + return RNP_SUCCESS; } diff --git a/src/lib/crypto/ecdsa.h b/src/lib/crypto/ecdsa.h index 86af7ed27..c7ccbdcca 100644 --- a/src/lib/crypto/ecdsa.h +++ b/src/lib/crypto/ecdsa.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017 Ribose Inc. + * Copyright (c) 2017-2024 Ribose Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,20 +29,20 @@ #include "crypto/ec.h" -rnp_result_t ecdsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret); +rnp_result_t ecdsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret); -rnp_result_t ecdsa_sign(rnp::RNG * rng, - pgp_ec_signature_t *sig, +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_t *key); + const pgp::ec::Key &key); -rnp_result_t ecdsa_verify(const pgp_ec_signature_t *sig, +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_t * key); + const pgp::ec::Key & key); const char *ecdsa_padding_str_for(pgp_hash_alg_t hash_alg); diff --git a/src/lib/crypto/ecdsa_ossl.cpp b/src/lib/crypto/ecdsa_ossl.cpp index bebc7e51a..d439f3327 100644 --- a/src/lib/crypto/ecdsa_ossl.cpp +++ b/src/lib/crypto/ecdsa_ossl.cpp @@ -34,7 +34,7 @@ #include static bool -ecdsa_decode_sig(const uint8_t *data, size_t len, pgp_ec_signature_t &sig) +ecdsa_decode_sig(const uint8_t *data, size_t len, pgp::ec::Signature &sig) { ECDSA_SIG *esig = d2i_ECDSA_SIG(NULL, &data, len); if (!esig) { @@ -50,7 +50,7 @@ ecdsa_decode_sig(const uint8_t *data, size_t len, pgp_ec_signature_t &sig) } static bool -ecdsa_encode_sig(uint8_t *data, size_t *len, const pgp_ec_signature_t &sig) +ecdsa_encode_sig(uint8_t *data, size_t *len, const pgp::ec::Signature &sig) { bool res = false; ECDSA_SIG *dsig = ECDSA_SIG_new(); @@ -79,26 +79,26 @@ ecdsa_encode_sig(uint8_t *data, size_t *len, const pgp_ec_signature_t &sig) } rnp_result_t -ecdsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +ecdsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { - return ec_validate_key(*key, secret); + return pgp::ec::validate_key(key, secret); } rnp_result_t -ecdsa_sign(rnp::RNG * rng, - pgp_ec_signature_t *sig, +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_t *key) + const pgp::ec::Key &key) { - if (!key->x.bytes()) { + if (!key.x.bytes()) { RNP_LOG("private key not set"); return RNP_ERROR_BAD_PARAMETERS; } /* Load secret key to DSA structure*/ - EVP_PKEY *evpkey = ec_load_key(key->p, &key->x, key->curve); + EVP_PKEY *evpkey = pgp::ec::load_key(key.p, &key.x, key.curve); if (!evpkey) { RNP_LOG("Failed to load key"); return RNP_ERROR_BAD_PARAMETERS; @@ -115,13 +115,13 @@ ecdsa_sign(rnp::RNG * rng, RNP_LOG("Failed to initialize signing: %lu", ERR_peek_last_error()); goto done; } - sig->s.len = PGP_MPINT_SIZE; - if (EVP_PKEY_sign(ctx, sig->s.mpi, &sig->s.len, hash, hash_len) <= 0) { + sig.s.len = PGP_MPINT_SIZE; + if (EVP_PKEY_sign(ctx, sig.s.mpi, &sig.s.len, hash, hash_len) <= 0) { RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); - sig->s.len = 0; + sig.s.len = 0; goto done; } - if (!ecdsa_decode_sig(&sig->s.mpi[0], sig->s.len, *sig)) { + if (!ecdsa_decode_sig(&sig.s.mpi[0], sig.s.len, sig)) { RNP_LOG("Failed to parse ECDSA sig: %lu", ERR_peek_last_error()); goto done; } @@ -133,14 +133,14 @@ ecdsa_sign(rnp::RNG * rng, } rnp_result_t -ecdsa_verify(const pgp_ec_signature_t *sig, +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_t * key) + const pgp::ec::Key & key) { /* Load secret key to DSA structure*/ - EVP_PKEY *evpkey = ec_load_key(key->p, NULL, key->curve); + EVP_PKEY *evpkey = pgp::ec::load_key(key.p, NULL, key.curve); if (!evpkey) { RNP_LOG("Failed to load key"); return RNP_ERROR_BAD_PARAMETERS; @@ -158,7 +158,7 @@ ecdsa_verify(const pgp_ec_signature_t *sig, goto done; } pgp::mpi sigbuf; - if (!ecdsa_encode_sig(sigbuf.mpi, &sigbuf.len, *sig)) { + if (!ecdsa_encode_sig(sigbuf.mpi, &sigbuf.len, sig)) { goto done; } if (EVP_PKEY_verify(ctx, sigbuf.mpi, sigbuf.len, hash, hash_len) > 0) { diff --git a/src/lib/crypto/eddsa.cpp b/src/lib/crypto/eddsa.cpp index 80a4259c7..9104d864a 100644 --- a/src/lib/crypto/eddsa.cpp +++ b/src/lib/crypto/eddsa.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2017-2024, [Ribose Inc](https://www.ribose.com). * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,42 +25,43 @@ */ #include +#include #include #include "eddsa.h" #include "utils.h" +#include "botan_utils.hpp" static bool -eddsa_load_public_key(botan_pubkey_t *pubkey, const pgp_ec_key_t *keydata) +eddsa_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) { - if (keydata->curve != PGP_CURVE_ED25519) { + if (keydata.curve != PGP_CURVE_ED25519) { return false; } /* * See draft-ietf-openpgp-rfc4880bis-01 section 13.3 */ - if ((keydata->p.bytes() != 33) || (keydata->p.mpi[0] != 0x40)) { + if ((keydata.p.bytes() != 33) || (keydata.p.mpi[0] != 0x40)) { return false; } - if (botan_pubkey_load_ed25519(pubkey, keydata->p.mpi + 1)) { + if (botan_pubkey_load_ed25519(&pubkey.get(), keydata.p.mpi + 1)) { return false; } - return true; } static bool -eddsa_load_secret_key(botan_privkey_t *seckey, const pgp_ec_key_t *keydata) +eddsa_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) { - if (keydata->curve != PGP_CURVE_ED25519) { + if (keydata.curve != PGP_CURVE_ED25519) { return false; } - size_t sz = keydata->x.bytes(); + size_t sz = keydata.x.bytes(); if (!sz || (sz > 32)) { return false; } uint8_t keybuf[32] = {0}; - keydata->x.to_mem(keybuf + 32 - sz); - if (botan_privkey_load_ed25519(seckey, keybuf)) { + keydata.x.to_mem(keybuf + 32 - sz); + if (botan_privkey_load_ed25519(&seckey.get(), keybuf)) { return false; } @@ -68,143 +69,107 @@ eddsa_load_secret_key(botan_privkey_t *seckey, const pgp_ec_key_t *keydata) } rnp_result_t -eddsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +eddsa_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { - botan_pubkey_t bpkey = NULL; - botan_privkey_t bskey = NULL; - rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; - - if (!eddsa_load_public_key(&bpkey, key) || - botan_pubkey_check_key(bpkey, rng->handle(), 0)) { - goto done; + rnp::botan::Pubkey bpkey; + if (!eddsa_load_public_key(bpkey, key) || + botan_pubkey_check_key(bpkey.get(), rng.handle(), 0)) { + return RNP_ERROR_BAD_PARAMETERS; } if (!secret) { - ret = RNP_SUCCESS; - goto done; + return RNP_SUCCESS; } - if (!eddsa_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng->handle(), 0)) { - goto done; + rnp::botan::Privkey bskey; + if (!eddsa_load_secret_key(bskey, key) || + botan_privkey_check_key(bskey.get(), rng.handle(), 0)) { + return RNP_ERROR_BAD_PARAMETERS; } - ret = RNP_SUCCESS; -done: - botan_privkey_destroy(bskey); - botan_pubkey_destroy(bpkey); - return ret; + return RNP_SUCCESS; } rnp_result_t -eddsa_generate(rnp::RNG *rng, pgp_ec_key_t *key) +eddsa_generate(rnp::RNG &rng, pgp::ec::Key &key) { - botan_privkey_t eddsa = NULL; - rnp_result_t ret = RNP_ERROR_GENERIC; - uint8_t key_bits[64]; - - if (botan_privkey_create(&eddsa, "Ed25519", NULL, rng->handle()) != 0) { - goto end; + rnp::botan::Privkey eddsa; + if (botan_privkey_create(&eddsa.get(), "Ed25519", NULL, rng.handle())) { + return RNP_ERROR_GENERIC; } - if (botan_privkey_ed25519_get_privkey(eddsa, key_bits)) { - goto end; + uint8_t key_bits[64]; + if (botan_privkey_ed25519_get_privkey(eddsa.get(), key_bits)) { + return RNP_ERROR_GENERIC; } // First 32 bytes of key_bits are the EdDSA seed (private key) // Second 32 bytes are the EdDSA public key - - key->x.from_mem(key_bits, 32); + key.x.from_mem(key_bits, 32); // insert the required 0x40 prefix on the public key key_bits[31] = 0x40; - key->p.from_mem(key_bits + 31, 33); - key->curve = PGP_CURVE_ED25519; - - ret = RNP_SUCCESS; -end: - botan_privkey_destroy(eddsa); - return ret; + key.p.from_mem(key_bits + 31, 33); + key.curve = PGP_CURVE_ED25519; + return RNP_SUCCESS; } rnp_result_t -eddsa_verify(const pgp_ec_signature_t *sig, +eddsa_verify(const pgp::ec::Signature &sig, const uint8_t * hash, size_t hash_len, - const pgp_ec_key_t * key) + const pgp::ec::Key & key) { - botan_pubkey_t eddsa = NULL; - botan_pk_op_verify_t verify_op = NULL; - rnp_result_t ret = RNP_ERROR_SIGNATURE_INVALID; - uint8_t bn_buf[64] = {0}; - - if (!eddsa_load_public_key(&eddsa, key)) { - ret = RNP_ERROR_BAD_PARAMETERS; - goto done; + // Unexpected size for Ed25519 signature + if ((sig.r.bytes() > 32) || (sig.s.bytes() > 32)) { + return RNP_ERROR_SIGNATURE_INVALID; } - if (botan_pk_op_verify_create(&verify_op, eddsa, "Pure", 0) != 0) { - goto done; + rnp::botan::Pubkey eddsa; + if (!eddsa_load_public_key(eddsa, key)) { + return RNP_ERROR_BAD_PARAMETERS; } - if (botan_pk_op_verify_update(verify_op, hash, hash_len) != 0) { - goto done; + 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)) { + return RNP_ERROR_SIGNATURE_INVALID; } - // Unexpected size for Ed25519 signature - if ((sig->r.bytes() > 32) || (sig->s.bytes() > 32)) { - goto done; - } - sig->r.to_mem(&bn_buf[32 - sig->r.bytes()]); - sig->s.to_mem(&bn_buf[64 - sig->s.bytes()]); + uint8_t bn_buf[64] = {0}; + sig.r.to_mem(bn_buf + 32 - sig.r.bytes()); + sig.s.to_mem(bn_buf + 64 - sig.s.bytes()); - if (botan_pk_op_verify_finish(verify_op, bn_buf, 64) == 0) { - ret = RNP_SUCCESS; + if (botan_pk_op_verify_finish(verify_op.get(), bn_buf, 64)) { + return RNP_ERROR_SIGNATURE_INVALID; } -done: - botan_pk_op_verify_destroy(verify_op); - botan_pubkey_destroy(eddsa); - return ret; + return RNP_SUCCESS; } rnp_result_t -eddsa_sign(rnp::RNG * rng, - pgp_ec_signature_t *sig, +eddsa_sign(rnp::RNG & rng, + pgp::ec::Signature &sig, const uint8_t * hash, size_t hash_len, - const pgp_ec_key_t *key) + const pgp::ec::Key &key) { - botan_privkey_t eddsa = NULL; - botan_pk_op_sign_t sign_op = NULL; - rnp_result_t ret = RNP_ERROR_SIGNING_FAILED; - uint8_t bn_buf[64] = {0}; - size_t sig_size = sizeof(bn_buf); - - if (!eddsa_load_secret_key(&eddsa, key)) { - ret = RNP_ERROR_BAD_PARAMETERS; - goto done; - } - - if (botan_pk_op_sign_create(&sign_op, eddsa, "Pure", 0) != 0) { - goto done; + rnp::botan::Privkey eddsa; + if (!eddsa_load_secret_key(eddsa, key)) { + return RNP_ERROR_BAD_PARAMETERS; } - if (botan_pk_op_sign_update(sign_op, hash, hash_len) != 0) { - goto done; + 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)) { + return RNP_ERROR_SIGNING_FAILED; } - if (botan_pk_op_sign_finish(sign_op, rng->handle(), bn_buf, &sig_size) != 0) { - goto done; + uint8_t bn_buf[64] = {0}; + size_t sig_size = sizeof(bn_buf); + if (botan_pk_op_sign_finish(sign_op.get(), rng.handle(), bn_buf, &sig_size)) { + return RNP_ERROR_SIGNING_FAILED; } - // Unexpected size... - if (sig_size != 64) { - goto done; - } - - sig->r.from_mem(bn_buf, 32); - sig->s.from_mem(bn_buf + 32, 32); - ret = RNP_SUCCESS; -done: - botan_pk_op_sign_destroy(sign_op); - botan_privkey_destroy(eddsa); - return ret; + assert(sig_size == 64); + sig.r.from_mem(bn_buf, 32); + sig.s.from_mem(bn_buf + 32, 32); + return RNP_SUCCESS; } diff --git a/src/lib/crypto/eddsa.h b/src/lib/crypto/eddsa.h index 7410a2806..f347f5892 100644 --- a/src/lib/crypto/eddsa.h +++ b/src/lib/crypto/eddsa.h @@ -1,11 +1,7 @@ -/* - * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com). +/*- + * Copyright (c) 2017-2024 Ribose Inc. * All rights reserved. * - * This code is originally derived from software contributed to - * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), and - * carried further by Ribose Inc (https://www.ribose.com). - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,22 +29,22 @@ #include "ec.h" -rnp_result_t eddsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret); +rnp_result_t eddsa_validate_key(rnp::RNG &rng, const pgp::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_t *key); +rnp_result_t eddsa_generate(rnp::RNG &rng, pgp::ec::Key &key); -rnp_result_t eddsa_verify(const pgp_ec_signature_t *sig, +rnp_result_t eddsa_verify(const pgp::ec::Signature &sig, const uint8_t * hash, size_t hash_len, - const pgp_ec_key_t * key); + const pgp::ec::Key & key); -rnp_result_t eddsa_sign(rnp::RNG * rng, - pgp_ec_signature_t *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_t *key); + const pgp::ec::Key &key); #endif diff --git a/src/lib/crypto/eddsa_ossl.cpp b/src/lib/crypto/eddsa_ossl.cpp index 4558fbe6c..8655ade35 100644 --- a/src/lib/crypto/eddsa_ossl.cpp +++ b/src/lib/crypto/eddsa_ossl.cpp @@ -37,44 +37,44 @@ #include rnp_result_t -eddsa_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +eddsa_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)) { + if ((key.p.bytes() != 33) || (key.p.mpi[0] != 0x40)) { return RNP_ERROR_BAD_PARAMETERS; } - if (secret && key->x.bytes() > 32) { + if (secret && key.x.bytes() > 32) { return RNP_ERROR_BAD_PARAMETERS; } return RNP_SUCCESS; } rnp_result_t -eddsa_generate(rnp::RNG *rng, pgp_ec_key_t *key) +eddsa_generate(rnp::RNG &rng, pgp::ec::Key &key) { - rnp_result_t ret = ec_generate(rng, key, PGP_PKA_EDDSA, PGP_CURVE_ED25519); + rnp_result_t ret = key.generate(rng, PGP_PKA_EDDSA, PGP_CURVE_ED25519); if (!ret) { - key->curve = PGP_CURVE_ED25519; + key.curve = PGP_CURVE_ED25519; } return ret; } rnp_result_t -eddsa_verify(const pgp_ec_signature_t *sig, +eddsa_verify(const pgp::ec::Signature &sig, const uint8_t * hash, size_t hash_len, - const pgp_ec_key_t * key) + const pgp::ec::Key & key) { - if ((sig->r.bytes() > 32) || (sig->s.bytes() > 32)) { + if ((sig.r.bytes() > 32) || (sig.s.bytes() > 32)) { RNP_LOG("Invalid EdDSA signature."); return RNP_ERROR_BAD_PARAMETERS; } - if ((key->p.bytes() != 33) || (key->p.mpi[0] != 0x40)) { + if ((key.p.bytes() != 33) || (key.p.mpi[0] != 0x40)) { RNP_LOG("Invalid EdDSA public key."); return RNP_ERROR_BAD_PARAMETERS; } - EVP_PKEY *evpkey = ec_load_key(key->p, NULL, PGP_CURVE_ED25519); + EVP_PKEY *evpkey = pgp::ec::load_key(key.p, NULL, PGP_CURVE_ED25519); if (!evpkey) { RNP_LOG("Failed to load key"); return RNP_ERROR_BAD_PARAMETERS; @@ -93,8 +93,8 @@ eddsa_verify(const pgp_ec_signature_t *sig, RNP_LOG("Failed to initialize signing: %lu", ERR_peek_last_error()); goto done; } - sig->r.to_mem(&sigbuf[32 - sig->r.bytes()]); - sig->s.to_mem(&sigbuf[64 - sig->s.bytes()]); + sig.r.to_mem(&sigbuf[32 - sig.r.bytes()]); + sig.s.to_mem(&sigbuf[64 - sig.s.bytes()]); if (EVP_DigestVerify(md, sigbuf, 64, hash, hash_len) > 0) { ret = RNP_SUCCESS; @@ -107,17 +107,17 @@ eddsa_verify(const pgp_ec_signature_t *sig, } rnp_result_t -eddsa_sign(rnp::RNG * rng, - pgp_ec_signature_t *sig, +eddsa_sign(rnp::RNG & rng, + pgp::ec::Signature &sig, const uint8_t * hash, size_t hash_len, - const pgp_ec_key_t *key) + const pgp::ec::Key &key) { - if (!key->x.bytes()) { + if (!key.x.bytes()) { RNP_LOG("private key not set"); return RNP_ERROR_BAD_PARAMETERS; } - EVP_PKEY *evpkey = ec_load_key(key->p, &key->x, PGP_CURVE_ED25519); + EVP_PKEY *evpkey = pgp::ec::load_key(key.p, &key.x, PGP_CURVE_ED25519); if (!evpkey) { RNP_LOG("Failed to load private key: %lu", ERR_peek_last_error()); return RNP_ERROR_BAD_PARAMETERS; @@ -135,18 +135,18 @@ eddsa_sign(rnp::RNG * rng, RNP_LOG("Failed to initialize signing: %lu", ERR_peek_last_error()); goto done; } - static_assert((sizeof(sig->r.mpi) == PGP_MPINT_SIZE) && (PGP_MPINT_SIZE >= 64), + 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, sig->r.mpi, &sig->r.len, hash, hash_len) <= 0) { + sig.r.len = PGP_MPINT_SIZE; + if (EVP_DigestSign(md, sig.r.mpi, &sig.r.len, hash, hash_len) <= 0) { RNP_LOG("Signing failed: %lu", ERR_peek_last_error()); - sig->r.len = 0; + sig.r.len = 0; goto done; } - assert(sig->r.len == 64); - sig->r.len = 32; - sig->s.len = 32; - memcpy(sig->s.mpi, &sig->r.mpi[32], 32); + assert(sig.r.len == 64); + sig.r.len = 32; + sig.s.len = 32; + memcpy(sig.s.mpi, &sig.r.mpi[32], 32); ret = RNP_SUCCESS; done: /* line below will also free ctx */ diff --git a/src/lib/crypto/exdsa_ecdhkem.cpp b/src/lib/crypto/exdsa_ecdhkem.cpp index d7df8bfce..464a8e4ee 100644 --- a/src/lib/crypto/exdsa_ecdhkem.cpp +++ b/src/lib/crypto/exdsa_ecdhkem.cpp @@ -69,7 +69,7 @@ Botan::ECDH_PrivateKey ecdh_kem_private_key_t::botan_key_ecdh(rnp::RNG *rng) const { assert(curve_ >= PGP_CURVE_NIST_P_256 && curve_ <= PGP_CURVE_P256K1); - auto ec_desc = get_curve_desc(curve_); + auto ec_desc = pgp::ec::Curve::get(curve_); return Botan::ECDH_PrivateKey( *(rng->obj()), Botan::EC_Group(ec_desc->botan_name), Botan::BigInt(key_)); } @@ -79,9 +79,9 @@ ecdh_kem_public_key_t::botan_key_ecdh(rnp::RNG *rng) const { assert(curve_ >= PGP_CURVE_NIST_P_256 && curve_ <= PGP_CURVE_P256K1); - auto ec_desc = get_curve_desc(curve_); + auto ec_desc = pgp::ec::Curve::get(curve_); Botan::EC_Group group(ec_desc->botan_name); - const size_t curve_order = BITS_TO_BYTES(ec_desc->bitlen); + const size_t curve_order = ec_desc->bytes(); Botan::BigInt x(key_.data() + 1, curve_order); Botan::BigInt y(key_.data() + 1 + curve_order, curve_order); return Botan::ECDH_PublicKey(group, group.point(x, y)); @@ -124,7 +124,7 @@ ecdh_kem_public_key_t::encapsulate(rnp::RNG * rng, Botan::PK_Key_Agreement key_agreement(eph_prv_key, *(rng->obj()), "Raw"); symmetric_key = Botan::unlock(key_agreement.derive_key(0, key_).bits_of()); } else { - auto curve_desc = get_curve_desc(curve_); + auto curve_desc = pgp::ec::Curve::get(curve_); if (!curve_desc) { RNP_LOG("unknown curve"); return RNP_ERROR_NOT_SUPPORTED; @@ -211,7 +211,7 @@ ec_key_t::generate_exdsa_key_pair(rnp::RNG *rng, exdsa_key_t *out, pgp_curve_t c Botan::ECDSA_PrivateKey exdsa_private_key_t::botan_key(rnp::RNG *rng) const { - auto ec_desc = get_curve_desc(curve_); + auto ec_desc = pgp::ec::Curve::get(curve_); Botan::ECDSA_PrivateKey priv_key( *(rng->obj()), Botan::EC_Group(ec_desc->botan_name), Botan::BigInt(key_)); return priv_key; @@ -221,9 +221,9 @@ Botan::ECDSA_PublicKey exdsa_public_key_t::botan_key() const { // format: 04 | X | Y - auto ec_desc = get_curve_desc(curve_); + auto ec_desc = pgp::ec::Curve::get(curve_); Botan::EC_Group group(ec_desc->botan_name); - const size_t curve_order = BITS_TO_BYTES(ec_desc->bitlen); + const size_t curve_order = ec_desc->bytes(); Botan::BigInt x(key_.data() + 1, curve_order); Botan::BigInt y(key_.data() + 1 + curve_order, curve_order); return Botan::ECDSA_PublicKey(group, group.point(x, y)); diff --git a/src/lib/crypto/sm2.cpp b/src/lib/crypto/sm2.cpp index 9fabcbe63..5312e320a 100644 --- a/src/lib/crypto/sm2.cpp +++ b/src/lib/crypto/sm2.cpp @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017-2022 Ribose Inc. + * Copyright (c) 2017-2024 Ribose Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,139 +25,110 @@ */ #include +#include #include #include "hash_botan.hpp" +#include "botan_utils.hpp" #include "sm2.h" #include "utils.h" #include "bn.h" static bool -sm2_load_public_key(botan_pubkey_t *pubkey, const pgp_ec_key_t *keydata) +sm2_load_public_key(rnp::botan::Pubkey &pubkey, const pgp::ec::Key &keydata) { - auto curve = get_curve_desc(keydata->curve); + auto curve = pgp::ec::Curve::get(keydata.curve); if (!curve) { return false; } - const size_t sign_half_len = BITS_TO_BYTES(curve->bitlen); - size_t sz = keydata->p.bytes(); - if (!sz || (sz != (2 * sign_half_len + 1)) || (keydata->p.mpi[0] != 0x04)) { + const size_t sign_half_len = curve->bytes(); + size_t sz = keydata.p.bytes(); + if (!sz || (sz != (2 * sign_half_len + 1)) || (keydata.p.mpi[0] != 0x04)) { return false; } - botan_mp_t px = NULL; - botan_mp_t py = NULL; - bool res = false; - if (botan_mp_init(&px) || botan_mp_init(&py) || - botan_mp_from_bin(px, &keydata->p.mpi[1], sign_half_len) || - botan_mp_from_bin(py, &keydata->p.mpi[1 + sign_half_len], sign_half_len)) { - goto end; + rnp::bn px(keydata.p.mpi + 1, sign_half_len); + rnp::bn py(keydata.p.mpi + 1 + sign_half_len, sign_half_len); + + if (!px || !py) { + return false; } - res = !botan_pubkey_load_sm2(pubkey, px, py, curve->botan_name); -end: - botan_mp_destroy(px); - botan_mp_destroy(py); - return res; + return !botan_pubkey_load_sm2(&pubkey.get(), px.get(), py.get(), curve->botan_name); } static bool -sm2_load_secret_key(botan_privkey_t *seckey, const pgp_ec_key_t *keydata) +sm2_load_secret_key(rnp::botan::Privkey &seckey, const pgp::ec::Key &keydata) { - auto curve = get_curve_desc(keydata->curve); + auto curve = pgp::ec::Curve::get(keydata.curve); if (!curve) { return false; } - bignum_t *x = mpi2bn(&keydata->x); + rnp::bn x(keydata.x); if (!x) { return false; } - bool res = !botan_privkey_load_sm2(seckey, BN_HANDLE_PTR(x), curve->botan_name); - bn_free(x); - return res; + return !botan_privkey_load_sm2(&seckey.get(), x.get(), curve->botan_name); } rnp_result_t -sm2_compute_za(const pgp_ec_key_t &key, rnp::Hash &hash, const char *ident_field) +sm2_compute_za(const pgp::ec::Key &key, rnp::Hash &hash, const char *ident_field) { - rnp_result_t result = RNP_ERROR_GENERIC; - botan_pubkey_t sm2_key = NULL; - int rc; - - const char *hash_algo = rnp::Hash_Botan::name_backend(hash.alg()); - size_t digest_len = hash.size(); - - uint8_t *digest_buf = (uint8_t *) malloc(digest_len); - if (!digest_buf) { - return RNP_ERROR_OUT_OF_MEMORY; - } - - if (!sm2_load_public_key(&sm2_key, &key)) { + rnp::botan::Pubkey sm2_key; + if (!sm2_load_public_key(sm2_key, key)) { RNP_LOG("Failed to load SM2 key"); - goto done; + return RNP_ERROR_GENERIC; } - if (ident_field == NULL) + if (!ident_field) { ident_field = "1234567812345678"; + } - rc = botan_pubkey_sm2_compute_za(digest_buf, &digest_len, ident_field, hash_algo, sm2_key); + auto hash_algo = rnp::Hash_Botan::name_backend(hash.alg()); + size_t digest_len = hash.size(); + std::vector digest_buf(digest_len, 0); - if (rc != 0) { + int rc = botan_pubkey_sm2_compute_za( + digest_buf.data(), &digest_len, ident_field, hash_algo, sm2_key.get()); + if (rc) { RNP_LOG("compute_za failed %d", rc); - goto done; - } - - try { - hash.add(digest_buf, digest_len); - } catch (const std::exception &e) { - RNP_LOG("Failed to update hash: %s", e.what()); - goto done; + return RNP_ERROR_GENERIC; } - - result = RNP_SUCCESS; -done: - free(digest_buf); - botan_pubkey_destroy(sm2_key); - return result; + hash.add(digest_buf.data(), digest_len); + return RNP_SUCCESS; } rnp_result_t -sm2_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +sm2_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { - botan_pubkey_t bpkey = NULL; - botan_privkey_t bskey = NULL; - rnp_result_t ret = RNP_ERROR_BAD_PARAMETERS; - - if (!sm2_load_public_key(&bpkey, key) || botan_pubkey_check_key(bpkey, rng->handle(), 0)) { - goto done; + rnp::botan::Pubkey bpkey; + if (!sm2_load_public_key(bpkey, key) || + botan_pubkey_check_key(bpkey.get(), rng.handle(), 0)) { + return RNP_ERROR_BAD_PARAMETERS; } if (!secret) { - ret = RNP_SUCCESS; - goto done; + return RNP_SUCCESS; } - if (!sm2_load_secret_key(&bskey, key) || - botan_privkey_check_key(bskey, rng->handle(), 0)) { - goto done; + rnp::botan::Privkey bskey; + if (!sm2_load_secret_key(bskey, key) || + botan_privkey_check_key(bskey.get(), rng.handle(), 0)) { + return RNP_ERROR_BAD_PARAMETERS; } - ret = RNP_SUCCESS; -done: - botan_privkey_destroy(bskey); - botan_pubkey_destroy(bpkey); - return ret; + return RNP_SUCCESS; } rnp_result_t -sm2_sign(rnp::RNG * rng, - pgp_ec_signature_t *sig, +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_t *key) + const pgp::ec::Key &key) { - if (botan_ffi_supports_api(20180713) != 0) { + if (botan_ffi_supports_api(20180713)) { RNP_LOG("SM2 signatures requires Botan 2.8 or higher"); return RNP_ERROR_NOT_SUPPORTED; } @@ -166,55 +137,46 @@ sm2_sign(rnp::RNG * rng, return RNP_ERROR_BAD_PARAMETERS; } - auto curve = get_curve_desc(key->curve); + auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { return RNP_ERROR_BAD_PARAMETERS; } - botan_privkey_t b_key = NULL; - if (!sm2_load_secret_key(&b_key, key)) { + rnp::botan::Privkey b_key; + if (!sm2_load_secret_key(b_key, key)) { RNP_LOG("Can't load private key"); return RNP_ERROR_BAD_PARAMETERS; } - botan_pk_op_sign_t signer = NULL; - uint8_t out_buf[2 * MAX_CURVE_BYTELEN] = {0}; - size_t sig_len = 0; - rnp_result_t ret = RNP_ERROR_SIGNING_FAILED; - size_t sign_half_len = BITS_TO_BYTES(curve->bitlen); - sig_len = 2 * sign_half_len; - - if (botan_pk_op_sign_create(&signer, b_key, ",Raw", 0)) { - goto end; + 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)) { + return RNP_ERROR_SIGNING_FAILED; } - if (botan_pk_op_sign_update(signer, hash, hash_len)) { - goto end; - } - - if (botan_pk_op_sign_finish(signer, rng->handle(), out_buf, &sig_len)) { + size_t sign_half_len = curve->bytes(); + size_t sig_len = 2 * sign_half_len; + std::vector out_buf(sig_len, 0); + if (botan_pk_op_sign_finish(signer.get(), rng.handle(), out_buf.data(), &sig_len)) { RNP_LOG("Signing failed"); - goto end; + return RNP_ERROR_SIGNING_FAILED; } // Allocate memory and copy results - if (sig->r.from_mem(out_buf, sign_half_len) && - sig->s.from_mem(out_buf + sign_half_len, sign_half_len)) { - // All good now - ret = RNP_SUCCESS; - } -end: - botan_privkey_destroy(b_key); - botan_pk_op_sign_destroy(signer); - return ret; + if (!sig.r.from_mem(out_buf.data(), sign_half_len) || + !sig.s.from_mem(out_buf.data() + sign_half_len, sign_half_len)) { + return RNP_ERROR_SIGNING_FAILED; + } + // All good now + return RNP_SUCCESS; } rnp_result_t -sm2_verify(const pgp_ec_signature_t *sig, +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_t * key) + const pgp::ec::Key & key) { if (botan_ffi_supports_api(20180713) != 0) { RNP_LOG("SM2 signatures requires Botan 2.8 or higher"); @@ -225,58 +187,51 @@ sm2_verify(const pgp_ec_signature_t *sig, return RNP_ERROR_BAD_PARAMETERS; } - auto curve = get_curve_desc(key->curve); + auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { return RNP_ERROR_BAD_PARAMETERS; } - botan_pubkey_t pub = NULL; - if (!sm2_load_public_key(&pub, key)) { - RNP_LOG("Failed to load public key"); - return RNP_ERROR_SIGNATURE_INVALID; - } + size_t r_blen = sig.r.len; + size_t s_blen = sig.s.len; + size_t sign_half_len = curve->bytes(); - botan_pk_op_verify_t verifier = NULL; - rnp_result_t ret = RNP_ERROR_SIGNATURE_INVALID; - uint8_t sign_buf[2 * MAX_CURVE_BYTELEN] = {0}; - size_t r_blen = sig->r.len; - size_t s_blen = sig->s.len; - size_t sign_half_len = BITS_TO_BYTES(curve->bitlen); - - if (botan_pk_op_verify_create(&verifier, pub, ",Raw", 0)) { - goto end; + assert(sign_half_len <= MAX_CURVE_BYTELEN); + if (!r_blen || (r_blen > sign_half_len) || !s_blen || (s_blen > sign_half_len)) { + return RNP_ERROR_SIGNATURE_INVALID; } - if (botan_pk_op_verify_update(verifier, hash, hash_len)) { - goto end; + rnp::botan::Pubkey pub; + if (!sm2_load_public_key(pub, key)) { + RNP_LOG("Failed to load public key"); + return RNP_ERROR_SIGNATURE_INVALID; } - if (!r_blen || (r_blen > sign_half_len) || !s_blen || (s_blen > sign_half_len) || - (sign_half_len > MAX_CURVE_BYTELEN)) { - goto end; + 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)) { + return RNP_ERROR_SIGNATURE_INVALID; } - sig->r.to_mem(sign_buf + sign_half_len - r_blen); - sig->s.to_mem(sign_buf + 2 * sign_half_len - s_blen); + std::vector sign_buf(2 * sign_half_len, 0); + sig.r.to_mem(sign_buf.data() + sign_half_len - r_blen); + sig.s.to_mem(sign_buf.data() + 2 * sign_half_len - s_blen); - if (!botan_pk_op_verify_finish(verifier, sign_buf, sign_half_len * 2)) { - ret = RNP_SUCCESS; + if (botan_pk_op_verify_finish(verifier.get(), sign_buf.data(), sign_buf.size())) { + return RNP_ERROR_SIGNATURE_INVALID; } -end: - botan_pubkey_destroy(pub); - botan_pk_op_verify_destroy(verifier); - return ret; + return RNP_SUCCESS; } rnp_result_t -sm2_encrypt(rnp::RNG * rng, - pgp_sm2_encrypted_t *out, +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_t * key) + const pgp::ec::Key & key) { - auto curve = get_curve_desc(key->curve); + auto curve = pgp::ec::Curve::get(key.curve); if (!curve) { return RNP_ERROR_GENERIC; } @@ -291,15 +246,15 @@ sm2_encrypt(rnp::RNG * rng, * Format of SM2 ciphertext is a point (2*point_len+1) plus * the masked ciphertext (out_len) plus a hash. */ - size_t point_len = BITS_TO_BYTES(curve->bitlen); + size_t point_len = curve->bytes(); size_t ctext_len = (2 * point_len + 1) + in_len + hash_alg_len; if (ctext_len > PGP_MPINT_SIZE) { RNP_LOG("too large output for SM2 encryption"); return RNP_ERROR_GENERIC; } - botan_pubkey_t sm2_key = NULL; - if (!sm2_load_public_key(&sm2_key, key)) { + rnp::botan::Pubkey sm2_key; + if (!sm2_load_public_key(sm2_key, key)) { RNP_LOG("Failed to load public key"); return RNP_ERROR_GENERIC; } @@ -309,63 +264,49 @@ sm2_encrypt(rnp::RNG * rng, it's an all in one scheme, only the hash (used for the integrity check) is specified. */ - rnp_result_t ret = RNP_ERROR_GENERIC; - botan_pk_op_encrypt_t enc_op = NULL; + rnp::botan::op::Encrypt enc_op; if (botan_pk_op_encrypt_create( - &enc_op, sm2_key, rnp::Hash_Botan::name_backend(hash_algo), 0)) { - goto done; + &enc_op.get(), sm2_key.get(), rnp::Hash_Botan::name_backend(hash_algo), 0)) { + return RNP_ERROR_GENERIC; } - out->m.len = sizeof(out->m.mpi); - if (botan_pk_op_encrypt(enc_op, rng->handle(), out->m.mpi, &out->m.len, in, in_len) == 0) { - out->m.mpi[out->m.len++] = hash_algo; - ret = RNP_SUCCESS; + 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)) { + return RNP_ERROR_GENERIC; } -done: - botan_pk_op_encrypt_destroy(enc_op); - botan_pubkey_destroy(sm2_key); - return ret; + out.m.mpi[out.m.len++] = hash_algo; + return RNP_SUCCESS; } rnp_result_t sm2_decrypt(uint8_t * out, size_t * out_len, - const pgp_sm2_encrypted_t *in, - const pgp_ec_key_t * key) + const pgp_sm2_encrypted_t &in, + const pgp::ec::Key & key) { - botan_pk_op_decrypt_t decrypt_op = NULL; - botan_privkey_t b_key = NULL; - rnp_result_t ret = RNP_ERROR_GENERIC; - uint8_t hash_id; - const char * hash_name = NULL; - - auto curve = get_curve_desc(key->curve); - size_t in_len = in->m.bytes(); + auto curve = pgp::ec::Curve::get(key.curve); + size_t in_len = in.m.bytes(); if (!curve || in_len < 64) { - goto done; - } - - if (!sm2_load_secret_key(&b_key, key)) { - RNP_LOG("Can't load private key"); - goto done; + return RNP_ERROR_GENERIC; } - hash_id = in->m.mpi[in_len - 1]; - hash_name = rnp::Hash_Botan::name_backend((pgp_hash_alg_t) hash_id); + uint8_t hash_id = in.m.mpi[in_len - 1]; + auto hash_name = rnp::Hash_Botan::name_backend((pgp_hash_alg_t) hash_id); if (!hash_name) { RNP_LOG("Unknown hash used in SM2 ciphertext"); - goto done; + return RNP_ERROR_GENERIC; } - if (botan_pk_op_decrypt_create(&decrypt_op, b_key, hash_name, 0) != 0) { - goto done; + rnp::botan::Privkey b_key; + if (!sm2_load_secret_key(b_key, key)) { + RNP_LOG("Can't load private key"); + return RNP_ERROR_GENERIC; } - if (botan_pk_op_decrypt(decrypt_op, out, out_len, in->m.mpi, in_len - 1) == 0) { - ret = RNP_SUCCESS; + 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)) { + return RNP_ERROR_GENERIC; } -done: - botan_privkey_destroy(b_key); - botan_pk_op_decrypt_destroy(decrypt_op); - return ret; + return RNP_SUCCESS; } diff --git a/src/lib/crypto/sm2.h b/src/lib/crypto/sm2.h index 28627acdb..d48e3eac6 100644 --- a/src/lib/crypto/sm2.h +++ b/src/lib/crypto/sm2.h @@ -39,41 +39,41 @@ class Hash; } // namespace rnp #if defined(ENABLE_SM2) -rnp_result_t sm2_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret); +rnp_result_t sm2_validate_key(rnp::RNG &rng, const pgp::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_t &key, +rnp_result_t sm2_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_t *sig, +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_t *key); + const pgp::ec::Key &key); -rnp_result_t sm2_verify(const pgp_ec_signature_t *sig, +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_t * key); + const pgp::ec::Key & key); -rnp_result_t sm2_encrypt(rnp::RNG * rng, - pgp_sm2_encrypted_t *out, +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_t * key); + const pgp::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_t * key); + const pgp_sm2_encrypted_t &in, + const pgp::ec::Key & key); #endif // defined(ENABLE_SM2) #endif // SM2_H_ diff --git a/src/lib/crypto/sm2_ossl.cpp b/src/lib/crypto/sm2_ossl.cpp index 4c1eaf17a..86f3ebd32 100644 --- a/src/lib/crypto/sm2_ossl.cpp +++ b/src/lib/crypto/sm2_ossl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2021-2024, [Ribose Inc](https://www.ribose.com). * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,39 +29,39 @@ #include "utils.h" rnp_result_t -sm2_validate_key(rnp::RNG *rng, const pgp_ec_key_t *key, bool secret) +sm2_validate_key(rnp::RNG &rng, const pgp::ec::Key &key, bool secret) { return RNP_ERROR_NOT_IMPLEMENTED; } rnp_result_t -sm2_sign(rnp::RNG * rng, - pgp_ec_signature_t *sig, +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_t *key) + const pgp::ec::Key &key) { return RNP_ERROR_NOT_IMPLEMENTED; } rnp_result_t -sm2_verify(const pgp_ec_signature_t *sig, +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_t * key) + const pgp::ec::Key & key) { return RNP_ERROR_NOT_IMPLEMENTED; } rnp_result_t -sm2_encrypt(rnp::RNG * rng, - pgp_sm2_encrypted_t *out, +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_t * key) + const pgp::ec::Key & key) { return RNP_ERROR_NOT_IMPLEMENTED; } @@ -69,8 +69,8 @@ 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_t * key) + const pgp_sm2_encrypted_t &in, + const pgp::ec::Key & key) { return RNP_ERROR_NOT_IMPLEMENTED; } diff --git a/src/lib/key_material.cpp b/src/lib/key_material.cpp index b912e52eb..e6a06cd61 100644 --- a/src/lib/key_material.cpp +++ b/src/lib/key_material.cpp @@ -79,9 +79,9 @@ grip_hash_ecc_hex(rnp::Hash &hash, const char *hex, char name) } void -grip_hash_ec(rnp::Hash &hash, const pgp_ec_key_t &key) +grip_hash_ec(rnp::Hash &hash, const pgp::ec::Key &key) { - auto desc = get_curve_desc(key.curve); + auto desc = pgp::ec::Curve::get(key.curve); if (!desc) { RNP_LOG("unknown curve %d", (int) key.curve); throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); @@ -208,7 +208,7 @@ DSAKeyParams::min_hash() const noexcept size_t ECCKeyParams::bits() const noexcept { - auto curve = get_curve_desc(curve_); + auto curve = ec::Curve::get(curve_); return curve ? curve->bitlen : 0; } @@ -462,7 +462,7 @@ KeyMaterial::create(pgp_pubkey_alg_t alg, const eg::Key &key) } std::unique_ptr -KeyMaterial::create(pgp_pubkey_alg_t alg, const pgp_ec_key_t &key) +KeyMaterial::create(pgp_pubkey_alg_t alg, const ec::Key &key) { switch (alg) { case PGP_PKA_ECDSA: @@ -989,17 +989,17 @@ ECKeyMaterial::clear_secret() noexcept rnp_result_t ECKeyMaterial::check_curve(size_t hash_len) const { - auto curve = get_curve_desc(key_.curve); + auto curve = ec::Curve::get(key_.curve); if (!curve) { RNP_LOG("Unknown curve"); return RNP_ERROR_BAD_PARAMETERS; } - if (!curve_supported(key_.curve)) { + if (!curve->supported) { RNP_LOG("EC sign: curve %s is not supported.", curve->pgp_name); return RNP_ERROR_NOT_SUPPORTED; } /* "-2" because ECDSA on P-521 must work with SHA-512 digest */ - if (BITS_TO_BYTES(curve->bitlen) - 2 > hash_len) { + if (curve->bytes() - 2 > hash_len) { RNP_LOG("Message hash too small"); return RNP_ERROR_BAD_PARAMETERS; } @@ -1044,11 +1044,11 @@ bool ECKeyMaterial::generate(rnp::SecurityContext &ctx, const KeyParams ¶ms) { auto &ecc = dynamic_cast(params); - if (!curve_supported(ecc.curve())) { + if (!ec::Curve::is_supported(ecc.curve())) { RNP_LOG("EC generate: curve %d is not supported.", ecc.curve()); return false; } - if (ec_generate(&ctx.rng, &key_, alg_, ecc.curve())) { + if (key_.generate(ctx.rng, alg_, ecc.curve())) { RNP_LOG("failed to generate EC key"); return false; } @@ -1066,7 +1066,7 @@ ECKeyMaterial::set_secret(const mpi &x) size_t ECKeyMaterial::bits() const noexcept { - auto curve_desc = get_curve_desc(key_.curve); + auto curve_desc = ec::Curve::get(key_.curve); return curve_desc ? curve_desc->bitlen : 0; } @@ -1091,12 +1091,12 @@ ECKeyMaterial::x() const noexcept bool ECDSAKeyMaterial::validate_material(rnp::SecurityContext &ctx, bool reset) { - if (!curve_supported(key_.curve)) { + if (!ec::Curve::is_supported(key_.curve)) { /* allow to import key if curve is not supported */ 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 @@ -1110,11 +1110,11 @@ ECDSAKeyMaterial::verify(const rnp::SecurityContext & ctx, const pgp_signature_material_t & sig, const rnp::secure_vector &hash) const { - if (!curve_supported(key_.curve)) { + if (!ec::Curve::is_supported(key_.curve)) { 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.data(), hash.size(), key_); } rnp_result_t @@ -1126,7 +1126,7 @@ 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.data(), hash.size(), key_); } pgp_hash_alg_t @@ -1142,12 +1142,12 @@ ECDSAKeyMaterial::adjust_hash(pgp_hash_alg_t hash) const bool ECDHKeyMaterial::validate_material(rnp::SecurityContext &ctx, bool reset) { - if (!curve_supported(key_.curve)) { + if (!ec::Curve::is_supported(key_.curve)) { /* allow to import key if curve is not supported */ 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,13 +1193,13 @@ 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; } /* Special case for x25519*/ if (ecc.curve() == PGP_CURVE_25519) { - if (x25519_generate(&ctx.rng, &key_)) { + if (key_.generate_x25519(ctx.rng)) { RNP_LOG("failed to generate x25519 key"); return false; } @@ -1216,12 +1216,12 @@ ECDHKeyMaterial::encrypt(rnp::SecurityContext & ctx, const uint8_t * data, size_t len) const { - if (!curve_supported(key_.curve)) { + 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, len, key_, *out.ecdh.fp); } rnp_result_t @@ -1230,14 +1230,14 @@ ECDHKeyMaterial::decrypt(rnp::SecurityContext & ctx, size_t & out_len, const pgp_encrypted_material_t &in) const { - if (!curve_supported(key_.curve)) { + if (!ec::Curve::is_supported(key_.curve)) { RNP_LOG("ECDH decrypt: curve %d is not supported.", key_.curve); return RNP_ERROR_BAD_PARAMETERS; } 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, &out_len, in.ecdh, key_, *in.ecdh.fp); } pgp_hash_alg_t @@ -1267,7 +1267,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 @@ -1279,7 +1279,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; } @@ -1291,7 +1291,7 @@ EDDSAKeyMaterial::verify(const rnp::SecurityContext & ctx, const pgp_signature_material_t & sig, const rnp::secure_vector &hash) const { - return eddsa_verify(&sig.ecc, hash.data(), hash.size(), &key_); + return eddsa_verify(sig.ecc, hash.data(), hash.size(), key_); } rnp_result_t @@ -1299,14 +1299,14 @@ EDDSAKeyMaterial::sign(rnp::SecurityContext & ctx, pgp_signature_material_t & sig, const rnp::secure_vector &hash) const { - return eddsa_sign(&ctx.rng, &sig.ecc, hash.data(), hash.size(), &key_); + return eddsa_sign(ctx.rng, sig.ecc, hash.data(), hash.size(), key_); } bool SM2KeyMaterial::validate_material(rnp::SecurityContext &ctx, bool reset) { #if defined(ENABLE_SM2) - return !sm2_validate_key(&ctx.rng, &key_, secret_); + return !sm2_validate_key(ctx.rng, key_, secret_); #else RNP_LOG("SM2 key validation is not available."); return false; @@ -1326,7 +1326,7 @@ SM2KeyMaterial::encrypt(rnp::SecurityContext & ctx, size_t len) const { #if defined(ENABLE_SM2) - return sm2_encrypt(&ctx.rng, &out.sm2, data, len, PGP_HASH_SM3, &key_); + return sm2_encrypt(ctx.rng, out.sm2, data, len, PGP_HASH_SM3, key_); #else RNP_LOG("sm2_encrypt is not available"); return RNP_ERROR_NOT_IMPLEMENTED; @@ -1340,7 +1340,7 @@ SM2KeyMaterial::decrypt(rnp::SecurityContext & ctx, const pgp_encrypted_material_t &in) const { #if defined(ENABLE_SM2) - return sm2_decrypt(out, &out_len, &in.sm2, &key_); + return sm2_decrypt(out, &out_len, in.sm2, key_); #else RNP_LOG("SM2 decryption is not available."); return RNP_ERROR_NOT_IMPLEMENTED; @@ -1353,7 +1353,7 @@ SM2KeyMaterial::verify(const rnp::SecurityContext & ctx, const rnp::secure_vector &hash) const { #if defined(ENABLE_SM2) - return sm2_verify(&sig.ecc, sig.halg, hash.data(), hash.size(), &key_); + return sm2_verify(sig.ecc, sig.halg, hash.data(), hash.size(), key_); #else RNP_LOG("SM2 verification is not available."); return RNP_ERROR_NOT_IMPLEMENTED; @@ -1370,7 +1370,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 sm2_sign(ctx.rng, sig.ecc, sig.halg, hash.data(), hash.size(), key_); #else RNP_LOG("SM2 signing is not available."); return RNP_ERROR_NOT_IMPLEMENTED; @@ -1433,8 +1433,8 @@ bool Ed25519KeyMaterial::parse(pgp_packet_body_t &pkt) noexcept { secret_ = false; - auto ec_desc = get_curve_desc(PGP_CURVE_ED25519); - std::vector buf(BITS_TO_BYTES(ec_desc->bitlen)); + auto ec_desc = pgp::ec::Curve::get(PGP_CURVE_ED25519); + std::vector buf(ec_desc->bytes()); if (!pkt.get(buf.data(), buf.size())) { RNP_LOG("failed to parse Ed25519 public key data"); return false; @@ -1446,8 +1446,8 @@ Ed25519KeyMaterial::parse(pgp_packet_body_t &pkt) noexcept bool Ed25519KeyMaterial::parse_secret(pgp_packet_body_t &pkt) noexcept { - auto ec_desc = get_curve_desc(PGP_CURVE_ED25519); - std::vector buf(BITS_TO_BYTES(ec_desc->bitlen)); + auto ec_desc = pgp::ec::Curve::get(PGP_CURVE_ED25519); + std::vector buf(ec_desc->bytes()); if (!pkt.get(buf.data(), buf.size())) { RNP_LOG("failed to parse Ed25519 secret key data"); return false; @@ -1559,8 +1559,8 @@ bool X25519KeyMaterial::parse(pgp_packet_body_t &pkt) noexcept { secret_ = false; - auto ec_desc = get_curve_desc(PGP_CURVE_25519); - std::vector buf(BITS_TO_BYTES(ec_desc->bitlen)); + auto ec_desc = pgp::ec::Curve::get(PGP_CURVE_25519); + std::vector buf(ec_desc->bytes()); if (!pkt.get(buf.data(), buf.size())) { RNP_LOG("failed to parse X25519 public key data"); return false; @@ -1572,8 +1572,8 @@ X25519KeyMaterial::parse(pgp_packet_body_t &pkt) noexcept bool X25519KeyMaterial::parse_secret(pgp_packet_body_t &pkt) noexcept { - auto ec_desc = get_curve_desc(PGP_CURVE_25519); - std::vector buf(BITS_TO_BYTES(ec_desc->bitlen)); + auto ec_desc = pgp::ec::Curve::get(PGP_CURVE_25519); + std::vector buf(ec_desc->bytes()); if (!pkt.get(buf.data(), buf.size())) { RNP_LOG("failed to parse X25519 secret key data"); return false; diff --git a/src/lib/key_material.hpp b/src/lib/key_material.hpp index 9f3fbbc2d..6cad688eb 100644 --- a/src/lib/key_material.hpp +++ b/src/lib/key_material.hpp @@ -233,7 +233,7 @@ class KeyMaterial { static std::unique_ptr create(pgp_pubkey_alg_t alg, const rsa::Key &key); static std::unique_ptr create(const dsa::Key &key); static std::unique_ptr create(pgp_pubkey_alg_t alg, const eg::Key &key); - static std::unique_ptr create(pgp_pubkey_alg_t alg, const pgp_ec_key_t &key); + static std::unique_ptr create(pgp_pubkey_alg_t alg, const ec::Key &key); }; class RSAKeyMaterial : public KeyMaterial { @@ -363,14 +363,14 @@ class EGKeyMaterial : public KeyMaterial { class ECKeyMaterial : public KeyMaterial { protected: - pgp_ec_key_t key_; + ec::Key key_; void grip_update(rnp::Hash &hash) const override; rnp_result_t check_curve(size_t hash_len) const; public: ECKeyMaterial(pgp_pubkey_alg_t kalg) : KeyMaterial(kalg), key_{} {}; - ECKeyMaterial(pgp_pubkey_alg_t kalg, const pgp_ec_key_t &key, bool secret = false) + ECKeyMaterial(pgp_pubkey_alg_t kalg, const ec::Key &key, bool secret = false) : KeyMaterial(kalg, secret), key_(key){}; bool equals(const KeyMaterial &value) const noexcept override; @@ -394,7 +394,7 @@ class ECDSAKeyMaterial : public ECKeyMaterial { public: ECDSAKeyMaterial() : ECKeyMaterial(PGP_PKA_ECDSA){}; - ECDSAKeyMaterial(const pgp_ec_key_t &key, bool secret = false) + ECDSAKeyMaterial(const ec::Key &key, bool secret = false) : ECKeyMaterial(PGP_PKA_ECDSA, key, secret){}; std::unique_ptr clone() override; @@ -413,7 +413,7 @@ class ECDHKeyMaterial : public ECKeyMaterial { public: ECDHKeyMaterial() : ECKeyMaterial(PGP_PKA_ECDH){}; - ECDHKeyMaterial(const pgp_ec_key_t &key, bool secret = false) + ECDHKeyMaterial(const ec::Key &key, bool secret = false) : ECKeyMaterial(PGP_PKA_ECDH, key, secret){}; std::unique_ptr clone() override; @@ -441,7 +441,7 @@ class EDDSAKeyMaterial : public ECKeyMaterial { public: EDDSAKeyMaterial() : ECKeyMaterial(PGP_PKA_EDDSA){}; - EDDSAKeyMaterial(const pgp_ec_key_t &key, bool secret = false) + EDDSAKeyMaterial(const ec::Key &key, bool secret = false) : ECKeyMaterial(PGP_PKA_EDDSA, key, secret){}; std::unique_ptr clone() override; @@ -460,7 +460,7 @@ class SM2KeyMaterial : public ECKeyMaterial { public: SM2KeyMaterial() : ECKeyMaterial(PGP_PKA_SM2){}; - SM2KeyMaterial(const pgp_ec_key_t &key, bool secret = false) + SM2KeyMaterial(const ec::Key &key, bool secret = false) : ECKeyMaterial(PGP_PKA_SM2, key, secret){}; std::unique_ptr clone() override; diff --git a/src/lib/rnp.cpp b/src/lib/rnp.cpp index ca5e3ef91..a59ff102e 100644 --- a/src/lib/rnp.cpp +++ b/src/lib/rnp.cpp @@ -390,14 +390,14 @@ z_alg_supported(int alg) static bool curve_str_to_type(const char *str, pgp_curve_t *value) { - *value = find_curve_by_name(str); - return curve_supported(*value); + *value = pgp::ec::Curve::by_name(str); + return pgp::ec::Curve::is_supported(*value); } static bool curve_type_to_str(pgp_curve_t type, const char **str) { - auto desc = get_curve_desc(type); + auto desc = pgp::ec::Curve::get(type); if (!desc) { return false; } @@ -1134,7 +1134,7 @@ try { } else if (rnp::str_case_eq(type, RNP_FEATURE_CURVE)) { for (pgp_curve_t curve = PGP_CURVE_NIST_P_256; curve < PGP_CURVE_MAX; curve = (pgp_curve_t)(curve + 1)) { - auto desc = get_curve_desc(curve); + auto desc = pgp::ec::Curve::get(curve); if (!desc) { return RNP_ERROR_BAD_STATE; // LCOV_EXCL_LINE } diff --git a/src/lib/types.h b/src/lib/types.h index 4fec2da93..34762ae3d 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -172,7 +172,7 @@ typedef struct pgp_signature_material_t { union { pgp::rsa::Signature rsa; pgp::dsa::Signature dsa; - pgp_ec_signature_t ecc; + pgp::ec::Signature ecc; pgp::eg::Signature eg; }; #if defined(ENABLE_CRYPTO_REFRESH) diff --git a/src/librekey/key_store_g10.cpp b/src/librekey/key_store_g10.cpp index 80c14bf67..06e16096e 100644 --- a/src/librekey/key_store_g10.cpp +++ b/src/librekey/key_store_g10.cpp @@ -302,7 +302,7 @@ read_mpi(const sexp_list_t *list, const std::string &name, pgp::mpi &val) noexce } static bool -read_curve(const sexp_list_t *list, const std::string &name, pgp_ec_key_t &key) noexcept +read_curve(const sexp_list_t *list, const std::string &name, pgp::ec::Key &key) noexcept { const sexp_string_t *data = lookup_var_data(list, name); if (!data) { @@ -406,7 +406,7 @@ parse_pubkey(pgp_key_pkt_t &pubkey, const sexp_list_t *s_exp, pgp_pubkey_alg_t a case PGP_PKA_ECDSA: case PGP_PKA_ECDH: case PGP_PKA_EDDSA: { - pgp_ec_key_t ec{}; + pgp::ec::Key ec{}; if (!read_curve(s_exp, "curve", ec) || !read_mpi(s_exp, "q", ec.p)) { return false; } diff --git a/src/librepgp/stream-dump.cpp b/src/librepgp/stream-dump.cpp index ad425c955..93d5f43e7 100644 --- a/src/librepgp/stream-dump.cpp +++ b/src/librepgp/stream-dump.cpp @@ -941,14 +941,14 @@ stream_dump_key_material(rnp_dump_ctx_t & ctx, case PGP_PKA_EDDSA: case PGP_PKA_SM2: { auto &ec = dynamic_cast(*material); - auto cdesc = get_curve_desc(ec.curve()); + auto cdesc = pgp::ec::Curve::get(ec.curve()); dst_print_mpi(dst, "ecc p", ec.p(), ctx.dump_mpi); dst_printf(dst, "ecc curve: %s\n", cdesc ? cdesc->pgp_name : "unknown"); return; } case PGP_PKA_ECDH: { auto &ec = dynamic_cast(*material); - auto cdesc = get_curve_desc(ec.curve()); + auto cdesc = pgp::ec::Curve::get(ec.curve()); /* Common EC fields */ dst_print_mpi(dst, "ecdh p", ec.p(), ctx.dump_mpi); dst_printf(dst, "ecdh curve: %s\n", cdesc ? cdesc->pgp_name : "unknown"); @@ -2156,7 +2156,7 @@ stream_dump_key_material_json(rnp_dump_ctx_t & ctx, case PGP_PKA_SM2: case PGP_PKA_ECDH: { auto &ec = dynamic_cast(*material); - auto cdesc = get_curve_desc(ec.curve()); + auto cdesc = pgp::ec::Curve::get(ec.curve()); /* Common EC fields */ if (!obj_add_mpi_json(jso, "p", ec.p(), ctx.dump_mpi)) { return false; // LCOV_EXCL_LINE diff --git a/src/librepgp/stream-packet.cpp b/src/librepgp/stream-packet.cpp index 64292ffb9..ab973a74c 100644 --- a/src/librepgp/stream-packet.cpp +++ b/src/librepgp/stream-packet.cpp @@ -619,7 +619,7 @@ pgp_packet_body_t::get(pgp_curve_t &val) noexcept if (!get(oid, oidlen)) { return false; } - pgp_curve_t res = find_curve_by_OID(oid); + pgp_curve_t res = pgp::ec::Curve::by_OID(oid); if (res == PGP_CURVE_MAX) { RNP_LOG("unsupported curve"); return false; @@ -804,7 +804,7 @@ pgp_packet_body_t::add_subpackets(const pgp_signature_t &sig, bool hashed) void pgp_packet_body_t::add(const pgp_curve_t curve) { - auto desc = get_curve_desc(curve); + auto desc = pgp::ec::Curve::get(curve); if (!desc) { throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } @@ -1245,8 +1245,8 @@ pgp_pk_sesskey_t::parse_material(pgp_encrypted_material_t &material) #if defined(ENABLE_CRYPTO_REFRESH) case PGP_PKA_X25519: { uint8_t bt = 0; - auto ec_desc = get_curve_desc(PGP_CURVE_25519); - material.x25519.eph_key.resize(BITS_TO_BYTES(ec_desc->bitlen)); + auto ec_desc = pgp::ec::Curve::get(PGP_CURVE_25519); + material.x25519.eph_key.resize(ec_desc->bytes()); if (!pkt.get(material.x25519.eph_key.data(), material.x25519.eph_key.size())) { RNP_LOG("failed to parse X25519 PKESK (eph. pubkey)"); return false; diff --git a/src/librepgp/stream-sig.cpp b/src/librepgp/stream-sig.cpp index 416ef5fa7..d7935bdbc 100644 --- a/src/librepgp/stream-sig.cpp +++ b/src/librepgp/stream-sig.cpp @@ -1073,8 +1073,8 @@ pgp_signature_t::parse_material(pgp_signature_material_t &material) const break; #if defined(ENABLE_CRYPTO_REFRESH) case PGP_PKA_ED25519: { - auto ec_desc = get_curve_desc(PGP_CURVE_25519); - material.ed25519.sig.resize(2 * BITS_TO_BYTES(ec_desc->bitlen)); + auto ec_desc = pgp::ec::Curve::get(PGP_CURVE_25519); + material.ed25519.sig.resize(2 * ec_desc->bytes()); if (!pkt.get(material.ed25519.sig.data(), material.ed25519.sig.size())) { RNP_LOG("failed to parse ED25519 signature data"); return false; diff --git a/src/tests/cipher.cpp b/src/tests/cipher.cpp index 1dd8e8ae7..fa19717f2 100644 --- a/src/tests/cipher.cpp +++ b/src/tests/cipher.cpp @@ -317,7 +317,7 @@ class ECDHTestKeyMaterial : public ECDHKeyMaterial { key_.key_wrap_alg = alg; } - pgp_ec_key_t & + ec::Key & ec() { return key_; @@ -401,8 +401,8 @@ TEST_F(rnp_tests, sm2_sm3_signature_test) { const char *msg = "no backdoors here"; - pgp_ec_key_t sm2_key; - pgp_ec_signature_t sig; + pgp::ec::Key sm2_key; + pgp::ec::Signature sig; pgp_hash_alg_t hash_alg = PGP_HASH_SM3; const size_t hash_len = rnp::Hash::size(hash_alg); @@ -416,30 +416,29 @@ TEST_F(rnp_tests, sm2_sm3_signature_test) "c82f49ee0a5b11df22cb0c3c6d9d5526d9e24d02ff8c83c06a859c26565f1"); hex2mpi(&sm2_key.x, "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC"); - assert_int_equal(sm2_validate_key(&global_ctx.rng, &sm2_key, true), RNP_SUCCESS); + assert_rnp_success(sm2_validate_key(global_ctx.rng, sm2_key, true)); auto hash = rnp::Hash::create(hash_alg); - assert_int_equal(sm2_compute_za(sm2_key, *hash, "sm2_p256_test@example.com"), RNP_SUCCESS); + assert_rnp_success(sm2_compute_za(sm2_key, *hash, "sm2_p256_test@example.com")); hash->add(msg, strlen(msg)); assert_int_equal(hash->finish(digest), hash_len); // First generate a signature, then verify it - assert_int_equal(sm2_sign(&global_ctx.rng, &sig, hash_alg, digest, hash_len, &sm2_key), - RNP_SUCCESS); - assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); + 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)); // Check that invalid signatures are rejected digest[0] ^= 1; - assert_int_not_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); + assert_rnp_failure(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); digest[0] ^= 1; - assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); + assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); // Now verify a known good signature for this key/message (generated by GmSSL) hex2mpi(&sig.r, "96AA39A0C4A5C454653F394E86386F2E38BE14C57D0E555F3A27A5CEF30E51BD"); hex2mpi(&sig.s, "62372BE4AC97DBE725AC0B279BB8FD15883858D814FD792DDB0A401DCC988E70"); - assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); + assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); } #endif @@ -447,8 +446,8 @@ TEST_F(rnp_tests, sm2_sm3_signature_test) TEST_F(rnp_tests, sm2_sha256_signature_test) { const char * msg = "hi chappy"; - pgp_ec_key_t sm2_key; - pgp_ec_signature_t sig; + pgp::ec::Key sm2_key; + 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]; @@ -459,29 +458,28 @@ TEST_F(rnp_tests, sm2_sha256_signature_test) "05e6213eee145b748e36e274e5f101dc10d7bbc9dab9a04022e73b76e02cd"); hex2mpi(&sm2_key.x, "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC"); - assert_int_equal(sm2_validate_key(&global_ctx.rng, &sm2_key, true), RNP_SUCCESS); + assert_rnp_success(sm2_validate_key(global_ctx.rng, sm2_key, true)); auto hash = rnp::Hash::create(hash_alg); - assert_int_equal(sm2_compute_za(sm2_key, *hash, "sm2test@example.com"), RNP_SUCCESS); + assert_rnp_success(sm2_compute_za(sm2_key, *hash, "sm2test@example.com")); hash->add(msg, strlen(msg)); assert_int_equal(hash->finish(digest), hash_len); // First generate a signature, then verify it - assert_int_equal(sm2_sign(&global_ctx.rng, &sig, hash_alg, digest, hash_len, &sm2_key), - RNP_SUCCESS); - assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); + 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)); // Check that invalid signatures are rejected digest[0] ^= 1; - assert_int_not_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); + assert_rnp_failure(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); digest[0] ^= 1; - assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); + assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); // Now verify a known good signature for this key/message (generated by GmSSL) hex2mpi(&sig.r, "94DA20EA69E4FC70692158BF3D30F87682A4B2F84DF4A4829A1EFC5D9C979D3F"); hex2mpi(&sig.s, "EE15AF8D455B728AB80E592FCB654BF5B05620B2F4D25749D263D5C01FAD365F"); - assert_int_equal(sm2_verify(&sig, hash_alg, digest, hash_len, &sm2_key), RNP_SUCCESS); + assert_rnp_success(sm2_verify(sig, hash_alg, digest, hash_len, sm2_key)); } #endif @@ -793,7 +791,7 @@ class ECDSATestKeyMaterial : public ECDSAKeyMaterial { { } - pgp_ec_key_t & + ec::Key & ec() { return key_; @@ -806,7 +804,7 @@ class EDDSATestKeyMaterial : public EDDSAKeyMaterial { { } - pgp_ec_key_t & + ec::Key & ec() { return key_;