Skip to content

Commit 4c72d6d

Browse files
committed
src: add BoringSSL EVP enumeration fallback
BoringSSL declares EVP_CIPHER_do_all_sorted and EVP_MD_do_all_sorted, but stock no-decrepit builds do not provide those symbols. Add a Node build flag that keeps ncrypto and its dependents on a local BoringSSL fallback list when libdecrepit is absent. Keep embedders that provide the EVP enumeration symbols on the normal OpenSSL-compatible path, matching Electron's patched BoringSSL build. Signed-off-by: Filip Skokan <panva.ip@gmail.com>
1 parent a0a9a68 commit 4c72d6d

5 files changed

Lines changed: 108 additions & 1 deletion

File tree

deps/ncrypto/ncrypto.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <openssl/x509v3.h>
1010
#ifdef OPENSSL_IS_BORINGSSL
1111
#include <openssl/bytestring.h>
12+
#include <openssl/cipher.h>
1213
#include <openssl/pem.h>
1314
#endif
1415
#include <algorithm>
@@ -76,6 +77,28 @@ using NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
7677

7778
static constexpr int kX509NameFlagsRFC2253WithinUtf8JSON =
7879
XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB & ~ASN1_STRFLGS_ESC_CTRL;
80+
81+
#if NCRYPTO_USE_BORINGSSL_EVP_DO_ALL_FALLBACK
82+
struct BoringSSLCipher {
83+
const EVP_CIPHER* (*get)();
84+
const char* name;
85+
};
86+
87+
constexpr BoringSSLCipher kBoringSSLCiphers[] = {
88+
{EVP_aes_128_cbc, "aes-128-cbc"}, {EVP_aes_128_ctr, "aes-128-ctr"},
89+
{EVP_aes_128_ecb, "aes-128-ecb"}, {EVP_aes_128_gcm, "aes-128-gcm"},
90+
{EVP_aes_128_ofb, "aes-128-ofb"}, {EVP_aes_192_cbc, "aes-192-cbc"},
91+
{EVP_aes_192_ctr, "aes-192-ctr"}, {EVP_aes_192_ecb, "aes-192-ecb"},
92+
{EVP_aes_192_gcm, "aes-192-gcm"}, {EVP_aes_192_ofb, "aes-192-ofb"},
93+
{EVP_aes_256_cbc, "aes-256-cbc"}, {EVP_aes_256_ctr, "aes-256-ctr"},
94+
{EVP_aes_256_ecb, "aes-256-ecb"}, {EVP_aes_256_gcm, "aes-256-gcm"},
95+
{EVP_aes_256_ofb, "aes-256-ofb"}, {EVP_des_cbc, "des-cbc"},
96+
{EVP_des_ecb, "des-ecb"}, {EVP_des_ede, "des-ede"},
97+
{EVP_des_ede3_cbc, "des-ede3-cbc"}, {EVP_des_ede_cbc, "des-ede-cbc"},
98+
{EVP_rc2_cbc, "rc2-cbc"}, {EVP_rc4, "rc4"},
99+
};
100+
101+
#endif
79102
} // namespace
80103

81104
// ============================================================================
@@ -4286,6 +4309,12 @@ void Cipher::ForEach(Cipher::CipherNameCallback callback) {
42864309
CipherCallbackContext context;
42874310
context.cb = std::move(callback);
42884311

4312+
#if NCRYPTO_USE_BORINGSSL_EVP_DO_ALL_FALLBACK
4313+
for (const auto& cipher : kBoringSSLCiphers) {
4314+
static_cast<void>(cipher.get);
4315+
context.cb(cipher.name);
4316+
}
4317+
#else
42894318
EVP_CIPHER_do_all_sorted(
42904319
#if OPENSSL_VERSION_MAJOR >= 3
42914320
array_push_back<EVP_CIPHER,
@@ -4297,6 +4326,7 @@ void Cipher::ForEach(Cipher::CipherNameCallback callback) {
42974326
array_push_back<EVP_CIPHER>,
42984327
#endif
42994328
&context);
4329+
#endif
43004330
}
43014331

43024332
// ============================================================================

deps/ncrypto/ncrypto.gyp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
'variables': {
3+
'ncrypto_bssl_libdecrepit_missing%': 1,
34
'ncrypto_sources': [
45
'engine.cc',
56
'ncrypto.cc',
@@ -11,8 +12,14 @@
1112
'target_name': 'ncrypto',
1213
'type': 'static_library',
1314
'include_dirs': ['.'],
15+
'defines': [
16+
'NCRYPTO_BSSL_LIBDECREPIT_MISSING=<(ncrypto_bssl_libdecrepit_missing)',
17+
],
1418
'direct_dependent_settings': {
1519
'include_dirs': ['.'],
20+
'defines': [
21+
'NCRYPTO_BSSL_LIBDECREPIT_MISSING=<(ncrypto_bssl_libdecrepit_missing)',
22+
],
1623
},
1724
'sources': [ '<@(ncrypto_sources)' ],
1825
'conditions': [

deps/ncrypto/ncrypto.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@
2828
(OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20)))
2929
#endif
3030

31+
// BoringSSL declares the EVP_*_do_all* APIs, but their implementation may
32+
// live in libdecrepit. This matches standalone ncrypto's build flag.
33+
#ifndef NCRYPTO_BSSL_LIBDECREPIT_MISSING
34+
#define NCRYPTO_BSSL_LIBDECREPIT_MISSING 0
35+
#endif
36+
37+
#if defined(OPENSSL_IS_BORINGSSL) && NCRYPTO_BSSL_LIBDECREPIT_MISSING
38+
#define NCRYPTO_USE_BORINGSSL_EVP_DO_ALL_FALLBACK 1
39+
#else
40+
#define NCRYPTO_USE_BORINGSSL_EVP_DO_ALL_FALLBACK 0
41+
#endif
42+
3143
// The FIPS-related functions are only available
3244
// when the OpenSSL itself was compiled with FIPS support.
3345
#if defined(OPENSSL_FIPS) && !OPENSSL_VERSION_PREREQ(3, 0)

src/crypto/crypto_hash.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
#include "threadpoolwork-inl.h"
88
#include "v8.h"
99

10+
#if NCRYPTO_USE_BORINGSSL_EVP_DO_ALL_FALLBACK
11+
#include <openssl/digest.h>
12+
#endif
13+
1014
#include <cstdio>
1115

1216
namespace node {
@@ -41,6 +45,24 @@ void Hash::MemoryInfo(MemoryTracker* tracker) const {
4145
tracker->TrackFieldWithSize("md", digest_ ? md_len_ : 0);
4246
}
4347

48+
#if NCRYPTO_USE_BORINGSSL_EVP_DO_ALL_FALLBACK
49+
struct BoringSSLDigest {
50+
const EVP_MD* (*get)();
51+
const char* name;
52+
};
53+
54+
constexpr BoringSSLDigest kBoringSSLDigests[] = {
55+
{EVP_md4, "md4"},
56+
{EVP_md5, "md5"},
57+
{EVP_sha1, "sha1"},
58+
{EVP_sha224, "sha224"},
59+
{EVP_sha256, "sha256"},
60+
{EVP_sha384, "sha384"},
61+
{EVP_sha512, "sha512"},
62+
{EVP_sha512_256, "sha512-256"},
63+
};
64+
#endif
65+
4466
#if OPENSSL_VERSION_MAJOR >= 3
4567
void PushAliases(const char* name, void* data) {
4668
static_cast<std::vector<std::string>*>(data)->push_back(name);
@@ -122,7 +144,12 @@ void SaveSupportedHashAlgorithms(const EVP_MD* md,
122144
const std::vector<std::string>& GetSupportedHashAlgorithms(Environment* env) {
123145
if (env->supported_hash_algorithms.empty()) {
124146
MarkPopErrorOnReturn mark_pop_error_on_return;
125-
#if OPENSSL_VERSION_MAJOR >= 3
147+
#if NCRYPTO_USE_BORINGSSL_EVP_DO_ALL_FALLBACK
148+
for (const auto& digest : kBoringSSLDigests) {
149+
static_cast<void>(digest.get);
150+
env->supported_hash_algorithms.emplace_back(digest.name);
151+
}
152+
#elif OPENSSL_VERSION_MAJOR >= 3
126153
// Since we'll fetch the EVP_MD*, cache them along the way to speed up
127154
// later lookups instead of throwing them away immediately.
128155
EVP_MD_do_all_sorted(SaveSupportedHashAlgorithmsAndCacheMD, env);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
if (!process.features.openssl_is_boringssl)
8+
common.skip('BoringSSL-only test');
9+
10+
const assert = require('assert');
11+
const { getCiphers, getHashes } = require('crypto');
12+
13+
const ciphers = getCiphers();
14+
[
15+
'aes-128-cbc',
16+
'aes-256-gcm',
17+
'des-ede',
18+
'des-ede-cbc',
19+
'des-ede3-cbc',
20+
'rc2-cbc',
21+
'rc4',
22+
].forEach((cipher) => assert(ciphers.includes(cipher), cipher));
23+
24+
const hashes = getHashes();
25+
[
26+
'md4',
27+
'md5',
28+
'sha1',
29+
'sha256',
30+
'sha512-256',
31+
].forEach((hash) => assert(hashes.includes(hash), hash));

0 commit comments

Comments
 (0)