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

addition of v6 and PQC #2124

Closed
wants to merge 18 commits into from
Closed
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
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ tristate_feature_auto(ENABLE_BLOWFISH "Enable Blowfish cipher support.")
tristate_feature_auto(ENABLE_CAST5 "Enable CAST5 cipher support.")
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 - requires ENABLE_CRYPTO_REFRESH")

if((NOT ENABLE_CRYPTO_REFRESH) AND ENABLE_PQC)
message(FATAL_ERROR "ENABLE_PQC requires ENABLE_CRYPTO_REFRESH")
endif()


set(ENABLE_DOC Auto CACHE STRING "Enable building documentation.")
set_property(CACHE ENABLE_DOC PROPERTY STRINGS ${TRISTATE_VALUES})

Expand Down
97 changes: 88 additions & 9 deletions include/repgp/repgp_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#define REPGP_DEF_H_

#include <cstdint>
#include "config.h"

/************************************/
/* Packet Tags - RFC4880, 4.2 */
Expand Down Expand Up @@ -94,8 +95,19 @@
#define PGP_KEY_ID_SIZE 8

/* Size of the fingerprint */
#define PGP_FINGERPRINT_SIZE 20
#define PGP_FINGERPRINT_HEX_SIZE (PGP_FINGERPRINT_SIZE * 2) + 1
#define PGP_FINGERPRINT_V4_SIZE 20
#if defined(ENABLE_CRYPTO_REFRESH)
#define PGP_FINGERPRINT_V6_SIZE 32
#define PGP_MAX_FINGERPRINT_SIZE PGP_FINGERPRINT_V6_SIZE
#else
#define PGP_MAX_FINGERPRINT_SIZE PGP_FINGERPRINT_V4_SIZE
#endif
#define PGP_MAX_FINGERPRINT_HEX_SIZE (PGP_MAX_FINGERPRINT_SIZE * 2) + 1

/* SEIPDv2 salt length */
#ifdef ENABLE_CRYPTO_REFRESH
#define PGP_SEIPDV2_SALT_LEN 32
#endif

/* Size of the key grip */
#define PGP_KEY_GRIP_SIZE 20
Expand All @@ -104,6 +116,11 @@
#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 @@ -203,8 +220,43 @@ typedef enum : uint8_t {
* (X9.42, as defined for
* IETF-S/MIME) */
PGP_PKA_EDDSA = 22, /* EdDSA from draft-ietf-openpgp-rfc4880bis */
PGP_PKA_SM2 = 99, /* SM2 encryption/signature schemes */

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

#if defined(ENABLE_PQC)
/* PQC-ECC composite */
PGP_PKA_KYBER768_X25519 = 29, /* Kyber768 + X25519 from draft-wussler-openpgp-pqc-02 */
// PGP_PKA_KYBER1024_X448 = 30, /* Kyer1024 + X448 from
// draft-wussler-openpgp-pqc-02 */
PGP_PKA_KYBER768_P256 = 31, /* Kyber768 + NIST P-256 from draft-wussler-openpgp-pqc-02 */
PGP_PKA_KYBER1024_P384 = 32, /* Kyber1024 + NIST P-384 from draft-wussler-openpgp-pqc-02 */
PGP_PKA_KYBER768_BP256 =
33, /* Kyber768 + Brainpool P256r1 from draft-wussler-openpgp-pqc-02 */
PGP_PKA_KYBER1024_BP384 =
34, /* Kyber1024 + Brainpool P384r1 from draft-wussler-openpgp-pqc-02 */

PGP_PKA_DILITHIUM3_ED25519 =
35, /* Dilithium 3 + Ed25519 from draft-wussler-openpgp-pqc-02 */
// PGP_PKA_DILITHIUM5_ED448 = 36, /* Dilithium 5 + Ed448 from
// draft-wussler-openpgp-pqc-02 */
PGP_PKA_DILITHIUM3_P256 =
37, /* Dilithium 3 + ECDSA-NIST-P-256 from draft-wussler-openpgp-pqc-02 */
PGP_PKA_DILITHIUM5_P384 =
38, /* Dilithium 5 + ECDSA-NIST-P-384 from draft-wussler-openpgp-pqc-02 */
PGP_PKA_DILITHIUM3_BP256 =
39, /* Dilithium 3 + ECDSA-brainpoolP256r1 from draft-wussler-openpgp-pqc-02 */
PGP_PKA_DILITHIUM5_BP384 =
40, /* Dilithium 5 + ECDSA-brainpoolP384r1 from draft-wussler-openpgp-pqc-02 */

PGP_PKA_SPHINCSPLUS_SHA2 = 41, /* SPHINCS+-simple-SHA2 from draft-wussler-openpgp-pqc-02 */
PGP_PKA_SPHINCSPLUS_SHAKE =
42, /* SPHINCS+-simple-SHAKE from draft-wussler-openpgp-pqc-02 */
#endif

PGP_PKA_SM2 = 99, /* SM2 encryption/signature schemes */
PGP_PKA_PRIVATE00 = 100, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE01 = 101, /* Private/Experimental Algorithm */
PGP_PKA_PRIVATE02 = 102, /* Private/Experimental Algorithm */
Expand Down Expand Up @@ -388,7 +440,11 @@ typedef enum {
PGP_SIG_SUBPKT_EMBEDDED_SIGNATURE = 32, /* embedded signature */
PGP_SIG_SUBPKT_ISSUER_FPR = 33, /* issuer fingerprint */
PGP_SIG_SUBPKT_PREFERRED_AEAD = 34, /* preferred AEAD algorithms */
PGP_SIG_SUBPKT_PRIVATE_100 = 100, /* private/experimental subpackets */
#if defined(ENABLE_CRYPTO_REFRESH)
/* PGP_SIG_SUBPKT_INTENDED_RECIPIENT_FINGERPRINT = 35, */
PGP_SIG_SUBPKT_PREFERRED_AEAD_CIPHERSUITES = 39,
#endif
PGP_SIG_SUBPKT_PRIVATE_100 = 100, /* private/experimental subpackets */
PGP_SIG_SUBPKT_PRIVATE_101 = 101,
PGP_SIG_SUBPKT_PRIVATE_102 = 102,
PGP_SIG_SUBPKT_PRIVATE_103 = 103,
Expand Down Expand Up @@ -423,7 +479,10 @@ typedef enum {
typedef enum {
PGP_KEY_FEATURE_MDC = 0x01,
PGP_KEY_FEATURE_AEAD = 0x02,
PGP_KEY_FEATURE_V5 = 0x04
PGP_KEY_FEATURE_V5 = 0x04,
#if defined(ENABLE_CRYPTO_REFRESH)
PGP_KEY_FEATURE_SEIPDV2 = 0x08
#endif
} pgp_key_feature_t;

/** Types of Compression */
Expand All @@ -435,18 +494,30 @@ typedef enum {
PGP_C_UNKNOWN = 255
} pgp_compression_type_t;

enum { PGP_SE_IP_DATA_VERSION = 1, PGP_PKSK_V3 = 3, PGP_SKSK_V4 = 4, PGP_SKSK_V5 = 5 };
enum { PGP_SKSK_V4 = 4, PGP_SKSK_V5 = 5 };
typedef enum {
PGP_PKSK_V3 = 3,
#if defined(ENABLE_CRYPTO_REFRESH)
PGP_PKSK_V6 = 6
#endif
} pgp_pkesk_version_t;
typedef enum { PGP_SE_IP_DATA_V1 = 1, PGP_SE_IP_DATA_V2 = 2 } pgp_seipd_version_t;

/** Version.
* OpenPGP has two different protocol versions: version 3 and version 4.
* Also there is a draft that defines version 5, see
* https://datatracker.ietf.org/doc/draft-ietf-openpgp-crypto-refresh/
*
* \see RFC4880 5.2
*/
typedef enum {
PGP_VUNKNOWN = 0,
PGP_V2 = 2, /* Version 2 (essentially the same as v3) */
PGP_V3 = 3, /* Version 3 */
PGP_V4 = 4 /* Version 4 */
PGP_V4 = 4, /* Version 4 */
#if defined(ENABLE_CRYPTO_REFRESH)
PGP_V6 = 6 /* Version 6 (crypto refresh) */
#endif
} pgp_version_t;

typedef enum pgp_op_t {
Expand Down Expand Up @@ -499,7 +570,15 @@ typedef enum pgp_key_store_format_t {
} pgp_key_store_format_t;

namespace rnp {
enum class AuthType { None, MDC, AEADv1 };
}
enum class AuthType {
None,
MDC,
AEADv1,
#ifdef ENABLE_CRYPTO_REFRESH
AEADv2
#endif
};

} // namespace rnp

#endif
60 changes: 60 additions & 0 deletions include/rnp/rnp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,31 @@ RNP_API rnp_result_t rnp_op_generate_clear_pref_ciphers(rnp_op_generate_t op);
RNP_API rnp_result_t rnp_op_generate_set_pref_keyserver(rnp_op_generate_t op,
const char * keyserver);

/** Set the generated key version to v6.
* NOTE: This is an experimantal feature and this function can be replaced (or removed) at any
* time.
*
* @param op pointer to opaque key generation context.
* @return RNP_SUCCESS or error code if failed.
*/
RNP_API rnp_result_t rnp_op_generate_set_v6_key(rnp_op_generate_t op);

/** Set the SPHINCS+ parameter set
* NOTE: This is an experimantal 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);

/** 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 @@ -1716,6 +1741,14 @@ RNP_API rnp_result_t rnp_uid_remove(rnp_key_handle_t key, rnp_uid_handle_t uid);
*/
RNP_API rnp_result_t rnp_uid_handle_destroy(rnp_uid_handle_t uid);

/**
* @brief Get key's version as integer.
*
* @param key key handle, should not be NULL
* @return RNP_SUCCESS or error code on failure.
*/
RNP_API rnp_result_t rnp_key_get_version(rnp_key_handle_t handle, uint32_t *version);

/** Get number of the key's subkeys.
*
* @param key key handle.
Expand Down Expand Up @@ -2972,6 +3005,17 @@ RNP_API rnp_result_t rnp_op_encrypt_create(rnp_op_encrypt_t *op,
*/
RNP_API rnp_result_t rnp_op_encrypt_add_recipient(rnp_op_encrypt_t op, rnp_key_handle_t key);

/**
* @brief Enables the creation of PKESK v6 (instead of v3) which results in the use of SEIPDv2.
* The actually created version depends on the capabilities of the list of recipients.
* NOTE: This is an experimental feature and this function can be replaced (or removed) at any
* time.
*
* @param op opaque encrypting context. Must be allocated and initialized.
* @return RNP_SUCCESS or errorcode if failed.
*/
RNP_API rnp_result_t rnp_op_encrypt_enable_pkesk_v6(rnp_op_encrypt_t op);

/**
* @brief Add signature to encrypting context, so data will be encrypted and signed.
*
Expand Down Expand Up @@ -3368,6 +3412,22 @@ RNP_API const char *rnp_backend_version();
#define RNP_ALGNAME_ECDH "ECDH"
#define RNP_ALGNAME_ECDSA "ECDSA"
#define RNP_ALGNAME_EDDSA "EDDSA"
#define RNP_ALGNAME_ED25519 "ED25519"
#define RNP_ALGNAME_X25519 "X25519"
#define RNP_ALGNAME_KYBER768_X25519 "KYBER768_X25519"
#define RNP_ALGNAME_KYBER1024_X448 "KYBER1024_X448"
#define RNP_ALGNAME_KYBER768_P256 "KYBER768_P256"
#define RNP_ALGNAME_KYBER1024_P384 "KYBER1024_P384"
#define RNP_ALGNAME_KYBER768_BP256 "KYBER768_BP256"
#define RNP_ALGNAME_KYBER1024_BP384 "KYBER1024_BP384"
#define RNP_ALGNAME_DILITHIUM3_ED25519 "DILITHIUM3_ED25519"
#define RNP_ALGNAME_DILITHIUM5_ED448 "DILITHIUM5_ED448"
#define RNP_ALGNAME_DILITHIUM3_P256 "DILITHIUM3_P256"
#define RNP_ALGNAME_DILITHIUM5_P384 "DILITHIUM5_P384"
#define RNP_ALGNAME_DILITHIUM3_BP256 "DILITHIUM3_BP256"
#define RNP_ALGNAME_DILITHIUM5_BP384 "DILITHIUM5_BP384"
#define RNP_ALGNAME_SPHINCSPLUS_SHA2 "SPHINCSPLUS_SHA2"
#define RNP_ALGNAME_SPHINCSPLUS_SHAKE "SPHINCSPLUS_SHAKE"
#define RNP_ALGNAME_IDEA "IDEA"
#define RNP_ALGNAME_TRIPLEDES "TRIPLEDES"
#define RNP_ALGNAME_CAST5 "CAST5"
Expand Down
1 change: 1 addition & 0 deletions include/rnp/rnp_err.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ enum {
RNP_ERROR_KEY_NOT_FOUND,
RNP_ERROR_NO_SUITABLE_KEY,
RNP_ERROR_DECRYPT_FAILED,
RNP_ERROR_ENCRYPT_FAILED,
RNP_ERROR_RNG,
RNP_ERROR_SIGNING_FAILED,
RNP_ERROR_NO_SIGNATURES_FOUND,
Expand Down
53 changes: 52 additions & 1 deletion src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ if(CRYPTO_BACKEND_BOTAN3)
set(CMAKE_CXX_STANDARD 20)
endif()

if(ENABLE_PQC)
if (NOT CRYPTO_BACKEND_BOTAN3)
message(FATAL_ERROR "ENABLE_PQC requires Botan 3 as crypto backend")
endif()
if (NOT ENABLE_CRYPTO_REFRESH)
message(FATAL_ERROR "ENABLE_PQC requires ENABLE_CRYPTO_REFRESH")
endif()
endif()

# check that AEAD is enabled and not turned off for ENABLE_CRYPTO_REFRESH
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()

# generate a config.h
include(CheckIncludeFileCXX)
include(CheckCXXSymbolExists)
Expand Down Expand Up @@ -173,10 +187,14 @@ 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")
# Botan supports Brainpool curves together with SECP via the ECC_GROUP define
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_BLOWFISH "BLOWFISH")
resolve_feature_state(ENABLE_CAST5 "CAST_128")
resolve_feature_state(ENABLE_RIPEMD160 "RIPEMD_160")
# Botan supports Brainpool curves together with SECP via the ECC_GROUP define


set(CMAKE_REQUIRED_INCLUDES)
endif()
if(CRYPTO_BACKEND_OPENSSL)
Expand Down Expand Up @@ -212,6 +230,8 @@ if(CRYPTO_BACKEND_OPENSSL)
openssl_nope(ENABLE_SM2 "it's on our roadmap, see https://github.com/rnpgp/rnp/issues/1877")
#resolve_feature_state(ENABLE_SM2 "SM2;SM3;SM4-ECB")
openssl_nope(ENABLE_TWOFISH "Twofish isn't and won't be supported by OpenSSL, see https://github.com/openssl/openssl/issues/2046")
openssl_nope(ENABLE_CRYPTO_REFRESH, "not yet implemented")
openssl_nope(ENABLE_PQC, "not yet implemented")
endif()

configure_file(config.h.in config.h)
Expand Down Expand Up @@ -271,6 +291,28 @@ elseif(CRYPTO_BACKEND_BOTAN)
if(ENABLE_SM2)
list(APPEND CRYPTO_SOURCES crypto/sm2.cpp)
endif()
if(ENABLE_CRYPTO_REFRESH)
list(APPEND CRYPTO_SOURCES
crypto/hkdf.cpp
crypto/hkdf_botan.cpp
crypto/ed25519.cpp
crypto/x25519.cpp
crypto/exdsa_ecdhkem.cpp
)
endif()
if(ENABLE_PQC)
list(APPEND CRYPTO_SOURCES
crypto/dilithium.cpp
crypto/dilithium_common.cpp
crypto/sphincsplus.cpp
crypto/kyber_common.cpp
crypto/kyber.cpp
crypto/kyber_ecdh_composite.cpp
crypto/dilithium_exdsa_composite.cpp
crypto/kmac.cpp
crypto/kmac_botan.cpp
)
endif()
else()
message(FATAL_ERROR "Unknown crypto backend: ${CRYPTO_BACKEND}.")
endif()
Expand All @@ -279,6 +321,14 @@ list(APPEND CRYPTO_SOURCES crypto/backend_version.cpp)
# sha11collisiondetection sources
list(APPEND CRYPTO_SOURCES crypto/hash_sha1cd.cpp crypto/sha1cd/sha1.c crypto/sha1cd/ubc_check.c)


set(CRYPTO_REFRESH_SOURCES )
if(ENABLE_CRYPTO_REFRESH)
list(APPEND CRYPTO_REFRESH_SOURCES
../librepgp/v2_seipd.cpp
)
endif()

add_library(librnp-obj OBJECT
# librepgp
../librepgp/stream-armor.cpp
Expand All @@ -290,6 +340,7 @@ add_library(librnp-obj OBJECT
../librepgp/stream-parse.cpp
../librepgp/stream-sig.cpp
../librepgp/stream-write.cpp
${CRYPTO_REFRESH_SOURCES}

# librekey
../librekey/key_store_g10.cpp
Expand Down
9 changes: 9 additions & 0 deletions src/lib/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
#cmakedefine ENABLE_TWOFISH
#cmakedefine ENABLE_BRAINPOOL
#cmakedefine ENABLE_IDEA
#cmakedefine ENABLE_CRYPTO_REFRESH
#cmakedefine ENABLE_PQC
#cmakedefine ENABLE_BLOWFISH
#cmakedefine ENABLE_CAST5
#cmakedefine ENABLE_RIPEMD160
Expand All @@ -71,3 +73,10 @@
((defined(__clang__) && (__clang_major__ >= 4)) )
#define RNP_USE_STD_REGEX 1
#endif

/* do not use the statement for old MSVC versions */
#if (!defined(_MSVC_LANG) || _MSVC_LANG >= 201703L)
# define FALLTHROUGH_STATEMENT [[fallthrough]];
#else
# define FALLTHROUGH_STATEMENT
#endif
Loading