Skip to content

Commit

Permalink
Merge pull request #27 from jasnell/jasnell/even-moar-crypto2
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell authored Jan 2, 2025
2 parents 1093eec + 4f43fd0 commit 2466074
Show file tree
Hide file tree
Showing 14 changed files with 919 additions and 456 deletions.
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

0 comments on commit 2466074

Please sign in to comment.