Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update draft 06 #2287

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,7 @@ tristate_feature_auto(ENABLE_RIPEMD160 "Enable RIPEMD-160 hash support.")
option(ENABLE_CRYPTO_REFRESH "Enable crypto-refresh support (v6)")
option(ENABLE_PQC "Enable PQC support")

# Note: The following two flags are only temporary and will be removed once POC is in a stable state
if (DEFINED ENABLE_PQC_MLKEM_IPD)
add_definitions(-DENABLE_PQC_MLKEM_IPD)
endif()
# Note: The following flag is only temporary and will be removed once POC is in a stable state
if (DEFINED ENABLE_PQC_DBG_LOG)
add_definitions(-DENABLE_PQC_DBG_LOG)
endif()
Expand Down
33 changes: 19 additions & 14 deletions include/repgp/repgp_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,6 @@ static_assert(PGP_FINGERPRINT_V5_SIZE == PGP_FINGERPRINT_V6_SIZE, "FP size misma
#define PGP_MARKER_CONTENTS "PGP"
#define PGP_MARKER_LEN 3

/* V6 Signature Salt */
#if defined(ENABLE_CRYPTO_REFRESH)
#define PGP_MAX_SALT_SIZE_V6_SIG 32
#endif

/** Old Packet Format Lengths.
* Defines the meanings of the 2 bits for length type in the
* old packet format.
Expand Down Expand Up @@ -227,38 +222,39 @@ typedef enum : uint8_t {
PGP_PKA_EDDSA = 22, /* EdDSA from draft-ietf-openpgp-rfc4880bis */

#if defined(ENABLE_CRYPTO_REFRESH)
PGP_PKA_X25519 = 25, /* v6 / Crypto Refresh */
PGP_PKA_ED25519 = 27, /* v6 / Crypto Refresh */
PGP_PKA_X25519 = 25,
PGP_PKA_X448 = 26,
PGP_PKA_ED25519 = 27,
PGP_PKA_ED448 = 28,
#endif

PGP_PKA_SM2 = 99, /* SM2 encryption/signature schemes */

#if defined(ENABLE_PQC)
/* PQC-ECC composite */
PGP_PKA_KYBER768_X25519 = 105,
// PGP_PKA_KYBER1024_X448 = 106,
PGP_PKA_KYBER1024_X448 = 106,
PGP_PKA_KYBER768_P256 = 111,
PGP_PKA_KYBER1024_P384 = 112,
PGP_PKA_KYBER768_BP256 = 113,
PGP_PKA_KYBER1024_BP384 = 114,

PGP_PKA_DILITHIUM3_ED25519 = 107,
// PGP_PKA_DILITHIUM5_ED448 = 108,
PGP_PKA_DILITHIUM5_ED448 = 108,
PGP_PKA_DILITHIUM3_P256 = 115,
PGP_PKA_DILITHIUM5_P384 = 116,
PGP_PKA_DILITHIUM3_BP256 = 117,
PGP_PKA_DILITHIUM5_BP384 = 118,

PGP_PKA_SPHINCSPLUS_SHA2 = 109,
PGP_PKA_SPHINCSPLUS_SHAKE = 119,
PGP_PKA_SPHINCSPLUS_SHAKE_128f = 119,
PGP_PKA_SPHINCSPLUS_SHAKE_128s = 120,
PGP_PKA_SPHINCSPLUS_SHAKE_256s = 121,

PGP_PKA_PRIVATE00 = 100, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE01 = 101, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE02 = 102, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE03 = 103, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE04 = 104, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE06 = 106, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE08 = 108, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE10 = 110 /* Private/Experimental Algorithm */
#else
PGP_PKA_PRIVATE00 = 100, /* Private/Experimental Algorithm */
Expand Down Expand Up @@ -295,7 +291,10 @@ typedef enum {
PGP_CURVE_P256K1,

PGP_CURVE_SM2_P_256,

#if defined(ENABLE_CRYPTO_REFRESH)
PGP_CURVE_ED448,
PGP_CURVE_448,
#endif
// Keep always last one
PGP_CURVE_MAX
} pgp_curve_t;
Expand Down Expand Up @@ -507,6 +506,12 @@ typedef enum {
#endif
} pgp_pkesk_version_t;
typedef enum { PGP_SE_IP_DATA_V1 = 1, PGP_SE_IP_DATA_V2 = 2 } pgp_seipd_version_t;
typedef enum {
PGP_OPS_V3 = 3,
#if defined(ENABLE_CRYPTO_REFRESH)
PGP_OPS_V6 = 6
#endif
} pgp_ops_version_t;

/** Version.
* OpenPGP has two different protocol versions: version 3 and version 4.
Expand Down
40 changes: 6 additions & 34 deletions include/rnp/rnp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1218,24 +1218,6 @@ RNP_API rnp_result_t rnp_op_generate_set_pref_keyserver(rnp_op_generate_t op,
RNP_API rnp_result_t rnp_op_generate_set_v6_key(rnp_op_generate_t op);
#endif

#if defined(RNP_EXPERIMENTAL_PQC)
/** Set the SPHINCS+ parameter set
* NOTE: This is an experimental feature and this function can be replaced (or removed) at any
* time.
*
* @param op pointer to opaque key generation context.
* @param param string, representing the SHPINCS+ parameter set.
* Possible Values:
* 128s, 128f, 192s, 192f, 256s, 256f
* All parameter sets refer to the simple variant and the hash function is given
* by the algorithm id.
*
* @return RNP_SUCCESS or error code if failed.
*/
RNP_API rnp_result_t rnp_op_generate_set_sphincsplus_param(rnp_op_generate_t op,
const char * param);
#endif

/** Execute the prepared key or subkey generation operation.
* Note: if you set protection algorithm, then you need to specify ffi password provider to
* be able to request password for key encryption.
Expand Down Expand Up @@ -2375,19 +2357,6 @@ RNP_API rnp_result_t rnp_key_get_default_key(rnp_key_handle_t primary_key,
*/
RNP_API rnp_result_t rnp_key_get_alg(rnp_key_handle_t key, char **alg);

#if defined(RNP_EXPERIMENTAL_PQC)
/** Get a SPHINCS+ key's parameter string
*
* @param key key handle
* @param alg string with parameter name will be stored here. You must free it using the
* rnp_buffer_destroy() function.
* @return RNP_SUCCESS or error code if failed.
* NOTE: This is an experimental feature and this function can be replaced (or removed) at any
* time.
*/
RNP_API rnp_result_t rnp_key_sphincsplus_get_param(rnp_key_handle_t handle, char **param);
#endif

/** Get number of bits in the key. For EC-based keys it will return size of the curve.
*
* @param key key handle
Expand Down Expand Up @@ -4041,9 +4010,11 @@ RNP_API const char *rnp_backend_version();
#define RNP_ALGNAME_ECDH "ECDH"
#define RNP_ALGNAME_ECDSA "ECDSA"
#define RNP_ALGNAME_EDDSA "EDDSA"
#if defined(RNP_EXPERIMENTAL_CRYPTO_REFRESH) || defined(RNP_EXPERIMENTAL_PQC)
#if defined(RNP_EXPERIMENTAL_CRYPTO_REFRESH)
#define RNP_ALGNAME_ED25519 "ED25519"
#define RNP_ALGNAME_X25519 "X25519"
#define RNP_ALGNAME_ED448 "ED448"
#define RNP_ALGNAME_X448 "X448"
#endif
#if defined(RNP_EXPERIMENTAL_PQC)
#define RNP_ALGNAME_KYBER768_X25519 "ML-KEM-768+X25519"
Expand All @@ -4058,8 +4029,9 @@ RNP_API const char *rnp_backend_version();
#define RNP_ALGNAME_DILITHIUM5_P384 "ML-DSA-87+ECDSA-P384"
#define RNP_ALGNAME_DILITHIUM3_BP256 "ML-DSA-65+ECDSA-BP256"
#define RNP_ALGNAME_DILITHIUM5_BP384 "ML-DSA-87+ECDSA-BP384"
#define RNP_ALGNAME_SPHINCSPLUS_SHA2 "SLH-DSA-SHA2"
#define RNP_ALGNAME_SPHINCSPLUS_SHAKE "SLH-DSA-SHAKE"
#define RNP_ALGNAME_SPHINCSPLUS_SHAKE_128f "SLH-DSA-SHAKE-128f"
#define RNP_ALGNAME_SPHINCSPLUS_SHAKE_128s "SLH-DSA-SHAKE-128s"
#define RNP_ALGNAME_SPHINCSPLUS_SHAKE_256s "SLH-DSA-SHAKE-256s"
#endif
#define RNP_ALGNAME_IDEA "IDEA"
#define RNP_ALGNAME_TRIPLEDES "TRIPLEDES"
Expand Down
35 changes: 20 additions & 15 deletions src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@ find_package(ZLIB REQUIRED)

# required packages
find_package(JSON-C 0.11 REQUIRED)
if (CRYPTO_BACKEND_BOTAN3)
find_package(Botan 3.0.0 REQUIRED)
elseif (CRYPTO_BACKEND_BOTAN)
find_package(Botan 2.14.0 REQUIRED)
if(BOTAN_VERSION VERSION_GREATER_EQUAL 3.0.0)
set(CRYPTO_BACKEND_BOTAN3 1)
if(ENABLE_CRYPTO_REFRESH)
find_package(Botan 3.6.0 REQUIRED)
set(CRYPTO_BACKEND_BOTAN3 1)
else()
if (CRYPTO_BACKEND_BOTAN3)
find_package(Botan 3.0.0 REQUIRED)
elseif (CRYPTO_BACKEND_BOTAN)
find_package(Botan 2.14.0 REQUIRED)
if(BOTAN_VERSION VERSION_GREATER_EQUAL 3.0.0)
set(CRYPTO_BACKEND_BOTAN3 1)
endif()
endif()
endif()
if (CRYPTO_BACKEND_OPENSSL)
Expand All @@ -51,7 +56,7 @@ if(CRYPTO_BACKEND_BOTAN3)
set(CMAKE_CXX_STANDARD 20)
endif()

if(ENABLE_PQC)
if(ENABLE_CRYPTO_REFRESH)
if (NOT CRYPTO_BACKEND_BOTAN3)
message(FATAL_ERROR "ENABLE_PQC requires Botan 3 as crypto backend")
endif()
Expand All @@ -61,6 +66,10 @@ endif()
if(ENABLE_CRYPTO_REFRESH AND (NOT ENABLE_AEAD))
message(FATAL_ERROR "ENABLE_CRYPTO_REFRESH requires ENABLE_AEAD, but it's either Off or Auto and got turned off")
endif()
# check that ENABLE_CRYPTO_REFRESH is enabled for ENABLE_PQC
if(ENABLE_PQC AND (NOT ENABLE_CRYPTO_REFRESH))
message(FATAL_ERROR "ENABLE_PQC requires ENABLE_CRYPTO_REFRESH")
endif()

# generate a config.h
include(CheckIncludeFileCXX)
Expand Down Expand Up @@ -183,7 +192,7 @@ if(CRYPTO_BACKEND_BOTAN)
resolve_feature_state(ENABLE_AEAD "AEAD_EAX;AEAD_OCB")
resolve_feature_state(ENABLE_TWOFISH "TWOFISH")
resolve_feature_state(ENABLE_IDEA "IDEA")
resolve_feature_state(ENABLE_CRYPTO_REFRESH "HKDF")
resolve_feature_state(ENABLE_CRYPTO_REFRESH "HKDF;ED448;X448")
resolve_feature_state(ENABLE_PQC "KMAC;DILITHIUM;KYBER;SPHINCS_PLUS_WITH_SHA2;SPHINCS_PLUS_WITH_SHAKE")
resolve_feature_state(ENABLE_BLOWFISH "BLOWFISH")
resolve_feature_state(ENABLE_CAST5 "CAST_128")
Expand Down Expand Up @@ -298,14 +307,11 @@ elseif(CRYPTO_BACKEND_BOTAN)
if(ENABLE_SM2)
list(APPEND CRYPTO_SOURCES crypto/sm2.cpp)
endif()
if(ENABLE_PQC OR ENABLE_CRYPTO_REFRESH)
list(APPEND CRYPTO_SOURCES
crypto/exdsa_ecdhkem.cpp
crypto/ed25519.cpp
crypto/x25519.cpp
)
if(ENABLE_CRYPTO_REFRESH)
list(APPEND CRYPTO_SOURCES
crypto/exdsa_ecdhkem.cpp
crypto/ed25519_ed448.cpp
crypto/x25519_x448.cpp
crypto/hkdf.cpp
crypto/hkdf_botan.cpp
)
Expand All @@ -323,7 +329,6 @@ elseif(CRYPTO_BACKEND_BOTAN)
crypto/kmac_botan.cpp
)
endif()
endif()
else()
message(FATAL_ERROR "Unknown crypto backend: ${CRYPTO_BACKEND}.")
endif()
Expand Down
4 changes: 2 additions & 2 deletions src/lib/crypto/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
#include "sphincsplus.h"
#endif
#if defined(ENABLE_CRYPTO_REFRESH)
#include "x25519.h"
#include "ed25519.h"
#include "x25519_x448.h"
#include "ed25519_ed448.h"
#endif
/* symmetric crypto */
#include "symmetric.h"
Expand Down
48 changes: 38 additions & 10 deletions src/lib/crypto/dilithium.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@
*/

#include "dilithium.h"
#include "logging.h"
#include "types.h"
#include <cassert>

namespace {

Botan::DilithiumMode
rnp_dilithium_param_to_botan_dimension(dilithium_parameter_e mode)
{
Botan::DilithiumMode result = Botan::DilithiumMode::Dilithium8x7;
Botan::DilithiumMode result = Botan::DilithiumMode::ML_DSA_8x7;
if (mode == dilithium_parameter_e::dilithium_L3) {
result = Botan::DilithiumMode::Dilithium6x5;
result = Botan::DilithiumMode::ML_DSA_6x5;
}
return result;
}
Expand Down Expand Up @@ -119,19 +121,45 @@ pgp_dilithium_private_key_t::is_valid(rnp::RNG *rng) const
}

bool
dilithium_hash_allowed(pgp_hash_alg_t hash_alg)
dilithium_hash_allowed(pgp_pubkey_alg_t pk_alg, pgp_hash_alg_t hash_alg)
{
switch (hash_alg) {
case PGP_HASH_SHA3_256:
case PGP_HASH_SHA3_512:
return true;
switch (pk_alg) {
case PGP_PKA_DILITHIUM3_ED25519:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_P256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_BP256:
return hash_alg == PGP_HASH_SHA3_256;
case PGP_PKA_DILITHIUM5_ED448:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_P384:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_BP384:
return hash_alg == PGP_HASH_SHA3_512;
default:
return false;
RNP_LOG("invalid algorithm ID given");
throw rnp::rnp_exception(RNP_ERROR_BAD_STATE);
}
}

pgp_hash_alg_t
dilithium_default_hash_alg()
dilithium_default_hash_alg(pgp_pubkey_alg_t pk_alg)
{
return PGP_HASH_SHA3_256;
switch (pk_alg) {
case PGP_PKA_DILITHIUM3_ED25519:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_P256:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM3_BP256:
return PGP_HASH_SHA3_256;
case PGP_PKA_DILITHIUM5_ED448:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_P384:
FALLTHROUGH_STATEMENT;
case PGP_PKA_DILITHIUM5_BP384:
return PGP_HASH_SHA3_512;
default:
RNP_LOG("invalid algorithm ID given");
throw rnp::rnp_exception(RNP_ERROR_BAD_STATE);
}
}
4 changes: 2 additions & 2 deletions src/lib/crypto/dilithium.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ class pgp_dilithium_public_key_t {
std::pair<pgp_dilithium_public_key_t, pgp_dilithium_private_key_t> dilithium_generate_keypair(
rnp::RNG *rng, dilithium_parameter_e dilithium_param);

bool dilithium_hash_allowed(pgp_hash_alg_t hash_alg);
bool dilithium_hash_allowed(pgp_pubkey_alg_t pk_alg, pgp_hash_alg_t hash_alg);

pgp_hash_alg_t dilithium_default_hash_alg();
pgp_hash_alg_t dilithium_default_hash_alg(pgp_pubkey_alg_t pk_alg);

#endif
17 changes: 5 additions & 12 deletions src/lib/crypto/dilithium_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,10 @@ pgp_dilithium_private_key_t::pgp_dilithium_private_key_t(
}

size_t
dilithium_privkey_size(dilithium_parameter_e parameter)
dilithium_privkey_size()
{
switch (parameter) {
case dilithium_L3:
return 4000;
case dilithium_L5:
return 4864;
default:
RNP_LOG("invalid parameter given");
throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS);
}
/* seed format */
return 32;
}

size_t
Expand All @@ -90,9 +83,9 @@ dilithium_signature_size(dilithium_parameter_e parameter)
{
switch (parameter) {
case dilithium_L3:
return 3293;
return 3309;
case dilithium_L5:
return 4595;
return 4627;
default:
RNP_LOG("invalid parameter given");
throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/crypto/dilithium_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

#include "dilithium.h"

size_t dilithium_privkey_size(dilithium_parameter_e parameter);
size_t dilithium_privkey_size();
size_t dilithium_pubkey_size(dilithium_parameter_e parameter);
size_t dilithium_signature_size(dilithium_parameter_e parameter);

Expand Down
Loading
Loading