Skip to content

Commit

Permalink
src: move more crypto impl details into ncrypto
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell committed Mar 3, 2025
1 parent 873def6 commit 1030f85
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 98 deletions.
82 changes: 65 additions & 17 deletions deps/ncrypto/ncrypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1669,17 +1669,17 @@ const EVP_CIPHER* getCipherByName(const std::string_view name) {
return EVP_get_cipherbyname(name.data());
}

bool checkHkdfLength(const EVP_MD* md, size_t length) {
bool checkHkdfLength(const Digest& md, size_t length) {
// HKDF-Expand computes up to 255 HMAC blocks, each having as many bits as
// the output of the hash function. 255 is a hard limit because HKDF appends
// an 8-bit counter to each HMAC'd message, starting at 1.
static constexpr size_t kMaxDigestMultiplier = 255;
size_t max_length = EVP_MD_size(md) * kMaxDigestMultiplier;
size_t max_length = md.size() * kMaxDigestMultiplier;
if (length > max_length) return false;
return true;
}

DataPointer hkdf(const EVP_MD* md,
DataPointer hkdf(const Digest& md,
const Buffer<const unsigned char>& key,
const Buffer<const unsigned char>& info,
const Buffer<const unsigned char>& salt,
Expand All @@ -1703,7 +1703,7 @@ DataPointer hkdf(const EVP_MD* md,
if (salt.len > 0) {
actual_salt = {reinterpret_cast<const char*>(salt.data), salt.len};
} else {
actual_salt = {default_salt, static_cast<unsigned>(EVP_MD_size(md))};
actual_salt = {default_salt, static_cast<unsigned>(md.size())};
}

// We do not use EVP_PKEY_HKDF_MODE_EXTRACT_AND_EXPAND because and instead
Expand Down Expand Up @@ -2786,6 +2786,11 @@ bool Cipher::isStreamMode() const {
return getMode() == EVP_CIPH_STREAM_CIPHER;
}

bool Cipher::isChaCha20Poly1305() const {
if (!cipher_) return false;
return getNid() == NID_chacha20_poly1305;
}

int Cipher::getMode() const {
if (!cipher_) return 0;
return EVP_CIPHER_mode(cipher_);
Expand Down Expand Up @@ -2862,6 +2867,14 @@ bool Cipher::isSupportedAuthenticatedMode() const {
}
}

int Cipher::bytesToKey(const Digest& digest,
const Buffer<const unsigned char>& input,
unsigned char* key,
unsigned char* iv) const {
return EVP_BytesToKey(
*this, Digest::MD5, nullptr, input.data, input.len, 1, key, iv);
}

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

CipherCtxPointer CipherCtxPointer::New() {
Expand Down Expand Up @@ -2938,6 +2951,26 @@ int CipherCtxPointer::getMode() const {
return EVP_CIPHER_CTX_mode(ctx_.get());
}

bool CipherCtxPointer::isGcmMode() const {
if (!ctx_) return false;
return getMode() == EVP_CIPH_GCM_MODE;
}

bool CipherCtxPointer::isCcmMode() const {
if (!ctx_) return false;
return getMode() == EVP_CIPH_CCM_MODE;
}

bool CipherCtxPointer::isWrapMode() const {
if (!ctx_) return false;
return getMode() == EVP_CIPH_WRAP_MODE;
}

bool CipherCtxPointer::isChaCha20Poly1305() const {
if (!ctx_) return false;
return getNid() == NID_chacha20_poly1305;
}

int CipherCtxPointer::getNid() const {
if (!ctx_) return 0;
return EVP_CIPHER_CTX_nid(ctx_.get());
Expand Down Expand Up @@ -3720,9 +3753,7 @@ DataPointer Cipher::recover(const EVPKeyPointer& key,
namespace {
struct CipherCallbackContext {
Cipher::CipherNameCallback cb;
void operator()(std::string_view name) {
cb(name);
}
void operator()(std::string_view name) { cb(name); }
};

#if OPENSSL_VERSION_MAJOR >= 3
Expand Down Expand Up @@ -3759,9 +3790,9 @@ void array_push_back(const TypeName* evp_ref,
#else
template <class TypeName>
void array_push_back(const TypeName* evp_ref,
const char* from,
const char* to,
void* arg) {
const char* from,
const char* to,
void* arg) {
if (!from) return;
auto& cb = *(static_cast<CipherCallbackContext*>(arg));
cb(from);
Expand All @@ -3776,15 +3807,15 @@ void Cipher::ForEach(Cipher::CipherNameCallback callback) {

EVP_CIPHER_do_all_sorted(
#if OPENSSL_VERSION_MAJOR >= 3
array_push_back<EVP_CIPHER,
EVP_CIPHER_fetch,
EVP_CIPHER_free,
EVP_get_cipherbyname,
EVP_CIPHER_get0_name>,
array_push_back<EVP_CIPHER,
EVP_CIPHER_fetch,
EVP_CIPHER_free,
EVP_get_cipherbyname,
EVP_CIPHER_get0_name>,
#else
array_push_back<EVP_CIPHER>,
array_push_back<EVP_CIPHER>,
#endif
&context);
&context);
}

// ============================================================================
Expand Down Expand Up @@ -4143,4 +4174,21 @@ size_t Dsa::getDivisorLength() const {
return BignumPointer::GetBitCount(getQ());
}

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

size_t Digest::size() const {
if (md_ == nullptr) return 0;
return EVP_MD_size(md_);
}

const Digest Digest::MD5 = Digest(EVP_md5());
const Digest Digest::SHA1 = Digest(EVP_sha1());
const Digest Digest::SHA256 = Digest(EVP_sha256());
const Digest Digest::SHA384 = Digest(EVP_sha384());
const Digest Digest::SHA512 = Digest(EVP_sha512());

const Digest Digest::FromName(std::string_view name) {
return ncrypto::getDigestByName(name);
}

} // namespace ncrypto
48 changes: 46 additions & 2 deletions deps/ncrypto/ncrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,44 @@ struct Buffer {
size_t len = 0;
};

class Digest final {
public:
Digest() = default;
Digest(const EVP_MD* md) : md_(md) {}
Digest(const Digest&) = default;
Digest& operator=(const Digest&) = default;
inline Digest& operator=(const EVP_MD* md) {
md_ = md;
return *this;
}
NCRYPTO_DISALLOW_MOVE(Digest)

size_t size() const;

inline const EVP_MD* get() const { return md_; }
inline operator const EVP_MD*() const { return md_; }
inline operator bool() const { return md_ != nullptr; }

static const Digest MD5;
static const Digest SHA1;
static const Digest SHA256;
static const Digest SHA384;
static const Digest SHA512;

static const Digest FromName(std::string_view name);

private:
const EVP_MD* md_ = nullptr;
};

DataPointer hashDigest(const Buffer<const unsigned char>& data,
const EVP_MD* md);

class Cipher final {
public:
static constexpr size_t MAX_KEY_LENGTH = EVP_MAX_KEY_LENGTH;
static constexpr size_t MAX_IV_LENGTH = EVP_MAX_IV_LENGTH;

Cipher() = default;
Cipher(const EVP_CIPHER* cipher) : cipher_(cipher) {}
Cipher(const Cipher&) = default;
Expand Down Expand Up @@ -280,9 +313,15 @@ class Cipher final {
bool isCcmMode() const;
bool isOcbMode() const;
bool isStreamMode() const;
bool isChaCha20Poly1305() const;

bool isSupportedAuthenticatedMode() const;

int bytesToKey(const Digest& digest,
const Buffer<const unsigned char>& input,
unsigned char* key,
unsigned char* iv) const;

static const Cipher FromName(std::string_view name);
static const Cipher FromNid(int nid);
static const Cipher FromCtx(const CipherCtxPointer& ctx);
Expand Down Expand Up @@ -644,6 +683,11 @@ class CipherCtxPointer final {
int getMode() const;
int getNid() const;

bool isGcmMode() const;
bool isCcmMode() const;
bool isWrapMode() const;
bool isChaCha20Poly1305() const;

bool update(const Buffer<const unsigned char>& in,
unsigned char* out,
int* out_len,
Expand Down Expand Up @@ -1420,13 +1464,13 @@ const EVP_CIPHER* getCipherByName(const std::string_view name);
// Verify that the specified HKDF output length is valid for the given digest.
// The maximum length for HKDF output for a given digest is 255 times the
// hash size for the given digest algorithm.
bool checkHkdfLength(const EVP_MD* md, size_t length);
bool checkHkdfLength(const Digest& digest, size_t length);

bool extractP1363(const Buffer<const unsigned char>& buf,
unsigned char* dest,
size_t n);

DataPointer hkdf(const EVP_MD* md,
DataPointer hkdf(const Digest& md,
const Buffer<const unsigned char>& key,
const Buffer<const unsigned char>& info,
const Buffer<const unsigned char>& salt,
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/crypto_aes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ Maybe<void> AESCipherTraits::AdditionalConfig(
return Nothing<void>();
}

if (params->cipher.isWrapMode()) {
if (!params->cipher.isWrapMode()) {
if (!ValidateIV(env, mode, args[offset + 1], params)) {
return Nothing<void>();
}
Expand Down
Loading

0 comments on commit 1030f85

Please sign in to comment.