Skip to content

Commit 2888f80

Browse files
tniessentargos
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 c54e423 commit 2888f80

File tree

2 files changed

+64
-77
lines changed

2 files changed

+64
-77
lines changed

src/node_crypto.cc

+55-75
Original file line numberDiff line numberDiff line change
@@ -2539,6 +2539,12 @@ int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
25392539
return 1;
25402540
}
25412541

2542+
static bool IsSupportedAuthenticatedMode(int mode) {
2543+
return mode == EVP_CIPH_CCM_MODE ||
2544+
mode == EVP_CIPH_GCM_MODE ||
2545+
mode == EVP_CIPH_OCB_MODE;
2546+
}
2547+
25422548
void CipherBase::Initialize(Environment* env, Local<Object> target) {
25432549
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
25442550

@@ -2565,6 +2571,43 @@ void CipherBase::New(const FunctionCallbackInfo<Value>& args) {
25652571
new CipherBase(env, args.This(), kind);
25662572
}
25672573

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

25692612
void CipherBase::Init(const char* cipher_type,
25702613
const char* key_buf,
@@ -2580,7 +2623,6 @@ void CipherBase::Init(const char* cipher_type,
25802623
}
25812624
#endif // NODE_FIPS_MODE
25822625

2583-
CHECK(!ctx_);
25842626
const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type);
25852627
if (cipher == nullptr)
25862628
return env()->ThrowError("Unknown cipher");
@@ -2598,45 +2640,19 @@ void CipherBase::Init(const char* cipher_type,
25982640
iv);
25992641
CHECK_NE(key_len, 0);
26002642

2601-
ctx_.reset(EVP_CIPHER_CTX_new());
2602-
26032643
const int mode = EVP_CIPHER_mode(cipher);
2604-
if (mode == EVP_CIPH_WRAP_MODE)
2605-
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
2606-
2607-
const bool encrypt = (kind_ == kCipher);
2608-
if (1 != EVP_CipherInit_ex(ctx_.get(), cipher, nullptr,
2609-
nullptr, nullptr, encrypt)) {
2610-
return ThrowCryptoError(env(), ERR_get_error(),
2611-
"Failed to initialize cipher");
2612-
}
2613-
2614-
if (encrypt && (mode == EVP_CIPH_CTR_MODE || mode == EVP_CIPH_GCM_MODE ||
2615-
mode == EVP_CIPH_CCM_MODE)) {
2644+
if (kind_ == kCipher && (mode == EVP_CIPH_CTR_MODE ||
2645+
mode == EVP_CIPH_GCM_MODE ||
2646+
mode == EVP_CIPH_CCM_MODE)) {
26162647
// Ignore the return value (i.e. possible exception) because we are
26172648
// not calling back into JS anyway.
26182649
ProcessEmitWarning(env(),
26192650
"Use Cipheriv for counter mode of %s",
26202651
cipher_type);
26212652
}
26222653

2623-
if (IsAuthenticatedMode()) {
2624-
if (!InitAuthenticated(cipher_type, EVP_CIPHER_iv_length(cipher),
2625-
auth_tag_len))
2626-
return;
2627-
}
2628-
2629-
CHECK_EQ(1, EVP_CIPHER_CTX_set_key_length(ctx_.get(), key_len));
2630-
2631-
if (1 != EVP_CipherInit_ex(ctx_.get(),
2632-
nullptr,
2633-
nullptr,
2634-
reinterpret_cast<unsigned char*>(key),
2635-
reinterpret_cast<unsigned char*>(iv),
2636-
encrypt)) {
2637-
return ThrowCryptoError(env(), ERR_get_error(),
2638-
"Failed to initialize cipher");
2639-
}
2654+
CommonInit(cipher_type, cipher, key, key_len, iv,
2655+
EVP_CIPHER_iv_length(cipher), auth_tag_len);
26402656
}
26412657

26422658

@@ -2663,16 +2679,10 @@ void CipherBase::Init(const FunctionCallbackInfo<Value>& args) {
26632679
cipher->Init(*cipher_type, key_buf, key_buf_len, auth_tag_len);
26642680
}
26652681

2666-
static bool IsSupportedAuthenticatedMode(int mode) {
2667-
return mode == EVP_CIPH_CCM_MODE ||
2668-
mode == EVP_CIPH_GCM_MODE ||
2669-
mode == EVP_CIPH_OCB_MODE;
2670-
}
2671-
26722682
void CipherBase::InitIv(const char* cipher_type,
2673-
const char* key,
2683+
const unsigned char* key,
26742684
int key_len,
2675-
const char* iv,
2685+
const unsigned char* iv,
26762686
int iv_len,
26772687
unsigned int auth_tag_len) {
26782688
HandleScope scope(env()->isolate());
@@ -2700,38 +2710,7 @@ void CipherBase::InitIv(const char* cipher_type,
27002710
return env()->ThrowError("Invalid IV length");
27012711
}
27022712

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

27372716

@@ -2744,14 +2723,15 @@ void CipherBase::InitIv(const FunctionCallbackInfo<Value>& args) {
27442723

27452724
const node::Utf8Value cipher_type(env->isolate(), args[0]);
27462725
ssize_t key_len = Buffer::Length(args[1]);
2747-
const char* key_buf = Buffer::Data(args[1]);
2726+
const unsigned char* key_buf = reinterpret_cast<unsigned char*>(
2727+
Buffer::Data(args[1]));
27482728
ssize_t iv_len;
2749-
const char* iv_buf;
2729+
const unsigned char* iv_buf;
27502730
if (args[2]->IsNull()) {
27512731
iv_buf = nullptr;
27522732
iv_len = -1;
27532733
} else {
2754-
iv_buf = Buffer::Data(args[2]);
2734+
iv_buf = reinterpret_cast<unsigned char*>(Buffer::Data(args[2]));
27552735
iv_len = Buffer::Length(args[2]);
27562736
}
27572737

src/node_crypto.h

+9-2
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)