Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose security levels #56601

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/internal/crypto/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const {
setEngine: _setEngine,
secureHeapUsed: _secureHeapUsed,
getCachedAliases,
getOpenSSLSecLevelCrypto: getOpenSSLSecLevel,
} = internalBinding('crypto');

const { getOptionValue } = require('internal/options');
Expand Down Expand Up @@ -631,4 +632,5 @@ module.exports = {
secureHeapUsed,
getCachedHashId,
getHashCache,
getOpenSSLSecLevel,
};
27 changes: 27 additions & 0 deletions src/crypto/crypto_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ using ncrypto::BIOPointer;
using ncrypto::CryptoErrorList;
using ncrypto::EnginePointer;
using ncrypto::EVPKeyCtxPointer;
using ncrypto::SSLCtxPointer;
using ncrypto::SSLPointer;
using v8::ArrayBuffer;
using v8::BackingStore;
using v8::BigInt;
Expand Down Expand Up @@ -201,6 +203,27 @@ void TestFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args) {
args.GetReturnValue().Set(ncrypto::testFipsEnabled() ? 1 : 0);
}

void GetOpenSSLSecLevelCrypto(const FunctionCallbackInfo<Value>& args) {
// for BoringSSL assume the same as the default
int sec_level = OPENSSL_TLS_SECURITY_LEVEL;
#ifndef OPENSSL_IS_BORINGSSL
Environment* env = Environment::GetCurrent(args);

auto ctx = SSLCtxPointer::New();
if (!ctx) {
return ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_new");
}

auto ssl = SSLPointer::New(ctx);
if (!ssl) {
return ThrowCryptoError(env, ERR_get_error(), "SSL_new");
}

sec_level = SSL_get_security_level(ssl);
#endif // OPENSSL_IS_BORINGSSL
args.GetReturnValue().Set(sec_level);
}

void CryptoErrorStore::Capture() {
errors_.clear();
while (const uint32_t err = ERR_get_error()) {
Expand Down Expand Up @@ -699,6 +722,9 @@ void Initialize(Environment* env, Local<Object> target) {

SetMethod(context, target, "secureBuffer", SecureBuffer);
SetMethod(context, target, "secureHeapUsed", SecureHeapUsed);

SetMethodNoSideEffect(
context, target, "getOpenSSLSecLevelCrypto", GetOpenSSLSecLevelCrypto);
}
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
#ifndef OPENSSL_NO_ENGINE
Expand All @@ -710,6 +736,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
registry->Register(TestFipsCrypto);
registry->Register(SecureBuffer);
registry->Register(SecureHeapUsed);
registry->Register(GetOpenSSLSecLevelCrypto);
}

} // namespace Util
Expand Down
18 changes: 18 additions & 0 deletions test/parallel/test-crypto-sec-level.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Flags: --expose-internals
'use strict';

const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');

// OpenSSL has a set of security levels which affect what algorithms
// are available by default. Different OpenSSL veresions have different
// default security levels and we use this value to adjust what a test
// expects based on the security level. You can read more in
// https://docs.openssl.org/1.1.1/man3/SSL_CTX_set_security_level/#default-callback-behaviour
// This test simply validates that we can get some value for the secLevel
// when needed by tests.
const secLevel = require('internal/crypto/util').getOpenSSLSecLevel();
assert.ok(secLevel >= 0 && secLevel <= 5);
16 changes: 12 additions & 4 deletions test/parallel/test-tls-dhe.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Flags: --no-warnings
// Flags: --no-warnings --expose-internals
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
Expand Down Expand Up @@ -27,10 +27,16 @@ if (!common.hasCrypto) {
}

const {
hasOpenSSL,
opensslCli,
} = require('../common/crypto');

// OpenSSL has a set of security levels which affect what algorithms
// are available by default. Different OpenSSL veresions have different
// default security levels and we use this value to adjust what a test
// expects based on the security level. You can read more in
// https://docs.openssl.org/1.1.1/man3/SSL_CTX_set_security_level/#default-callback-behaviour
const secLevel = require('internal/crypto/util').getOpenSSLSecLevel();

if (!opensslCli) {
common.skip('missing openssl-cli');
}
Expand All @@ -50,7 +56,7 @@ const dheCipher = 'DHE-RSA-AES128-SHA256';
const ecdheCipher = 'ECDHE-RSA-AES128-SHA256';
const ciphers = `${dheCipher}:${ecdheCipher}`;

if (!hasOpenSSL(3, 2)) {
if (secLevel < 2) {
// Test will emit a warning because the DH parameter size is < 2048 bits
// when the test is run on versions lower than OpenSSL32
common.expectWarning('SecurityWarning',
Expand Down Expand Up @@ -114,7 +120,9 @@ function testCustomParam(keylen, expectedCipher) {
}, /DH parameter is less than 1024 bits/);

// Custom DHE parameters are supported (but discouraged).
if (!hasOpenSSL(3, 2)) {
// 1024 is disallowed at security level 2 and above so use 3072 instead
// for higher security levels
if (secLevel < 2) {
await testCustomParam(1024, dheCipher);
} else {
await testCustomParam(3072, dheCipher);
Expand Down
Loading