/src/node/deps/ncrypto/ncrypto.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include <openssl/bio.h> |
4 | | #include <openssl/bn.h> |
5 | | #include <openssl/dh.h> |
6 | | #include <openssl/dsa.h> |
7 | | #include <openssl/ec.h> |
8 | | #include <openssl/err.h> |
9 | | #include <openssl/evp.h> |
10 | | #include <openssl/hmac.h> |
11 | | #include <openssl/kdf.h> |
12 | | #include <openssl/rsa.h> |
13 | | #include <openssl/ssl.h> |
14 | | #include <openssl/x509.h> |
15 | | #include <cstddef> |
16 | | #include <functional> |
17 | | #include <list> |
18 | | #include <memory> |
19 | | #include <optional> |
20 | | #include <string> |
21 | | #include <string_view> |
22 | | #ifndef OPENSSL_NO_ENGINE |
23 | | #include <openssl/engine.h> |
24 | | #endif // !OPENSSL_NO_ENGINE |
25 | | // The FIPS-related functions are only available |
26 | | // when the OpenSSL itself was compiled with FIPS support. |
27 | | #if defined(OPENSSL_FIPS) && OPENSSL_VERSION_MAJOR < 3 |
28 | | #include <openssl/fips.h> |
29 | | #endif // OPENSSL_FIPS |
30 | | |
31 | | // Define OPENSSL_WITH_PQC for post-quantum cryptography support |
32 | | #if OPENSSL_VERSION_NUMBER >= 0x30500000L |
33 | | #define OPENSSL_WITH_PQC 1 |
34 | 0 | #define EVP_PKEY_ML_KEM_512 NID_ML_KEM_512 |
35 | 0 | #define EVP_PKEY_ML_KEM_768 NID_ML_KEM_768 |
36 | 0 | #define EVP_PKEY_ML_KEM_1024 NID_ML_KEM_1024 |
37 | | #include <openssl/core_names.h> |
38 | | #endif |
39 | | |
40 | | #if OPENSSL_VERSION_MAJOR >= 3 |
41 | | #define OSSL3_CONST const |
42 | | #else |
43 | | #define OSSL3_CONST |
44 | | #endif |
45 | | |
46 | | #ifdef __GNUC__ |
47 | | #define NCRYPTO_MUST_USE_RESULT __attribute__((warn_unused_result)) |
48 | | #else |
49 | | #define NCRYPTO_MUST_USE_RESULT |
50 | | #endif |
51 | | |
52 | | #ifdef OPENSSL_IS_BORINGSSL |
53 | | // Boringssl has opted to use size_t for some size related |
54 | | // APIs while Openssl is still using ints |
55 | | using OPENSSL_SIZE_T = size_t; |
56 | | #else |
57 | | using OPENSSL_SIZE_T = int; |
58 | | #endif |
59 | | |
60 | | namespace ncrypto { |
61 | | |
62 | | // ============================================================================ |
63 | | // Utility macros |
64 | | |
65 | | #if NCRYPTO_DEVELOPMENT_CHECKS |
66 | | #define NCRYPTO_STR(x) #x |
67 | | #define NCRYPTO_REQUIRE(EXPR) \ |
68 | | { \ |
69 | | if (!(EXPR)) { \ |
70 | | abort(); \ |
71 | | } \ |
72 | | } |
73 | | |
74 | | #define NCRYPTO_FAIL(MESSAGE) \ |
75 | | do { \ |
76 | | std::cerr << "FAIL: " << (MESSAGE) << std::endl; \ |
77 | | abort(); \ |
78 | | } while (0); |
79 | | #define NCRYPTO_ASSERT_EQUAL(LHS, RHS, MESSAGE) \ |
80 | | do { \ |
81 | | if (LHS != RHS) { \ |
82 | | std::cerr << "Mismatch: '" << LHS << "' - '" << RHS << "'" << std::endl; \ |
83 | | NCRYPTO_FAIL(MESSAGE); \ |
84 | | } \ |
85 | | } while (0); |
86 | | #define NCRYPTO_ASSERT_TRUE(COND) \ |
87 | | do { \ |
88 | | if (!(COND)) { \ |
89 | | std::cerr << "Assert at line " << __LINE__ << " of file " << __FILE__ \ |
90 | | << std::endl; \ |
91 | | NCRYPTO_FAIL(NCRYPTO_STR(COND)); \ |
92 | | } \ |
93 | | } while (0); |
94 | | #else |
95 | | #define NCRYPTO_FAIL(MESSAGE) |
96 | | #define NCRYPTO_ASSERT_EQUAL(LHS, RHS, MESSAGE) |
97 | | #define NCRYPTO_ASSERT_TRUE(COND) |
98 | | #endif |
99 | | |
100 | | #define NCRYPTO_DISALLOW_COPY(Name) \ |
101 | | Name(const Name&) = delete; \ |
102 | | Name& operator=(const Name&) = delete; |
103 | | #define NCRYPTO_DISALLOW_MOVE(Name) \ |
104 | | Name(Name&&) = delete; \ |
105 | | Name& operator=(Name&&) = delete; |
106 | | #define NCRYPTO_DISALLOW_COPY_AND_MOVE(Name) \ |
107 | | NCRYPTO_DISALLOW_COPY(Name) \ |
108 | | NCRYPTO_DISALLOW_MOVE(Name) |
109 | | #define NCRYPTO_DISALLOW_NEW_DELETE() \ |
110 | | void* operator new(size_t) = delete; \ |
111 | | void operator delete(void*) = delete; |
112 | | |
113 | 0 | [[noreturn]] inline void unreachable() { |
114 | 0 | #ifdef __GNUC__ |
115 | 0 | __builtin_unreachable(); |
116 | 0 | #elif defined(_MSC_VER) |
117 | 0 | __assume(false); |
118 | 0 | #else |
119 | 0 | #endif |
120 | 0 | } |
121 | | |
122 | | static constexpr int kX509NameFlagsMultiline = |
123 | | ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_UTF8_CONVERT | |
124 | | XN_FLAG_SEP_MULTILINE | XN_FLAG_FN_SN; |
125 | | |
126 | | // ============================================================================ |
127 | | // Error handling utilities |
128 | | |
129 | | // Capture the current OpenSSL Error Stack. The stack will be ordered such |
130 | | // that the error currently at the top of the stack is at the end of the |
131 | | // list and the error at the bottom of the stack is at the beginning. |
132 | | class CryptoErrorList final { |
133 | | public: |
134 | | enum class Option { NONE, CAPTURE_ON_CONSTRUCT }; |
135 | | CryptoErrorList(Option option = Option::CAPTURE_ON_CONSTRUCT); |
136 | | |
137 | | void capture(); |
138 | | |
139 | | // Add an error message to the end of the stack. |
140 | | void add(std::string message); |
141 | | |
142 | 0 | inline const std::string& peek_back() const { return errors_.back(); } |
143 | 0 | inline size_t size() const { return errors_.size(); } |
144 | 0 | inline bool empty() const { return errors_.empty(); } |
145 | | |
146 | 0 | inline auto begin() const noexcept { return errors_.begin(); } |
147 | 0 | inline auto end() const noexcept { return errors_.end(); } |
148 | 0 | inline auto rbegin() const noexcept { return errors_.rbegin(); } |
149 | 0 | inline auto rend() const noexcept { return errors_.rend(); } |
150 | | |
151 | | std::optional<std::string> pop_back(); |
152 | | std::optional<std::string> pop_front(); |
153 | | |
154 | | private: |
155 | | std::list<std::string> errors_; |
156 | | }; |
157 | | |
158 | | // Forcibly clears the error stack on destruction. This stops stale errors |
159 | | // from popping up later in the lifecycle of crypto operations where they |
160 | | // would cause spurious failures. It is a rather blunt method, though, and |
161 | | // ERR_clear_error() isn't necessarily cheap. |
162 | | // |
163 | | // If created with a pointer to a CryptoErrorList, the current OpenSSL error |
164 | | // stack will be captured before clearing the error. |
165 | | class ClearErrorOnReturn final { |
166 | | public: |
167 | | ClearErrorOnReturn(CryptoErrorList* errors = nullptr); |
168 | | ~ClearErrorOnReturn(); |
169 | | NCRYPTO_DISALLOW_COPY_AND_MOVE(ClearErrorOnReturn) |
170 | | NCRYPTO_DISALLOW_NEW_DELETE() |
171 | | |
172 | | int peekError(); |
173 | | |
174 | | private: |
175 | | CryptoErrorList* errors_; |
176 | | }; |
177 | | |
178 | | // Pop errors from OpenSSL's error stack that were added between when this |
179 | | // was constructed and destructed. |
180 | | // |
181 | | // If created with a pointer to a CryptoErrorList, the current OpenSSL error |
182 | | // stack will be captured before resetting the error to the mark. |
183 | | class MarkPopErrorOnReturn final { |
184 | | public: |
185 | | MarkPopErrorOnReturn(CryptoErrorList* errors = nullptr); |
186 | | ~MarkPopErrorOnReturn(); |
187 | | NCRYPTO_DISALLOW_COPY_AND_MOVE(MarkPopErrorOnReturn) |
188 | | NCRYPTO_DISALLOW_NEW_DELETE() |
189 | | |
190 | | int peekError(); |
191 | | |
192 | | private: |
193 | | CryptoErrorList* errors_; |
194 | | }; |
195 | | |
196 | | // TODO(@jasnell): Eventually replace with std::expected when we are able to |
197 | | // bump up to c++23. |
198 | | template <typename T, typename E> |
199 | | struct Result final { |
200 | | const bool has_value; |
201 | | T value; |
202 | | std::optional<E> error = std::nullopt; |
203 | | std::optional<int> openssl_error = std::nullopt; |
204 | | Result(T&& value) : has_value(true), value(std::move(value)) {} |
205 | | Result(E&& error, std::optional<int> openssl_error = std::nullopt) |
206 | | : has_value(false), |
207 | | error(std::move(error)), |
208 | | openssl_error(std::move(openssl_error)) {} |
209 | 0 | inline operator bool() const { return has_value; }Unexecuted instantiation: ncrypto::Result<ncrypto::BIOPointer, bool>::operator bool() const Unexecuted instantiation: ncrypto::Result<ncrypto::EVPKeyPointer, ncrypto::EVPKeyPointer::PKParseError>::operator bool() const |
210 | | }; |
211 | | |
212 | | // ============================================================================ |
213 | | // Various smart pointer aliases for OpenSSL types. |
214 | | |
215 | | template <typename T, void (*function)(T*)> |
216 | | struct FunctionDeleter { |
217 | 0 | void operator()(T* pointer) const { function(pointer); }Unexecuted instantiation: ncrypto::FunctionDeleter<bio_st, &BIO_free_all>::operator()(bio_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<evp_pkey_st, &EVP_PKEY_free>::operator()(evp_pkey_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<ssl_ctx_st, &SSL_CTX_free>::operator()(ssl_ctx_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<x509_st, &X509_free>::operator()(x509_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<dh_st, &DH_free>::operator()(dh_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<pkcs8_priv_key_info_st, &PKCS8_PRIV_KEY_INFO_free>::operator()(pkcs8_priv_key_info_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<ssl_session_st, &SSL_SESSION_free>::operator()(ssl_session_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<ssl_st, &SSL_free>::operator()(ssl_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<bignum_st, &BN_clear_free>::operator()(bignum_st*) const Unexecuted instantiation: ncrypto::FunctionDeleter<rsa_st, &RSA_free>::operator()(rsa_st*) const |
218 | | typedef std::unique_ptr<T, FunctionDeleter> Pointer; |
219 | | }; |
220 | | |
221 | | template <typename T, void (*function)(T*)> |
222 | | using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer; |
223 | | |
224 | | using PKCS8Pointer = DeleteFnPtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>; |
225 | | using RSAPointer = DeleteFnPtr<RSA, RSA_free>; |
226 | | using SSLSessionPointer = DeleteFnPtr<SSL_SESSION, SSL_SESSION_free>; |
227 | | |
228 | | class BIOPointer; |
229 | | class BignumPointer; |
230 | | class CipherCtxPointer; |
231 | | class DataPointer; |
232 | | class DHPointer; |
233 | | class ECKeyPointer; |
234 | | class EVPKeyPointer; |
235 | | class EVPMacCtxPointer; |
236 | | class EVPMacPointer; |
237 | | class EVPMDCtxPointer; |
238 | | class SSLCtxPointer; |
239 | | class SSLPointer; |
240 | | class X509View; |
241 | | class X509Pointer; |
242 | | class ECDSASigPointer; |
243 | | class ECGroupPointer; |
244 | | class ECPointPointer; |
245 | | class ECKeyPointer; |
246 | | class Dsa; |
247 | | class Rsa; |
248 | | class Ec; |
249 | | |
250 | | struct StackOfXASN1Deleter { |
251 | 0 | void operator()(STACK_OF(ASN1_OBJECT) * p) const { |
252 | 0 | sk_ASN1_OBJECT_pop_free(p, ASN1_OBJECT_free); |
253 | 0 | } |
254 | | }; |
255 | | using StackOfASN1 = std::unique_ptr<STACK_OF(ASN1_OBJECT), StackOfXASN1Deleter>; |
256 | | |
257 | | // An unowned, unmanaged pointer to a buffer of data. |
258 | | template <typename T> |
259 | | struct Buffer { |
260 | | T* data = nullptr; |
261 | | size_t len = 0; |
262 | | }; |
263 | | |
264 | | class Digest final { |
265 | | public: |
266 | | static constexpr size_t MAX_SIZE = EVP_MAX_MD_SIZE; |
267 | 0 | Digest() = default; |
268 | 0 | Digest(const EVP_MD* md) : md_(md) {} |
269 | | Digest(const Digest&) = default; |
270 | | Digest& operator=(const Digest&) = default; |
271 | 0 | inline Digest& operator=(const EVP_MD* md) { |
272 | 0 | md_ = md; |
273 | 0 | return *this; |
274 | 0 | } |
275 | | NCRYPTO_DISALLOW_MOVE(Digest) |
276 | | |
277 | | size_t size() const; |
278 | | |
279 | 0 | inline const EVP_MD* get() const { return md_; } |
280 | 0 | inline operator const EVP_MD*() const { return md_; } |
281 | 0 | inline operator bool() const { return md_ != nullptr; } |
282 | | |
283 | | static const Digest MD5; |
284 | | static const Digest SHA1; |
285 | | static const Digest SHA256; |
286 | | static const Digest SHA384; |
287 | | static const Digest SHA512; |
288 | | |
289 | | static const Digest FromName(const char* name); |
290 | | |
291 | | private: |
292 | | const EVP_MD* md_ = nullptr; |
293 | | }; |
294 | | |
295 | | // Computes a fixed-length digest. |
296 | | DataPointer hashDigest(const Buffer<const unsigned char>& data, |
297 | | const EVP_MD* md); |
298 | | // Computes a variable-length digest for XOF algorithms (e.g. SHAKE128). |
299 | | DataPointer xofHashDigest(const Buffer<const unsigned char>& data, |
300 | | const EVP_MD* md, |
301 | | size_t length); |
302 | | |
303 | | class Cipher final { |
304 | | public: |
305 | | static constexpr size_t MAX_KEY_LENGTH = EVP_MAX_KEY_LENGTH; |
306 | | static constexpr size_t MAX_IV_LENGTH = EVP_MAX_IV_LENGTH; |
307 | | #ifdef EVP_MAX_AEAD_TAG_LENGTH |
308 | | static constexpr size_t MAX_AUTH_TAG_LENGTH = EVP_MAX_AEAD_TAG_LENGTH; |
309 | | #else |
310 | | static constexpr size_t MAX_AUTH_TAG_LENGTH = 16; |
311 | | #endif |
312 | | static_assert(EVP_GCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && |
313 | | EVP_CCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && |
314 | | EVP_CHACHAPOLY_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH); |
315 | | |
316 | 0 | Cipher() = default; |
317 | 0 | Cipher(const EVP_CIPHER* cipher) : cipher_(cipher) {} |
318 | | Cipher(const Cipher&) = default; |
319 | | Cipher& operator=(const Cipher&) = default; |
320 | 0 | inline Cipher& operator=(const EVP_CIPHER* cipher) { |
321 | 0 | cipher_ = cipher; |
322 | 0 | return *this; |
323 | 0 | } |
324 | | NCRYPTO_DISALLOW_MOVE(Cipher) |
325 | | |
326 | 0 | inline const EVP_CIPHER* get() const { return cipher_; } |
327 | 0 | inline operator const EVP_CIPHER*() const { return cipher_; } |
328 | 0 | inline operator bool() const { return cipher_ != nullptr; } |
329 | | |
330 | | int getNid() const; |
331 | | int getMode() const; |
332 | | int getIvLength() const; |
333 | | int getKeyLength() const; |
334 | | int getBlockSize() const; |
335 | | std::string_view getModeLabel() const; |
336 | | const char* getName() const; |
337 | | |
338 | | bool isGcmMode() const; |
339 | | bool isWrapMode() const; |
340 | | bool isCtrMode() const; |
341 | | bool isCcmMode() const; |
342 | | bool isOcbMode() const; |
343 | | bool isStreamMode() const; |
344 | | bool isChaCha20Poly1305() const; |
345 | | |
346 | | bool isSupportedAuthenticatedMode() const; |
347 | | |
348 | | int bytesToKey(const Digest& digest, |
349 | | const Buffer<const unsigned char>& input, |
350 | | unsigned char* key, |
351 | | unsigned char* iv) const; |
352 | | |
353 | | static const Cipher FromName(const char* name); |
354 | | static const Cipher FromNid(int nid); |
355 | | static const Cipher FromCtx(const CipherCtxPointer& ctx); |
356 | | |
357 | | using CipherNameCallback = std::function<void(const char* name)>; |
358 | | |
359 | | // Iterates the known ciphers if the underlying implementation |
360 | | // is able to do so. |
361 | | static void ForEach(CipherNameCallback callback); |
362 | | |
363 | | // Utilities to get various ciphers by type. If the underlying |
364 | | // implementation does not support the requested cipher, then |
365 | | // the result will be an empty Cipher object whose bool operator |
366 | | // will return false. |
367 | | |
368 | | static const Cipher EMPTY; |
369 | | static const Cipher AES_128_CBC; |
370 | | static const Cipher AES_192_CBC; |
371 | | static const Cipher AES_256_CBC; |
372 | | static const Cipher AES_128_CTR; |
373 | | static const Cipher AES_192_CTR; |
374 | | static const Cipher AES_256_CTR; |
375 | | static const Cipher AES_128_GCM; |
376 | | static const Cipher AES_192_GCM; |
377 | | static const Cipher AES_256_GCM; |
378 | | static const Cipher AES_128_KW; |
379 | | static const Cipher AES_192_KW; |
380 | | static const Cipher AES_256_KW; |
381 | | static const Cipher AES_128_OCB; |
382 | | static const Cipher AES_192_OCB; |
383 | | static const Cipher AES_256_OCB; |
384 | | static const Cipher CHACHA20_POLY1305; |
385 | | |
386 | | struct CipherParams { |
387 | | int padding; |
388 | | Digest digest; |
389 | | const Buffer<const void> label; |
390 | | }; |
391 | | |
392 | | static DataPointer encrypt(const EVPKeyPointer& key, |
393 | | const CipherParams& params, |
394 | | const Buffer<const void> in); |
395 | | static DataPointer decrypt(const EVPKeyPointer& key, |
396 | | const CipherParams& params, |
397 | | const Buffer<const void> in); |
398 | | |
399 | | static DataPointer sign(const EVPKeyPointer& key, |
400 | | const CipherParams& params, |
401 | | const Buffer<const void> in); |
402 | | |
403 | | static DataPointer recover(const EVPKeyPointer& key, |
404 | | const CipherParams& params, |
405 | | const Buffer<const void> in); |
406 | | |
407 | 0 | static constexpr bool IsValidGCMTagLength(unsigned int tag_len) { |
408 | 0 | return tag_len == 4 || tag_len == 8 || (tag_len >= 12 && tag_len <= 16); |
409 | 0 | } |
410 | | |
411 | | private: |
412 | | const EVP_CIPHER* cipher_ = nullptr; |
413 | | }; |
414 | | |
415 | | // ============================================================================ |
416 | | // DSA |
417 | | |
418 | | class Dsa final { |
419 | | public: |
420 | | Dsa(); |
421 | | Dsa(OSSL3_CONST DSA* dsa); |
422 | | NCRYPTO_DISALLOW_COPY_AND_MOVE(Dsa) |
423 | | |
424 | 0 | inline operator bool() const { return dsa_ != nullptr; } |
425 | 0 | inline operator OSSL3_CONST DSA*() const { return dsa_; } |
426 | | |
427 | | const BIGNUM* getP() const; |
428 | | const BIGNUM* getQ() const; |
429 | | size_t getModulusLength() const; |
430 | | size_t getDivisorLength() const; |
431 | | |
432 | | private: |
433 | | OSSL3_CONST DSA* dsa_; |
434 | | }; |
435 | | |
436 | | // ============================================================================ |
437 | | // RSA |
438 | | |
439 | | class Rsa final { |
440 | | public: |
441 | | Rsa(); |
442 | | Rsa(OSSL3_CONST RSA* rsa); |
443 | | NCRYPTO_DISALLOW_COPY_AND_MOVE(Rsa) |
444 | | |
445 | 0 | inline operator bool() const { return rsa_ != nullptr; } |
446 | 0 | inline operator OSSL3_CONST RSA*() const { return rsa_; } |
447 | | |
448 | | struct PublicKey { |
449 | | const BIGNUM* n; |
450 | | const BIGNUM* e; |
451 | | const BIGNUM* d; |
452 | | }; |
453 | | struct PrivateKey { |
454 | | const BIGNUM* p; |
455 | | const BIGNUM* q; |
456 | | const BIGNUM* dp; |
457 | | const BIGNUM* dq; |
458 | | const BIGNUM* qi; |
459 | | }; |
460 | | struct PssParams { |
461 | | std::string_view digest = "sha1"; |
462 | | std::optional<std::string_view> mgf1_digest = "sha1"; |
463 | | int64_t salt_length = 20; |
464 | | }; |
465 | | |
466 | | const PublicKey getPublicKey() const; |
467 | | const PrivateKey getPrivateKey() const; |
468 | | const std::optional<PssParams> getPssParams() const; |
469 | | |
470 | | bool setPublicKey(BignumPointer&& n, BignumPointer&& e); |
471 | | bool setPrivateKey(BignumPointer&& d, |
472 | | BignumPointer&& q, |
473 | | BignumPointer&& p, |
474 | | BignumPointer&& dp, |
475 | | BignumPointer&& dq, |
476 | | BignumPointer&& qi); |
477 | | |
478 | | using CipherParams = Cipher::CipherParams; |
479 | | |
480 | | static DataPointer encrypt(const EVPKeyPointer& key, |
481 | | const CipherParams& params, |
482 | | const Buffer<const void> in); |
483 | | static DataPointer decrypt(const EVPKeyPointer& key, |
484 | | const CipherParams& params, |
485 | | const Buffer<const void> in); |
486 | | |
487 | | private: |
488 | | OSSL3_CONST RSA* rsa_; |
489 | | }; |
490 | | |
491 | | class Ec final { |
492 | | public: |
493 | | Ec(); |
494 | | Ec(OSSL3_CONST EC_KEY* key); |
495 | | NCRYPTO_DISALLOW_COPY_AND_MOVE(Ec) |
496 | | |
497 | | const EC_GROUP* getGroup() const; |
498 | | int getCurve() const; |
499 | | |
500 | 0 | inline operator bool() const { return ec_ != nullptr; } |
501 | 0 | inline operator OSSL3_CONST EC_KEY*() const { return ec_; } |
502 | | |
503 | | static int GetCurveIdFromName(const char* name); |
504 | | |
505 | | using GetCurveCallback = std::function<bool(const char*)>; |
506 | | static bool GetCurves(GetCurveCallback callback); |
507 | | |
508 | | private: |
509 | | OSSL3_CONST EC_KEY* ec_ = nullptr; |
510 | | }; |
511 | | |
512 | | // A managed pointer to a buffer of data. When destroyed the underlying |
513 | | // buffer will be freed. |
514 | | class DataPointer final { |
515 | | public: |
516 | | static DataPointer Alloc(size_t len); |
517 | | static DataPointer Copy(const Buffer<const void>& buffer); |
518 | | |
519 | | // Attempts to allocate the buffer space using the secure heap, if |
520 | | // supported/enabled. If the secure heap is disabled, then this |
521 | | // ends up being equivalent to Alloc(len). Note that allocation |
522 | | // will fail if there is not enough free space remaining in the |
523 | | // secure heap space. |
524 | | static DataPointer SecureAlloc(size_t len); |
525 | | |
526 | | // If the secure heap is enabled, returns the amount of data that |
527 | | // has been allocated from the heap. |
528 | | static size_t GetSecureHeapUsed(); |
529 | | |
530 | | enum class InitSecureHeapResult { |
531 | | FAILED, |
532 | | UNABLE_TO_MEMORY_MAP, |
533 | | OK, |
534 | | }; |
535 | | |
536 | | // Attempt to initialize the secure heap. The secure heap is not |
537 | | // supported on all operating systems and whenever boringssl is |
538 | | // used. |
539 | | static InitSecureHeapResult TryInitSecureHeap(size_t amount, size_t min); |
540 | | |
541 | 0 | DataPointer() = default; |
542 | | explicit DataPointer(void* data, size_t len, bool secure = false); |
543 | | explicit DataPointer(const Buffer<void>& buffer, bool secure = false); |
544 | | DataPointer(DataPointer&& other) noexcept; |
545 | | DataPointer& operator=(DataPointer&& other) noexcept; |
546 | | NCRYPTO_DISALLOW_COPY(DataPointer) |
547 | | ~DataPointer(); |
548 | | |
549 | 0 | inline bool operator==(std::nullptr_t) noexcept { return data_ == nullptr; } |
550 | 0 | inline operator bool() const { return data_ != nullptr; } |
551 | | |
552 | | template <typename T = void> |
553 | 0 | inline T* get() const noexcept { |
554 | 0 | return static_cast<T*>(data_); |
555 | 0 | } |
556 | | |
557 | 0 | inline size_t size() const noexcept { return len_; } |
558 | | void reset(void* data = nullptr, size_t len = 0); |
559 | | void reset(const Buffer<void>& buffer); |
560 | | |
561 | | // Sets the underlying data buffer to all zeros. |
562 | | void zero(); |
563 | | |
564 | | DataPointer resize(size_t len); |
565 | | |
566 | | // Releases ownership of the underlying data buffer. It is the caller's |
567 | | // responsibility to ensure the buffer is appropriately freed. |
568 | | Buffer<void> release(); |
569 | | |
570 | | // Returns a Buffer struct that is a view of the underlying data. |
571 | | template <typename T = void> |
572 | 0 | inline operator const Buffer<T>() const { |
573 | 0 | return { |
574 | 0 | .data = static_cast<T*>(data_), |
575 | 0 | .len = len_, |
576 | 0 | }; |
577 | 0 | } Unexecuted instantiation: ncrypto::DataPointer::operator ncrypto::Buffer<unsigned char const> const<unsigned char const>() const Unexecuted instantiation: ncrypto::DataPointer::operator ncrypto::Buffer<char const> const<char const>() const |
578 | | |
579 | 0 | bool isSecure() const { return secure_; } |
580 | | |
581 | | private: |
582 | | void* data_ = nullptr; |
583 | | size_t len_ = 0; |
584 | | bool secure_ = false; |
585 | | }; |
586 | | |
587 | | class BIOPointer final { |
588 | | public: |
589 | | static BIOPointer NewMem(); |
590 | | static BIOPointer NewSecMem(); |
591 | | static BIOPointer New(const BIO_METHOD* method); |
592 | | static BIOPointer New(const void* data, size_t len); |
593 | | static BIOPointer New(const BIGNUM* bn); |
594 | | static BIOPointer NewFile(const char* filename, const char* mode); |
595 | | static BIOPointer NewFp(FILE* fd, int flags); |
596 | | |
597 | | template <typename T> |
598 | | static BIOPointer New(const Buffer<T>& buf) { |
599 | | return New(buf.data, buf.len); |
600 | | } |
601 | | |
602 | 0 | BIOPointer() = default; |
603 | 0 | BIOPointer(std::nullptr_t) : bio_(nullptr) {} |
604 | | explicit BIOPointer(BIO* bio); |
605 | | BIOPointer(BIOPointer&& other) noexcept; |
606 | | BIOPointer& operator=(BIOPointer&& other) noexcept; |
607 | | NCRYPTO_DISALLOW_COPY(BIOPointer) |
608 | | ~BIOPointer(); |
609 | | |
610 | 0 | inline bool operator==(std::nullptr_t) noexcept { return bio_ == nullptr; } |
611 | 0 | inline operator bool() const { return bio_ != nullptr; } |
612 | 0 | inline BIO* get() const noexcept { return bio_.get(); } |
613 | | |
614 | 0 | inline operator BUF_MEM*() const { |
615 | 0 | BUF_MEM* mem = nullptr; |
616 | 0 | if (!bio_) return mem; |
617 | 0 | BIO_get_mem_ptr(bio_.get(), &mem); |
618 | 0 | return mem; |
619 | 0 | } |
620 | | |
621 | 0 | inline operator BIO*() const { return bio_.get(); } |
622 | | |
623 | | void reset(BIO* bio = nullptr); |
624 | | BIO* release(); |
625 | | |
626 | | bool resetBio() const; |
627 | | |
628 | | static int Write(BIOPointer* bio, std::string_view message); |
629 | | |
630 | | template <typename... Args> |
631 | | static void Printf(BIOPointer* bio, const char* format, Args... args) { |
632 | | if (bio == nullptr || !*bio) return; |
633 | | BIO_printf(bio->get(), format, std::forward<Args...>(args...)); |
634 | | } |
635 | | |
636 | | private: |
637 | | mutable DeleteFnPtr<BIO, BIO_free_all> bio_; |
638 | | }; |
639 | | |
640 | | class BignumPointer final { |
641 | | public: |
642 | 0 | BignumPointer() = default; |
643 | | explicit BignumPointer(BIGNUM* bignum); |
644 | | explicit BignumPointer(const unsigned char* data, size_t len); |
645 | | BignumPointer(BignumPointer&& other) noexcept; |
646 | | BignumPointer& operator=(BignumPointer&& other) noexcept; |
647 | | NCRYPTO_DISALLOW_COPY(BignumPointer) |
648 | | ~BignumPointer(); |
649 | | |
650 | | int operator<=>(const BignumPointer& other) const noexcept; |
651 | | int operator<=>(const BIGNUM* other) const noexcept; |
652 | 0 | inline operator bool() const { return bn_ != nullptr; } |
653 | 0 | inline BIGNUM* get() const noexcept { return bn_.get(); } |
654 | | void reset(BIGNUM* bn = nullptr); |
655 | | void reset(const unsigned char* data, size_t len); |
656 | | BIGNUM* release(); |
657 | | |
658 | | bool isZero() const; |
659 | | bool isOne() const; |
660 | | |
661 | | bool setWord(unsigned long w); // NOLINT(runtime/int) |
662 | | unsigned long getWord() const; // NOLINT(runtime/int) |
663 | | |
664 | | size_t byteLength() const; |
665 | | |
666 | | DataPointer toHex() const; |
667 | | DataPointer encode() const; |
668 | | DataPointer encodePadded(size_t size) const; |
669 | | size_t encodeInto(unsigned char* out) const; |
670 | | size_t encodePaddedInto(unsigned char* out, size_t size) const; |
671 | | |
672 | | using PrimeCheckCallback = std::function<bool(int, int)>; |
673 | | int isPrime(int checks, |
674 | | PrimeCheckCallback cb = defaultPrimeCheckCallback) const; |
675 | | struct PrimeConfig { |
676 | | int bits; |
677 | | bool safe = false; |
678 | | const BignumPointer& add; |
679 | | const BignumPointer& rem; |
680 | | }; |
681 | | |
682 | | static BignumPointer NewPrime( |
683 | | const PrimeConfig& params, |
684 | | PrimeCheckCallback cb = defaultPrimeCheckCallback); |
685 | | |
686 | | bool generate(const PrimeConfig& params, |
687 | | PrimeCheckCallback cb = defaultPrimeCheckCallback) const; |
688 | | |
689 | | static BignumPointer New(); |
690 | | static BignumPointer NewSecure(); |
691 | | static BignumPointer NewSub(const BignumPointer& a, const BignumPointer& b); |
692 | | static BignumPointer NewLShift(size_t length); |
693 | | |
694 | | static DataPointer Encode(const BIGNUM* bn); |
695 | | static DataPointer EncodePadded(const BIGNUM* bn, size_t size); |
696 | | static size_t EncodePaddedInto(const BIGNUM* bn, |
697 | | unsigned char* out, |
698 | | size_t size); |
699 | | static int GetBitCount(const BIGNUM* bn); |
700 | | static int GetByteCount(const BIGNUM* bn); |
701 | | static unsigned long GetWord(const BIGNUM* bn); // NOLINT(runtime/int) |
702 | | static const BIGNUM* One(); |
703 | | |
704 | | BignumPointer clone(); |
705 | | |
706 | | private: |
707 | | DeleteFnPtr<BIGNUM, BN_clear_free> bn_; |
708 | | |
709 | 0 | static bool defaultPrimeCheckCallback(int, int) { return 1; } |
710 | | }; |
711 | | |
712 | | class CipherCtxPointer final { |
713 | | public: |
714 | | static CipherCtxPointer New(); |
715 | | |
716 | | CipherCtxPointer() = default; |
717 | | explicit CipherCtxPointer(EVP_CIPHER_CTX* ctx); |
718 | | CipherCtxPointer(CipherCtxPointer&& other) noexcept; |
719 | | CipherCtxPointer& operator=(CipherCtxPointer&& other) noexcept; |
720 | | NCRYPTO_DISALLOW_COPY(CipherCtxPointer) |
721 | | ~CipherCtxPointer(); |
722 | | |
723 | 0 | inline bool operator==(std::nullptr_t) const noexcept { |
724 | 0 | return ctx_ == nullptr; |
725 | 0 | } |
726 | 0 | inline operator bool() const { return ctx_ != nullptr; } |
727 | 0 | inline EVP_CIPHER_CTX* get() const { return ctx_.get(); } |
728 | 0 | inline operator EVP_CIPHER_CTX*() const { return ctx_.get(); } |
729 | | void reset(EVP_CIPHER_CTX* ctx = nullptr); |
730 | | EVP_CIPHER_CTX* release(); |
731 | | |
732 | | void setAllowWrap(); |
733 | | |
734 | | bool setKeyLength(size_t length); |
735 | | bool setIvLength(size_t length); |
736 | | bool setAeadTag(const Buffer<const char>& tag); |
737 | | bool setAeadTagLength(size_t length); |
738 | | bool setPadding(bool padding); |
739 | | bool init(const Cipher& cipher, |
740 | | bool encrypt, |
741 | | const unsigned char* key = nullptr, |
742 | | const unsigned char* iv = nullptr); |
743 | | |
744 | | int getBlockSize() const; |
745 | | int getMode() const; |
746 | | int getNid() const; |
747 | | |
748 | | bool isGcmMode() const; |
749 | | bool isOcbMode() const; |
750 | | bool isCcmMode() const; |
751 | | bool isWrapMode() const; |
752 | | bool isChaCha20Poly1305() const; |
753 | | |
754 | | bool update(const Buffer<const unsigned char>& in, |
755 | | unsigned char* out, |
756 | | int* out_len, |
757 | | bool finalize = false); |
758 | | bool getAeadTag(size_t len, unsigned char* out); |
759 | | |
760 | | private: |
761 | | DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> ctx_; |
762 | | }; |
763 | | |
764 | | class EVPKeyCtxPointer final { |
765 | | public: |
766 | | EVPKeyCtxPointer(); |
767 | | explicit EVPKeyCtxPointer(EVP_PKEY_CTX* ctx); |
768 | | EVPKeyCtxPointer(EVPKeyCtxPointer&& other) noexcept; |
769 | | EVPKeyCtxPointer& operator=(EVPKeyCtxPointer&& other) noexcept; |
770 | | NCRYPTO_DISALLOW_COPY(EVPKeyCtxPointer) |
771 | | ~EVPKeyCtxPointer(); |
772 | | |
773 | 0 | inline bool operator==(std::nullptr_t) const noexcept { |
774 | 0 | return ctx_ == nullptr; |
775 | 0 | } |
776 | 0 | inline operator bool() const { return ctx_ != nullptr; } |
777 | 0 | inline EVP_PKEY_CTX* get() const { return ctx_.get(); } |
778 | | void reset(EVP_PKEY_CTX* ctx = nullptr); |
779 | | EVP_PKEY_CTX* release(); |
780 | | |
781 | | bool initForDerive(const EVPKeyPointer& peer); |
782 | | DataPointer derive() const; |
783 | | |
784 | | bool initForParamgen(); |
785 | | bool setDhParameters(int prime_size, uint32_t generator); |
786 | | bool setDsaParameters(uint32_t bits, std::optional<int> q_bits); |
787 | | bool setEcParameters(int curve, int encoding); |
788 | | |
789 | | bool setRsaOaepMd(const Digest& md); |
790 | | bool setRsaMgf1Md(const Digest& md); |
791 | | bool setRsaPadding(int padding); |
792 | | bool setRsaKeygenPubExp(BignumPointer&& e); |
793 | | bool setRsaKeygenBits(int bits); |
794 | | bool setRsaPssKeygenMd(const Digest& md); |
795 | | bool setRsaPssKeygenMgf1Md(const Digest& md); |
796 | | bool setRsaPssSaltlen(int salt_len); |
797 | | bool setRsaImplicitRejection(); |
798 | | bool setRsaOaepLabel(DataPointer&& data); |
799 | | |
800 | | bool setSignatureMd(const EVPMDCtxPointer& md); |
801 | | |
802 | | bool publicCheck() const; |
803 | | bool privateCheck() const; |
804 | | |
805 | | bool verify(const Buffer<const unsigned char>& sig, |
806 | | const Buffer<const unsigned char>& data); |
807 | | DataPointer sign(const Buffer<const unsigned char>& data); |
808 | | bool signInto(const Buffer<const unsigned char>& data, |
809 | | Buffer<unsigned char>* sig); |
810 | | |
811 | | static constexpr int kDefaultRsaExponent = 0x10001; |
812 | | |
813 | | static bool setRsaPadding(EVP_PKEY_CTX* ctx, |
814 | | int padding, |
815 | | std::optional<int> salt_len = std::nullopt); |
816 | | |
817 | | EVPKeyPointer paramgen() const; |
818 | | |
819 | | bool initForEncrypt(); |
820 | | bool initForDecrypt(); |
821 | | bool initForKeygen(); |
822 | | int initForVerify(); |
823 | | int initForSign(); |
824 | | |
825 | | static EVPKeyCtxPointer New(const EVPKeyPointer& key); |
826 | | static EVPKeyCtxPointer NewFromID(int id); |
827 | | |
828 | | private: |
829 | | DeleteFnPtr<EVP_PKEY_CTX, EVP_PKEY_CTX_free> ctx_; |
830 | | }; |
831 | | |
832 | | class EVPKeyPointer final { |
833 | | public: |
834 | | static EVPKeyPointer New(); |
835 | | static EVPKeyPointer NewRawPublic(int id, |
836 | | const Buffer<const unsigned char>& data); |
837 | | static EVPKeyPointer NewRawPrivate(int id, |
838 | | const Buffer<const unsigned char>& data); |
839 | | #if OPENSSL_WITH_PQC |
840 | | static EVPKeyPointer NewRawSeed(int id, |
841 | | const Buffer<const unsigned char>& data); |
842 | | #endif |
843 | | static EVPKeyPointer NewDH(DHPointer&& dh); |
844 | | static EVPKeyPointer NewRSA(RSAPointer&& rsa); |
845 | | |
846 | | enum class PKEncodingType { |
847 | | // RSAPublicKey / RSAPrivateKey according to PKCS#1. |
848 | | PKCS1, |
849 | | // PrivateKeyInfo or EncryptedPrivateKeyInfo according to PKCS#8. |
850 | | PKCS8, |
851 | | // SubjectPublicKeyInfo according to X.509. |
852 | | SPKI, |
853 | | // ECPrivateKey according to SEC1. |
854 | | SEC1, |
855 | | }; |
856 | | |
857 | | enum class PKFormatType { |
858 | | DER, |
859 | | PEM, |
860 | | JWK, |
861 | | }; |
862 | | |
863 | | enum class PKParseError { NOT_RECOGNIZED, NEED_PASSPHRASE, FAILED }; |
864 | | using ParseKeyResult = Result<EVPKeyPointer, PKParseError>; |
865 | | |
866 | | struct AsymmetricKeyEncodingConfig { |
867 | | bool output_key_object = false; |
868 | | PKFormatType format = PKFormatType::DER; |
869 | | PKEncodingType type = PKEncodingType::PKCS8; |
870 | 0 | AsymmetricKeyEncodingConfig() = default; |
871 | | AsymmetricKeyEncodingConfig(bool output_key_object, |
872 | | PKFormatType format, |
873 | | PKEncodingType type); |
874 | | AsymmetricKeyEncodingConfig(const AsymmetricKeyEncodingConfig&) = default; |
875 | | AsymmetricKeyEncodingConfig& operator=(const AsymmetricKeyEncodingConfig&) = |
876 | | default; |
877 | | }; |
878 | | using PublicKeyEncodingConfig = AsymmetricKeyEncodingConfig; |
879 | | |
880 | | struct PrivateKeyEncodingConfig : public AsymmetricKeyEncodingConfig { |
881 | | const EVP_CIPHER* cipher = nullptr; |
882 | | std::optional<DataPointer> passphrase = std::nullopt; |
883 | 0 | PrivateKeyEncodingConfig() = default; |
884 | | PrivateKeyEncodingConfig(bool output_key_object, |
885 | | PKFormatType format, |
886 | | PKEncodingType type) |
887 | 0 | : AsymmetricKeyEncodingConfig(output_key_object, format, type) {} |
888 | | PrivateKeyEncodingConfig(const PrivateKeyEncodingConfig&); |
889 | | PrivateKeyEncodingConfig& operator=(const PrivateKeyEncodingConfig&); |
890 | | }; |
891 | | |
892 | | static ParseKeyResult TryParsePublicKey( |
893 | | const PublicKeyEncodingConfig& config, |
894 | | const Buffer<const unsigned char>& buffer); |
895 | | |
896 | | static ParseKeyResult TryParsePublicKeyPEM( |
897 | | const Buffer<const unsigned char>& buffer); |
898 | | |
899 | | static ParseKeyResult TryParsePrivateKey( |
900 | | const PrivateKeyEncodingConfig& config, |
901 | | const Buffer<const unsigned char>& buffer); |
902 | | |
903 | 0 | EVPKeyPointer() = default; |
904 | | explicit EVPKeyPointer(EVP_PKEY* pkey); |
905 | | EVPKeyPointer(EVPKeyPointer&& other) noexcept; |
906 | | EVPKeyPointer& operator=(EVPKeyPointer&& other) noexcept; |
907 | | NCRYPTO_DISALLOW_COPY(EVPKeyPointer) |
908 | | ~EVPKeyPointer(); |
909 | | |
910 | | bool assign(const ECKeyPointer& eckey); |
911 | | bool set(const ECKeyPointer& eckey); |
912 | | operator const EC_KEY*() const; |
913 | | |
914 | 0 | inline bool operator==(std::nullptr_t) const noexcept { |
915 | 0 | return pkey_ == nullptr; |
916 | 0 | } |
917 | 0 | inline operator bool() const { return pkey_ != nullptr; } |
918 | 0 | inline EVP_PKEY* get() const { return pkey_.get(); } |
919 | | void reset(EVP_PKEY* pkey = nullptr); |
920 | | EVP_PKEY* release(); |
921 | | |
922 | | static int id(const EVP_PKEY* key); |
923 | | static int base_id(const EVP_PKEY* key); |
924 | | |
925 | | int id() const; |
926 | | int base_id() const; |
927 | | int bits() const; |
928 | | size_t size() const; |
929 | | |
930 | | size_t rawPublicKeySize() const; |
931 | | size_t rawPrivateKeySize() const; |
932 | | DataPointer rawPublicKey() const; |
933 | | DataPointer rawPrivateKey() const; |
934 | | BIOPointer derPublicKey() const; |
935 | | |
936 | | #if OPENSSL_WITH_PQC |
937 | | DataPointer rawSeed() const; |
938 | | #endif |
939 | | |
940 | | Result<BIOPointer, bool> writePrivateKey( |
941 | | const PrivateKeyEncodingConfig& config) const; |
942 | | Result<BIOPointer, bool> writePublicKey( |
943 | | const PublicKeyEncodingConfig& config) const; |
944 | | |
945 | | EVPKeyCtxPointer newCtx() const; |
946 | | |
947 | | static bool IsRSAPrivateKey(const Buffer<const unsigned char>& buffer); |
948 | | |
949 | | std::optional<uint32_t> getBytesOfRS() const; |
950 | | int getDefaultSignPadding() const; |
951 | | operator Rsa() const; |
952 | | operator Dsa() const; |
953 | | |
954 | | bool isRsaVariant() const; |
955 | | bool isOneShotVariant() const; |
956 | | bool isSigVariant() const; |
957 | | bool validateDsaParameters() const; |
958 | | |
959 | | private: |
960 | | DeleteFnPtr<EVP_PKEY, EVP_PKEY_free> pkey_; |
961 | | }; |
962 | | |
963 | | class DHPointer final { |
964 | | public: |
965 | | enum class FindGroupOption { |
966 | | NONE, |
967 | | // There are known and documented security issues with prime groups smaller |
968 | | // than 2048 bits. When the NO_SMALL_PRIMES option is set, these small prime |
969 | | // groups will not be supported. |
970 | | NO_SMALL_PRIMES, |
971 | | }; |
972 | | |
973 | | static BignumPointer GetStandardGenerator(); |
974 | | |
975 | | static BignumPointer FindGroup( |
976 | | std::string_view name, FindGroupOption option = FindGroupOption::NONE); |
977 | | static DHPointer FromGroup(std::string_view name, |
978 | | FindGroupOption option = FindGroupOption::NONE); |
979 | | |
980 | | static DHPointer New(BignumPointer&& p, BignumPointer&& g); |
981 | | static DHPointer New(size_t bits, unsigned int generator); |
982 | | |
983 | 0 | DHPointer() = default; |
984 | | explicit DHPointer(DH* dh); |
985 | | DHPointer(DHPointer&& other) noexcept; |
986 | | DHPointer& operator=(DHPointer&& other) noexcept; |
987 | | NCRYPTO_DISALLOW_COPY(DHPointer) |
988 | | ~DHPointer(); |
989 | | |
990 | 0 | inline bool operator==(std::nullptr_t) noexcept { return dh_ == nullptr; } |
991 | 0 | inline operator bool() const { return dh_ != nullptr; } |
992 | 0 | inline DH* get() const { return dh_.get(); } |
993 | | void reset(DH* dh = nullptr); |
994 | | DH* release(); |
995 | | |
996 | | enum class CheckResult { |
997 | | NONE, |
998 | | P_NOT_PRIME = DH_CHECK_P_NOT_PRIME, |
999 | | P_NOT_SAFE_PRIME = DH_CHECK_P_NOT_SAFE_PRIME, |
1000 | | UNABLE_TO_CHECK_GENERATOR = DH_UNABLE_TO_CHECK_GENERATOR, |
1001 | | NOT_SUITABLE_GENERATOR = DH_NOT_SUITABLE_GENERATOR, |
1002 | | Q_NOT_PRIME = DH_CHECK_Q_NOT_PRIME, |
1003 | | #ifndef OPENSSL_IS_BORINGSSL |
1004 | | // Boringssl does not define the DH_CHECK_INVALID_[Q or J]_VALUE |
1005 | | INVALID_Q = DH_CHECK_INVALID_Q_VALUE, |
1006 | | INVALID_J = DH_CHECK_INVALID_J_VALUE, |
1007 | | #endif |
1008 | | CHECK_FAILED = 512, |
1009 | | }; |
1010 | | CheckResult check(); |
1011 | | |
1012 | | enum class CheckPublicKeyResult { |
1013 | | NONE, |
1014 | | #ifndef OPENSSL_IS_BORINGSSL |
1015 | | // Boringssl does not define DH_R_CHECK_PUBKEY_TOO_SMALL or TOO_LARGE |
1016 | | TOO_SMALL = DH_R_CHECK_PUBKEY_TOO_SMALL, |
1017 | | TOO_LARGE = DH_R_CHECK_PUBKEY_TOO_LARGE, |
1018 | | INVALID = DH_R_CHECK_PUBKEY_INVALID, |
1019 | | #else |
1020 | | INVALID = DH_R_INVALID_PUBKEY, |
1021 | | #endif |
1022 | | CHECK_FAILED = 512, |
1023 | | }; |
1024 | | // Check to see if the given public key is suitable for this DH instance. |
1025 | | CheckPublicKeyResult checkPublicKey(const BignumPointer& pub_key); |
1026 | | |
1027 | | DataPointer getPrime() const; |
1028 | | DataPointer getGenerator() const; |
1029 | | DataPointer getPublicKey() const; |
1030 | | DataPointer getPrivateKey() const; |
1031 | | DataPointer generateKeys() const; |
1032 | | DataPointer computeSecret(const BignumPointer& peer) const; |
1033 | | |
1034 | | bool setPublicKey(BignumPointer&& key); |
1035 | | bool setPrivateKey(BignumPointer&& key); |
1036 | | |
1037 | | size_t size() const; |
1038 | | |
1039 | | static DataPointer stateless(const EVPKeyPointer& ourKey, |
1040 | | const EVPKeyPointer& theirKey); |
1041 | | |
1042 | | private: |
1043 | | DeleteFnPtr<DH, DH_free> dh_; |
1044 | | }; |
1045 | | |
1046 | | struct StackOfX509Deleter { |
1047 | 0 | void operator()(STACK_OF(X509) * p) const { sk_X509_pop_free(p, X509_free); } |
1048 | | }; |
1049 | | using StackOfX509 = std::unique_ptr<STACK_OF(X509), StackOfX509Deleter>; |
1050 | | |
1051 | | class SSLCtxPointer final { |
1052 | | public: |
1053 | 0 | SSLCtxPointer() = default; |
1054 | | explicit SSLCtxPointer(SSL_CTX* ctx); |
1055 | | SSLCtxPointer(SSLCtxPointer&& other) noexcept; |
1056 | | SSLCtxPointer& operator=(SSLCtxPointer&& other) noexcept; |
1057 | | NCRYPTO_DISALLOW_COPY(SSLCtxPointer) |
1058 | | ~SSLCtxPointer(); |
1059 | | |
1060 | 0 | inline bool operator==(std::nullptr_t) const noexcept { |
1061 | 0 | return ctx_ == nullptr; |
1062 | 0 | } |
1063 | 0 | inline operator bool() const { return ctx_ != nullptr; } |
1064 | 0 | inline SSL_CTX* get() const { return ctx_.get(); } |
1065 | | void reset(SSL_CTX* ctx = nullptr); |
1066 | | void reset(const SSL_METHOD* method); |
1067 | | SSL_CTX* release(); |
1068 | | |
1069 | | bool setGroups(const char* groups); |
1070 | 0 | void setStatusCallback(auto callback) { |
1071 | 0 | if (!ctx_) return; |
1072 | 0 | SSL_CTX_set_tlsext_status_cb(get(), callback); |
1073 | 0 | SSL_CTX_set_tlsext_status_arg(get(), nullptr); |
1074 | 0 | } |
1075 | | |
1076 | | bool setCipherSuites(const char* ciphers); |
1077 | | |
1078 | | static SSLCtxPointer NewServer(); |
1079 | | static SSLCtxPointer NewClient(); |
1080 | | static SSLCtxPointer New(const SSL_METHOD* method = TLS_method()); |
1081 | | |
1082 | | private: |
1083 | | DeleteFnPtr<SSL_CTX, SSL_CTX_free> ctx_; |
1084 | | }; |
1085 | | |
1086 | | class SSLPointer final { |
1087 | | public: |
1088 | 0 | SSLPointer() = default; |
1089 | | explicit SSLPointer(SSL* ssl); |
1090 | | SSLPointer(SSLPointer&& other) noexcept; |
1091 | | SSLPointer& operator=(SSLPointer&& other) noexcept; |
1092 | | NCRYPTO_DISALLOW_COPY(SSLPointer) |
1093 | | ~SSLPointer(); |
1094 | | |
1095 | 0 | inline bool operator==(std::nullptr_t) noexcept { return ssl_ == nullptr; } |
1096 | 0 | inline operator bool() const { return ssl_ != nullptr; } |
1097 | 0 | inline SSL* get() const { return ssl_.get(); } |
1098 | 0 | inline operator SSL*() const { return ssl_.get(); } |
1099 | | void reset(SSL* ssl = nullptr); |
1100 | | SSL* release(); |
1101 | | |
1102 | | bool setSession(const SSLSessionPointer& session); |
1103 | | bool setSniContext(const SSLCtxPointer& ctx) const; |
1104 | | |
1105 | | const char* getClientHelloAlpn() const; |
1106 | | const char* getClientHelloServerName() const; |
1107 | | |
1108 | | std::optional<const std::string_view> getServerName() const; |
1109 | | X509View getCertificate() const; |
1110 | | EVPKeyPointer getPeerTempKey() const; |
1111 | | const SSL_CIPHER* getCipher() const; |
1112 | | bool isServer() const; |
1113 | | |
1114 | | std::optional<std::string_view> getCipherName() const; |
1115 | | std::optional<std::string_view> getCipherStandardName() const; |
1116 | | std::optional<std::string_view> getCipherVersion() const; |
1117 | | |
1118 | | std::optional<uint32_t> verifyPeerCertificate() const; |
1119 | | |
1120 | | static std::optional<int> getSecurityLevel(); |
1121 | | |
1122 | | void getCiphers(std::function<void(const char*)> cb) const; |
1123 | | |
1124 | | static SSLPointer New(const SSLCtxPointer& ctx); |
1125 | | static std::optional<const std::string_view> GetServerName(const SSL* ssl); |
1126 | | |
1127 | | private: |
1128 | | DeleteFnPtr<SSL, SSL_free> ssl_; |
1129 | | }; |
1130 | | |
1131 | | class X509Name final { |
1132 | | public: |
1133 | | X509Name(); |
1134 | | explicit X509Name(const X509_NAME* name); |
1135 | | NCRYPTO_DISALLOW_COPY_AND_MOVE(X509Name) |
1136 | | |
1137 | 0 | inline operator const X509_NAME*() const { return name_; } |
1138 | 0 | inline operator bool() const { return name_ != nullptr; } |
1139 | 0 | inline const X509_NAME* get() const { return name_; } |
1140 | 0 | inline size_t size() const { return total_; } |
1141 | | |
1142 | | class Iterator final { |
1143 | | public: |
1144 | | Iterator(const X509Name& name, int pos); |
1145 | | Iterator(const Iterator& other) = default; |
1146 | | Iterator(Iterator&& other) = default; |
1147 | | Iterator& operator=(const Iterator& other) = delete; |
1148 | | Iterator& operator=(Iterator&& other) = delete; |
1149 | | Iterator& operator++(); |
1150 | | operator bool() const; |
1151 | | bool operator==(const Iterator& other) const; |
1152 | | bool operator!=(const Iterator& other) const; |
1153 | | std::pair<std::string, std::string> operator*() const; |
1154 | | |
1155 | | private: |
1156 | | const X509Name& name_; |
1157 | | int loc_; |
1158 | | }; |
1159 | | |
1160 | 0 | inline Iterator begin() const { return Iterator(*this, 0); } |
1161 | 0 | inline Iterator end() const { return Iterator(*this, total_); } |
1162 | | |
1163 | | private: |
1164 | | const X509_NAME* name_; |
1165 | | int total_; |
1166 | | }; |
1167 | | |
1168 | | class X509View final { |
1169 | | public: |
1170 | | static X509View From(const SSLPointer& ssl); |
1171 | | static X509View From(const SSLCtxPointer& ctx); |
1172 | | |
1173 | | X509View() = default; |
1174 | 0 | inline explicit X509View(const X509* cert) : cert_(cert) {} |
1175 | | X509View(const X509View& other) = default; |
1176 | | X509View& operator=(const X509View& other) = default; |
1177 | | NCRYPTO_DISALLOW_MOVE(X509View) |
1178 | | |
1179 | 0 | inline X509* get() const { return const_cast<X509*>(cert_); } |
1180 | 0 | inline operator X509*() const { return const_cast<X509*>(cert_); } |
1181 | 0 | inline operator const X509*() const { return cert_; } |
1182 | | |
1183 | 0 | inline bool operator==(std::nullptr_t) noexcept { return cert_ == nullptr; } |
1184 | 0 | inline operator bool() const { return cert_ != nullptr; } |
1185 | | |
1186 | | BIOPointer toPEM() const; |
1187 | | BIOPointer toDER() const; |
1188 | | |
1189 | | const X509Name getSubjectName() const; |
1190 | | const X509Name getIssuerName() const; |
1191 | | BIOPointer getSubject() const; |
1192 | | BIOPointer getSubjectAltName() const; |
1193 | | BIOPointer getIssuer() const; |
1194 | | BIOPointer getInfoAccess() const; |
1195 | | BIOPointer getValidFrom() const; |
1196 | | BIOPointer getValidTo() const; |
1197 | | std::optional<std::string_view> getSignatureAlgorithm() const; |
1198 | | std::optional<std::string> getSignatureAlgorithmOID() const; |
1199 | | int64_t getValidFromTime() const; |
1200 | | int64_t getValidToTime() const; |
1201 | | DataPointer getSerialNumber() const; |
1202 | | Result<EVPKeyPointer, int> getPublicKey() const; |
1203 | | StackOfASN1 getKeyUsage() const; |
1204 | | |
1205 | | bool isCA() const; |
1206 | | bool isIssuedBy(const X509View& other) const; |
1207 | | bool checkPrivateKey(const EVPKeyPointer& pkey) const; |
1208 | | bool checkPublicKey(const EVPKeyPointer& pkey) const; |
1209 | | |
1210 | | std::optional<std::string> getFingerprint(const Digest& method) const; |
1211 | | |
1212 | | X509Pointer clone() const; |
1213 | | |
1214 | | enum class CheckMatch { |
1215 | | NO_MATCH, |
1216 | | MATCH, |
1217 | | INVALID_NAME, |
1218 | | OPERATION_FAILED, |
1219 | | }; |
1220 | | CheckMatch checkHost(std::string_view host, |
1221 | | int flags, |
1222 | | DataPointer* peerName = nullptr) const; |
1223 | | CheckMatch checkEmail(std::string_view email, int flags) const; |
1224 | | CheckMatch checkIp(std::string_view ip, int flags) const; |
1225 | | |
1226 | | using UsageCallback = std::function<void(const char*)>; |
1227 | | bool enumUsages(UsageCallback callback) const; |
1228 | | |
1229 | | template <typename T> |
1230 | | using KeyCallback = std::function<bool(const T& t)>; |
1231 | | bool ifRsa(KeyCallback<Rsa> callback) const; |
1232 | | bool ifEc(KeyCallback<Ec> callback) const; |
1233 | | |
1234 | | private: |
1235 | | const X509* cert_ = nullptr; |
1236 | | }; |
1237 | | |
1238 | | class X509Pointer final { |
1239 | | public: |
1240 | | static Result<X509Pointer, int> Parse(Buffer<const unsigned char> buffer); |
1241 | | static X509Pointer IssuerFrom(const SSLPointer& ssl, const X509View& view); |
1242 | | static X509Pointer IssuerFrom(const SSL_CTX* ctx, const X509View& view); |
1243 | | static X509Pointer PeerFrom(const SSLPointer& ssl); |
1244 | | |
1245 | 0 | X509Pointer() = default; |
1246 | | explicit X509Pointer(X509* cert); |
1247 | | X509Pointer(X509Pointer&& other) noexcept; |
1248 | | X509Pointer& operator=(X509Pointer&& other) noexcept; |
1249 | | NCRYPTO_DISALLOW_COPY(X509Pointer) |
1250 | | ~X509Pointer(); |
1251 | | |
1252 | 0 | inline bool operator==(std::nullptr_t) noexcept { return cert_ == nullptr; } |
1253 | 0 | inline operator bool() const { return cert_ != nullptr; } |
1254 | 0 | inline X509* get() const { return cert_.get(); } |
1255 | 0 | inline operator X509*() const { return cert_.get(); } |
1256 | 0 | inline operator const X509*() const { return cert_.get(); } |
1257 | | void reset(X509* cert = nullptr); |
1258 | | X509* release(); |
1259 | | |
1260 | | X509View view() const; |
1261 | 0 | operator X509View() const { return view(); } |
1262 | | |
1263 | | static const char* ErrorCode(int32_t err); |
1264 | | static std::optional<const char*> ErrorReason(int32_t err); |
1265 | | |
1266 | | private: |
1267 | | DeleteFnPtr<X509, X509_free> cert_; |
1268 | | }; |
1269 | | |
1270 | | class ECDSASigPointer final { |
1271 | | public: |
1272 | | explicit ECDSASigPointer(); |
1273 | | explicit ECDSASigPointer(ECDSA_SIG* sig); |
1274 | | ECDSASigPointer(ECDSASigPointer&& other) noexcept; |
1275 | | ECDSASigPointer& operator=(ECDSASigPointer&& other) noexcept; |
1276 | | NCRYPTO_DISALLOW_COPY(ECDSASigPointer) |
1277 | | ~ECDSASigPointer(); |
1278 | | |
1279 | 0 | inline bool operator==(std::nullptr_t) noexcept { return sig_ == nullptr; } |
1280 | 0 | inline operator bool() const { return sig_ != nullptr; } |
1281 | 0 | inline ECDSA_SIG* get() const { return sig_.get(); } |
1282 | 0 | inline operator ECDSA_SIG*() const { return sig_.get(); } |
1283 | | void reset(ECDSA_SIG* sig = nullptr); |
1284 | | ECDSA_SIG* release(); |
1285 | | |
1286 | | static ECDSASigPointer New(); |
1287 | | static ECDSASigPointer Parse(const Buffer<const unsigned char>& buffer); |
1288 | | |
1289 | 0 | inline const BIGNUM* r() const { return pr_; } |
1290 | 0 | inline const BIGNUM* s() const { return ps_; } |
1291 | | |
1292 | | bool setParams(BignumPointer&& r, BignumPointer&& s); |
1293 | | |
1294 | | Buffer<unsigned char> encode() const; |
1295 | | |
1296 | | private: |
1297 | | DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free> sig_; |
1298 | | const BIGNUM* pr_ = nullptr; |
1299 | | const BIGNUM* ps_ = nullptr; |
1300 | | }; |
1301 | | |
1302 | | class ECGroupPointer final { |
1303 | | public: |
1304 | | explicit ECGroupPointer(); |
1305 | | explicit ECGroupPointer(EC_GROUP* group); |
1306 | | ECGroupPointer(ECGroupPointer&& other) noexcept; |
1307 | | ECGroupPointer& operator=(ECGroupPointer&& other) noexcept; |
1308 | | NCRYPTO_DISALLOW_COPY(ECGroupPointer) |
1309 | | ~ECGroupPointer(); |
1310 | | |
1311 | 0 | inline bool operator==(std::nullptr_t) noexcept { return group_ == nullptr; } |
1312 | 0 | inline operator bool() const { return group_ != nullptr; } |
1313 | 0 | inline EC_GROUP* get() const { return group_.get(); } |
1314 | 0 | inline operator EC_GROUP*() const { return group_.get(); } |
1315 | | void reset(EC_GROUP* group = nullptr); |
1316 | | EC_GROUP* release(); |
1317 | | |
1318 | | static ECGroupPointer NewByCurveName(int nid); |
1319 | | |
1320 | | private: |
1321 | | DeleteFnPtr<EC_GROUP, EC_GROUP_free> group_; |
1322 | | }; |
1323 | | |
1324 | | class ECPointPointer final { |
1325 | | public: |
1326 | | ECPointPointer(); |
1327 | | explicit ECPointPointer(EC_POINT* point); |
1328 | | ECPointPointer(ECPointPointer&& other) noexcept; |
1329 | | ECPointPointer& operator=(ECPointPointer&& other) noexcept; |
1330 | | NCRYPTO_DISALLOW_COPY(ECPointPointer) |
1331 | | ~ECPointPointer(); |
1332 | | |
1333 | 0 | inline bool operator==(std::nullptr_t) noexcept { return point_ == nullptr; } |
1334 | 0 | inline operator bool() const { return point_ != nullptr; } |
1335 | 0 | inline EC_POINT* get() const { return point_.get(); } |
1336 | 0 | inline operator EC_POINT*() const { return point_.get(); } |
1337 | | void reset(EC_POINT* point = nullptr); |
1338 | | EC_POINT* release(); |
1339 | | |
1340 | | bool setFromBuffer(const Buffer<const unsigned char>& buffer, |
1341 | | const EC_GROUP* group); |
1342 | | bool mul(const EC_GROUP* group, const BIGNUM* priv_key); |
1343 | | |
1344 | | static ECPointPointer New(const EC_GROUP* group); |
1345 | | |
1346 | | private: |
1347 | | DeleteFnPtr<EC_POINT, EC_POINT_free> point_; |
1348 | | }; |
1349 | | |
1350 | | class ECKeyPointer final { |
1351 | | public: |
1352 | | ECKeyPointer(); |
1353 | | explicit ECKeyPointer(EC_KEY* key); |
1354 | | ECKeyPointer(ECKeyPointer&& other) noexcept; |
1355 | | ECKeyPointer& operator=(ECKeyPointer&& other) noexcept; |
1356 | | NCRYPTO_DISALLOW_COPY(ECKeyPointer) |
1357 | | ~ECKeyPointer(); |
1358 | | |
1359 | 0 | inline bool operator==(std::nullptr_t) noexcept { return key_ == nullptr; } |
1360 | 0 | inline operator bool() const { return key_ != nullptr; } |
1361 | 0 | inline EC_KEY* get() const { return key_.get(); } |
1362 | 0 | inline operator EC_KEY*() const { return key_.get(); } |
1363 | | void reset(EC_KEY* key = nullptr); |
1364 | | EC_KEY* release(); |
1365 | | |
1366 | | ECKeyPointer clone() const; |
1367 | | bool setPrivateKey(const BignumPointer& priv); |
1368 | | bool setPublicKey(const ECPointPointer& pub); |
1369 | | bool setPublicKeyRaw(const BignumPointer& x, const BignumPointer& y); |
1370 | | bool generate(); |
1371 | | bool checkKey() const; |
1372 | | |
1373 | | const EC_GROUP* getGroup() const; |
1374 | | const BIGNUM* getPrivateKey() const; |
1375 | | const EC_POINT* getPublicKey() const; |
1376 | | |
1377 | | static ECKeyPointer New(const EC_GROUP* group); |
1378 | | static ECKeyPointer NewByCurveName(int nid); |
1379 | | |
1380 | | static const EC_POINT* GetPublicKey(const EC_KEY* key); |
1381 | | static const BIGNUM* GetPrivateKey(const EC_KEY* key); |
1382 | | static const EC_GROUP* GetGroup(const EC_KEY* key); |
1383 | | static int GetGroupName(const EC_KEY* key); |
1384 | | static bool Check(const EC_KEY* key); |
1385 | | |
1386 | | private: |
1387 | | DeleteFnPtr<EC_KEY, EC_KEY_free> key_; |
1388 | | }; |
1389 | | |
1390 | | class EVPMDCtxPointer final { |
1391 | | public: |
1392 | | EVPMDCtxPointer(); |
1393 | | explicit EVPMDCtxPointer(EVP_MD_CTX* ctx); |
1394 | | EVPMDCtxPointer(EVPMDCtxPointer&& other) noexcept; |
1395 | | EVPMDCtxPointer& operator=(EVPMDCtxPointer&& other) noexcept; |
1396 | | NCRYPTO_DISALLOW_COPY(EVPMDCtxPointer) |
1397 | | ~EVPMDCtxPointer(); |
1398 | | |
1399 | 0 | inline bool operator==(std::nullptr_t) noexcept { return ctx_ == nullptr; } |
1400 | 0 | inline operator bool() const { return ctx_ != nullptr; } |
1401 | 0 | inline EVP_MD_CTX* get() const { return ctx_.get(); } |
1402 | 0 | inline operator EVP_MD_CTX*() const { return ctx_.get(); } |
1403 | | void reset(EVP_MD_CTX* ctx = nullptr); |
1404 | | EVP_MD_CTX* release(); |
1405 | | |
1406 | | bool digestInit(const Digest& digest); |
1407 | | bool digestUpdate(const Buffer<const void>& in); |
1408 | | DataPointer digestFinal(size_t length); |
1409 | | bool digestFinalInto(Buffer<void>* buf); |
1410 | | size_t getExpectedSize(); |
1411 | | |
1412 | | std::optional<EVP_PKEY_CTX*> signInit(const EVPKeyPointer& key, |
1413 | | const Digest& digest); |
1414 | | std::optional<EVP_PKEY_CTX*> verifyInit(const EVPKeyPointer& key, |
1415 | | const Digest& digest); |
1416 | | |
1417 | | std::optional<EVP_PKEY_CTX*> signInitWithContext( |
1418 | | const EVPKeyPointer& key, |
1419 | | const Digest& digest, |
1420 | | const Buffer<const unsigned char>& context_string); |
1421 | | std::optional<EVP_PKEY_CTX*> verifyInitWithContext( |
1422 | | const EVPKeyPointer& key, |
1423 | | const Digest& digest, |
1424 | | const Buffer<const unsigned char>& context_string); |
1425 | | |
1426 | | DataPointer signOneShot(const Buffer<const unsigned char>& buf) const; |
1427 | | DataPointer sign(const Buffer<const unsigned char>& buf) const; |
1428 | | bool verify(const Buffer<const unsigned char>& buf, |
1429 | | const Buffer<const unsigned char>& sig) const; |
1430 | | |
1431 | | const EVP_MD* getDigest() const; |
1432 | | size_t getDigestSize() const; |
1433 | | bool hasXofFlag() const; |
1434 | | |
1435 | | bool copyTo(const EVPMDCtxPointer& other) const; |
1436 | | |
1437 | | static EVPMDCtxPointer New(); |
1438 | | |
1439 | | private: |
1440 | | DeleteFnPtr<EVP_MD_CTX, EVP_MD_CTX_free> ctx_; |
1441 | | }; |
1442 | | |
1443 | | class HMACCtxPointer final { |
1444 | | public: |
1445 | | HMACCtxPointer(); |
1446 | | explicit HMACCtxPointer(HMAC_CTX* ctx); |
1447 | | HMACCtxPointer(HMACCtxPointer&& other) noexcept; |
1448 | | HMACCtxPointer& operator=(HMACCtxPointer&& other) noexcept; |
1449 | | NCRYPTO_DISALLOW_COPY(HMACCtxPointer) |
1450 | | ~HMACCtxPointer(); |
1451 | | |
1452 | 0 | inline bool operator==(std::nullptr_t) noexcept { return ctx_ == nullptr; } |
1453 | 0 | inline operator bool() const { return ctx_ != nullptr; } |
1454 | 0 | inline HMAC_CTX* get() const { return ctx_.get(); } |
1455 | 0 | inline operator HMAC_CTX*() const { return ctx_.get(); } |
1456 | | void reset(HMAC_CTX* ctx = nullptr); |
1457 | | HMAC_CTX* release(); |
1458 | | |
1459 | | bool init(const Buffer<const void>& buf, const Digest& md); |
1460 | | bool update(const Buffer<const void>& buf); |
1461 | | DataPointer digest(); |
1462 | | bool digestInto(Buffer<void>* buf); |
1463 | | |
1464 | | static HMACCtxPointer New(); |
1465 | | |
1466 | | private: |
1467 | | DeleteFnPtr<HMAC_CTX, HMAC_CTX_free> ctx_; |
1468 | | }; |
1469 | | |
1470 | | #if OPENSSL_VERSION_MAJOR >= 3 |
1471 | | class EVPMacPointer final { |
1472 | | public: |
1473 | | EVPMacPointer() = default; |
1474 | | explicit EVPMacPointer(EVP_MAC* mac); |
1475 | | EVPMacPointer(EVPMacPointer&& other) noexcept; |
1476 | | EVPMacPointer& operator=(EVPMacPointer&& other) noexcept; |
1477 | | NCRYPTO_DISALLOW_COPY(EVPMacPointer) |
1478 | | ~EVPMacPointer(); |
1479 | | |
1480 | 0 | inline bool operator==(std::nullptr_t) noexcept { return mac_ == nullptr; } |
1481 | 0 | inline operator bool() const { return mac_ != nullptr; } |
1482 | 0 | inline EVP_MAC* get() const { return mac_.get(); } |
1483 | 0 | inline operator EVP_MAC*() const { return mac_.get(); } |
1484 | | void reset(EVP_MAC* mac = nullptr); |
1485 | | EVP_MAC* release(); |
1486 | | |
1487 | | static EVPMacPointer Fetch(const char* algorithm); |
1488 | | |
1489 | | private: |
1490 | | DeleteFnPtr<EVP_MAC, EVP_MAC_free> mac_; |
1491 | | }; |
1492 | | |
1493 | | class EVPMacCtxPointer final { |
1494 | | public: |
1495 | | EVPMacCtxPointer() = default; |
1496 | | explicit EVPMacCtxPointer(EVP_MAC_CTX* ctx); |
1497 | | EVPMacCtxPointer(EVPMacCtxPointer&& other) noexcept; |
1498 | | EVPMacCtxPointer& operator=(EVPMacCtxPointer&& other) noexcept; |
1499 | | NCRYPTO_DISALLOW_COPY(EVPMacCtxPointer) |
1500 | | ~EVPMacCtxPointer(); |
1501 | | |
1502 | 0 | inline bool operator==(std::nullptr_t) noexcept { return ctx_ == nullptr; } |
1503 | 0 | inline operator bool() const { return ctx_ != nullptr; } |
1504 | 0 | inline EVP_MAC_CTX* get() const { return ctx_.get(); } |
1505 | 0 | inline operator EVP_MAC_CTX*() const { return ctx_.get(); } |
1506 | | void reset(EVP_MAC_CTX* ctx = nullptr); |
1507 | | EVP_MAC_CTX* release(); |
1508 | | |
1509 | | bool init(const Buffer<const void>& key, const OSSL_PARAM* params = nullptr); |
1510 | | bool update(const Buffer<const void>& data); |
1511 | | DataPointer final(size_t length); |
1512 | | |
1513 | | static EVPMacCtxPointer New(EVP_MAC* mac); |
1514 | | |
1515 | | private: |
1516 | | DeleteFnPtr<EVP_MAC_CTX, EVP_MAC_CTX_free> ctx_; |
1517 | | }; |
1518 | | #endif // OPENSSL_VERSION_MAJOR >= 3 |
1519 | | |
1520 | | #ifndef OPENSSL_NO_ENGINE |
1521 | | class EnginePointer final { |
1522 | | public: |
1523 | 0 | EnginePointer() = default; |
1524 | | |
1525 | | explicit EnginePointer(ENGINE* engine_, bool finish_on_exit = false); |
1526 | | EnginePointer(EnginePointer&& other) noexcept; |
1527 | | EnginePointer& operator=(EnginePointer&& other) noexcept; |
1528 | | NCRYPTO_DISALLOW_COPY(EnginePointer) |
1529 | | ~EnginePointer(); |
1530 | | |
1531 | 0 | inline operator bool() const { return engine != nullptr; } |
1532 | 0 | inline ENGINE* get() { return engine; } |
1533 | 0 | inline void setFinishOnExit() { finish_on_exit = true; } |
1534 | | |
1535 | | void reset(ENGINE* engine_ = nullptr, bool finish_on_exit_ = false); |
1536 | | |
1537 | | bool setAsDefault(uint32_t flags, CryptoErrorList* errors = nullptr); |
1538 | | bool init(bool finish_on_exit = false); |
1539 | | EVPKeyPointer loadPrivateKey(const char* key_name); |
1540 | | |
1541 | | // Release ownership of the ENGINE* pointer. |
1542 | | ENGINE* release(); |
1543 | | |
1544 | | // Retrieve an OpenSSL Engine instance by name. If the name does not |
1545 | | // identify a valid named engine, the returned EnginePointer will be |
1546 | | // empty. |
1547 | | static EnginePointer getEngineByName(const char* name, |
1548 | | CryptoErrorList* errors = nullptr); |
1549 | | |
1550 | | // Call once when initializing OpenSSL at startup for the process. |
1551 | | static void initEnginesOnce(); |
1552 | | |
1553 | | private: |
1554 | | ENGINE* engine = nullptr; |
1555 | | bool finish_on_exit = false; |
1556 | | }; |
1557 | | #endif // !OPENSSL_NO_ENGINE |
1558 | | |
1559 | | // ============================================================================ |
1560 | | // FIPS |
1561 | | bool isFipsEnabled(); |
1562 | | |
1563 | | bool setFipsEnabled(bool enabled, CryptoErrorList* errors); |
1564 | | |
1565 | | bool testFipsEnabled(); |
1566 | | |
1567 | | // ============================================================================ |
1568 | | // Various utilities |
1569 | | |
1570 | | bool CSPRNG(void* buffer, size_t length) NCRYPTO_MUST_USE_RESULT; |
1571 | | |
1572 | | // This callback is used to avoid the default passphrase callback in OpenSSL |
1573 | | // which will typically prompt for the passphrase. The prompting is designed |
1574 | | // for the OpenSSL CLI, but works poorly for some environments like Node.js |
1575 | | // because it involves synchronous interaction with the controlling terminal, |
1576 | | // something we never want, and use this function to avoid it. |
1577 | | int NoPasswordCallback(char* buf, int size, int rwflag, void* u); |
1578 | | |
1579 | | int PasswordCallback(char* buf, int size, int rwflag, void* u); |
1580 | | |
1581 | | bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext); |
1582 | | bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext); |
1583 | | |
1584 | | // ============================================================================ |
1585 | | // SPKAC |
1586 | | |
1587 | | bool VerifySpkac(const char* input, size_t length); |
1588 | | BIOPointer ExportPublicKey(const char* input, size_t length); |
1589 | | |
1590 | | // The caller takes ownership of the returned Buffer<char> |
1591 | | Buffer<char> ExportChallenge(const char* input, size_t length); |
1592 | | |
1593 | | // ============================================================================ |
1594 | | // KDF |
1595 | | |
1596 | | const EVP_MD* getDigestByName(const char* name); |
1597 | | const EVP_CIPHER* getCipherByName(const char* name); |
1598 | | |
1599 | | // Verify that the specified HKDF output length is valid for the given digest. |
1600 | | // The maximum length for HKDF output for a given digest is 255 times the |
1601 | | // hash size for the given digest algorithm. |
1602 | | bool checkHkdfLength(const Digest& digest, size_t length); |
1603 | | |
1604 | | bool extractP1363(const Buffer<const unsigned char>& buf, |
1605 | | unsigned char* dest, |
1606 | | size_t n); |
1607 | | |
1608 | | DataPointer hkdf(const Digest& md, |
1609 | | const Buffer<const unsigned char>& key, |
1610 | | const Buffer<const unsigned char>& info, |
1611 | | const Buffer<const unsigned char>& salt, |
1612 | | size_t length); |
1613 | | |
1614 | | bool checkScryptParams(uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem); |
1615 | | |
1616 | | DataPointer scrypt(const Buffer<const char>& pass, |
1617 | | const Buffer<const unsigned char>& salt, |
1618 | | uint64_t N, |
1619 | | uint64_t r, |
1620 | | uint64_t p, |
1621 | | uint64_t maxmem, |
1622 | | size_t length); |
1623 | | |
1624 | | DataPointer pbkdf2(const Digest& md, |
1625 | | const Buffer<const char>& pass, |
1626 | | const Buffer<const unsigned char>& salt, |
1627 | | uint32_t iterations, |
1628 | | size_t length); |
1629 | | |
1630 | | #if OPENSSL_VERSION_NUMBER >= 0x30200000L |
1631 | | #ifndef OPENSSL_NO_ARGON2 |
1632 | | enum class Argon2Type { ARGON2D, ARGON2I, ARGON2ID }; |
1633 | | |
1634 | | DataPointer argon2(const Buffer<const char>& pass, |
1635 | | const Buffer<const unsigned char>& salt, |
1636 | | uint32_t lanes, |
1637 | | size_t length, |
1638 | | uint32_t memcost, |
1639 | | uint32_t iter, |
1640 | | uint32_t version, |
1641 | | const Buffer<const unsigned char>& secret, |
1642 | | const Buffer<const unsigned char>& ad, |
1643 | | Argon2Type type); |
1644 | | #endif |
1645 | | #endif |
1646 | | |
1647 | | // ============================================================================ |
1648 | | // KEM (Key Encapsulation Mechanism) |
1649 | | #if OPENSSL_VERSION_MAJOR >= 3 |
1650 | | |
1651 | | class KEM final { |
1652 | | public: |
1653 | | struct EncapsulateResult { |
1654 | | DataPointer ciphertext; |
1655 | | DataPointer shared_key; |
1656 | | |
1657 | | EncapsulateResult() = default; |
1658 | | EncapsulateResult(DataPointer ct, DataPointer sk) |
1659 | 0 | : ciphertext(std::move(ct)), shared_key(std::move(sk)) {} |
1660 | | }; |
1661 | | |
1662 | | // Encapsulate a shared secret using KEM with a public key. |
1663 | | // Returns both the ciphertext and shared secret. |
1664 | | static std::optional<EncapsulateResult> Encapsulate( |
1665 | | const EVPKeyPointer& public_key); |
1666 | | |
1667 | | // Decapsulate a shared secret using KEM with a private key and ciphertext. |
1668 | | // Returns the shared secret. |
1669 | | static DataPointer Decapsulate(const EVPKeyPointer& private_key, |
1670 | | const Buffer<const void>& ciphertext); |
1671 | | |
1672 | | private: |
1673 | | #if !OPENSSL_VERSION_PREREQ(3, 5) |
1674 | | static bool SetOperationParameter(EVP_PKEY_CTX* ctx, |
1675 | | const EVPKeyPointer& key); |
1676 | | #endif |
1677 | | }; |
1678 | | |
1679 | | #endif // OPENSSL_VERSION_MAJOR >= 3 |
1680 | | |
1681 | | // ============================================================================ |
1682 | | // Version metadata |
1683 | 72 | #define NCRYPTO_VERSION "0.0.1" |
1684 | | |
1685 | | enum { |
1686 | | NCRYPTO_VERSION_MAJOR = 0, |
1687 | | NCRYPTO_VERSION_MINOR = 0, |
1688 | | NCRYPTO_VERSION_REVISION = 1, |
1689 | | }; |
1690 | | |
1691 | | } // namespace ncrypto |