Skip to content

Commit

Permalink
src: move CipherCtx methods to ncrypto
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell committed Jan 2, 2025
1 parent fb74dd7 commit 6715521
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 134 deletions.
124 changes: 115 additions & 9 deletions deps/ncrypto/ncrypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2294,7 +2294,7 @@ std::optional<uint32_t> SSLPointer::verifyPeerCertificate() const {
}

const std::string_view SSLPointer::getClientHelloAlpn() const {
if (ssl_ == nullptr) return std::string_view();
if (ssl_ == nullptr) return {};
const unsigned char* buf;
size_t len;
size_t rem;
Expand All @@ -2305,34 +2305,34 @@ const std::string_view SSLPointer::getClientHelloAlpn() const {
&buf,
&rem) ||
rem < 2) {
return nullptr;
return {};
}

len = (buf[0] << 8) | buf[1];
if (len + 2 != rem) return nullptr;
if (len + 2 != rem) return {};
return reinterpret_cast<const char*>(buf + 3);
}

const std::string_view SSLPointer::getClientHelloServerName() const {
if (ssl_ == nullptr) return std::string_view();
if (ssl_ == nullptr) return {};
const unsigned char* buf;
size_t len;
size_t rem;

if (!SSL_client_hello_get0_ext(get(), TLSEXT_TYPE_server_name, &buf, &rem) ||
rem <= 2) {
return nullptr;
return {};
}

len = (*buf << 8) | *(buf + 1);
if (len + 2 != rem) return nullptr;
if (len + 2 != rem) return {};
rem = len;

if (rem == 0 || *(buf + 2) != TLSEXT_NAMETYPE_host_name) return nullptr;
if (rem == 0 || *(buf + 2) != TLSEXT_NAMETYPE_host_name) return {};
rem--;
if (rem <= 2) return nullptr;
if (rem <= 2) return {};
len = (*(buf + 3) << 8) | *(buf + 4);
if (len + 2 > rem) return nullptr;
if (len + 2 > rem) return {};
return reinterpret_cast<const char*>(buf + 5);
}

Expand Down Expand Up @@ -2504,4 +2504,110 @@ bool Cipher::isSupportedAuthenticatedMode() const {
}
}

// ============================================================================

CipherCtxPointer CipherCtxPointer::New() {
auto ret = CipherCtxPointer(EVP_CIPHER_CTX_new());
if (!ret) return {};
EVP_CIPHER_CTX_init(ret.get());
return ret;
}

CipherCtxPointer::CipherCtxPointer(EVP_CIPHER_CTX* ctx) : ctx_(ctx) {}

CipherCtxPointer::CipherCtxPointer(CipherCtxPointer&& other) noexcept
: ctx_(other.release()) {}

CipherCtxPointer& CipherCtxPointer::operator=(
CipherCtxPointer&& other) noexcept {
if (this == &other) return *this;
this->~CipherCtxPointer();
return *new (this) CipherCtxPointer(std::move(other));
}

CipherCtxPointer::~CipherCtxPointer() {
reset();
}

void CipherCtxPointer::reset(EVP_CIPHER_CTX* ctx) {
ctx_.reset(ctx);
}

EVP_CIPHER_CTX* CipherCtxPointer::release() {
return ctx_.release();
}

void CipherCtxPointer::setFlags(int flags) {
if (!ctx_) return;
EVP_CIPHER_CTX_set_flags(ctx_.get(), flags);
}

bool CipherCtxPointer::setKeyLength(size_t length) {
if (!ctx_) return false;
return EVP_CIPHER_CTX_set_key_length(ctx_.get(), length);
}

bool CipherCtxPointer::setIvLength(size_t length) {
if (!ctx_) return false;
return EVP_CIPHER_CTX_ctrl(
ctx_.get(), EVP_CTRL_AEAD_SET_IVLEN, length, nullptr);
}

bool CipherCtxPointer::setAeadTag(const Buffer<const char>& tag) {
if (!ctx_) return false;
return EVP_CIPHER_CTX_ctrl(
ctx_.get(), EVP_CTRL_AEAD_SET_TAG, tag.len, const_cast<char*>(tag.data));
}

bool CipherCtxPointer::setAeadTagLength(size_t length) {
if (!ctx_) return false;
return EVP_CIPHER_CTX_ctrl(
ctx_.get(), EVP_CTRL_AEAD_SET_TAG, length, nullptr);
}

bool CipherCtxPointer::setPadding(bool padding) {
if (!ctx_) return false;
return EVP_CIPHER_CTX_set_padding(ctx_.get(), padding);
}

int CipherCtxPointer::getBlockSize() const {
if (!ctx_) return 0;
return EVP_CIPHER_CTX_block_size(ctx_.get());
}

int CipherCtxPointer::getMode() const {
if (!ctx_) return 0;
return EVP_CIPHER_CTX_mode(ctx_.get());
}

int CipherCtxPointer::getNid() const {
if (!ctx_) return 0;
return EVP_CIPHER_CTX_nid(ctx_.get());
}

bool CipherCtxPointer::init(const Cipher& cipher,
bool encrypt,
const unsigned char* key,
const unsigned char* iv) {
if (!ctx_) return false;
return EVP_CipherInit_ex(
ctx_.get(), cipher, nullptr, key, iv, encrypt ? 1 : 0) == 1;
}

bool CipherCtxPointer::update(const Buffer<const unsigned char>& in,
unsigned char* out,
int* out_len,
bool finalize) {
if (!ctx_) return false;
if (!finalize) {
return EVP_CipherUpdate(ctx_.get(), out, out_len, in.data, in.len) == 1;
}
return EVP_CipherFinal_ex(ctx_.get(), out, out_len) == 1;
}

bool CipherCtxPointer::getAeadTag(size_t len, unsigned char* out) {
if (!ctx_) return false;
return EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_GET_TAG, len, out);
}

} // namespace ncrypto
48 changes: 47 additions & 1 deletion deps/ncrypto/ncrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;

using BignumCtxPointer = DeleteFnPtr<BN_CTX, BN_CTX_free>;
using BignumGenCallbackPointer = DeleteFnPtr<BN_GENCB, BN_GENCB_free>;
using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_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 @@ -213,6 +212,8 @@ using PKCS8Pointer = DeleteFnPtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
using RSAPointer = DeleteFnPtr<RSA, RSA_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 Down Expand Up @@ -425,6 +426,51 @@ class BignumPointer final {
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 {
public:
static EVPKeyPointer New();
Expand Down
Loading

0 comments on commit 6715521

Please sign in to comment.