Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8d268ea
change parametrized SPHINCS+ to separate SPHINCS+ algorithms
TJ-91 Sep 30, 2024
0094651
improve v6 enc test
TJ-91 Sep 30, 2024
055b589
fix key generation PQC hash requirements
TJ-91 Oct 1, 2024
e2a03f6
Update PQC to draft-05
TJ-91 Oct 1, 2024
3de8696
update C-R code to botan 3.6.0
TJ-91 Oct 2, 2024
e9c1d64
add X448/Ed448 (PQC and standalone)
TJ-91 Oct 17, 2024
61b3097
update order in KEM combiner: PQ first
TJ-91 Oct 21, 2024
b7c9c3b
update PQC test vectors; partially implement V6 OPS
TJ-91 Oct 23, 2024
812e922
fix v6 signature salt and add some test vectors
TJ-91 Oct 29, 2024
8c487d0
Some cleanup and refactoring
TJ-91 Oct 30, 2024
44ecc1a
update PQC test vectors to -06 draft
TJ-91 Nov 1, 2024
a1a0757
fix pqc signature hash binding
TJ-91 Nov 1, 2024
b554542
sensible values in ec_curves for Ed448/X448
TJ-91 Nov 4, 2024
2ea9ed1
fix some stuff after rebase
TJ-91 Nov 12, 2024
e101f28
set SHA3 support for PQC keys; fix backwards compatible key gen option
TJ-91 Nov 12, 2024
ee2a86e
KMAC to SHA3 KEM Combiner
TJ-91 Dec 6, 2024
796d7d1
update SPHINCS+ to SLHDSA
TJ-91 Jan 28, 2025
cc416a8
some fixes
TJ-91 Feb 3, 2025
1b7f466
assign mlkem code points
TJ-91 Feb 17, 2025
da1e17f
remove PQC hash binding; forbid ripemd for RFC9580
TJ-91 Feb 17, 2025
b78ee57
add quick fix for some tests when Crypto Refresh is enabled
TJ-91 Feb 17, 2025
4b3e091
check for v2 SEIPD feature flag when encrypting
TJ-91 Mar 28, 2025
8dd97ed
clang format
TJ-91 Mar 28, 2025
6ddf14b
adjust to kem combiner of PQC draft -08
TJ-91 Apr 10, 2025
22b82ed
adjust kem combiner to include the length byte
TJ-91 Apr 10, 2025
33f26da
check v6 for parsing PQC keys; update test vectors
TJ-91 Apr 14, 2025
414729d
add test vectors -09 and respective test cases
TJ-91 May 6, 2025
6d7b4f1
cleanup
TJ-91 May 15, 2025
2b2381d
minimum signature hash requirements for PQC sigs and Ed25519/Ed448;
TJ-91 Jun 16, 2025
ae08ba2
fixes after rebasing
TJ-91 Jul 14, 2025
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
39 changes: 22 additions & 17 deletions include/repgp/repgp_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,6 @@
#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 @@ -209,38 +204,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_KYBER768_X25519 = 35,
PGP_PKA_KYBER1024_X448 = 36,
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_DILITHIUM3_P256 = 115,
PGP_PKA_DILITHIUM3_ED25519 = 30,
PGP_PKA_DILITHIUM5_ED448 = 31,
PGP_PKA_DILITHIUM3_P256 = 132,
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_128s = 32,
PGP_PKA_SPHINCSPLUS_SHAKE_128f = 33,
PGP_PKA_SPHINCSPLUS_SHAKE_256s = 34,

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 @@ -277,7 +273,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 @@ -489,6 +488,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 @@ -1224,24 +1224,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 @@ -2446,19 +2428,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 @@ -4114,9 +4083,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 @@ -4131,8 +4102,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
38 changes: 21 additions & 17 deletions src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@ 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)
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)
# botan-config.cmake from Botan distribution doesn't support version 2.x,
# so use -DCRYPTO_BACKEND=botan3 to configure
find_package(Botan 2.14.0 REQUIRED)
if(Botan_VERSION VERSION_GREATER_EQUAL 3.0.0)
set(CRYPTO_BACKEND_BOTAN3 1)
if(Botan_VERSION VERSION_GREATER_EQUAL 3.0.0)
set(CRYPTO_BACKEND_BOTAN3 1)
endif()
endif()
endif()
if (CRYPTO_BACKEND_BOTAN)
Expand All @@ -60,7 +65,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 @@ -70,6 +75,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 @@ -211,8 +220,8 @@ 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_PQC "KMAC;DILITHIUM;KYBER;SPHINCS_PLUS_WITH_SHA2;SPHINCS_PLUS_WITH_SHAKE")
resolve_feature_state(ENABLE_CRYPTO_REFRESH "HKDF;ED448;X448")
resolve_feature_state(ENABLE_PQC "DILITHIUM;KYBER;SPHINCS_PLUS_WITH_SHA2;SPHINCS_PLUS_WITH_SHAKE")
resolve_feature_state(ENABLE_BLOWFISH "BLOWFISH")
resolve_feature_state(ENABLE_CAST5 "CAST_128")
resolve_feature_state(ENABLE_RIPEMD160 "RIPEMD_160")
Expand Down Expand Up @@ -348,14 +357,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 @@ -369,11 +375,9 @@ elseif(CRYPTO_BACKEND_BOTAN)
crypto/kyber.cpp
crypto/kyber_ecdh_composite.cpp
crypto/dilithium_exdsa_composite.cpp
crypto/kmac.cpp
crypto/kmac_botan.cpp
crypto/kem_combiner.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
24 changes: 4 additions & 20 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 @@ -117,21 +119,3 @@ pgp_dilithium_private_key_t::is_valid(rnp::RNG *rng) const
auto key = botan_key();
return key.check_key(*(rng->obj()), false);
}

bool
dilithium_hash_allowed(pgp_hash_alg_t hash_alg)
{
switch (hash_alg) {
case PGP_HASH_SHA3_256:
case PGP_HASH_SHA3_512:
return true;
default:
return false;
}
}

pgp_hash_alg_t
dilithium_default_hash_alg()
{
return PGP_HASH_SHA3_256;
}
4 changes: 0 additions & 4 deletions src/lib/crypto/dilithium.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,4 @@ 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);

pgp_hash_alg_t dilithium_default_hash_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