From 946c40aa8ab7c4b0115bee07c26f2bf712e9e3ef Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 31 Dec 2024 15:02:32 -0800 Subject: [PATCH] src: move x509 error code and reason to ncrypto --- deps/ncrypto/ncrypto.cc | 47 ++++++++++++++++++++++++++++++++++ deps/ncrypto/ncrypto.h | 3 +++ src/crypto/crypto_common.cc | 51 ++++--------------------------------- src/crypto/crypto_common.h | 2 -- src/crypto/crypto_tls.cc | 19 +++++++++----- 5 files changed, 67 insertions(+), 55 deletions(-) diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index f76b89574be5088..af796855abb38b6 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -1071,6 +1071,53 @@ X509Pointer X509Pointer::IssuerFrom(const SSL_CTX* ctx, const X509View& cert) { X509Pointer X509Pointer::PeerFrom(const SSLPointer& ssl) { return X509Pointer(SSL_get_peer_certificate(ssl.get())); } + +// When adding or removing errors below, please also update the list in the API +// documentation. See the "OpenSSL Error Codes" section of doc/api/errors.md +// Also *please* update the respective section in doc/api/tls.md as well +std::string_view X509Pointer::ErrorCode(int32_t err) { // NOLINT(runtime/int) +#define CASE(CODE) \ + case X509_V_ERR_##CODE: \ + return #CODE; + switch (err) { + CASE(UNABLE_TO_GET_ISSUER_CERT) + CASE(UNABLE_TO_GET_CRL) + CASE(UNABLE_TO_DECRYPT_CERT_SIGNATURE) + CASE(UNABLE_TO_DECRYPT_CRL_SIGNATURE) + CASE(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY) + CASE(CERT_SIGNATURE_FAILURE) + CASE(CRL_SIGNATURE_FAILURE) + CASE(CERT_NOT_YET_VALID) + CASE(CERT_HAS_EXPIRED) + CASE(CRL_NOT_YET_VALID) + CASE(CRL_HAS_EXPIRED) + CASE(ERROR_IN_CERT_NOT_BEFORE_FIELD) + CASE(ERROR_IN_CERT_NOT_AFTER_FIELD) + CASE(ERROR_IN_CRL_LAST_UPDATE_FIELD) + CASE(ERROR_IN_CRL_NEXT_UPDATE_FIELD) + CASE(OUT_OF_MEM) + CASE(DEPTH_ZERO_SELF_SIGNED_CERT) + CASE(SELF_SIGNED_CERT_IN_CHAIN) + CASE(UNABLE_TO_GET_ISSUER_CERT_LOCALLY) + CASE(UNABLE_TO_VERIFY_LEAF_SIGNATURE) + CASE(CERT_CHAIN_TOO_LONG) + CASE(CERT_REVOKED) + CASE(INVALID_CA) + CASE(PATH_LENGTH_EXCEEDED) + CASE(INVALID_PURPOSE) + CASE(CERT_UNTRUSTED) + CASE(CERT_REJECTED) + CASE(HOSTNAME_MISMATCH) + } +#undef CASE + return "UNSPECIFIED"; +} + +std::string_view X509Pointer::ErrorReason(int32_t err) { + if (err == X509_V_OK) return ""; + return X509_verify_cert_error_string(err); +} + // ============================================================================ // BIOPointer diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index 01117868ca8bc62..83ce2458bddaf45 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -637,6 +637,9 @@ class X509Pointer final { X509View view() const; operator X509View() const { return view(); } + static std::string_view ErrorCode(int32_t err); + static std::string_view ErrorReason(int32_t err); + private: DeleteFnPtr cert_; }; diff --git a/src/crypto/crypto_common.cc b/src/crypto/crypto_common.cc index eeacbf35186219f..2d1158313c85226 100644 --- a/src/crypto/crypto_common.cc +++ b/src/crypto/crypto_common.cc @@ -144,58 +144,17 @@ bool SetGroups(SecureContext* sc, const char* groups) { return SSL_CTX_set1_groups_list(sc->ctx().get(), groups) == 1; } -// When adding or removing errors below, please also update the list in the API -// documentation. See the "OpenSSL Error Codes" section of doc/api/errors.md -const char* X509ErrorCode(long err) { // NOLINT(runtime/int) - const char* code = "UNSPECIFIED"; -#define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: code = #CODE; break; - switch (err) { - // if you modify anything in here, *please* update the respective section in - // doc/api/tls.md as well - CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT) - CASE_X509_ERR(UNABLE_TO_GET_CRL) - CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE) - CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE) - CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY) - CASE_X509_ERR(CERT_SIGNATURE_FAILURE) - CASE_X509_ERR(CRL_SIGNATURE_FAILURE) - CASE_X509_ERR(CERT_NOT_YET_VALID) - CASE_X509_ERR(CERT_HAS_EXPIRED) - CASE_X509_ERR(CRL_NOT_YET_VALID) - CASE_X509_ERR(CRL_HAS_EXPIRED) - CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD) - CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD) - CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD) - CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD) - CASE_X509_ERR(OUT_OF_MEM) - CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT) - CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN) - CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY) - CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE) - CASE_X509_ERR(CERT_CHAIN_TOO_LONG) - CASE_X509_ERR(CERT_REVOKED) - CASE_X509_ERR(INVALID_CA) - CASE_X509_ERR(PATH_LENGTH_EXCEEDED) - CASE_X509_ERR(INVALID_PURPOSE) - CASE_X509_ERR(CERT_UNTRUSTED) - CASE_X509_ERR(CERT_REJECTED) - CASE_X509_ERR(HOSTNAME_MISMATCH) - } -#undef CASE_X509_ERR - return code; -} - MaybeLocal GetValidationErrorReason(Environment* env, int err) { - if (err == 0) - return Undefined(env->isolate()); - const char* reason = X509_verify_cert_error_string(err); - return OneByteString(env->isolate(), reason); + auto reason = X509Pointer::ErrorReason(err); + if (reason == "") return Undefined(env->isolate()); + return OneByteString(env->isolate(), reason.data(), reason.length()); } MaybeLocal GetValidationErrorCode(Environment* env, int err) { if (err == 0) return Undefined(env->isolate()); - return OneByteString(env->isolate(), X509ErrorCode(err)); + auto error = X509Pointer::ErrorCode(err); + return OneByteString(env->isolate(), error.data(), error.length()); } MaybeLocal GetCert(Environment* env, const SSLPointer& ssl) { diff --git a/src/crypto/crypto_common.h b/src/crypto/crypto_common.h index e264137ac5767a2..1067a6a73e114a3 100644 --- a/src/crypto/crypto_common.h +++ b/src/crypto/crypto_common.h @@ -46,8 +46,6 @@ v8::MaybeLocal GetClientHelloCiphers( bool SetGroups(SecureContext* sc, const char* groups); -const char* X509ErrorCode(long err); // NOLINT(runtime/int) - v8::MaybeLocal GetValidationErrorReason(Environment* env, int err); v8::MaybeLocal GetValidationErrorCode(Environment* env, int err); diff --git a/src/crypto/crypto_tls.cc b/src/crypto/crypto_tls.cc index 2ab407b5c9700af..3aa163a5e7294c6 100644 --- a/src/crypto/crypto_tls.cc +++ b/src/crypto/crypto_tls.cc @@ -386,6 +386,7 @@ std::string GetBIOError() { static_cast(&ret)); return ret; } + } // namespace TLSWrap::TLSWrap(Environment* env, @@ -1844,15 +1845,19 @@ void TLSWrap::VerifyError(const FunctionCallbackInfo& args) { if (x509_verify_error == X509_V_OK) return args.GetReturnValue().SetNull(); - const char* reason = X509_verify_cert_error_string(x509_verify_error); - const char* code = X509ErrorCode(x509_verify_error); + Local reason; + if (!GetValidationErrorReason(env, x509_verify_error).ToLocal(&reason)) { + return; + } + if (reason->IsUndefined()) [[unlikely]] + return; - Local error = - Exception::Error(OneByteString(env->isolate(), reason)) - ->ToObject(env->isolate()->GetCurrentContext()) - .FromMaybe(Local()); + Local error = Exception::Error(reason.As()) + ->ToObject(env->isolate()->GetCurrentContext()) + .FromMaybe(Local()); - if (Set(env, error, env->code_string(), code)) + auto code = X509Pointer::ErrorCode(x509_verify_error); + if (Set(env, error, env->code_string(), code.data())) args.GetReturnValue().Set(error); }