Skip to content

Commit b7bdde0

Browse files
tniessendanbev
authored andcommitted
crypto: deduplicate cipher initialization code
CipherBase::Init and CipherBase::InitIv contain a lot of duplicate code, this commit moves that into a separate function. PR-URL: #23011 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ujjwal Sharma <[email protected]>
1 parent 9b29227 commit b7bdde0

File tree

2 files changed

+64
-77
lines changed

2 files changed

+64
-77
lines changed

src/node_crypto.cc

Lines changed: 55 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,6 +2545,12 @@ int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
25452545
return 1;
25462546
}
25472547

2548+
static bool IsSupportedAuthenticatedMode(int mode) {
2549+
return mode == EVP_CIPH_CCM_MODE ||
2550+
mode == EVP_CIPH_GCM_MODE ||
2551+
mode == EVP_CIPH_OCB_MODE;
2552+
}
2553+
25482554
void CipherBase::Initialize(Environment* env, Local<Object> target) {
25492555
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
25502556

@@ -2571,6 +2577,43 @@ void CipherBase::New(const FunctionCallbackInfo<Value>& args) {
25712577
new CipherBase(env, args.This(), kind);
25722578
}
25732579

2580+
void CipherBase::CommonInit(const char* cipher_type,
2581+
const EVP_CIPHER* cipher,
2582+
const unsigned char* key,
2583+
int key_len,
2584+
const unsigned char* iv,
2585+
int iv_len,
2586+
unsigned int auth_tag_len) {
2587+
CHECK(!ctx_);
2588+
ctx_.reset(EVP_CIPHER_CTX_new());
2589+
2590+
const int mode = EVP_CIPHER_mode(cipher);
2591+
if (mode == EVP_CIPH_WRAP_MODE)
2592+
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
2593+
2594+
const bool encrypt = (kind_ == kCipher);
2595+
if (1 != EVP_CipherInit_ex(ctx_.get(), cipher, nullptr,
2596+
nullptr, nullptr, encrypt)) {
2597+
return ThrowCryptoError(env(), ERR_get_error(),
2598+
"Failed to initialize cipher");
2599+
}
2600+
2601+
if (IsSupportedAuthenticatedMode(mode)) {
2602+
CHECK_GE(iv_len, 0);
2603+
if (!InitAuthenticated(cipher_type, iv_len, auth_tag_len))
2604+
return;
2605+
}
2606+
2607+
if (!EVP_CIPHER_CTX_set_key_length(ctx_.get(), key_len)) {
2608+
ctx_.reset();
2609+
return env()->ThrowError("Invalid key length");
2610+
}
2611+
2612+
if (1 != EVP_CipherInit_ex(ctx_.get(), nullptr, nullptr, key, iv, encrypt)) {
2613+
return ThrowCryptoError(env(), ERR_get_error(),
2614+
"Failed to initialize cipher");
2615+
}
2616+
}
25742617

25752618
void CipherBase::Init(const char* cipher_type,
25762619
const char* key_buf,
@@ -2586,7 +2629,6 @@ void CipherBase::Init(const char* cipher_type,
25862629
}
25872630
#endif // NODE_FIPS_MODE
25882631

2589-
CHECK(!ctx_);
25902632
const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type);
25912633
if (cipher == nullptr)
25922634
return env()->ThrowError("Unknown cipher");
@@ -2604,45 +2646,19 @@ void CipherBase::Init(const char* cipher_type,
26042646
iv);
26052647
CHECK_NE(key_len, 0);
26062648

2607-
ctx_.reset(EVP_CIPHER_CTX_new());
2608-
26092649
const int mode = EVP_CIPHER_mode(cipher);
2610-
if (mode == EVP_CIPH_WRAP_MODE)
2611-
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
2612-
2613-
const bool encrypt = (kind_ == kCipher);
2614-
if (1 != EVP_CipherInit_ex(ctx_.get(), cipher, nullptr,
2615-
nullptr, nullptr, encrypt)) {
2616-
return ThrowCryptoError(env(), ERR_get_error(),
2617-
"Failed to initialize cipher");
2618-
}
2619-
2620-
if (encrypt && (mode == EVP_CIPH_CTR_MODE || mode == EVP_CIPH_GCM_MODE ||
2621-
mode == EVP_CIPH_CCM_MODE)) {
2650+
if (kind_ == kCipher && (mode == EVP_CIPH_CTR_MODE ||
2651+
mode == EVP_CIPH_GCM_MODE ||
2652+
mode == EVP_CIPH_CCM_MODE)) {
26222653
// Ignore the return value (i.e. possible exception) because we are
26232654
// not calling back into JS anyway.
26242655
ProcessEmitWarning(env(),
26252656
"Use Cipheriv for counter mode of %s",
26262657
cipher_type);
26272658
}
26282659

2629-
if (IsAuthenticatedMode()) {
2630-
if (!InitAuthenticated(cipher_type, EVP_CIPHER_iv_length(cipher),
2631-
auth_tag_len))
2632-
return;
2633-
}
2634-
2635-
CHECK_EQ(1, EVP_CIPHER_CTX_set_key_length(ctx_.get(), key_len));
2636-
2637-
if (1 != EVP_CipherInit_ex(ctx_.get(),
2638-
nullptr,
2639-
nullptr,
2640-
reinterpret_cast<unsigned char*>(key),
2641-
reinterpret_cast<unsigned char*>(iv),
2642-
encrypt)) {
2643-
return ThrowCryptoError(env(), ERR_get_error(),
2644-
"Failed to initialize cipher");
2645-
}
2660+
CommonInit(cipher_type, cipher, key, key_len, iv,
2661+
EVP_CIPHER_iv_length(cipher), auth_tag_len);
26462662
}
26472663

26482664

@@ -2669,16 +2685,10 @@ void CipherBase::Init(const FunctionCallbackInfo<Value>& args) {
26692685
cipher->Init(*cipher_type, key_buf, key_buf_len, auth_tag_len);
26702686
}
26712687

2672-
static bool IsSupportedAuthenticatedMode(int mode) {
2673-
return mode == EVP_CIPH_CCM_MODE ||
2674-
mode == EVP_CIPH_GCM_MODE ||
2675-
mode == EVP_CIPH_OCB_MODE;
2676-
}
2677-
26782688
void CipherBase::InitIv(const char* cipher_type,
2679-
const char* key,
2689+
const unsigned char* key,
26802690
int key_len,
2681-
const char* iv,
2691+
const unsigned char* iv,
26822692
int iv_len,
26832693
unsigned int auth_tag_len) {
26842694
HandleScope scope(env()->isolate());
@@ -2706,38 +2716,7 @@ void CipherBase::InitIv(const char* cipher_type,
27062716
return env()->ThrowError("Invalid IV length");
27072717
}
27082718

2709-
ctx_.reset(EVP_CIPHER_CTX_new());
2710-
2711-
if (mode == EVP_CIPH_WRAP_MODE)
2712-
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
2713-
2714-
const bool encrypt = (kind_ == kCipher);
2715-
if (1 != EVP_CipherInit_ex(ctx_.get(), cipher, nullptr,
2716-
nullptr, nullptr, encrypt)) {
2717-
return ThrowCryptoError(env(), ERR_get_error(),
2718-
"Failed to initialize cipher");
2719-
}
2720-
2721-
if (is_authenticated_mode) {
2722-
CHECK(has_iv);
2723-
if (!InitAuthenticated(cipher_type, iv_len, auth_tag_len))
2724-
return;
2725-
}
2726-
2727-
if (!EVP_CIPHER_CTX_set_key_length(ctx_.get(), key_len)) {
2728-
ctx_.reset();
2729-
return env()->ThrowError("Invalid key length");
2730-
}
2731-
2732-
if (1 != EVP_CipherInit_ex(ctx_.get(),
2733-
nullptr,
2734-
nullptr,
2735-
reinterpret_cast<const unsigned char*>(key),
2736-
reinterpret_cast<const unsigned char*>(iv),
2737-
encrypt)) {
2738-
return ThrowCryptoError(env(), ERR_get_error(),
2739-
"Failed to initialize cipher");
2740-
}
2719+
CommonInit(cipher_type, cipher, key, key_len, iv, iv_len, auth_tag_len);
27412720
}
27422721

27432722

@@ -2750,14 +2729,15 @@ void CipherBase::InitIv(const FunctionCallbackInfo<Value>& args) {
27502729

27512730
const node::Utf8Value cipher_type(env->isolate(), args[0]);
27522731
ssize_t key_len = Buffer::Length(args[1]);
2753-
const char* key_buf = Buffer::Data(args[1]);
2732+
const unsigned char* key_buf = reinterpret_cast<unsigned char*>(
2733+
Buffer::Data(args[1]));
27542734
ssize_t iv_len;
2755-
const char* iv_buf;
2735+
const unsigned char* iv_buf;
27562736
if (args[2]->IsNull()) {
27572737
iv_buf = nullptr;
27582738
iv_len = -1;
27592739
} else {
2760-
iv_buf = Buffer::Data(args[2]);
2740+
iv_buf = reinterpret_cast<unsigned char*>(Buffer::Data(args[2]));
27612741
iv_len = Buffer::Length(args[2]);
27622742
}
27632743

src/node_crypto.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,14 +370,21 @@ class CipherBase : public BaseObject {
370370
};
371371
static const unsigned kNoAuthTagLength = static_cast<unsigned>(-1);
372372

373+
void CommonInit(const char* cipher_type,
374+
const EVP_CIPHER* cipher,
375+
const unsigned char* key,
376+
int key_len,
377+
const unsigned char* iv,
378+
int iv_len,
379+
unsigned int auth_tag_len);
373380
void Init(const char* cipher_type,
374381
const char* key_buf,
375382
int key_buf_len,
376383
unsigned int auth_tag_len);
377384
void InitIv(const char* cipher_type,
378-
const char* key,
385+
const unsigned char* key,
379386
int key_len,
380-
const char* iv,
387+
const unsigned char* iv,
381388
int iv_len,
382389
unsigned int auth_tag_len);
383390
bool InitAuthenticated(const char* cipher_type, int iv_len,

0 commit comments

Comments
 (0)