Skip to content

Commit

Permalink
crypto: handle OpenSSL error queue in CipherBase
Browse files Browse the repository at this point in the history
This handles all errors produced by OpenSSL within the CipherBase
class. API functions ensure that they do not add any new errors to the
error queue. Also adds a couple of CHECKs and throws under certain
conditions.

PR-URL: #21288
Fixes: #21281
Refs: #21287
Reviewed-By: Ujjwal Sharma <[email protected]>
  • Loading branch information
tniessen authored and targos committed Jul 14, 2018
1 parent 48b16aa commit 07cce88
Showing 1 changed file with 39 additions and 18 deletions.
57 changes: 39 additions & 18 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2581,6 +2581,7 @@ void CipherBase::Init(const char* cipher_type,
int key_buf_len,
unsigned int auth_tag_len) {
HandleScope scope(env()->isolate());
MarkPopErrorOnReturn mark_pop_error_on_return;

#ifdef NODE_FIPS_MODE
if (FIPS_mode()) {
Expand All @@ -2605,6 +2606,7 @@ void CipherBase::Init(const char* cipher_type,
1,
key,
iv);
CHECK_NE(key_len, 0);

ctx_.reset(EVP_CIPHER_CTX_new());

Expand All @@ -2613,7 +2615,11 @@ void CipherBase::Init(const char* cipher_type,
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);

const bool encrypt = (kind_ == kCipher);
EVP_CipherInit_ex(ctx_.get(), cipher, nullptr, nullptr, nullptr, encrypt);
if (1 != EVP_CipherInit_ex(ctx_.get(), cipher, nullptr,
nullptr, nullptr, encrypt)) {
return ThrowCryptoError(env(), ERR_get_error(),
"Failed to initialize cipher");
}

if (encrypt && (mode == EVP_CIPH_CTR_MODE || mode == EVP_CIPH_GCM_MODE ||
mode == EVP_CIPH_CCM_MODE)) {
Expand All @@ -2632,12 +2638,15 @@ void CipherBase::Init(const char* cipher_type,

CHECK_EQ(1, EVP_CIPHER_CTX_set_key_length(ctx_.get(), key_len));

EVP_CipherInit_ex(ctx_.get(),
nullptr,
nullptr,
reinterpret_cast<unsigned char*>(key),
reinterpret_cast<unsigned char*>(iv),
encrypt);
if (1 != EVP_CipherInit_ex(ctx_.get(),
nullptr,
nullptr,
reinterpret_cast<unsigned char*>(key),
reinterpret_cast<unsigned char*>(iv),
encrypt)) {
return ThrowCryptoError(env(), ERR_get_error(),
"Failed to initialize cipher");
}
}


Expand Down Expand Up @@ -2672,6 +2681,7 @@ void CipherBase::InitIv(const char* cipher_type,
int iv_len,
unsigned int auth_tag_len) {
HandleScope scope(env()->isolate());
MarkPopErrorOnReturn mark_pop_error_on_return;

const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type);
if (cipher == nullptr) {
Expand Down Expand Up @@ -2702,7 +2712,11 @@ void CipherBase::InitIv(const char* cipher_type,
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);

const bool encrypt = (kind_ == kCipher);
EVP_CipherInit_ex(ctx_.get(), cipher, nullptr, nullptr, nullptr, encrypt);
if (1 != EVP_CipherInit_ex(ctx_.get(), cipher, nullptr,
nullptr, nullptr, encrypt)) {
return ThrowCryptoError(env(), ERR_get_error(),
"Failed to initialize cipher");
}

if (IsAuthenticatedMode()) {
CHECK(has_iv);
Expand All @@ -2715,12 +2729,15 @@ void CipherBase::InitIv(const char* cipher_type,
return env()->ThrowError("Invalid key length");
}

EVP_CipherInit_ex(ctx_.get(),
nullptr,
nullptr,
reinterpret_cast<const unsigned char*>(key),
reinterpret_cast<const unsigned char*>(iv),
encrypt);
if (1 != EVP_CipherInit_ex(ctx_.get(),
nullptr,
nullptr,
reinterpret_cast<const unsigned char*>(key),
reinterpret_cast<const unsigned char*>(iv),
encrypt)) {
return ThrowCryptoError(env(), ERR_get_error(),
"Failed to initialize cipher");
}
}


Expand Down Expand Up @@ -2765,6 +2782,7 @@ static bool IsValidGCMTagLength(unsigned int tag_len) {
bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
unsigned int auth_tag_len) {
CHECK(IsAuthenticatedMode());
MarkPopErrorOnReturn mark_pop_error_on_return;

if (!EVP_CIPHER_CTX_ctrl(ctx_.get(),
EVP_CTRL_AEAD_SET_IVLEN,
Expand Down Expand Up @@ -2910,6 +2928,7 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) {
bool CipherBase::SetAAD(const char* data, unsigned int len, int plaintext_len) {
if (!ctx_ || !IsAuthenticatedMode())
return false;
MarkPopErrorOnReturn mark_pop_error_on_return;

int outlen;
const int mode = EVP_CIPHER_CTX_mode(ctx_.get());
Expand Down Expand Up @@ -2969,6 +2988,7 @@ CipherBase::UpdateResult CipherBase::Update(const char* data,
int* out_len) {
if (!ctx_)
return kErrorState;
MarkPopErrorOnReturn mark_pop_error_on_return;

const int mode = EVP_CIPHER_CTX_mode(ctx_.get());

Expand All @@ -2980,10 +3000,10 @@ CipherBase::UpdateResult CipherBase::Update(const char* data,
// on first update:
if (kind_ == kDecipher && IsAuthenticatedMode() && auth_tag_len_ > 0 &&
auth_tag_len_ != kNoAuthTagLength && !auth_tag_set_) {
EVP_CIPHER_CTX_ctrl(ctx_.get(),
EVP_CTRL_GCM_SET_TAG,
auth_tag_len_,
reinterpret_cast<unsigned char*>(auth_tag_));
CHECK(EVP_CIPHER_CTX_ctrl(ctx_.get(),
EVP_CTRL_GCM_SET_TAG,
auth_tag_len_,
reinterpret_cast<unsigned char*>(auth_tag_)));
auth_tag_set_ = true;
}

Expand Down Expand Up @@ -3061,6 +3081,7 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
bool CipherBase::SetAutoPadding(bool auto_padding) {
if (!ctx_)
return false;
MarkPopErrorOnReturn mark_pop_error_on_return;
return EVP_CIPHER_CTX_set_padding(ctx_.get(), auto_padding);
}

Expand Down

0 comments on commit 07cce88

Please sign in to comment.