Coverage Report

Created: 2025-12-30 08:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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