Skip to content

Commit 0f5ce35

Browse files
jasnellclaude
authored andcommitted
src: cleanup crypto more
* Use ncrypto APIs where appropriate * Remove obsolete no-longer used functions * Improve error handling a bit * move secure heap handling to ncrypto To simplify handling of boringssl/openssl, move secure heap impl to ncrypto. Overall the reduces the complexity of the code in crypto_util by eliminating additional ifdef branches. * simplify CryptoErrorStore::ToException a bit * simplify error handling in crypto_common * move curve utility methods to ncrypto * verify that released DataPointers aren't on secure heap The ByteSource does not currently know how to free a DataPointer allocated on the secure heap, so just verify. DataPointers on the secure heap are not something that users can allocate on their own. Their use is rare. Eventually ByteSource is going to be refactored around ncrypto APIs so these additional checks should be temporary. * simplify some ifdefs that are covered by ncrypto * cleanup some obsolete includes in crypto_util Merge conflicts were resolved by Claude Code. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 91700f0 commit 0f5ce35

2 files changed

Lines changed: 139 additions & 16 deletions

File tree

include/ncrypto.h

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ using OPENSSL_SIZE_T = int;
5252
#ifdef NCRYPTO_BSSL_NEEDS_DH_PRIMES
5353
#include "dh-primes.h"
5454
#endif // NCRYPTO_BSSL_NEEDS_DH_PRIMES
55+
// FIXME: This should be removed when patch 0037 is applied
56+
#define OPENSSL_TLS_SECURITY_LEVEL 1
5557
#endif // OPENSSL_IS_BORINGSSL
5658

5759
namespace ncrypto {
@@ -549,6 +551,11 @@ class Ec final {
549551
inline operator bool() const { return ec_ != nullptr; }
550552
inline operator OSSL3_CONST EC_KEY*() const { return ec_; }
551553

554+
static int GetCurveIdFromName(std::string_view name);
555+
556+
using GetCurveCallback = std::function<bool(std::string_view)>;
557+
static bool GetCurves(GetCurveCallback callback);
558+
552559
inline const BignumPointer& getX() const { return x_; }
553560
inline const BignumPointer& getY() const { return y_; }
554561
inline const BignumPointer& getD() const { return d_; }
@@ -568,9 +575,31 @@ class DataPointer final {
568575
static DataPointer Alloc(size_t len);
569576
static DataPointer Copy(const Buffer<const void>& buffer);
570577

578+
// Attempts to allocate the buffer space using the secure heap, if
579+
// supported/enabled. If the secure heap is disabled, then this
580+
// ends up being equivalent to Alloc(len). Note that allocation
581+
// will fail if there is not enough free space remaining in the
582+
// secure heap space.
583+
static DataPointer SecureAlloc(size_t len);
584+
585+
// If the secure heap is enabled, returns the amount of data that
586+
// has been allocated from the heap.
587+
static size_t GetSecureHeapUsed();
588+
589+
enum class InitSecureHeapResult {
590+
FAILED,
591+
UNABLE_TO_MEMORY_MAP,
592+
OK,
593+
};
594+
595+
// Attempt to initialize the secure heap. The secure heap is not
596+
// supported on all operating systems and whenever boringssl is
597+
// used.
598+
static InitSecureHeapResult TryInitSecureHeap(size_t amount, size_t min);
599+
571600
DataPointer() = default;
572-
explicit DataPointer(void* data, size_t len);
573-
explicit DataPointer(const Buffer<void>& buffer);
601+
explicit DataPointer(void* data, size_t len, bool secure = false);
602+
explicit DataPointer(const Buffer<void>& buffer, bool secure = false);
574603
DataPointer(DataPointer&& other) noexcept;
575604
DataPointer& operator=(DataPointer&& other) noexcept;
576605
NCRYPTO_DISALLOW_COPY(DataPointer)
@@ -606,9 +635,12 @@ class DataPointer final {
606635
};
607636
}
608637

638+
bool isSecure() const { return secure_; }
639+
609640
private:
610641
void* data_ = nullptr;
611642
size_t len_ = 0;
643+
bool secure_ = false;
612644
};
613645

614646
class BIOPointer final {
@@ -1067,6 +1099,8 @@ class SSLPointer final {
10671099

10681100
std::optional<uint32_t> verifyPeerCertificate() const;
10691101

1102+
static std::optional<int> getSecurityLevel();
1103+
10701104
void getCiphers(std::function<void(const std::string_view)> cb) const;
10711105

10721106
static SSLPointer New(const SSLCtxPointer& ctx);

src/ncrypto.cpp

Lines changed: 103 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -118,20 +118,64 @@ DataPointer DataPointer::Alloc(size_t len) {
118118
#endif
119119
}
120120

121+
DataPointer DataPointer::SecureAlloc(size_t len) {
122+
#ifndef OPENSSL_IS_BORINGSSL
123+
auto ptr = OPENSSL_secure_zalloc(len);
124+
if (ptr == nullptr) return {};
125+
return DataPointer(ptr, len, true);
126+
#else
127+
// BoringSSL does not implement the OPENSSL_secure_zalloc API.
128+
auto ptr = OPENSSL_malloc(len);
129+
if (ptr == nullptr) return {};
130+
memset(ptr, 0, len);
131+
return DataPointer(ptr, len);
132+
#endif
133+
}
134+
135+
size_t DataPointer::GetSecureHeapUsed() {
136+
#ifndef OPENSSL_IS_BORINGSSL
137+
return CRYPTO_secure_malloc_initialized() ? CRYPTO_secure_used() : 0;
138+
#else
139+
// BoringSSL does not have the secure heap and therefore
140+
// will always return 0.
141+
return 0;
142+
#endif
143+
}
144+
145+
DataPointer::InitSecureHeapResult DataPointer::TryInitSecureHeap(size_t amount,
146+
size_t min) {
147+
#ifndef OPENSSL_IS_BORINGSSL
148+
switch (CRYPTO_secure_malloc_init(amount, min)) {
149+
case 0:
150+
return InitSecureHeapResult::FAILED;
151+
case 2:
152+
return InitSecureHeapResult::UNABLE_TO_MEMORY_MAP;
153+
case 1:
154+
return InitSecureHeapResult::OK;
155+
default:
156+
return InitSecureHeapResult::FAILED;
157+
}
158+
#else
159+
// BoringSSL does not actually support the secure heap
160+
return InitSecureHeapResult::FAILED;
161+
#endif
162+
}
163+
121164
DataPointer DataPointer::Copy(const Buffer<const void>& buffer) {
122165
return DataPointer(OPENSSL_memdup(buffer.data, buffer.len), buffer.len);
123166
}
124167

125-
DataPointer::DataPointer(void* data, size_t length)
126-
: data_(data), len_(length) {}
168+
DataPointer::DataPointer(void* data, size_t length, bool secure)
169+
: data_(data), len_(length), secure_(secure) {}
127170

128-
DataPointer::DataPointer(const Buffer<void>& buffer)
129-
: data_(buffer.data), len_(buffer.len) {}
171+
DataPointer::DataPointer(const Buffer<void>& buffer, bool secure)
172+
: data_(buffer.data), len_(buffer.len), secure_(secure) {}
130173

131174
DataPointer::DataPointer(DataPointer&& other) noexcept
132-
: data_(other.data_), len_(other.len_) {
175+
: data_(other.data_), len_(other.len_), secure_(other.secure_) {
133176
other.data_ = nullptr;
134177
other.len_ = 0;
178+
other.secure_ = false;
135179
}
136180

137181
DataPointer& DataPointer::operator=(DataPointer&& other) noexcept {
@@ -151,7 +195,11 @@ void DataPointer::zero() {
151195

152196
void DataPointer::reset(void* data, size_t length) {
153197
if (data_ != nullptr) {
154-
OPENSSL_clear_free(data_, len_);
198+
if (secure_) {
199+
OPENSSL_secure_clear_free(data_, len_);
200+
} else {
201+
OPENSSL_clear_free(data_, len_);
202+
}
155203
}
156204
data_ = data;
157205
len_ = length;
@@ -182,6 +230,7 @@ DataPointer DataPointer::resize(size_t len) {
182230

183231
// ============================================================================
184232
bool isFipsEnabled() {
233+
ClearErrorOnReturn clear_error_on_return;
185234
#if OPENSSL_VERSION_MAJOR >= 3
186235
return EVP_default_properties_is_fips_enabled(nullptr) == 1;
187236
#else
@@ -193,30 +242,31 @@ bool setFipsEnabled(bool enable, CryptoErrorList* errors) {
193242
if (isFipsEnabled() == enable) return true;
194243
ClearErrorOnReturn clearErrorOnReturn(errors);
195244
#if OPENSSL_VERSION_MAJOR >= 3
196-
return EVP_default_properties_enable_fips(nullptr, enable ? 1 : 0) == 1;
245+
return EVP_default_properties_enable_fips(nullptr, enable ? 1 : 0) == 1 &&
246+
EVP_default_properties_is_fips_enabled(nullptr);
197247
#else
198248
return FIPS_mode_set(enable ? 1 : 0) == 1;
199249
#endif
200250
}
201251

202252
bool testFipsEnabled() {
253+
ClearErrorOnReturn clear_error_on_return;
203254
#if OPENSSL_VERSION_MAJOR >= 3
204255
OSSL_PROVIDER* fips_provider = nullptr;
205256
if (OSSL_PROVIDER_available(nullptr, "fips")) {
206257
fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
207258
}
208-
const auto enabled = fips_provider == nullptr ? 0
209-
: OSSL_PROVIDER_self_test(fips_provider) ? 1
210-
: 0;
259+
if (fips_provider == nullptr) return false;
260+
int result = OSSL_PROVIDER_self_test(fips_provider);
261+
OSSL_PROVIDER_unload(fips_provider);
262+
return result;
211263
#else
212264
#ifdef OPENSSL_FIPS
213-
const auto enabled = FIPS_selftest() ? 1 : 0;
265+
return FIPS_selftest();
214266
#else // OPENSSL_FIPS
215-
const auto enabled = 0;
267+
return false;
216268
#endif // OPENSSL_FIPS
217269
#endif
218-
219-
return enabled;
220270
}
221271

222272
// ============================================================================
@@ -2840,6 +2890,21 @@ std::optional<std::string_view> SSLPointer::getCipherVersion() const {
28402890
return SSL_CIPHER_get_version(cipher);
28412891
}
28422892

2893+
std::optional<int> SSLPointer::getSecurityLevel() {
2894+
#ifndef OPENSSL_IS_BORINGSSL
2895+
auto ctx = SSLCtxPointer::New();
2896+
if (!ctx) return std::nullopt;
2897+
2898+
auto ssl = SSLPointer::New(ctx);
2899+
if (!ssl) return std::nullopt;
2900+
2901+
return SSL_get_security_level(ssl);
2902+
#else
2903+
// for BoringSSL assume the same as the default
2904+
return OPENSSL_TLS_SECURITY_LEVEL;
2905+
#endif // OPENSSL_IS_BORINGSSL
2906+
}
2907+
28432908
SSLCtxPointer::SSLCtxPointer(SSL_CTX* ctx) : ctx_(ctx) {}
28442909

28452910
SSLCtxPointer::SSLCtxPointer(SSLCtxPointer&& other) noexcept
@@ -3515,6 +3580,10 @@ EVPKeyCtxPointer EVPKeyCtxPointer::New(const EVPKeyPointer& key) {
35153580
}
35163581

35173582
EVPKeyCtxPointer EVPKeyCtxPointer::NewFromID(int id) {
3583+
#ifdef OPENSSL_IS_BORINGSSL
3584+
// DSA keys are not supported with BoringSSL
3585+
if (id == EVP_PKEY_DSA) return {};
3586+
#endif
35183587
return EVPKeyCtxPointer(EVP_PKEY_CTX_new_id(id, nullptr));
35193588
}
35203589

@@ -4026,6 +4095,26 @@ int Ec::getCurve() const {
40264095
return EC_GROUP_get_curve_name(getGroup());
40274096
}
40284097

4098+
int Ec::GetCurveIdFromName(std::string_view name) {
4099+
int nid = EC_curve_nist2nid(name.data());
4100+
if (nid == NID_undef) {
4101+
nid = OBJ_sn2nid(name.data());
4102+
}
4103+
return nid;
4104+
}
4105+
4106+
bool Ec::GetCurves(Ec::GetCurveCallback callback) {
4107+
const size_t count = EC_get_builtin_curves(nullptr, 0);
4108+
std::vector<EC_builtin_curve> curves(count);
4109+
if (EC_get_builtin_curves(curves.data(), count) != count) {
4110+
return false;
4111+
}
4112+
for (auto curve : curves) {
4113+
if (!callback(OBJ_nid2sn(curve.nid))) return false;
4114+
}
4115+
return true;
4116+
}
4117+
40294118
uint32_t Ec::getDegree() const {
40304119
return EC_GROUP_get_degree(getGroup());
40314120
}

0 commit comments

Comments
 (0)