Skip to content

Commit

Permalink
add SPHINCS+
Browse files Browse the repository at this point in the history
  • Loading branch information
TJ-91 committed Jul 28, 2023
1 parent dcb7636 commit 87cae3d
Show file tree
Hide file tree
Showing 22 changed files with 994 additions and 9 deletions.
4 changes: 4 additions & 0 deletions include/repgp/repgp_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ typedef enum : uint8_t {
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 */
Expand Down
23 changes: 22 additions & 1 deletion include/rnp/rnp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,24 @@ 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(ENABLE_PQC)
/** 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);
#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 @@ -2996,7 +3014,8 @@ RNP_API rnp_result_t rnp_op_encrypt_add_recipient(rnp_op_encrypt_t op, rnp_key_h
/**
* @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.
* 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.
Expand Down Expand Up @@ -3417,6 +3436,8 @@ RNP_API const char *rnp_backend_version();
#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"
#endif
#define RNP_ALGNAME_IDEA "IDEA"
#define RNP_ALGNAME_TRIPLEDES "TRIPLEDES"
Expand Down
3 changes: 2 additions & 1 deletion src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,9 @@ elseif(CRYPTO_BACKEND_BOTAN)
endif()
if(ENABLE_PQC)
list(APPEND CRYPTO_SOURCES
crypto/dilithium.cpp
crypto/dilithium.cpp
crypto/dilithium_common.cpp
crypto/sphincsplus.cpp
crypto/kyber_common.cpp
crypto/kyber.cpp
crypto/kyber_ecdh_composite.cpp
Expand Down
19 changes: 19 additions & 0 deletions src/lib/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,17 @@ pgp_generate_seckey(const rnp_keygen_crypto_params_t &crypto,
return false;
}
break;
case PGP_PKA_SPHINCSPLUS_SHA2:
[[fallthrough]];
case PGP_PKA_SPHINCSPLUS_SHAKE:
if (pgp_sphincsplus_generate(&crypto.ctx->rng,
&seckey.material.sphincsplus,
crypto.sphincsplus.param,
seckey.alg)) {
RNP_LOG("failed to generate SPHINCS+ key for PK alg %d", seckey.alg);
return false;
}
break;
#endif
default:
RNP_LOG("key generation not implemented for PK alg: %d", seckey.alg);
Expand Down Expand Up @@ -275,6 +286,10 @@ key_material_equal(const pgp_key_material_t *key1, const pgp_key_material_t *key
[[fallthrough]];
case PGP_PKA_DILITHIUM5_BP384:
return (key1->dilithium_exdsa.pub == key2->dilithium_exdsa.pub);
case PGP_PKA_SPHINCSPLUS_SHA2:
[[fallthrough]];
case PGP_PKA_SPHINCSPLUS_SHAKE:
return (key1->sphincsplus.pub == key2->sphincsplus.pub);
#endif
default:
RNP_LOG("unknown public key algorithm: %d", (int) key1->alg);
Expand Down Expand Up @@ -352,6 +367,10 @@ validate_pgp_key_material(const pgp_key_material_t *material, rnp::RNG *rng)
[[fallthrough]];
case PGP_PKA_DILITHIUM5_BP384:
return dilithium_exdsa_validate_key(rng, &material->dilithium_exdsa, material->secret);
case PGP_PKA_SPHINCSPLUS_SHA2:
[[fallthrough]];
case PGP_PKA_SPHINCSPLUS_SHAKE:
return sphincsplus_validate_key(rng, &material->sphincsplus, material->secret);
#endif
default:
RNP_LOG("unknown public key algorithm: %d", (int) material->alg);
Expand Down
1 change: 1 addition & 0 deletions src/lib/crypto/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#if defined(ENABLE_PQC)
#include "kyber_ecdh_composite.h"
#include "dilithium_exdsa_composite.h"
#include "sphincsplus.h"
#endif
#if defined(ENABLE_CRYPTO_REFRESH)
#include "x25519.h"
Expand Down
30 changes: 30 additions & 0 deletions src/lib/crypto/signatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ signature_calculate(pgp_signature_t & sig,
ret = seckey.dilithium_exdsa.priv.sign(
&ctx.rng, &material.dilithium_exdsa, hash_alg, hval, hlen);
break;
case PGP_PKA_SPHINCSPLUS_SHA2:
[[fallthrough]];
case PGP_PKA_SPHINCSPLUS_SHAKE:
ret = seckey.sphincsplus.priv.sign(&ctx.rng, &material.sphincsplus, hval, hlen);
break;
#endif
default:
RNP_LOG("Unsupported algorithm %d", sig.palg);
Expand Down Expand Up @@ -246,6 +251,26 @@ signature_validate(const pgp_signature_t & sig,
return RNP_ERROR_SIGNATURE_INVALID;
}

#if defined(ENABLE_PQC)
/* check that hash matches key requirements */
bool hash_alg_valid = false;
switch (key.alg) {
case PGP_PKA_SPHINCSPLUS_SHA2:
[[fallthrough]];
case PGP_PKA_SPHINCSPLUS_SHAKE:
hash_alg_valid = key.sphincsplus.pub.validate_signature_hash_requirements(hash.alg());
break;
default:
hash_alg_valid = true;
break;
}
if (!hash_alg_valid) {
RNP_LOG("Signature invalid since hash algorithm requirements are not met for the "
"given key.");
return RNP_ERROR_SIGNATURE_INVALID;
}
#endif

/* Finalize hash */
uint8_t hval[PGP_MAX_HASH_SIZE];
size_t hlen = 0;
Expand Down Expand Up @@ -326,6 +351,11 @@ signature_validate(const pgp_signature_t & sig,
ret =
key.dilithium_exdsa.pub.verify(&material.dilithium_exdsa, hash.alg(), hval, hlen);
break;
case PGP_PKA_SPHINCSPLUS_SHA2:
[[fallthrough]];
case PGP_PKA_SPHINCSPLUS_SHAKE:
ret = key.sphincsplus.pub.verify(&material.sphincsplus, hval, hlen);
break;
#endif
default:
RNP_LOG("Unknown algorithm");
Expand Down
Loading

0 comments on commit 87cae3d

Please sign in to comment.