Skip to content

Commit

Permalink
crypto: add api to get openssl security level
Browse files Browse the repository at this point in the history
Distros may compile with a different openssl security level than the
default. In addition there has been some discussion with respect
to shipping with a different default security security level in
different Node.js versions in order to main stabilty. Exposing the
default openssl security level with let us have tests that work in
these situations as well as allow applications to better cope with
the avialable crypto algorithms.

- add API to get openssl security level
- modify one test to use security level instead
  of openssl version as an example

Signed-off-by: Michael Dawson <[email protected]>
  • Loading branch information
mhdawson committed Jan 15, 2025
1 parent 58ac655 commit 3f76985
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 3 deletions.
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 = 1;
#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 @@ -704,6 +727,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 @@ -715,6 +741,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
registry->Register(TestFipsCrypto);
registry->Register(SecureBuffer);
registry->Register(SecureHeapUsed);
registry->Register(GetOpenSSLSecLevelCrypto);
}

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

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

const assert = require('assert');

const secLevel = require('internal/crypto/util').getOpenSSLSecLevel();
assert.ok(secLevel >= 0 && secLevel <= 5);
10 changes: 7 additions & 3 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 All @@ -25,6 +25,8 @@ const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

const secLevel = require('internal/crypto/util').getOpenSSLSecLevel();

if (!common.opensslCli)
common.skip('missing openssl-cli');

Expand All @@ -43,7 +45,7 @@ const dheCipher = 'DHE-RSA-AES128-SHA256';
const ecdheCipher = 'ECDHE-RSA-AES128-SHA256';
const ciphers = `${dheCipher}:${ecdheCipher}`;

if (!common.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 @@ -107,7 +109,9 @@ function testCustomParam(keylen, expectedCipher) {
}, /DH parameter is less than 1024 bits/);

// Custom DHE parameters are supported (but discouraged).
if (!common.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

0 comments on commit 3f76985

Please sign in to comment.