Skip to content

Commit 0fff4d2

Browse files
mscdexbengl
authored andcommitted
crypto: do not advertise unsupported algorithms
Fixes: #41857 PR-URL: #41864 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Filip Skokan <[email protected]>
1 parent 76f0f1c commit 0fff4d2

File tree

4 files changed

+79
-3
lines changed

4 files changed

+79
-3
lines changed

src/crypto/crypto_cipher.cc

+12-1
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,19 @@ void CipherBase::GetSSLCiphers(const FunctionCallbackInfo<Value>& args) {
235235

236236
void CipherBase::GetCiphers(const FunctionCallbackInfo<Value>& args) {
237237
Environment* env = Environment::GetCurrent(args);
238+
MarkPopErrorOnReturn mark_pop_error_on_return;
238239
CipherPushContext ctx(env);
239-
EVP_CIPHER_do_all_sorted(array_push_back<EVP_CIPHER>, &ctx);
240+
EVP_CIPHER_do_all_sorted(
241+
#if OPENSSL_VERSION_MAJOR >= 3
242+
array_push_back<EVP_CIPHER,
243+
EVP_CIPHER_fetch,
244+
EVP_CIPHER_free,
245+
EVP_get_cipherbyname,
246+
EVP_CIPHER_get0_name>,
247+
#else
248+
array_push_back<EVP_CIPHER>,
249+
#endif
250+
&ctx);
240251
args.GetReturnValue().Set(ctx.ToJSArray());
241252
}
242253

src/crypto/crypto_hash.cc

+12-1
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,19 @@ void Hash::MemoryInfo(MemoryTracker* tracker) const {
3535

3636
void Hash::GetHashes(const FunctionCallbackInfo<Value>& args) {
3737
Environment* env = Environment::GetCurrent(args);
38+
MarkPopErrorOnReturn mark_pop_error_on_return;
3839
CipherPushContext ctx(env);
39-
EVP_MD_do_all_sorted(array_push_back<EVP_MD>, &ctx);
40+
EVP_MD_do_all_sorted(
41+
#if OPENSSL_VERSION_MAJOR >= 3
42+
array_push_back<EVP_MD,
43+
EVP_MD_fetch,
44+
EVP_MD_free,
45+
EVP_get_digestbyname,
46+
EVP_MD_get0_name>,
47+
#else
48+
array_push_back<EVP_MD>,
49+
#endif
50+
&ctx);
4051
args.GetReturnValue().Set(ctx.ToJSArray());
4152
}
4253

src/crypto/crypto_util.h

+39-1
Original file line numberDiff line numberDiff line change
@@ -616,13 +616,51 @@ class CipherPushContext {
616616
Environment* env_;
617617
};
618618

619+
#if OPENSSL_VERSION_MAJOR >= 3
620+
template <class TypeName,
621+
TypeName* fetch_type(OSSL_LIB_CTX*, const char*, const char*),
622+
void free_type(TypeName*),
623+
const TypeName* getbyname(const char*),
624+
const char* getname(const TypeName*)>
625+
void array_push_back(const TypeName* evp_ref,
626+
const char* from,
627+
const char* to,
628+
void* arg) {
629+
if (!from)
630+
return;
631+
632+
const TypeName* real_instance = getbyname(from);
633+
if (!real_instance)
634+
return;
635+
636+
const char* real_name = getname(real_instance);
637+
if (!real_name)
638+
return;
639+
640+
// EVP_*_fetch() does not support alias names, so we need to pass it the
641+
// real/original algorithm name.
642+
// We use EVP_*_fetch() as a filter here because it will only return an
643+
// instance if the algorithm is supported by the public OpenSSL APIs (some
644+
// algorithms are used internally by OpenSSL and are also passed to this
645+
// callback).
646+
TypeName* fetched = fetch_type(nullptr, real_name, nullptr);
647+
if (!fetched)
648+
return;
649+
650+
free_type(fetched);
651+
static_cast<CipherPushContext*>(arg)->push_back(from);
652+
}
653+
#else
619654
template <class TypeName>
620-
void array_push_back(const TypeName* md,
655+
void array_push_back(const TypeName* evp_ref,
621656
const char* from,
622657
const char* to,
623658
void* arg) {
659+
if (!from)
660+
return;
624661
static_cast<CipherPushContext*>(arg)->push_back(from);
625662
}
663+
#endif
626664

627665
inline bool IsAnyByteSource(v8::Local<v8::Value> arg) {
628666
return arg->IsArrayBufferView() ||

test/parallel/test-crypto.js

+16
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,19 @@ function validateList(list) {
121121
const cryptoCiphers = crypto.getCiphers();
122122
assert(crypto.getCiphers().includes('aes-128-cbc'));
123123
validateList(cryptoCiphers);
124+
// Make sure all of the ciphers are supported by OpenSSL
125+
for (const algo of cryptoCiphers) {
126+
const { ivLength, keyLength, mode } = crypto.getCipherInfo(algo);
127+
let options;
128+
if (mode === 'ccm')
129+
options = { authTagLength: 8 };
130+
else if (mode === 'ocb' || algo === 'chacha20-poly1305')
131+
options = { authTagLength: 16 };
132+
crypto.createCipheriv(algo,
133+
crypto.randomBytes(keyLength),
134+
crypto.randomBytes(ivLength || 0),
135+
options);
136+
}
124137

125138
// Assume that we have at least AES256-SHA.
126139
const tlsCiphers = tls.getCiphers();
@@ -140,6 +153,9 @@ assert(!crypto.getHashes().includes('SHA256'));
140153
assert(crypto.getHashes().includes('RSA-SHA1'));
141154
assert(!crypto.getHashes().includes('rsa-sha1'));
142155
validateList(crypto.getHashes());
156+
// Make sure all of the hashes are supported by OpenSSL
157+
for (const algo of crypto.getHashes())
158+
crypto.createHash(algo);
143159

144160
// Assume that we have at least secp384r1.
145161
assert.notStrictEqual(crypto.getCurves().length, 0);

0 commit comments

Comments
 (0)