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: https://github.com/nodejs/node/pull/23011 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
This commit is contained in:
parent
9b292272ff
commit
b7bdde013a
@ -2545,6 +2545,12 @@ int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsSupportedAuthenticatedMode(int mode) {
|
||||||
|
return mode == EVP_CIPH_CCM_MODE ||
|
||||||
|
mode == EVP_CIPH_GCM_MODE ||
|
||||||
|
mode == EVP_CIPH_OCB_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
void CipherBase::Initialize(Environment* env, Local<Object> target) {
|
void CipherBase::Initialize(Environment* env, Local<Object> target) {
|
||||||
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
|
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
|
||||||
|
|
||||||
@ -2571,6 +2577,43 @@ void CipherBase::New(const FunctionCallbackInfo<Value>& args) {
|
|||||||
new CipherBase(env, args.This(), kind);
|
new CipherBase(env, args.This(), kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CipherBase::CommonInit(const char* cipher_type,
|
||||||
|
const EVP_CIPHER* cipher,
|
||||||
|
const unsigned char* key,
|
||||||
|
int key_len,
|
||||||
|
const unsigned char* iv,
|
||||||
|
int iv_len,
|
||||||
|
unsigned int auth_tag_len) {
|
||||||
|
CHECK(!ctx_);
|
||||||
|
ctx_.reset(EVP_CIPHER_CTX_new());
|
||||||
|
|
||||||
|
const int mode = EVP_CIPHER_mode(cipher);
|
||||||
|
if (mode == EVP_CIPH_WRAP_MODE)
|
||||||
|
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
||||||
|
|
||||||
|
const bool encrypt = (kind_ == kCipher);
|
||||||
|
if (1 != EVP_CipherInit_ex(ctx_.get(), cipher, nullptr,
|
||||||
|
nullptr, nullptr, encrypt)) {
|
||||||
|
return ThrowCryptoError(env(), ERR_get_error(),
|
||||||
|
"Failed to initialize cipher");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSupportedAuthenticatedMode(mode)) {
|
||||||
|
CHECK_GE(iv_len, 0);
|
||||||
|
if (!InitAuthenticated(cipher_type, iv_len, auth_tag_len))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_.get(), key_len)) {
|
||||||
|
ctx_.reset();
|
||||||
|
return env()->ThrowError("Invalid key length");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 != EVP_CipherInit_ex(ctx_.get(), nullptr, nullptr, key, iv, encrypt)) {
|
||||||
|
return ThrowCryptoError(env(), ERR_get_error(),
|
||||||
|
"Failed to initialize cipher");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CipherBase::Init(const char* cipher_type,
|
void CipherBase::Init(const char* cipher_type,
|
||||||
const char* key_buf,
|
const char* key_buf,
|
||||||
@ -2586,7 +2629,6 @@ void CipherBase::Init(const char* cipher_type,
|
|||||||
}
|
}
|
||||||
#endif // NODE_FIPS_MODE
|
#endif // NODE_FIPS_MODE
|
||||||
|
|
||||||
CHECK(!ctx_);
|
|
||||||
const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type);
|
const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type);
|
||||||
if (cipher == nullptr)
|
if (cipher == nullptr)
|
||||||
return env()->ThrowError("Unknown cipher");
|
return env()->ThrowError("Unknown cipher");
|
||||||
@ -2604,20 +2646,9 @@ void CipherBase::Init(const char* cipher_type,
|
|||||||
iv);
|
iv);
|
||||||
CHECK_NE(key_len, 0);
|
CHECK_NE(key_len, 0);
|
||||||
|
|
||||||
ctx_.reset(EVP_CIPHER_CTX_new());
|
|
||||||
|
|
||||||
const int mode = EVP_CIPHER_mode(cipher);
|
const int mode = EVP_CIPHER_mode(cipher);
|
||||||
if (mode == EVP_CIPH_WRAP_MODE)
|
if (kind_ == kCipher && (mode == EVP_CIPH_CTR_MODE ||
|
||||||
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
mode == EVP_CIPH_GCM_MODE ||
|
||||||
|
|
||||||
const bool encrypt = (kind_ == kCipher);
|
|
||||||
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)) {
|
mode == EVP_CIPH_CCM_MODE)) {
|
||||||
// Ignore the return value (i.e. possible exception) because we are
|
// Ignore the return value (i.e. possible exception) because we are
|
||||||
// not calling back into JS anyway.
|
// not calling back into JS anyway.
|
||||||
@ -2626,23 +2657,8 @@ void CipherBase::Init(const char* cipher_type,
|
|||||||
cipher_type);
|
cipher_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsAuthenticatedMode()) {
|
CommonInit(cipher_type, cipher, key, key_len, iv,
|
||||||
if (!InitAuthenticated(cipher_type, EVP_CIPHER_iv_length(cipher),
|
EVP_CIPHER_iv_length(cipher), auth_tag_len);
|
||||||
auth_tag_len))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_EQ(1, EVP_CIPHER_CTX_set_key_length(ctx_.get(), key_len));
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2669,16 +2685,10 @@ void CipherBase::Init(const FunctionCallbackInfo<Value>& args) {
|
|||||||
cipher->Init(*cipher_type, key_buf, key_buf_len, auth_tag_len);
|
cipher->Init(*cipher_type, key_buf, key_buf_len, auth_tag_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsSupportedAuthenticatedMode(int mode) {
|
|
||||||
return mode == EVP_CIPH_CCM_MODE ||
|
|
||||||
mode == EVP_CIPH_GCM_MODE ||
|
|
||||||
mode == EVP_CIPH_OCB_MODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CipherBase::InitIv(const char* cipher_type,
|
void CipherBase::InitIv(const char* cipher_type,
|
||||||
const char* key,
|
const unsigned char* key,
|
||||||
int key_len,
|
int key_len,
|
||||||
const char* iv,
|
const unsigned char* iv,
|
||||||
int iv_len,
|
int iv_len,
|
||||||
unsigned int auth_tag_len) {
|
unsigned int auth_tag_len) {
|
||||||
HandleScope scope(env()->isolate());
|
HandleScope scope(env()->isolate());
|
||||||
@ -2706,38 +2716,7 @@ void CipherBase::InitIv(const char* cipher_type,
|
|||||||
return env()->ThrowError("Invalid IV length");
|
return env()->ThrowError("Invalid IV length");
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx_.reset(EVP_CIPHER_CTX_new());
|
CommonInit(cipher_type, cipher, key, key_len, iv, iv_len, auth_tag_len);
|
||||||
|
|
||||||
if (mode == EVP_CIPH_WRAP_MODE)
|
|
||||||
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
|
||||||
|
|
||||||
const bool encrypt = (kind_ == kCipher);
|
|
||||||
if (1 != EVP_CipherInit_ex(ctx_.get(), cipher, nullptr,
|
|
||||||
nullptr, nullptr, encrypt)) {
|
|
||||||
return ThrowCryptoError(env(), ERR_get_error(),
|
|
||||||
"Failed to initialize cipher");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_authenticated_mode) {
|
|
||||||
CHECK(has_iv);
|
|
||||||
if (!InitAuthenticated(cipher_type, iv_len, auth_tag_len))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EVP_CIPHER_CTX_set_key_length(ctx_.get(), key_len)) {
|
|
||||||
ctx_.reset();
|
|
||||||
return env()->ThrowError("Invalid key length");
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2750,14 +2729,15 @@ void CipherBase::InitIv(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
const node::Utf8Value cipher_type(env->isolate(), args[0]);
|
const node::Utf8Value cipher_type(env->isolate(), args[0]);
|
||||||
ssize_t key_len = Buffer::Length(args[1]);
|
ssize_t key_len = Buffer::Length(args[1]);
|
||||||
const char* key_buf = Buffer::Data(args[1]);
|
const unsigned char* key_buf = reinterpret_cast<unsigned char*>(
|
||||||
|
Buffer::Data(args[1]));
|
||||||
ssize_t iv_len;
|
ssize_t iv_len;
|
||||||
const char* iv_buf;
|
const unsigned char* iv_buf;
|
||||||
if (args[2]->IsNull()) {
|
if (args[2]->IsNull()) {
|
||||||
iv_buf = nullptr;
|
iv_buf = nullptr;
|
||||||
iv_len = -1;
|
iv_len = -1;
|
||||||
} else {
|
} else {
|
||||||
iv_buf = Buffer::Data(args[2]);
|
iv_buf = reinterpret_cast<unsigned char*>(Buffer::Data(args[2]));
|
||||||
iv_len = Buffer::Length(args[2]);
|
iv_len = Buffer::Length(args[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,14 +370,21 @@ class CipherBase : public BaseObject {
|
|||||||
};
|
};
|
||||||
static const unsigned kNoAuthTagLength = static_cast<unsigned>(-1);
|
static const unsigned kNoAuthTagLength = static_cast<unsigned>(-1);
|
||||||
|
|
||||||
|
void CommonInit(const char* cipher_type,
|
||||||
|
const EVP_CIPHER* cipher,
|
||||||
|
const unsigned char* key,
|
||||||
|
int key_len,
|
||||||
|
const unsigned char* iv,
|
||||||
|
int iv_len,
|
||||||
|
unsigned int auth_tag_len);
|
||||||
void Init(const char* cipher_type,
|
void Init(const char* cipher_type,
|
||||||
const char* key_buf,
|
const char* key_buf,
|
||||||
int key_buf_len,
|
int key_buf_len,
|
||||||
unsigned int auth_tag_len);
|
unsigned int auth_tag_len);
|
||||||
void InitIv(const char* cipher_type,
|
void InitIv(const char* cipher_type,
|
||||||
const char* key,
|
const unsigned char* key,
|
||||||
int key_len,
|
int key_len,
|
||||||
const char* iv,
|
const unsigned char* iv,
|
||||||
int iv_len,
|
int iv_len,
|
||||||
unsigned int auth_tag_len);
|
unsigned int auth_tag_len);
|
||||||
bool InitAuthenticated(const char* cipher_type, int iv_len,
|
bool InitAuthenticated(const char* cipher_type, int iv_len,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user