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

src,deps: port some electron boringssl workarounds #56812

Closed
wants to merge 1 commit 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
100 changes: 94 additions & 6 deletions deps/ncrypto/ncrypto.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ncrypto.h"
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
Expand Down Expand Up @@ -99,7 +100,15 @@ std::optional<std::string> CryptoErrorList::pop_front() {

// ============================================================================
DataPointer DataPointer::Alloc(size_t len) {
#ifdef OPENSSL_IS_BORINGSSL
// Boringssl does not implement OPENSSL_zalloc
auto ptr = OPENSSL_malloc(len);
if (ptr == nullptr) return {};
memset(ptr, 0, len);
return DataPointer(ptr, len);
#else
return DataPointer(OPENSSL_zalloc(len), len);
#endif
}

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

BignumPointer BignumPointer::NewSecure() {
#ifdef OPENSSL_IS_BORINGSSL
// Boringssl does not implement BN_secure_new.
return New();
#else
return BignumPointer(BN_secure_new());
#endif
}

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

#ifndef OPENSSL_IS_BORINGSSL
// tm must be in UTC
// using time_t causes problems on 32-bit systems and windows x64.
int64_t PortableTimeGM(struct tm* t) {
Expand All @@ -512,6 +527,7 @@ int64_t PortableTimeGM(struct tm* t) {
t->tm_min) +
t->tm_sec;
}
#endif

// ============================================================================
// SPKAC
Expand Down Expand Up @@ -822,7 +838,7 @@ bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {

bool ok = true;

for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
for (OPENSSL_SIZE_T i = 0; i < sk_GENERAL_NAME_num(names); i++) {
GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);

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

bool ok = true;

for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(descs); i++) {
for (OPENSSL_SIZE_T i = 0; i < sk_ACCESS_DESCRIPTION_num(descs); i++) {
ACCESS_DESCRIPTION* desc = sk_ACCESS_DESCRIPTION_value(descs, i);

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

int64_t X509View::getValidToTime() const {
#ifdef OPENSSL_IS_BORINGSSL
// Boringssl does not implement ASN1_TIME_to_tm in a public way,
// and only recently added ASN1_TIME_to_posix. Some boringssl
// users on older version may still need to patch around this
// or use a different implementation.
int64_t tp;
ASN1_TIME_to_posix(X509_get0_notAfter(cert_), &tp);
return tp;
#else
struct tm tp;
ASN1_TIME_to_tm(X509_get0_notAfter(cert_), &tp);
return PortableTimeGM(&tp);
#endif
}

int64_t X509View::getValidFromTime() const {
#ifdef OPENSSL_IS_BORINGSSL
int64_t tp;
ASN1_TIME_to_posix(X509_get0_notBefore(cert_), &tp);
return tp;
#else
struct tm tp;
ASN1_TIME_to_tm(X509_get0_notBefore(cert_), &tp);
return PortableTimeGM(&tp);
#endif
}

DataPointer X509View::getSerialNumber() const {
Expand Down Expand Up @@ -1324,7 +1356,12 @@ BIOPointer BIOPointer::NewMem() {
}

BIOPointer BIOPointer::NewSecMem() {
#ifdef OPENSSL_IS_BORINGSSL
// Boringssl does not implement the BIO_s_secmem API.
return BIOPointer(BIO_new(BIO_s_mem()));
#else
return BIOPointer(BIO_new(BIO_s_secmem()));
#endif
}

BIOPointer BIOPointer::New(const BIO_METHOD* method) {
Expand Down Expand Up @@ -1394,8 +1431,11 @@ BignumPointer DHPointer::FindGroup(const std::string_view name,
#define V(n, p) \
if (EqualNoCase(name, n)) return BignumPointer(p(nullptr));
if (option != FindGroupOption::NO_SMALL_PRIMES) {
#ifndef OPENSSL_IS_BORINGSSL
// Boringssl does not support the 768 and 1024 small primes
V("modp1", BN_get_rfc2409_prime_768);
V("modp2", BN_get_rfc2409_prime_1024);
#endif
V("modp5", BN_get_rfc3526_prime_1536);
}
V("modp14", BN_get_rfc3526_prime_2048);
Expand Down Expand Up @@ -1467,15 +1507,22 @@ DHPointer::CheckResult DHPointer::check() {
DHPointer::CheckPublicKeyResult DHPointer::checkPublicKey(
const BignumPointer& pub_key) {
ClearErrorOnReturn clearErrorOnReturn;
if (!pub_key || !dh_) return DHPointer::CheckPublicKeyResult::CHECK_FAILED;
if (!pub_key || !dh_) {
return DHPointer::CheckPublicKeyResult::CHECK_FAILED;
}
int codes = 0;
if (DH_check_pub_key(dh_.get(), pub_key.get(), &codes) != 1)
if (DH_check_pub_key(dh_.get(), pub_key.get(), &codes) != 1) {
return DHPointer::CheckPublicKeyResult::CHECK_FAILED;
}
#ifndef OPENSSL_IS_BORINGSSL
// Boringssl does not define DH_CHECK_PUBKEY_TOO_SMALL or TOO_LARGE
if (codes & DH_CHECK_PUBKEY_TOO_SMALL) {
return DHPointer::CheckPublicKeyResult::TOO_SMALL;
} else if (codes & DH_CHECK_PUBKEY_TOO_SMALL) {
} else if (codes & DH_CHECK_PUBKEY_TOO_LARGE) {
return DHPointer::CheckPublicKeyResult::TOO_LARGE;
} else if (codes != 0) {
}
#endif
if (codes != 0) {
return DHPointer::CheckPublicKeyResult::INVALID;
}
return CheckPublicKeyResult::NONE;
Expand Down Expand Up @@ -2530,6 +2577,7 @@ std::optional<uint32_t> SSLPointer::verifyPeerCertificate() const {

const std::string_view SSLPointer::getClientHelloAlpn() const {
if (ssl_ == nullptr) return {};
#ifndef OPENSSL_IS_BORINGSSL
const unsigned char* buf;
size_t len;
size_t rem;
Expand All @@ -2546,10 +2594,15 @@ const std::string_view SSLPointer::getClientHelloAlpn() const {
len = (buf[0] << 8) | buf[1];
if (len + 2 != rem) return {};
return reinterpret_cast<const char*>(buf + 3);
#else
// Boringssl doesn't have a public API for this.
return {};
#endif
}

const std::string_view SSLPointer::getClientHelloServerName() const {
if (ssl_ == nullptr) return {};
#ifndef OPENSSL_IS_BORINGSSL
const unsigned char* buf;
size_t len;
size_t rem;
Expand All @@ -2569,6 +2622,10 @@ const std::string_view SSLPointer::getClientHelloServerName() const {
len = (*(buf + 3) << 8) | *(buf + 4);
if (len + 2 > rem) return {};
return reinterpret_cast<const char*>(buf + 5);
#else
// Boringssl doesn't have a public API for this.
return {};
#endif
}

std::optional<const std::string_view> SSLPointer::GetServerName(
Expand Down Expand Up @@ -2602,7 +2659,11 @@ bool SSLPointer::isServer() const {
EVPKeyPointer SSLPointer::getPeerTempKey() const {
if (!ssl_) return {};
EVP_PKEY* raw_key = nullptr;
#ifndef OPENSSL_IS_BORINGSSL
if (!SSL_get_peer_tmp_key(get(), &raw_key)) return {};
#else
if (!SSL_get_server_tmp_key(get(), &raw_key)) return {};
#endif
return EVPKeyPointer(raw_key);
}

Expand Down Expand Up @@ -3167,9 +3228,15 @@ int EVPKeyCtxPointer::initForSign() {
}

bool EVPKeyCtxPointer::setDhParameters(int prime_size, uint32_t generator) {
#ifndef OPENSSL_IS_BORINGSSL
if (!ctx_) return false;
return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx_.get(), prime_size) == 1 &&
EVP_PKEY_CTX_set_dh_paramgen_generator(ctx_.get(), generator) == 1;
#else
// TODO(jasnell): Boringssl appears not to support this operation.
// Is there an alternative approach that Boringssl does support?
return false;
#endif
}

bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits,
Expand Down Expand Up @@ -3249,6 +3316,7 @@ bool EVPKeyCtxPointer::setRsaPssSaltlen(int salt_len) {
}

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

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

bool EVPKeyCtxPointer::publicCheck() const {
if (!ctx_) return false;
#ifndef OPENSSL_IS_BORINGSSL
return EVP_PKEY_public_check(ctx_.get()) == 1;
#if OPENSSL_VERSION_MAJOR >= 3
return EVP_PKEY_public_check_quick(ctx_.get()) == 1;
#else
return EVP_PKEY_public_check(ctx_.get()) == 1;
#endif
#else // OPENSSL_IS_BORINGSSL
// Boringssl appears not to support this operation.
// TODO(jasnell): Is there an alternative approach that Boringssl does
// support?
return true;
#endif
}

bool EVPKeyCtxPointer::privateCheck() const {
if (!ctx_) return false;
#ifndef OPENSSL_IS_BORINGSSL
return EVP_PKEY_check(ctx_.get()) == 1;
#else
// Boringssl appears not to support this operation.
// TODO(jasnell): Is there an alternative approach that Boringssl does
// support?
return true;
#endif
}

bool EVPKeyCtxPointer::verify(const Buffer<const unsigned char>& sig,
Expand Down
16 changes: 16 additions & 0 deletions deps/ncrypto/ncrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
#define NCRYPTO_MUST_USE_RESULT
#endif

#ifdef OPENSSL_IS_BORINGSSL
// Boringssl has opted to use size_t for some size related
// APIs while Openssl is still using ints
using OPENSSL_SIZE_T = size_t;
#else
using OPENSSL_SIZE_T = int;
#endif

namespace ncrypto {

// ============================================================================
Expand Down Expand Up @@ -845,17 +853,25 @@ class DHPointer final {
UNABLE_TO_CHECK_GENERATOR = DH_UNABLE_TO_CHECK_GENERATOR,
NOT_SUITABLE_GENERATOR = DH_NOT_SUITABLE_GENERATOR,
Q_NOT_PRIME = DH_CHECK_Q_NOT_PRIME,
#ifndef OPENSSL_IS_BORINGSSL
// Boringssl does not define the DH_CHECK_INVALID_[Q or J]_VALUE
INVALID_Q = DH_CHECK_INVALID_Q_VALUE,
INVALID_J = DH_CHECK_INVALID_J_VALUE,
#endif
CHECK_FAILED = 512,
};
CheckResult check();

enum class CheckPublicKeyResult {
NONE,
#ifndef OPENSSL_IS_BORINGSSL
// Boringssl does not define DH_R_CHECK_PUBKEY_TOO_SMALL or TOO_LARGE
TOO_SMALL = DH_R_CHECK_PUBKEY_TOO_SMALL,
TOO_LARGE = DH_R_CHECK_PUBKEY_TOO_LARGE,
INVALID = DH_R_CHECK_PUBKEY_INVALID,
#else
INVALID = DH_R_INVALID_PUBKEY,
#endif
CHECK_FAILED = 512,
};
// Check to see if the given public key is suitable for this DH instance.
Expand Down
Loading