Skip to content

Commit a94b745

Browse files
maxtropetsCopilotachamayou
authored
Revisit CCF crypto interfaces (mostly RSA/EC keys) (#7425)
Co-authored-by: Copilot <[email protected]> Co-authored-by: Amaury Chamayou <[email protected]> Co-authored-by: Amaury Chamayou <[email protected]>
1 parent a906943 commit a94b745

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+867
-864
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1616
### Changed
1717

1818
- 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).
19+
- Crypto interface for RSA and EC keys (#7425)
20+
- `ccf::crypto::PublicKey` becomes `ccf::crypto::ECPublicKey`
21+
- `ccf::crypto::KeyPair` becomes `ccf::crypto::ECKeyPair`
22+
- Error-prone inheritance between RSA and EC key classes has been removed.
23+
- RSA keys now don't re-use CSR functionality from EC key interface.
1924

2025
### Removed
2126

cmake/crypto.cmake

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,16 @@ set(CCFCRYPTO_SRC
77
${CCF_DIR}/src/crypto/hash.cpp
88
${CCF_DIR}/src/crypto/sha256_hash.cpp
99
${CCF_DIR}/src/crypto/symmetric_key.cpp
10-
${CCF_DIR}/src/crypto/key_pair.cpp
1110
${CCF_DIR}/src/crypto/eddsa_key_pair.cpp
12-
${CCF_DIR}/src/crypto/rsa_key_pair.cpp
1311
${CCF_DIR}/src/crypto/verifier.cpp
1412
${CCF_DIR}/src/crypto/key_wrap.cpp
1513
${CCF_DIR}/src/crypto/hmac.cpp
1614
${CCF_DIR}/src/crypto/pem.cpp
1715
${CCF_DIR}/src/crypto/ecdsa.cpp
1816
${CCF_DIR}/src/crypto/cose.cpp
1917
${CCF_DIR}/src/crypto/openssl/symmetric_key.cpp
20-
${CCF_DIR}/src/crypto/openssl/public_key.cpp
21-
${CCF_DIR}/src/crypto/openssl/key_pair.cpp
18+
${CCF_DIR}/src/crypto/openssl/ec_public_key.cpp
19+
${CCF_DIR}/src/crypto/openssl/ec_key_pair.cpp
2220
${CCF_DIR}/src/crypto/openssl/eddsa_public_key.cpp
2321
${CCF_DIR}/src/crypto/openssl/eddsa_key_pair.cpp
2422
${CCF_DIR}/src/crypto/openssl/hash.cpp

doc/build_apps/crypto.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ Hashing
2525
Asymmetric Keys
2626
-----------------------
2727

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

33-
.. doxygenclass:: ccf::crypto::PublicKey
33+
.. doxygenclass:: ccf::crypto::ECPublicKey
3434
:project: CCF
3535
:members:
3636

37-
.. doxygenclass:: ccf::crypto::KeyPair
37+
.. doxygenclass:: ccf::crypto::ECKeyPair
3838
:project: CCF
3939
:members:
4040

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

52-
.. doxygenfunction:: ccf::crypto::make_key_pair(CurveID)
52+
.. doxygenfunction:: ccf::crypto::make_ec_key_pair(CurveID)
5353
:project: CCF
5454

55-
.. doxygenfunction:: ccf::crypto::make_key_pair(const Pem&)
55+
.. doxygenfunction:: ccf::crypto::make_ec_key_pair(const Pem&)
5656
:project: CCF
5757

5858
.. doxygenfunction:: ccf::crypto::make_rsa_key_pair(size_t, size_t)

include/ccf/crypto/cose_verifier.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
// Licensed under the Apache 2.0 License.
33
#pragma once
44

5-
#include "ccf/crypto/key_pair.h"
6-
#include "ccf/crypto/pem.h"
7-
#include "ccf/crypto/public_key.h"
8-
#include "ccf/crypto/rsa_key_pair.h"
5+
#include "ccf/crypto/verifier.h"
96

107
#include <chrono>
118

include/ccf/crypto/key_pair.h renamed to include/ccf/crypto/ec_key_pair.h

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
#pragma once
44

55
#include "ccf/crypto/curve.h"
6+
#include "ccf/crypto/ec_public_key.h"
67
#include "ccf/crypto/jwk.h"
78
#include "ccf/crypto/pem.h"
8-
#include "ccf/crypto/public_key.h"
99
#include "ccf/crypto/san.h"
1010

1111
#include <cstdint>
@@ -15,10 +15,10 @@
1515

1616
namespace ccf::crypto
1717
{
18-
class KeyPair
18+
class ECKeyPair
1919
{
2020
public:
21-
virtual ~KeyPair() = default;
21+
virtual ~ECKeyPair() = default;
2222

2323
[[nodiscard]] virtual Pem private_key_pem() const = 0;
2424
[[nodiscard]] virtual Pem public_key_pem() const = 0;
@@ -129,44 +129,19 @@ namespace ccf::crypto
129129
}
130130

131131
virtual std::vector<uint8_t> derive_shared_secret(
132-
const PublicKey& peer_key) = 0;
132+
const ECPublicKey& peer_key) = 0;
133133

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

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

138-
[[nodiscard]] virtual PublicKey::Coordinates coordinates() const = 0;
138+
[[nodiscard]] virtual ECPublicKey::Coordinates coordinates() const = 0;
139139

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

144-
using PublicKeyPtr = std::shared_ptr<PublicKey>;
145-
using KeyPairPtr = std::shared_ptr<KeyPair>;
146-
147-
/**
148-
* Construct PublicKey from a raw public key in PEM format
149-
*
150-
* @param pem Sequence of bytes containing the key in PEM format
151-
* @return Public key
152-
*/
153-
PublicKeyPtr make_public_key(const Pem& pem);
154-
155-
/**
156-
* Construct PublicKey from a raw public key in DER format
157-
*
158-
* @param der Sequence of bytes containing the key in DER format
159-
* @return Public key
160-
*/
161-
PublicKeyPtr make_public_key(const std::vector<uint8_t>& der);
162-
163-
/**
164-
* Construct PublicKey from a JsonWebKeyECPublic object
165-
*
166-
* @param jwk JsonWebKeyECPublic object
167-
* @return Public key
168-
*/
169-
PublicKeyPtr make_public_key(const JsonWebKeyECPublic& jwk);
144+
using ECKeyPairPtr = std::shared_ptr<ECKeyPair>;
170145

171146
/**
172147
* Create a new public / private ECDSA key pair on specified curve and
@@ -175,15 +150,16 @@ namespace ccf::crypto
175150
* @param curve_id Elliptic curve to use
176151
* @return Key pair
177152
*/
178-
KeyPairPtr make_key_pair(CurveID curve_id = service_identity_curve_choice);
153+
ECKeyPairPtr make_ec_key_pair(
154+
CurveID curve_id = service_identity_curve_choice);
179155

180156
/**
181157
* Create a public / private ECDSA key pair from existing private key data
182158
*
183159
* @param pem PEM key to load
184160
* @return Key pair
185161
*/
186-
KeyPairPtr make_key_pair(const Pem& pem);
162+
ECKeyPairPtr make_ec_key_pair(const Pem& pem);
187163

188164
/**
189165
* Construct a new public / private ECDSA key pair from a JsonWebKeyECPrivate
@@ -192,5 +168,5 @@ namespace ccf::crypto
192168
* @param jwk JsonWebKeyECPrivate object
193169
* @return Key pair
194170
*/
195-
KeyPairPtr make_key_pair(const JsonWebKeyECPrivate& jwk);
171+
ECKeyPairPtr make_ec_key_pair(const JsonWebKeyECPrivate& jwk);
196172
}

include/ccf/crypto/public_key.h renamed to include/ccf/crypto/ec_public_key.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515

1616
namespace ccf::crypto
1717
{
18-
class PublicKey
18+
class ECPublicKey
1919
{
2020
public:
21+
virtual ~ECPublicKey() = default;
22+
2123
/**
2224
* Verify that a signature was produced on contents with the private key
2325
* associated with the public key held by the object.
@@ -151,7 +153,31 @@ namespace ccf::crypto
151153

152154
[[nodiscard]] virtual JsonWebKeyECPublic public_key_jwk(
153155
const std::optional<std::string>& kid = std::nullopt) const = 0;
154-
155-
virtual ~PublicKey() = default;
156156
};
157+
158+
using ECPublicKeyPtr = std::shared_ptr<ECPublicKey>;
159+
160+
/**
161+
* Construct ECPublicKey from a raw public key in PEM format
162+
*
163+
* @param pem Sequence of bytes containing the key in PEM format
164+
* @return Public key
165+
*/
166+
ECPublicKeyPtr make_ec_public_key(const Pem& pem);
167+
168+
/**
169+
* Construct ECPublicKey from a raw public key in DER format
170+
*
171+
* @param der Sequence of bytes containing the key in DER format
172+
* @return Public key
173+
*/
174+
ECPublicKeyPtr make_ec_public_key(const std::vector<uint8_t>& der);
175+
176+
/**
177+
* Construct ECPublicKey from a JsonWebKeyECPublic object
178+
*
179+
* @param jwk JsonWebKeyECPublic object
180+
* @return Public key
181+
*/
182+
ECPublicKeyPtr make_ec_public_key(const JsonWebKeyECPublic& jwk);
157183
}

include/ccf/crypto/eddsa_key_pair.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
#include "ccf/crypto/curve.h"
66
#include "ccf/crypto/eddsa_public_key.h"
77
#include "ccf/crypto/jwk.h"
8-
#include "ccf/crypto/key_pair.h"
98
#include "ccf/crypto/pem.h"
10-
#include "ccf/crypto/public_key.h"
119
#include "ccf/crypto/san.h"
1210

1311
#include <cstdint>

include/ccf/crypto/rsa_key_pair.h

Lines changed: 14 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#pragma once
44

55
#include "ccf/crypto/jwk.h"
6-
#include "ccf/crypto/key_pair.h"
76
#include "ccf/crypto/pem.h"
87
#include "ccf/crypto/rsa_public_key.h"
98

@@ -14,18 +13,18 @@
1413

1514
namespace ccf::crypto
1615
{
17-
class RSAKeyPair
16+
class RSAKeyPair : public RSAPublicKey
1817
{
1918
public:
20-
static constexpr size_t default_public_key_size = 2048;
21-
static constexpr size_t default_public_exponent = 65537;
22-
23-
RSAKeyPair() = default;
24-
RSAKeyPair(const RSAKeyPair&) = delete;
25-
RSAKeyPair(const Pem& pem);
26-
virtual ~RSAKeyPair() = default;
19+
[[nodiscard]] virtual Pem private_key_pem() const = 0;
20+
[[nodiscard]] virtual std::vector<uint8_t> private_key_der() const = 0;
21+
[[nodiscard]] virtual JsonWebKeyRSAPrivate private_key_jwk(
22+
const std::optional<std::string>& kid = std::nullopt) const = 0;
2723

28-
[[nodiscard]] virtual size_t key_size() const = 0;
24+
[[nodiscard]] virtual std::vector<uint8_t> sign(
25+
std::span<const uint8_t> d,
26+
MDType md_type = MDType::NONE,
27+
size_t salt_length = 0) const = 0;
2928

3029
/**
3130
* Unwrap data using RSA-OAEP-256 (CKM_RSA_PKCS_OAEP)
@@ -35,71 +34,22 @@ namespace ccf::crypto
3534
*
3635
* @return Unwrapped data
3736
*/
38-
virtual std::vector<uint8_t> rsa_oaep_unwrap(
37+
[[nodiscard]] virtual std::vector<uint8_t> rsa_oaep_unwrap(
3938
const std::vector<uint8_t>& input,
4039
const std::optional<std::vector<std::uint8_t>>& label = std::nullopt) = 0;
41-
42-
/**
43-
* Get the private key in PEM format
44-
*/
45-
[[nodiscard]] virtual Pem private_key_pem() const = 0;
46-
47-
/**
48-
* Get the public key in PEM format
49-
*/
50-
[[nodiscard]] virtual Pem public_key_pem() const = 0;
51-
52-
/**
53-
* Get the public key in DER format
54-
*/
55-
[[nodiscard]] virtual std::vector<uint8_t> public_key_der() const = 0;
56-
57-
[[nodiscard]] virtual std::vector<uint8_t> sign(
58-
std::span<const uint8_t> d,
59-
MDType md_type = MDType::NONE,
60-
size_t salt_length = 0) const = 0;
61-
62-
virtual bool verify(
63-
const uint8_t* contents,
64-
size_t contents_size,
65-
const uint8_t* signature,
66-
size_t signature_size,
67-
MDType md_type = MDType::NONE,
68-
size_t salt_length = 0) = 0;
69-
70-
virtual bool verify(
71-
const std::vector<uint8_t>& contents,
72-
const std::vector<uint8_t>& signature,
73-
MDType md_type = MDType::NONE,
74-
size_t salt_length = 0)
75-
{
76-
return verify(
77-
contents.data(),
78-
contents.size(),
79-
signature.data(),
80-
signature.size(),
81-
md_type,
82-
salt_length);
83-
}
84-
85-
[[nodiscard]] virtual JsonWebKeyRSAPrivate private_key_jwk_rsa(
86-
const std::optional<std::string>& kid = std::nullopt) const = 0;
8740
};
8841

89-
using RSAPublicKeyPtr = std::shared_ptr<RSAPublicKey>;
9042
using RSAKeyPairPtr = std::shared_ptr<RSAKeyPair>;
9143

92-
RSAPublicKeyPtr make_rsa_public_key(const Pem& pem);
93-
RSAPublicKeyPtr make_rsa_public_key(const std::vector<uint8_t>& der);
94-
RSAPublicKeyPtr make_rsa_public_key(const JsonWebKeyRSAPublic& jwk);
95-
RSAPublicKeyPtr make_rsa_public_key(const uint8_t* data, size_t size);
44+
static constexpr size_t default_rsa_public_key_size = 2048;
45+
static constexpr size_t default_rsa_public_exponent = 65537;
9646

9747
/**
9848
* Create a new public / private RSA key pair with specified size and exponent
9949
*/
10050
RSAKeyPairPtr make_rsa_key_pair(
101-
size_t public_key_size = RSAKeyPair::default_public_key_size,
102-
size_t public_exponent = RSAKeyPair::default_public_exponent);
51+
size_t public_key_size = default_rsa_public_key_size,
52+
size_t public_exponent = default_rsa_public_exponent);
10353

10454
/**
10555
* Create a public / private RSA key pair from existing private key data

0 commit comments

Comments
 (0)