Skip to content

Commit 1b53fec

Browse files
committed
src, deps: port electron's boringssl workarounds
Signed-off-by: James M Snell <[email protected]>
1 parent c21d576 commit 1b53fec

File tree

2 files changed

+110
-6
lines changed

2 files changed

+110
-6
lines changed

deps/ncrypto/ncrypto.cc

+94-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "ncrypto.h"
2+
#include <openssl/asn1.h>
23
#include <openssl/bn.h>
34
#include <openssl/dh.h>
45
#include <openssl/evp.h>
@@ -99,7 +100,15 @@ std::optional<std::string> CryptoErrorList::pop_front() {
99100

100101
// ============================================================================
101102
DataPointer DataPointer::Alloc(size_t len) {
103+
#ifdef OPENSSL_IS_BORINGSSL
104+
// Boringssl does not implement OPENSSL_zalloc
105+
auto ptr = OPENSSL_malloc(len);
106+
if (ptr == nullptr) return {};
107+
memset(ptr, 0, len);
108+
return DataPointer(ptr, len);
109+
#else
102110
return DataPointer(OPENSSL_zalloc(len), len);
111+
#endif
103112
}
104113

105114
DataPointer DataPointer::Copy(const Buffer<const void>& buffer) {
@@ -218,7 +227,12 @@ BignumPointer BignumPointer::New() {
218227
}
219228

220229
BignumPointer BignumPointer::NewSecure() {
230+
#ifdef OPENSSL_IS_BORINGSSL
231+
// Boringssl does not implement BN_secure_new.
232+
return New();
233+
#else
221234
return BignumPointer(BN_secure_new());
235+
#endif
222236
}
223237

224238
BignumPointer& BignumPointer::operator=(BignumPointer&& other) noexcept {
@@ -492,6 +506,7 @@ constexpr int days_from_epoch(int y, unsigned m, unsigned d) {
492506
return era * 146097 + static_cast<int>(doe) - 719468;
493507
}
494508

509+
#ifndef OPENSSL_IS_BORINGSSL
495510
// tm must be in UTC
496511
// using time_t causes problems on 32-bit systems and windows x64.
497512
int64_t PortableTimeGM(struct tm* t) {
@@ -512,6 +527,7 @@ int64_t PortableTimeGM(struct tm* t) {
512527
t->tm_min) +
513528
t->tm_sec;
514529
}
530+
#endif
515531

516532
// ============================================================================
517533
// SPKAC
@@ -822,7 +838,7 @@ bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {
822838

823839
bool ok = true;
824840

825-
for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
841+
for (OPENSSL_SIZE_T i = 0; i < sk_GENERAL_NAME_num(names); i++) {
826842
GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
827843

828844
if (i != 0) BIO_write(out.get(), ", ", 2);
@@ -846,7 +862,7 @@ bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) {
846862

847863
bool ok = true;
848864

849-
for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(descs); i++) {
865+
for (OPENSSL_SIZE_T i = 0; i < sk_ACCESS_DESCRIPTION_num(descs); i++) {
850866
ACCESS_DESCRIPTION* desc = sk_ACCESS_DESCRIPTION_value(descs, i);
851867

852868
if (i != 0) BIO_write(out.get(), "\n", 1);
@@ -999,15 +1015,31 @@ BIOPointer X509View::getValidTo() const {
9991015
}
10001016

10011017
int64_t X509View::getValidToTime() const {
1018+
#ifdef OPENSSL_IS_BORINGSSL
1019+
// Boringssl does not implement ASN1_TIME_to_tm in a public way,
1020+
// and only recently added ASN1_TIME_to_posix. Some boringssl
1021+
// users on older version may still need to patch around this
1022+
// or use a different implementation.
1023+
int64_t tp;
1024+
ASN1_TIME_to_posix(X509_get0_notAfter(cert_), &tp);
1025+
return tp;
1026+
#else
10021027
struct tm tp;
10031028
ASN1_TIME_to_tm(X509_get0_notAfter(cert_), &tp);
10041029
return PortableTimeGM(&tp);
1030+
#endif
10051031
}
10061032

10071033
int64_t X509View::getValidFromTime() const {
1034+
#ifdef OPENSSL_IS_BORINGSSL
1035+
int64_t tp;
1036+
ASN1_TIME_to_posix(X509_get0_notBefore(cert_), &tp);
1037+
return tp;
1038+
#else
10081039
struct tm tp;
10091040
ASN1_TIME_to_tm(X509_get0_notBefore(cert_), &tp);
10101041
return PortableTimeGM(&tp);
1042+
#endif
10111043
}
10121044

10131045
DataPointer X509View::getSerialNumber() const {
@@ -1324,7 +1356,12 @@ BIOPointer BIOPointer::NewMem() {
13241356
}
13251357

13261358
BIOPointer BIOPointer::NewSecMem() {
1359+
#ifdef OPENSSL_IS_BORINGSSL
1360+
// Boringssl does not implement the BIO_s_secmem API.
1361+
return BIOPointer(BIO_new(BIO_s_mem()));
1362+
#else
13271363
return BIOPointer(BIO_new(BIO_s_secmem()));
1364+
#endif
13281365
}
13291366

13301367
BIOPointer BIOPointer::New(const BIO_METHOD* method) {
@@ -1394,8 +1431,11 @@ BignumPointer DHPointer::FindGroup(const std::string_view name,
13941431
#define V(n, p) \
13951432
if (EqualNoCase(name, n)) return BignumPointer(p(nullptr));
13961433
if (option != FindGroupOption::NO_SMALL_PRIMES) {
1434+
#ifndef OPENSSL_IS_BORINGSSL
1435+
// Boringssl does not support the 768 and 1024 small primes
13971436
V("modp1", BN_get_rfc2409_prime_768);
13981437
V("modp2", BN_get_rfc2409_prime_1024);
1438+
#endif
13991439
V("modp5", BN_get_rfc3526_prime_1536);
14001440
}
14011441
V("modp14", BN_get_rfc3526_prime_2048);
@@ -1467,15 +1507,22 @@ DHPointer::CheckResult DHPointer::check() {
14671507
DHPointer::CheckPublicKeyResult DHPointer::checkPublicKey(
14681508
const BignumPointer& pub_key) {
14691509
ClearErrorOnReturn clearErrorOnReturn;
1470-
if (!pub_key || !dh_) return DHPointer::CheckPublicKeyResult::CHECK_FAILED;
1510+
if (!pub_key || !dh_) {
1511+
return DHPointer::CheckPublicKeyResult::CHECK_FAILED;
1512+
}
14711513
int codes = 0;
1472-
if (DH_check_pub_key(dh_.get(), pub_key.get(), &codes) != 1)
1514+
if (DH_check_pub_key(dh_.get(), pub_key.get(), &codes) != 1) {
14731515
return DHPointer::CheckPublicKeyResult::CHECK_FAILED;
1516+
}
1517+
#ifndef OPENSSL_IS_BORINGSSL
1518+
// Boringssl does not define DH_CHECK_PUBKEY_TOO_SMALL or TOO_LARGE
14741519
if (codes & DH_CHECK_PUBKEY_TOO_SMALL) {
14751520
return DHPointer::CheckPublicKeyResult::TOO_SMALL;
1476-
} else if (codes & DH_CHECK_PUBKEY_TOO_SMALL) {
1521+
} else if (codes & DH_CHECK_PUBKEY_TOO_LARGE) {
14771522
return DHPointer::CheckPublicKeyResult::TOO_LARGE;
1478-
} else if (codes != 0) {
1523+
}
1524+
#endif
1525+
if (codes != 0) {
14791526
return DHPointer::CheckPublicKeyResult::INVALID;
14801527
}
14811528
return CheckPublicKeyResult::NONE;
@@ -2530,6 +2577,7 @@ std::optional<uint32_t> SSLPointer::verifyPeerCertificate() const {
25302577

25312578
const std::string_view SSLPointer::getClientHelloAlpn() const {
25322579
if (ssl_ == nullptr) return {};
2580+
#ifndef OPENSSL_IS_BORINGSSL
25332581
const unsigned char* buf;
25342582
size_t len;
25352583
size_t rem;
@@ -2546,10 +2594,15 @@ const std::string_view SSLPointer::getClientHelloAlpn() const {
25462594
len = (buf[0] << 8) | buf[1];
25472595
if (len + 2 != rem) return {};
25482596
return reinterpret_cast<const char*>(buf + 3);
2597+
#else
2598+
// Boringssl doesn't have a public API for this.
2599+
return {};
2600+
#endif
25492601
}
25502602

25512603
const std::string_view SSLPointer::getClientHelloServerName() const {
25522604
if (ssl_ == nullptr) return {};
2605+
#ifndef OPENSSL_IS_BORINGSSL
25532606
const unsigned char* buf;
25542607
size_t len;
25552608
size_t rem;
@@ -2569,6 +2622,10 @@ const std::string_view SSLPointer::getClientHelloServerName() const {
25692622
len = (*(buf + 3) << 8) | *(buf + 4);
25702623
if (len + 2 > rem) return {};
25712624
return reinterpret_cast<const char*>(buf + 5);
2625+
#else
2626+
// Boringssl doesn't have a public API for this.
2627+
return {};
2628+
#endif
25722629
}
25732630

25742631
std::optional<const std::string_view> SSLPointer::GetServerName(
@@ -2602,7 +2659,11 @@ bool SSLPointer::isServer() const {
26022659
EVPKeyPointer SSLPointer::getPeerTempKey() const {
26032660
if (!ssl_) return {};
26042661
EVP_PKEY* raw_key = nullptr;
2662+
#ifndef OPENSSL_IS_BORINGSSL
26052663
if (!SSL_get_peer_tmp_key(get(), &raw_key)) return {};
2664+
#else
2665+
if (!SSL_get_server_tmp_key(get(), &raw_key)) return {};
2666+
#endif
26062667
return EVPKeyPointer(raw_key);
26072668
}
26082669

@@ -3167,9 +3228,15 @@ int EVPKeyCtxPointer::initForSign() {
31673228
}
31683229

31693230
bool EVPKeyCtxPointer::setDhParameters(int prime_size, uint32_t generator) {
3231+
#ifndef OPENSSL_IS_BORINGSSL
31703232
if (!ctx_) return false;
31713233
return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx_.get(), prime_size) == 1 &&
31723234
EVP_PKEY_CTX_set_dh_paramgen_generator(ctx_.get(), generator) == 1;
3235+
#else
3236+
// TODO(jasnell): Boringssl appears not to support this operation.
3237+
// Is there an alternative approach that Boringssl does support?
3238+
return false;
3239+
#endif
31733240
}
31743241

31753242
bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits,
@@ -3249,6 +3316,7 @@ bool EVPKeyCtxPointer::setRsaPssSaltlen(int salt_len) {
32493316
}
32503317

32513318
bool EVPKeyCtxPointer::setRsaImplicitRejection() {
3319+
#ifndef OPENSSL_IS_BORINGSSL
32523320
if (!ctx_) return false;
32533321
return EVP_PKEY_CTX_ctrl_str(
32543322
ctx_.get(), "rsa_pkcs1_implicit_rejection", "1") > 0;
@@ -3259,6 +3327,11 @@ bool EVPKeyCtxPointer::setRsaImplicitRejection() {
32593327
// of how it is set. The call to set the value
32603328
// will not affect what is used since a different context is
32613329
// used in the call if the option is supported
3330+
#else
3331+
// TODO(jasnell): Boringssl appears not to support this operation.
3332+
// Is there an alternative approach that Boringssl does support?
3333+
return true;
3334+
#endif
32623335
}
32633336

32643337
bool EVPKeyCtxPointer::setRsaOaepLabel(DataPointer&& data) {
@@ -3311,16 +3384,31 @@ EVPKeyPointer EVPKeyCtxPointer::paramgen() const {
33113384

33123385
bool EVPKeyCtxPointer::publicCheck() const {
33133386
if (!ctx_) return false;
3387+
#ifndef OPENSSL_IS_BORINGSSL
3388+
return EVP_PKEY_public_check(ctx_.get()) == 1;
33143389
#if OPENSSL_VERSION_MAJOR >= 3
33153390
return EVP_PKEY_public_check_quick(ctx_.get()) == 1;
33163391
#else
33173392
return EVP_PKEY_public_check(ctx_.get()) == 1;
33183393
#endif
3394+
#else // OPENSSL_IS_BORINGSSL
3395+
// Boringssl appears not to support this operation.
3396+
// TODO(jasnell): Is there an alternative approach that Boringssl does
3397+
// support?
3398+
return true;
3399+
#endif
33193400
}
33203401

33213402
bool EVPKeyCtxPointer::privateCheck() const {
33223403
if (!ctx_) return false;
3404+
#ifndef OPENSSL_IS_BORINGSSL
33233405
return EVP_PKEY_check(ctx_.get()) == 1;
3406+
#else
3407+
// Boringssl appears not to support this operation.
3408+
// TODO(jasnell): Is there an alternative approach that Boringssl does
3409+
// support?
3410+
return true;
3411+
#endif
33243412
}
33253413

33263414
bool EVPKeyCtxPointer::verify(const Buffer<const unsigned char>& sig,

deps/ncrypto/ncrypto.h

+16
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@
4040
#define NCRYPTO_MUST_USE_RESULT
4141
#endif
4242

43+
#ifdef OPENSSL_IS_BORINGSSL
44+
// Boringssl has opted to use size_t for some size related
45+
// APIs while Openssl is still using ints
46+
using OPENSSL_SIZE_T = size_t;
47+
#else
48+
using OPENSSL_SIZE_T = int;
49+
#endif
50+
4351
namespace ncrypto {
4452

4553
// ============================================================================
@@ -845,17 +853,25 @@ class DHPointer final {
845853
UNABLE_TO_CHECK_GENERATOR = DH_UNABLE_TO_CHECK_GENERATOR,
846854
NOT_SUITABLE_GENERATOR = DH_NOT_SUITABLE_GENERATOR,
847855
Q_NOT_PRIME = DH_CHECK_Q_NOT_PRIME,
856+
#ifndef OPENSSL_IS_BORINGSSL
857+
// Boringssl does not define the DH_CHECK_INVALID_[Q or J]_VALUE
848858
INVALID_Q = DH_CHECK_INVALID_Q_VALUE,
849859
INVALID_J = DH_CHECK_INVALID_J_VALUE,
860+
#endif
850861
CHECK_FAILED = 512,
851862
};
852863
CheckResult check();
853864

854865
enum class CheckPublicKeyResult {
855866
NONE,
867+
#ifndef OPENSSL_IS_BORINGSSL
868+
// Boringssl does not define DH_R_CHECK_PUBKEY_TOO_SMALL or TOO_LARGE
856869
TOO_SMALL = DH_R_CHECK_PUBKEY_TOO_SMALL,
857870
TOO_LARGE = DH_R_CHECK_PUBKEY_TOO_LARGE,
858871
INVALID = DH_R_CHECK_PUBKEY_INVALID,
872+
#else
873+
INVALID = DH_R_INVALID_PUBKEY,
874+
#endif
859875
CHECK_FAILED = 512,
860876
};
861877
// Check to see if the given public key is suitable for this DH instance.

0 commit comments

Comments
 (0)