Skip to content
Merged
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: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Changed

- When the `fetch_recent_snapshot` behaviour is enabled by the node config, the Joiner will now prefer the peer's snapshot over _any_ local snapshot, regardless of version (#7314).
- Crypto interface for RSA and EC keys (#7425)
- `ccf::crypto::PublicKey` becomes `ccf::crypto::ECPublicKey`
- `ccf::crypto::KeyPair` becomes `ccf::crypto::ECKeyPair`
- Error-prone inheritance between RSA and EC key classes has been removed.
- RSA keys now don't re-use CSR functionality from EC key interface.

### Removed

Expand Down
6 changes: 2 additions & 4 deletions cmake/crypto.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@ set(CCFCRYPTO_SRC
${CCF_DIR}/src/crypto/hash.cpp
${CCF_DIR}/src/crypto/sha256_hash.cpp
${CCF_DIR}/src/crypto/symmetric_key.cpp
${CCF_DIR}/src/crypto/key_pair.cpp
${CCF_DIR}/src/crypto/eddsa_key_pair.cpp
${CCF_DIR}/src/crypto/rsa_key_pair.cpp
${CCF_DIR}/src/crypto/verifier.cpp
${CCF_DIR}/src/crypto/key_wrap.cpp
${CCF_DIR}/src/crypto/hmac.cpp
${CCF_DIR}/src/crypto/pem.cpp
${CCF_DIR}/src/crypto/ecdsa.cpp
${CCF_DIR}/src/crypto/cose.cpp
${CCF_DIR}/src/crypto/openssl/symmetric_key.cpp
${CCF_DIR}/src/crypto/openssl/public_key.cpp
${CCF_DIR}/src/crypto/openssl/key_pair.cpp
${CCF_DIR}/src/crypto/openssl/ec_public_key.cpp
${CCF_DIR}/src/crypto/openssl/ec_key_pair.cpp
${CCF_DIR}/src/crypto/openssl/eddsa_public_key.cpp
${CCF_DIR}/src/crypto/openssl/eddsa_key_pair.cpp
${CCF_DIR}/src/crypto/openssl/hash.cpp
Expand Down
14 changes: 7 additions & 7 deletions doc/build_apps/crypto.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ Hashing
Asymmetric Keys
-----------------------

CCF supports EC and RSA keys; public keys are held in (RSA)PublicKey objects and
private keys in (RSA)KeyPair objects. (RSA)KeyPairs automatically generate random
keys when constructed via :cpp:func:`KeyPairPtr ccf::crypto::make_key_pair(CurveID)` or
CCF supports EC and RSA keys; public keys are held in [RSA|EC]PublicKey objects and
private keys in [RSA|EC]KeyPair objects. [RSA|EC]KeyPair automatically generate random
keys when constructed via :cpp:func:`ECKeyPairPtr ccf::crypto::make_ec_key_pair(CurveID)` or
:cpp:func:`RSAKeyPairPtr ccf::crypto::make_rsa_key_pair(size_t, size_t)`.

.. doxygenclass:: ccf::crypto::PublicKey
.. doxygenclass:: ccf::crypto::ECPublicKey
:project: CCF
:members:

.. doxygenclass:: ccf::crypto::KeyPair
.. doxygenclass:: ccf::crypto::ECKeyPair
:project: CCF
:members:

Expand All @@ -49,10 +49,10 @@ keys when constructed via :cpp:func:`KeyPairPtr ccf::crypto::make_key_pair(Curve
.. doxygenenum:: ccf::crypto::CurveID
:project: CCF

.. doxygenfunction:: ccf::crypto::make_key_pair(CurveID)
.. doxygenfunction:: ccf::crypto::make_ec_key_pair(CurveID)
:project: CCF

.. doxygenfunction:: ccf::crypto::make_key_pair(const Pem&)
.. doxygenfunction:: ccf::crypto::make_ec_key_pair(const Pem&)
:project: CCF

.. doxygenfunction:: ccf::crypto::make_rsa_key_pair(size_t, size_t)
Expand Down
5 changes: 1 addition & 4 deletions include/ccf/crypto/cose_verifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
// Licensed under the Apache 2.0 License.
#pragma once

#include "ccf/crypto/key_pair.h"
#include "ccf/crypto/pem.h"
#include "ccf/crypto/public_key.h"
#include "ccf/crypto/rsa_key_pair.h"
#include "ccf/crypto/verifier.h"

#include <chrono>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#pragma once

#include "ccf/crypto/curve.h"
#include "ccf/crypto/ec_public_key.h"
#include "ccf/crypto/jwk.h"
#include "ccf/crypto/pem.h"
#include "ccf/crypto/public_key.h"
#include "ccf/crypto/san.h"

#include <cstdint>
Expand All @@ -15,10 +15,10 @@

namespace ccf::crypto
{
class KeyPair
class ECKeyPair
{
public:
virtual ~KeyPair() = default;
virtual ~ECKeyPair() = default;

[[nodiscard]] virtual Pem private_key_pem() const = 0;
[[nodiscard]] virtual Pem public_key_pem() const = 0;
Expand Down Expand Up @@ -129,44 +129,19 @@ namespace ccf::crypto
}

virtual std::vector<uint8_t> derive_shared_secret(
const PublicKey& peer_key) = 0;
const ECPublicKey& peer_key) = 0;

[[nodiscard]] virtual std::vector<uint8_t> public_key_raw() const = 0;

[[nodiscard]] virtual CurveID get_curve_id() const = 0;

[[nodiscard]] virtual PublicKey::Coordinates coordinates() const = 0;
[[nodiscard]] virtual ECPublicKey::Coordinates coordinates() const = 0;

[[nodiscard]] virtual JsonWebKeyECPrivate private_key_jwk(
const std::optional<std::string>& kid = std::nullopt) const = 0;
};

using PublicKeyPtr = std::shared_ptr<PublicKey>;
using KeyPairPtr = std::shared_ptr<KeyPair>;

/**
* Construct PublicKey from a raw public key in PEM format
*
* @param pem Sequence of bytes containing the key in PEM format
* @return Public key
*/
PublicKeyPtr make_public_key(const Pem& pem);

/**
* Construct PublicKey from a raw public key in DER format
*
* @param der Sequence of bytes containing the key in DER format
* @return Public key
*/
PublicKeyPtr make_public_key(const std::vector<uint8_t>& der);

/**
* Construct PublicKey from a JsonWebKeyECPublic object
*
* @param jwk JsonWebKeyECPublic object
* @return Public key
*/
PublicKeyPtr make_public_key(const JsonWebKeyECPublic& jwk);
using ECKeyPairPtr = std::shared_ptr<ECKeyPair>;

/**
* Create a new public / private ECDSA key pair on specified curve and
Expand All @@ -175,15 +150,16 @@ namespace ccf::crypto
* @param curve_id Elliptic curve to use
* @return Key pair
*/
KeyPairPtr make_key_pair(CurveID curve_id = service_identity_curve_choice);
ECKeyPairPtr make_ec_key_pair(
CurveID curve_id = service_identity_curve_choice);

/**
* Create a public / private ECDSA key pair from existing private key data
*
* @param pem PEM key to load
* @return Key pair
*/
KeyPairPtr make_key_pair(const Pem& pem);
ECKeyPairPtr make_ec_key_pair(const Pem& pem);

/**
* Construct a new public / private ECDSA key pair from a JsonWebKeyECPrivate
Expand All @@ -192,5 +168,5 @@ namespace ccf::crypto
* @param jwk JsonWebKeyECPrivate object
* @return Key pair
*/
KeyPairPtr make_key_pair(const JsonWebKeyECPrivate& jwk);
ECKeyPairPtr make_ec_key_pair(const JsonWebKeyECPrivate& jwk);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@

namespace ccf::crypto
{
class PublicKey
class ECPublicKey
{
public:
virtual ~ECPublicKey() = default;

/**
* Verify that a signature was produced on contents with the private key
* associated with the public key held by the object.
Expand Down Expand Up @@ -151,7 +153,31 @@ namespace ccf::crypto

[[nodiscard]] virtual JsonWebKeyECPublic public_key_jwk(
const std::optional<std::string>& kid = std::nullopt) const = 0;

virtual ~PublicKey() = default;
};

using ECPublicKeyPtr = std::shared_ptr<ECPublicKey>;

/**
* Construct ECPublicKey from a raw public key in PEM format
*
* @param pem Sequence of bytes containing the key in PEM format
* @return Public key
*/
ECPublicKeyPtr make_ec_public_key(const Pem& pem);

/**
* Construct ECPublicKey from a raw public key in DER format
*
* @param der Sequence of bytes containing the key in DER format
* @return Public key
*/
ECPublicKeyPtr make_ec_public_key(const std::vector<uint8_t>& der);

/**
* Construct ECPublicKey from a JsonWebKeyECPublic object
*
* @param jwk JsonWebKeyECPublic object
* @return Public key
*/
ECPublicKeyPtr make_ec_public_key(const JsonWebKeyECPublic& jwk);
}
2 changes: 0 additions & 2 deletions include/ccf/crypto/eddsa_key_pair.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
#include "ccf/crypto/curve.h"
#include "ccf/crypto/eddsa_public_key.h"
#include "ccf/crypto/jwk.h"
#include "ccf/crypto/key_pair.h"
#include "ccf/crypto/pem.h"
#include "ccf/crypto/public_key.h"
#include "ccf/crypto/san.h"

#include <cstdint>
Expand Down
78 changes: 14 additions & 64 deletions include/ccf/crypto/rsa_key_pair.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#pragma once

#include "ccf/crypto/jwk.h"
#include "ccf/crypto/key_pair.h"
#include "ccf/crypto/pem.h"
#include "ccf/crypto/rsa_public_key.h"

Expand All @@ -14,18 +13,18 @@

namespace ccf::crypto
{
class RSAKeyPair
class RSAKeyPair : public RSAPublicKey
{
public:
static constexpr size_t default_public_key_size = 2048;
static constexpr size_t default_public_exponent = 65537;

RSAKeyPair() = default;
RSAKeyPair(const RSAKeyPair&) = delete;
RSAKeyPair(const Pem& pem);
virtual ~RSAKeyPair() = default;
[[nodiscard]] virtual Pem private_key_pem() const = 0;
[[nodiscard]] virtual std::vector<uint8_t> private_key_der() const = 0;
[[nodiscard]] virtual JsonWebKeyRSAPrivate private_key_jwk(
const std::optional<std::string>& kid = std::nullopt) const = 0;

[[nodiscard]] virtual size_t key_size() const = 0;
[[nodiscard]] virtual std::vector<uint8_t> sign(
std::span<const uint8_t> d,
MDType md_type = MDType::NONE,
size_t salt_length = 0) const = 0;

/**
* Unwrap data using RSA-OAEP-256 (CKM_RSA_PKCS_OAEP)
Expand All @@ -35,71 +34,22 @@ namespace ccf::crypto
*
* @return Unwrapped data
*/
virtual std::vector<uint8_t> rsa_oaep_unwrap(
[[nodiscard]] virtual std::vector<uint8_t> rsa_oaep_unwrap(
const std::vector<uint8_t>& input,
const std::optional<std::vector<std::uint8_t>>& label = std::nullopt) = 0;

/**
* Get the private key in PEM format
*/
[[nodiscard]] virtual Pem private_key_pem() const = 0;

/**
* Get the public key in PEM format
*/
[[nodiscard]] virtual Pem public_key_pem() const = 0;

/**
* Get the public key in DER format
*/
[[nodiscard]] virtual std::vector<uint8_t> public_key_der() const = 0;

[[nodiscard]] virtual std::vector<uint8_t> sign(
std::span<const uint8_t> d,
MDType md_type = MDType::NONE,
size_t salt_length = 0) const = 0;

virtual bool verify(
const uint8_t* contents,
size_t contents_size,
const uint8_t* signature,
size_t signature_size,
MDType md_type = MDType::NONE,
size_t salt_length = 0) = 0;

virtual bool verify(
const std::vector<uint8_t>& contents,
const std::vector<uint8_t>& signature,
MDType md_type = MDType::NONE,
size_t salt_length = 0)
{
return verify(
contents.data(),
contents.size(),
signature.data(),
signature.size(),
md_type,
salt_length);
}

[[nodiscard]] virtual JsonWebKeyRSAPrivate private_key_jwk_rsa(
const std::optional<std::string>& kid = std::nullopt) const = 0;
};

using RSAPublicKeyPtr = std::shared_ptr<RSAPublicKey>;
using RSAKeyPairPtr = std::shared_ptr<RSAKeyPair>;

RSAPublicKeyPtr make_rsa_public_key(const Pem& pem);
RSAPublicKeyPtr make_rsa_public_key(const std::vector<uint8_t>& der);
RSAPublicKeyPtr make_rsa_public_key(const JsonWebKeyRSAPublic& jwk);
RSAPublicKeyPtr make_rsa_public_key(const uint8_t* data, size_t size);
static constexpr size_t default_rsa_public_key_size = 2048;
static constexpr size_t default_rsa_public_exponent = 65537;

/**
* Create a new public / private RSA key pair with specified size and exponent
*/
RSAKeyPairPtr make_rsa_key_pair(
size_t public_key_size = RSAKeyPair::default_public_key_size,
size_t public_exponent = RSAKeyPair::default_public_exponent);
size_t public_key_size = default_rsa_public_key_size,
size_t public_exponent = default_rsa_public_exponent);

/**
* Create a public / private RSA key pair from existing private key data
Expand Down
Loading