Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
496 changes: 496 additions & 0 deletions deps/ncrypto/ncrypto.cc

Large diffs are not rendered by default.

182 changes: 179 additions & 3 deletions deps/ncrypto/ncrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <cstddef>
#include <functional>
#include <list>
#include <memory>
#include <optional>
Expand Down Expand Up @@ -195,7 +196,7 @@ template <typename T, void (*function)(T*)>
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;

using BignumCtxPointer = DeleteFnPtr<BN_CTX, BN_CTX_free>;
using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
using BignumGenCallbackPointer = DeleteFnPtr<BN_GENCB, BN_GENCB_free>;
using DSAPointer = DeleteFnPtr<DSA, DSA_free>;
using DSASigPointer = DeleteFnPtr<DSA_SIG, DSA_SIG_free>;
using ECDSASigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
Expand All @@ -209,10 +210,10 @@ using HMACCtxPointer = DeleteFnPtr<HMAC_CTX, HMAC_CTX_free>;
using NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
using PKCS8Pointer = DeleteFnPtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
using RSAPointer = DeleteFnPtr<RSA, RSA_free>;
using SSLCtxPointer = DeleteFnPtr<SSL_CTX, SSL_CTX_free>;
using SSLPointer = DeleteFnPtr<SSL, SSL_free>;
using SSLSessionPointer = DeleteFnPtr<SSL_SESSION, SSL_SESSION_free>;

class CipherCtxPointer;

struct StackOfXASN1Deleter {
void operator()(STACK_OF(ASN1_OBJECT) * p) const {
sk_ASN1_OBJECT_pop_free(p, ASN1_OBJECT_free);
Expand All @@ -227,6 +228,40 @@ struct Buffer {
size_t len = 0;
};

class Cipher final {
public:
Cipher() = default;
Cipher(const EVP_CIPHER* cipher) : cipher_(cipher) {}
Cipher(const Cipher&) = default;
Cipher& operator=(const Cipher&) = default;
inline Cipher& operator=(const EVP_CIPHER* cipher) {
cipher_ = cipher;
return *this;
}
NCRYPTO_DISALLOW_MOVE(Cipher)

inline const EVP_CIPHER* get() const { return cipher_; }
inline operator const EVP_CIPHER*() const { return cipher_; }
inline operator bool() const { return cipher_ != nullptr; }

int getNid() const;
int getMode() const;
int getIvLength() const;
int getKeyLength() const;
int getBlockSize() const;
const std::string_view getModeLabel() const;
const std::string_view getName() const;

bool isSupportedAuthenticatedMode() const;

static const Cipher FromName(const char* name);
static const Cipher FromNid(int nid);
static const Cipher FromCtx(const CipherCtxPointer& ctx);

private:
const EVP_CIPHER* cipher_ = nullptr;
};

// A managed pointer to a buffer of data. When destroyed the underlying
// buffer will be freed.
class DataPointer final {
Expand Down Expand Up @@ -272,6 +307,7 @@ class BIOPointer final {
static BIOPointer NewSecMem();
static BIOPointer New(const BIO_METHOD* method);
static BIOPointer New(const void* data, size_t len);
static BIOPointer New(const BIGNUM* bn);
static BIOPointer NewFile(std::string_view filename, std::string_view mode);
static BIOPointer NewFp(FILE* fd, int flags);

Expand Down Expand Up @@ -350,8 +386,28 @@ class BignumPointer final {
size_t encodeInto(unsigned char* out) const;
size_t encodePaddedInto(unsigned char* out, size_t size) const;

using PrimeCheckCallback = std::function<bool(int, int)>;
int isPrime(int checks,
PrimeCheckCallback cb = defaultPrimeCheckCallback) const;
struct PrimeConfig {
int bits;
bool safe = false;
const BignumPointer& add;
const BignumPointer& rem;
};

static BignumPointer NewPrime(
const PrimeConfig& params,
PrimeCheckCallback cb = defaultPrimeCheckCallback);

bool generate(const PrimeConfig& params,
PrimeCheckCallback cb = defaultPrimeCheckCallback) const;

static BignumPointer New();
static BignumPointer NewSecure();
static BignumPointer NewSub(const BignumPointer& a, const BignumPointer& b);
static BignumPointer NewLShift(size_t length);

static DataPointer Encode(const BIGNUM* bn);
static DataPointer EncodePadded(const BIGNUM* bn, size_t size);
static size_t EncodePaddedInto(const BIGNUM* bn,
Expand All @@ -366,6 +422,53 @@ class BignumPointer final {

private:
DeleteFnPtr<BIGNUM, BN_clear_free> bn_;

static bool defaultPrimeCheckCallback(int, int) { return 1; }
};

class CipherCtxPointer final {
public:
static CipherCtxPointer New();

CipherCtxPointer() = default;
explicit CipherCtxPointer(EVP_CIPHER_CTX* ctx);
CipherCtxPointer(CipherCtxPointer&& other) noexcept;
CipherCtxPointer& operator=(CipherCtxPointer&& other) noexcept;
NCRYPTO_DISALLOW_COPY(CipherCtxPointer)
~CipherCtxPointer();

inline bool operator==(std::nullptr_t) const noexcept {
return ctx_ == nullptr;
}
inline operator bool() const { return ctx_ != nullptr; }
inline EVP_CIPHER_CTX* get() const { return ctx_.get(); }
inline operator EVP_CIPHER_CTX*() const { return ctx_.get(); }
void reset(EVP_CIPHER_CTX* ctx = nullptr);
EVP_CIPHER_CTX* release();

void setFlags(int flags);
bool setKeyLength(size_t length);
bool setIvLength(size_t length);
bool setAeadTag(const Buffer<const char>& tag);
bool setAeadTagLength(size_t length);
bool setPadding(bool padding);
bool init(const Cipher& cipher,
bool encrypt,
const unsigned char* key = nullptr,
const unsigned char* iv = nullptr);

int getBlockSize() const;
int getMode() const;
int getNid() const;

bool update(const Buffer<const unsigned char>& in,
unsigned char* out,
int* out_len,
bool finalize = false);
bool getAeadTag(size_t len, unsigned char* out);

private:
DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> ctx_;
};

class EVPKeyPointer final {
Expand Down Expand Up @@ -557,6 +660,79 @@ struct StackOfX509Deleter {
using StackOfX509 = std::unique_ptr<STACK_OF(X509), StackOfX509Deleter>;

class X509Pointer;
class X509View;

class SSLCtxPointer final {
public:
SSLCtxPointer() = default;
explicit SSLCtxPointer(SSL_CTX* ctx);
SSLCtxPointer(SSLCtxPointer&& other) noexcept;
SSLCtxPointer& operator=(SSLCtxPointer&& other) noexcept;
NCRYPTO_DISALLOW_COPY(SSLCtxPointer)
~SSLCtxPointer();

inline bool operator==(std::nullptr_t) const noexcept {
return ctx_ == nullptr;
}
inline operator bool() const { return ctx_ != nullptr; }
inline SSL_CTX* get() const { return ctx_.get(); }
void reset(SSL_CTX* ctx = nullptr);
void reset(const SSL_METHOD* method);
SSL_CTX* release();

bool setGroups(const char* groups);
void setStatusCallback(auto callback) {
if (!ctx_) return;
SSL_CTX_set_tlsext_status_cb(get(), callback);
SSL_CTX_set_tlsext_status_arg(get(), nullptr);
}

static SSLCtxPointer NewServer();
static SSLCtxPointer NewClient();
static SSLCtxPointer New(const SSL_METHOD* method = TLS_method());

private:
DeleteFnPtr<SSL_CTX, SSL_CTX_free> ctx_;
};

class SSLPointer final {
public:
SSLPointer() = default;
explicit SSLPointer(SSL* ssl);
SSLPointer(SSLPointer&& other) noexcept;
SSLPointer& operator=(SSLPointer&& other) noexcept;
NCRYPTO_DISALLOW_COPY(SSLPointer)
~SSLPointer();

inline bool operator==(std::nullptr_t) noexcept { return ssl_ == nullptr; }
inline operator bool() const { return ssl_ != nullptr; }
inline SSL* get() const { return ssl_.get(); }
inline operator SSL*() const { return ssl_.get(); }
void reset(SSL* ssl = nullptr);
SSL* release();

bool setSession(const SSLSessionPointer& session);
bool setSniContext(const SSLCtxPointer& ctx) const;

const std::string_view getClientHelloAlpn() const;
const std::string_view getClientHelloServerName() const;

std::optional<const std::string_view> getServerName() const;
X509View getCertificate() const;
EVPKeyPointer getPeerTempKey() const;
const SSL_CIPHER* getCipher() const;
bool isServer() const;

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

void getCiphers(std::function<void(const std::string_view)> cb) const;

static SSLPointer New(const SSLCtxPointer& ctx);
static std::optional<const std::string_view> GetServerName(const SSL* ssl);

private:
DeleteFnPtr<SSL, SSL_free> ssl_;
};

class X509View final {
public:
Expand Down
Loading
Loading