Skip to content

Commit 55e5977

Browse files
Copilotmaxtropets
andauthored
Harden OpenSSL crypto error checking and resource management (#7817)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: maxtropets <16566519+maxtropets@users.noreply.github.com> Co-authored-by: Max <maxtropets@microsoft.com> Co-authored-by: Max Tropets <maxtropets@gmail.com>
1 parent 7f4c9b3 commit 55e5977

9 files changed

Lines changed: 45 additions & 43 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1515

1616
### Removed
1717

18+
- Removed `CHECK0()` from `ccf::crypto::OpenSSL` in the public header `openssl_wrappers.h` (#7817).
1819
- Removed `aes_gcm_encrypt()`, `aes_gcm_decrypt()`, and `default_iv` from `ccf::crypto` (#7811).
1920
- Removed `get_responder()` from the public `ccf::RpcContext` API and made `http_responder.h` a private header (#7818).
2021
- Removed the `/node/memory` endpoint. This endpoint was originally useful for monitoring SGX enclave memory usage, which is no longer relevant now that SGX support has been removed.

include/ccf/crypto/openssl/openssl_wrappers.h

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,25 +50,14 @@ namespace ccf::crypto::OpenSSL
5050
return "unknown error";
5151
}
5252

53-
/// Throws if rc is not 1 and has error
53+
/// Throws if rc is not 1
5454
inline void CHECK1(int rc)
5555
{
56-
unsigned long ec = ERR_get_error();
57-
if (rc != 1 && ec != 0)
56+
if (rc != 1)
5857
{
59-
throw std::runtime_error(
60-
fmt::format("OpenSSL error: {}", error_string(ec)));
61-
}
62-
}
63-
64-
/// Throws if rc is 0 and has error
65-
inline void CHECK0(int rc)
66-
{
67-
unsigned long ec = ERR_get_error();
68-
if (rc == 0 && ec != 0)
69-
{
70-
throw std::runtime_error(
71-
fmt::format("OpenSSL error: {}", error_string(ec)));
58+
unsigned long ec = ERR_get_error();
59+
throw std::runtime_error(fmt::format(
60+
"OpenSSL error (rc={}, ec={}): {}", rc, ec, error_string(ec)));
7261
}
7362
}
7463

@@ -87,8 +76,8 @@ namespace ccf::crypto::OpenSSL
8776
if (expect != actual)
8877
{
8978
unsigned long ec = ERR_get_error();
90-
throw std::runtime_error(
91-
fmt::format("OpenSSL error: {}", error_string(ec)));
79+
throw std::runtime_error(fmt::format(
80+
"OpenSSL error (rc={}, ec={}): {}", actual, ec, error_string(ec)));
9281
}
9382
}
9483

@@ -97,7 +86,9 @@ namespace ccf::crypto::OpenSSL
9786
{
9887
if (val <= 0)
9988
{
100-
throw std::runtime_error("OpenSSL error: expected positive value");
89+
unsigned long ec = ERR_get_error();
90+
throw std::runtime_error(fmt::format(
91+
"OpenSSL error (rc={}, ec={}): {}", val, ec, error_string(ec)));
10192
}
10293
}
10394

src/crypto/ecdsa.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ namespace ccf::crypto
3737
(void)r_bn.release();
3838
(void)s_bn.release();
3939
auto der_size = i2d_ECDSA_SIG(sig, nullptr);
40-
OpenSSL::CHECK0(der_size);
40+
OpenSSL::CHECKPOSITIVE(der_size);
4141
std::vector<uint8_t> der_sig(der_size);
4242
auto* der_sig_buf = der_sig.data();
43-
OpenSSL::CHECK0(i2d_ECDSA_SIG(sig, &der_sig_buf));
43+
OpenSSL::CHECKPOSITIVE(i2d_ECDSA_SIG(sig, &der_sig_buf));
4444
return der_sig;
4545
}
4646

src/crypto/openssl/ec_key_pair.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ namespace ccf::crypto
260260

261261
if (key != nullptr)
262262
{
263-
OpenSSL::CHECK1(X509_REQ_sign(req, key, EVP_sha512()));
263+
OpenSSL::CHECKPOSITIVE(X509_REQ_sign(req, key, EVP_sha512()));
264264
}
265265

266266
return req;

src/crypto/openssl/hash.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,32 +104,30 @@ namespace ccf::crypto
104104
const std::span<const uint8_t>& info)
105105
{
106106
const auto* md = get_md_type(md_type);
107-
EVP_PKEY_CTX* pctx = nullptr;
108107
std::vector<uint8_t> r(length);
109-
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
108+
Unique_EVP_PKEY_CTX pctx(EVP_PKEY_HKDF);
110109
CHECK1(EVP_PKEY_derive_init(pctx));
111-
CHECK1(EVP_PKEY_CTX_set_hkdf_md(pctx, md));
110+
CHECKPOSITIVE(EVP_PKEY_CTX_set_hkdf_md(pctx, md));
112111
if (salt.size() > std::numeric_limits<int>::max())
113112
{
114113
throw std::logic_error("Salt size is too large");
115114
}
116115
int salt_size = static_cast<int>(salt.size());
117-
CHECK1(EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt.data(), salt_size));
116+
CHECKPOSITIVE(EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt.data(), salt_size));
118117
if (ikm.size() > std::numeric_limits<int>::max())
119118
{
120119
throw std::logic_error("IKM size is too large");
121120
}
122121
int ikm_size = static_cast<int>(ikm.size());
123-
CHECK1(EVP_PKEY_CTX_set1_hkdf_key(pctx, ikm.data(), ikm_size));
122+
CHECKPOSITIVE(EVP_PKEY_CTX_set1_hkdf_key(pctx, ikm.data(), ikm_size));
124123
if (info.size() > std::numeric_limits<int>::max())
125124
{
126125
throw std::logic_error("Info size is too large");
127126
}
128127
int info_size = static_cast<int>(info.size());
129-
CHECK1(EVP_PKEY_CTX_add1_hkdf_info(pctx, info.data(), info_size));
128+
CHECKPOSITIVE(EVP_PKEY_CTX_add1_hkdf_info(pctx, info.data(), info_size));
130129
size_t outlen = length;
131130
CHECK1(EVP_PKEY_derive(pctx, r.data(), &outlen));
132-
EVP_PKEY_CTX_free(pctx);
133131
r.resize(outlen);
134132
return r;
135133
}

src/crypto/openssl/rsa_key_pair.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "ccf/crypto/openssl/openssl_wrappers.h"
77
#include "crypto/openssl/hash.h"
88

9+
#include <climits>
910
#include <openssl/core_names.h>
1011

1112
namespace ccf::crypto
@@ -134,9 +135,9 @@ namespace ccf::crypto
134135

135136
Unique_EVP_PKEY_CTX ctx(key);
136137
CHECK1(EVP_PKEY_decrypt_init(ctx));
137-
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING);
138-
EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256());
139-
EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256());
138+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING));
139+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()));
140+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()));
140141

141142
if (label_ != nullptr)
142143
{
@@ -222,9 +223,14 @@ namespace ccf::crypto
222223
auto hash = OpenSSLHashProvider().hash(d.data(), d.size(), md_type);
223224
Unique_EVP_PKEY_CTX pctx(key);
224225
CHECK1(EVP_PKEY_sign_init(pctx));
225-
CHECK1(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING));
226-
CHECK1(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, salt_length));
227-
CHECK1(EVP_PKEY_CTX_set_signature_md(pctx, get_md_type(md_type)));
226+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING));
227+
if (salt_length > INT_MAX)
228+
{
229+
throw std::invalid_argument(fmt::format(
230+
"salt_length {} exceeds maximum ({})", salt_length, INT_MAX));
231+
}
232+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, salt_length));
233+
CHECKPOSITIVE(EVP_PKEY_CTX_set_signature_md(pctx, get_md_type(md_type)));
228234
size_t olen = r.size();
229235
CHECK1(EVP_PKEY_sign(pctx, r.data(), &olen, hash.data(), hash.size()));
230236
r.resize(olen);

src/crypto/openssl/rsa_public_key.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "crypto/openssl/hash.h"
66
#include "crypto/openssl/rsa_key_pair.h"
77

8+
#include <climits>
89
#include <openssl/core_names.h>
910
#include <openssl/encoder.h>
1011

@@ -123,9 +124,9 @@ namespace ccf::crypto
123124
{
124125
Unique_EVP_PKEY_CTX ctx(key);
125126
OpenSSL::CHECK1(EVP_PKEY_encrypt_init(ctx));
126-
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING);
127-
EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256());
128-
EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256());
127+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING));
128+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()));
129+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()));
129130

130131
if (label != nullptr && label_size > 0)
131132
{
@@ -228,12 +229,17 @@ namespace ccf::crypto
228229

229230
Unique_EVP_PKEY_CTX pctx(key);
230231
CHECK1(EVP_PKEY_verify_init(pctx));
231-
CHECK1(EVP_PKEY_CTX_set_rsa_padding(pctx, ossl_padding->second));
232+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_padding(pctx, ossl_padding->second));
232233
if (ossl_padding->first == RSAPadding::PKCS_PSS)
233234
{
234-
CHECK1(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, salt_length));
235+
if (salt_length > INT_MAX)
236+
{
237+
throw std::invalid_argument(fmt::format(
238+
"salt_length {} exceeds maximum ({})", salt_length, INT_MAX));
239+
}
240+
CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, salt_length));
235241
}
236-
CHECK1(EVP_PKEY_CTX_set_signature_md(pctx, get_md_type(md_type)));
242+
CHECKPOSITIVE(EVP_PKEY_CTX_set_signature_md(pctx, get_md_type(md_type)));
237243
return EVP_PKEY_verify(pctx, signature, signature_size, hash, hash_size) ==
238244
1;
239245
}

src/crypto/openssl/verifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ namespace ccf::crypto
138138
return false;
139139
}
140140

141-
CHECK1(sk_X509_push(chain_stack, cert));
141+
CHECKPOSITIVE(sk_X509_push(chain_stack, cert));
142142
CHECK1(X509_up_ref(cert));
143143
}
144144

src/tls/cert.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ namespace tls
6464
Unique_BIO certbio(*it);
6565
Unique_X509 cert(certbio, true);
6666

67-
CHECK1(sk_X509_push(chain, cert));
67+
CHECKPOSITIVE(sk_X509_push(chain, cert));
6868
CHECK1(X509_up_ref(cert));
6969
}
7070
}

0 commit comments

Comments
 (0)