1
+
#include "ncrypto.h"
2
+
#include <algorithm>
3
+
#include <cstring>
4
+
#include "openssl/bn.h"
5
+
#if OPENSSL_VERSION_MAJOR >= 3
6
+
#include "openssl/provider.h"
7
+
#endif
8
+
9
+
namespace ncrypto {
10
+
11
+
// ============================================================================
12
+
13
+
ClearErrorOnReturn::ClearErrorOnReturn(CryptoErrorList* errors) : errors_(errors) {
14
+
ERR_clear_error();
15
+
}
16
+
17
+
ClearErrorOnReturn::~ClearErrorOnReturn() {
18
+
if (errors_ != nullptr) errors_->capture();
19
+
ERR_clear_error();
20
+
}
21
+
22
+
int ClearErrorOnReturn::peeKError() { return ERR_peek_error(); }
23
+
24
+
MarkPopErrorOnReturn::MarkPopErrorOnReturn(CryptoErrorList* errors) : errors_(errors) {
25
+
ERR_set_mark();
26
+
}
27
+
28
+
MarkPopErrorOnReturn::~MarkPopErrorOnReturn() {
29
+
if (errors_ != nullptr) errors_->capture();
30
+
ERR_pop_to_mark();
31
+
}
32
+
33
+
int MarkPopErrorOnReturn::peekError() { return ERR_peek_error(); }
34
+
35
+
CryptoErrorList::CryptoErrorList(CryptoErrorList::Option option) {
36
+
if (option == Option::CAPTURE_ON_CONSTRUCT) capture();
37
+
}
38
+
39
+
void CryptoErrorList::capture() {
40
+
errors_.clear();
41
+
while(const auto err = ERR_get_error()) {
42
+
char buf[256];
43
+
ERR_error_string_n(err, buf, sizeof(buf));
44
+
errors_.emplace_front(buf);
45
+
}
46
+
}
47
+
48
+
void CryptoErrorList::add(std::string error) {
49
+
errors_.push_back(error);
50
+
}
51
+
52
+
std::optional<std::string> CryptoErrorList::pop_back() {
53
+
if (errors_.empty()) return std::nullopt;
54
+
std::string error = errors_.back();
55
+
errors_.pop_back();
56
+
return error;
57
+
}
58
+
59
+
std::optional<std::string> CryptoErrorList::pop_front() {
60
+
if (errors_.empty()) return std::nullopt;
61
+
std::string error = errors_.front();
62
+
errors_.pop_front();
63
+
return error;
64
+
}
65
+
66
+
// ============================================================================
67
+
bool isFipsEnabled() {
68
+
#if OPENSSL_VERSION_MAJOR >= 3
69
+
return EVP_default_properties_is_fips_enabled(nullptr) == 1;
70
+
#else
71
+
return FIPS_mode() == 1;
72
+
#endif
73
+
}
74
+
75
+
bool setFipsEnabled(bool enable, CryptoErrorList* errors) {
76
+
if (isFipsEnabled() == enable) return true;
77
+
ClearErrorOnReturn clearErrorOnReturn(errors);
78
+
#if OPENSSL_VERSION_MAJOR >= 3
79
+
return EVP_default_properties_enable_fips(nullptr, enable ? 1 : 0) == 1;
80
+
#else
81
+
return FIPS_mode_set(enable ? 1 : 0) == 1;
82
+
#endif
83
+
}
84
+
85
+
bool testFipsEnabled() {
86
+
#if OPENSSL_VERSION_MAJOR >= 3
87
+
OSSL_PROVIDER* fips_provider = nullptr;
88
+
if (OSSL_PROVIDER_available(nullptr, "fips")) {
89
+
fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
90
+
}
91
+
const auto enabled = fips_provider == nullptr ? 0 :
92
+
OSSL_PROVIDER_self_test(fips_provider) ? 1 : 0;
93
+
#else
94
+
#ifdef OPENSSL_FIPS
95
+
const auto enabled = FIPS_selftest() ? 1 : 0;
96
+
#else // OPENSSL_FIPS
97
+
const auto enabled = 0;
98
+
#endif // OPENSSL_FIPS
99
+
#endif
100
+
101
+
return enabled;
102
+
}
103
+
104
+
// ============================================================================
105
+
// Bignum
106
+
BignumPointer::BignumPointer(BIGNUM* bignum) : bn_(bignum) {}
107
+
108
+
BignumPointer::BignumPointer(BignumPointer&& other) noexcept
109
+
: bn_(other.release()) {}
110
+
111
+
BignumPointer& BignumPointer::operator=(BignumPointer&& other) noexcept {
112
+
if (this == &other) return *this;
113
+
this->~BignumPointer();
114
+
return *new (this) BignumPointer(std::move(other));
115
+
}
116
+
117
+
BignumPointer::~BignumPointer() { reset(); }
118
+
119
+
void BignumPointer::reset(BIGNUM* bn) {
120
+
bn_.reset(bn);
121
+
}
122
+
123
+
BIGNUM* BignumPointer::release() {
124
+
return bn_.release();
125
+
}
126
+
127
+
size_t BignumPointer::byteLength() {
128
+
if (bn_ == nullptr) return 0;
129
+
return BN_num_bytes(bn_.get());
130
+
}
131
+
132
+
std::vector<uint8_t> BignumPointer::encode() {
133
+
return encodePadded(bn_.get(), byteLength());
134
+
}
135
+
136
+
std::vector<uint8_t> BignumPointer::encodePadded(size_t size) {
137
+
return encodePadded(bn_.get(), size);
138
+
}
139
+
140
+
std::vector<uint8_t> BignumPointer::encode(const BIGNUM* bn) {
141
+
return encodePadded(bn, bn != nullptr ? BN_num_bytes(bn) : 0);
142
+
}
143
+
144
+
std::vector<uint8_t> BignumPointer::encodePadded(const BIGNUM* bn, size_t s) {
145
+
if (bn == nullptr) return std::vector<uint8_t>(0);
146
+
size_t size = std::max(s, static_cast<size_t>(BN_num_bytes(bn)));
147
+
std::vector<uint8_t> buf(size);
148
+
BN_bn2binpad(bn, buf.data(), size);
149
+
return buf;
150
+
}
151
+
152
+
bool BignumPointer::operator==(const BignumPointer& other) noexcept {
153
+
if (bn_ == nullptr && other.bn_ != nullptr) return false;
154
+
if (bn_ != nullptr && other.bn_ == nullptr) return false;
155
+
if (bn_ == nullptr && other.bn_ == nullptr) return true;
156
+
return BN_cmp(bn_.get(), other.bn_.get()) == 0;
157
+
}
158
+
159
+
bool BignumPointer::operator==(const BIGNUM* other) noexcept {
160
+
if (bn_ == nullptr && other != nullptr) return false;
161
+
if (bn_ != nullptr && other == nullptr) return false;
162
+
if (bn_ == nullptr && other == nullptr) return true;
163
+
return BN_cmp(bn_.get(), other) == 0;
164
+
}
165
+
166
+
// ============================================================================
167
+
// Utility methods
168
+
169
+
bool CSPRNG(void* buffer, size_t length) {
170
+
auto buf = reinterpret_cast<unsigned char*>(buffer);
171
+
do {
172
+
if (1 == RAND_status()) {
173
+
#if OPENSSL_VERSION_MAJOR >= 3
174
+
if (1 == RAND_bytes_ex(nullptr, buf, length, 0)) {
175
+
return true;
176
+
}
177
+
#else
178
+
while (length > INT_MAX && 1 == RAND_bytes(buf, INT_MAX)) {
179
+
buf += INT_MAX;
180
+
length -= INT_MAX;
181
+
}
182
+
if (length <= INT_MAX && 1 == RAND_bytes(buf, static_cast<int>(length)))
183
+
return true;
184
+
#endif
185
+
}
186
+
#if OPENSSL_VERSION_MAJOR >= 3
187
+
const auto code = ERR_peek_last_error();
188
+
// A misconfigured OpenSSL 3 installation may report 1 from RAND_poll()
189
+
// and RAND_status() but fail in RAND_bytes() if it cannot look up
190
+
// a matching algorithm for the CSPRNG.
191
+
if (ERR_GET_LIB(code) == ERR_LIB_RAND) {
192
+
const auto reason = ERR_GET_REASON(code);
193
+
if (reason == RAND_R_ERROR_INSTANTIATING_DRBG ||
194
+
reason == RAND_R_UNABLE_TO_FETCH_DRBG ||
195
+
reason == RAND_R_UNABLE_TO_CREATE_DRBG) {
196
+
return false;
197
+
}
198
+
}
199
+
#endif
200
+
} while (1 == RAND_poll());
201
+
202
+
return false;
203
+
}
204
+
205
+
int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
206
+
return 0;
207
+
}
208
+
209
+
int PasswordCallback(char* buf, int size, int rwflag, void* u) {
210
+
const Buffer* passphrase = static_cast<const Buffer*>(u);
211
+
if (passphrase != nullptr) {
212
+
size_t buflen = static_cast<size_t>(size);
213
+
size_t len = passphrase->len;
214
+
if (buflen < len)
215
+
return -1;
216
+
memcpy(buf, reinterpret_cast<const char*>(passphrase->data), len);
217
+
return len;
218
+
}
219
+
220
+
return -1;
221
+
}
222
+
223
+
} // namespace ncrypto
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4