diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index 82da0d34cba4b6..0a0da0263676d9 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -1,4 +1,5 @@ #include "ncrypto.h" +#include #include #include #include @@ -99,7 +100,15 @@ std::optional 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& buffer) { @@ -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 { @@ -492,6 +506,7 @@ constexpr int days_from_epoch(int y, unsigned m, unsigned d) { return era * 146097 + static_cast(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) { @@ -512,6 +527,7 @@ int64_t PortableTimeGM(struct tm* t) { t->tm_min) + t->tm_sec; } +#endif // ============================================================================ // SPKAC @@ -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); @@ -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); @@ -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 { @@ -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) { @@ -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); @@ -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; @@ -2530,6 +2577,7 @@ std::optional 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; @@ -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(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; @@ -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(buf + 5); +#else + // Boringssl doesn't have a public API for this. + return {}; +#endif } std::optional SSLPointer::GetServerName( @@ -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); } @@ -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, @@ -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; @@ -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) { @@ -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& sig, diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index 31d999d3e7e235..f73c84edce20bf 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -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 { // ============================================================================ @@ -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.