Coverage Report

Created: 2025-10-31 09:06

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