diff --git a/docs/runtime/networking/fetch.mdx b/docs/runtime/networking/fetch.mdx index afe904b75e09..eddc7d9dd379 100644 --- a/docs/runtime/networking/fetch.mdx +++ b/docs/runtime/networking/fetch.mdx @@ -247,6 +247,8 @@ await fetch("https://example.com", { This avoids SSL errors with self-signed certificates, but it disables TLS validation, so use it with caution. +Like Node.js, Bun rejects a server's certificate chain when any certificate in it, including the `ca` it chains up to, has an RSA key shorter than 2048 bits or an EC key shorter than 224 bits. `fetch` reports this as a `CA_KEY_TOO_SMALL` or `EE_KEY_TOO_SMALL` error. + ### Request options In addition to the standard fetch options, Bun provides several extensions: diff --git a/packages/bun-usockets/src/crypto/openssl.c b/packages/bun-usockets/src/crypto/openssl.c index 1ae954c56e63..20f8ace6fe5f 100644 --- a/packages/bun-usockets/src/crypto/openssl.c +++ b/packages/bun-usockets/src/crypto/openssl.c @@ -1076,6 +1076,64 @@ void us_internal_ssl_set_inline_reject(SSL *ssl) { SSL_set_verify(ssl, SSL_VERIFY_PEER, us_inline_reject_verify_callback); } +/* ── Chain policy on top of X509_verify_cert ─────────────────────────────── */ + +/* BoringSSL's verifier has no security levels: it verifies a chain built + * through an RSA-512 CA (factorable in hours) as cleanly as one through an + * RSA-4096 CA, and its evp.h leaves bounding key sizes to the caller. Node gets + * OpenSSL's default level, 2 = 112-bit keys (RSA-2048 / P-224), applied to the + * leaf and then to every issuer up to and including the trust anchor: + * https://github.com/openssl/openssl/blob/openssl-3.5.0/crypto/x509/x509_vfy.c#L188-L205 + * https://github.com/openssl/openssl/blob/openssl-3.5.0/crypto/x509/x509_vfy.c#L3674-L3702 */ +#define US_MIN_RSA_KEY_BITS 2048 +#define US_MIN_EC_KEY_BITS 224 + +static int us_x509_key_too_small(const X509 *cert) { + const EVP_PKEY *key = X509_get0_pubkey(cert); + if (!key) return 1; + switch (EVP_PKEY_id(key)) { + case EVP_PKEY_RSA: + case EVP_PKEY_RSA_PSS: + return EVP_PKEY_bits(key) < US_MIN_RSA_KEY_BITS; + case EVP_PKEY_EC: + return EVP_PKEY_bits(key) < US_MIN_EC_KEY_BITS; + } + /* Ed25519, ML-DSA, ...: fixed-size keys, all at or above 128-bit security. */ + return 0; +} + +/* chain[0] is the end-entity certificate, chain[n-1] the trust anchor. */ +static int us_x509_chain_policy_error(X509_STORE_CTX *ctx) { + const STACK_OF(X509) *chain = X509_STORE_CTX_get0_chain(ctx); + size_t n = chain ? sk_X509_num(chain) : 0; + for (size_t i = 0; i < n; i++) { + if (us_x509_key_too_small(sk_X509_value(chain, i))) { + return i == 0 ? US_X509_V_ERR_EE_KEY_TOO_SMALL : US_X509_V_ERR_CA_KEY_TOO_SMALL; + } + } + return X509_V_OK; +} + +int us_internal_x509_verify_cert(X509_STORE_CTX *ctx) { + if (!X509_verify_cert(ctx)) return 0; + /* A verify callback already let an error through; that verdict stands. */ + if (X509_STORE_CTX_get_error(ctx) != X509_V_OK) return 1; + int err = us_x509_chain_policy_error(ctx); + if (err == X509_V_OK) return 1; + X509_STORE_CTX_set_error(ctx, err); + /* Surface it exactly like one of X509_verify_cert's own failures: the + * connection's verify callback records it (inline reject) and decides whether + * the handshake continues (us_verify_callback) or fails here. A ctx without a + * connection behind it (the QUIC client) has no callback and just fails. */ + SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); + int (*verify_cb)(int, X509_STORE_CTX *) = ssl ? SSL_get_verify_callback(ssl) : NULL; + return verify_cb ? verify_cb(0, ctx) : 0; +} + +static int us_ssl_ctx_verify_cert(X509_STORE_CTX *ctx, void *arg) { + return us_internal_x509_verify_cert(ctx); +} + /* Drop the strdup'd passphrase. Called as soon as private-key load completes * (the only consumer of the passwd_cb), so the secret never outlives ctx * construction and SSL_CTX_free() is sufficient on every later path. Also @@ -1110,6 +1168,10 @@ SSL_CTX *us_ssl_ctx_build_raw(struct us_bun_socket_context_options_t options, /* Default options we rely on — changing these breaks the BIO logic. */ SSL_CTX_set_read_ahead(ssl_context, 1); SSL_CTX_set_mode(ssl_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + /* Peer chains (server certs on clients, client certs on servers) go through + * us_internal_x509_verify_cert; the verify modes and callbacks configured + * below and per socket keep deciding what happens with the result. */ + SSL_CTX_set_cert_verify_callback(ssl_context, us_ssl_ctx_verify_cert, NULL); /* BoringSSL ships with SSL_MODE_NO_AUTO_CHAIN set; Node clears it so a * leaf-only `cert` presents the intermediates found in the context's store * (crypto_context.cc#L1640). It only runs when the configured chain is 1. */ @@ -1683,12 +1745,23 @@ static long us_internal_verify_peer_certificate(const SSL *ssl, long def) { return err; } +/* OpenSSL's wording for its X509_V_ERR_{EE,CA}_KEY_TOO_SMALL, so the messages + * match node's. The code matches too: node has no name for these either and + * reports UNSPECIFIED, which is us_X509_error_code's default. */ +static const char *us_X509_error_reason(long err) { + switch (err) { + case US_X509_V_ERR_EE_KEY_TOO_SMALL: return "EE certificate key too weak"; + case US_X509_V_ERR_CA_KEY_TOO_SMALL: return "CA certificate key too weak"; + } + return X509_verify_cert_error_string(err); +} + struct us_bun_verify_error_t us_ssl_socket_verify_error_from_ssl(SSL *ssl) { long x509_verify_error = us_internal_verify_peer_certificate(ssl, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT); if (x509_verify_error == X509_V_OK) return (struct us_bun_verify_error_t){.error = 0, .code = NULL, .reason = NULL}; - const char *reason = X509_verify_cert_error_string(x509_verify_error); + const char *reason = us_X509_error_reason(x509_verify_error); const char *code = us_X509_error_code(x509_verify_error); return (struct us_bun_verify_error_t){.error = x509_verify_error, .code = code, .reason = reason}; } diff --git a/packages/bun-usockets/src/internal/internal.h b/packages/bun-usockets/src/internal/internal.h index 3122b51de922..4ca3d169205d 100644 --- a/packages/bun-usockets/src/internal/internal.h +++ b/packages/bun-usockets/src/internal/internal.h @@ -248,6 +248,11 @@ void us_internal_listen_socket_ssl_free(struct us_listen_socket_t *ls); /* Opaque SSL_CTX_up_ref/SSL_CTX_free so context.c needn't include OpenSSL. */ void us_internal_ssl_ctx_up_ref(struct ssl_ctx_st *ssl_ctx); void us_internal_ssl_ctx_unref(struct ssl_ctx_st *ssl_ctx); +/* X509_verify_cert plus the chain policy BoringSSL's verifier lacks (minimum + * key sizes). Every peer chain, TCP or QUIC, must be verified through this so + * the policy applies uniformly; same contract as X509_verify_cert. */ +struct x509_store_ctx_st; +int us_internal_x509_verify_cert(struct x509_store_ctx_st *ctx); /* TCP-level FIN, bypassing the SSL layer (used by ssl_on_end). */ void us_internal_socket_raw_shutdown(us_socket_r s); diff --git a/packages/bun-usockets/src/libusockets.h b/packages/bun-usockets/src/libusockets.h index 186eb29377f6..cdc6f84323c4 100644 --- a/packages/bun-usockets/src/libusockets.h +++ b/packages/bun-usockets/src/libusockets.h @@ -297,6 +297,14 @@ struct us_bun_verify_error_t { const char* reason; }; +/* Verify results uSockets adds on top of BoringSSL's X509_V_ERR_* values (which + * end at 67): the peer's chain verified, but the end-entity (EE) certificate or + * one of the CA certificates above it has a public key below the minimum size + * (see us_internal_x509_verify_cert in crypto/openssl.c). The numbers are + * mirrored by get_cert_error_from_no in src/http/lib.rs. */ +#define US_X509_V_ERR_EE_KEY_TOO_SMALL 1001 +#define US_X509_V_ERR_CA_KEY_TOO_SMALL 1002 + /* Immutable callback table. ~20 instances total (one per kind), all static * const / .rodata. Nullable entries are skipped by dispatch. */ struct us_socket_vtable_t { diff --git a/packages/bun-usockets/src/quic.c b/packages/bun-usockets/src/quic.c index 62f14539cfec..e7851dc1baa0 100644 --- a/packages/bun-usockets/src/quic.c +++ b/packages/bun-usockets/src/quic.c @@ -1157,8 +1157,8 @@ static enum ssl_verify_result_t us_quic_client_verify(SSL *ssl, uint8_t *out_ale if (!qs) return ssl_verify_invalid; if (!qs->reject_unauthorized) return ssl_verify_ok; - /* custom_verify bypasses BoringSSL's built-in chain check, so run - * X509_verify_cert against the SSL_CTX store ourselves, then match the + /* custom_verify bypasses BoringSSL's built-in chain check, so run the + * chain verification against the SSL_CTX store ourselves, then match the * leaf against the SNI hostname. */ STACK_OF(X509) *chain = SSL_get_peer_full_cert_chain(ssl); if (!chain || sk_X509_num(chain) == 0) return ssl_verify_invalid; @@ -1169,7 +1169,7 @@ static enum ssl_verify_result_t us_quic_client_verify(SSL *ssl, uint8_t *out_ale int ok = 0; if (X509_STORE_CTX_init(vctx, store, leaf, chain) == 1) { X509_STORE_CTX_set_default(vctx, "ssl_server"); - ok = X509_verify_cert(vctx) == 1; + ok = us_internal_x509_verify_cert(vctx) == 1; } X509_STORE_CTX_free(vctx); if (!ok) return ssl_verify_invalid; diff --git a/src/http/error.rs b/src/http/error.rs index b7edb71da82a..992708edef5d 100644 --- a/src/http/error.rs +++ b/src/http/error.rs @@ -252,6 +252,10 @@ pub enum CertError { STORE_LOOKUP, #[error("NAME_CONSTRAINTS_WITHOUT_SANS")] NAME_CONSTRAINTS_WITHOUT_SANS, + #[error("EE_KEY_TOO_SMALL")] + EE_KEY_TOO_SMALL, + #[error("CA_KEY_TOO_SMALL")] + CA_KEY_TOO_SMALL, #[error("UNKNOWN_CERTIFICATE_VERIFICATION_ERROR")] UNKNOWN_CERTIFICATE_VERIFICATION_ERROR, } diff --git a/src/http/lib.rs b/src/http/lib.rs index 57bfb2fccb51..09897c6a56a9 100644 --- a/src/http/lib.rs +++ b/src/http/lib.rs @@ -1583,6 +1583,8 @@ pub(crate) fn get_cert_error_from_no(error_no: i32) -> crate::Error { 65 => CertError::INVALID_CALL, 66 => CertError::STORE_LOOKUP, 67 => CertError::NAME_CONSTRAINTS_WITHOUT_SANS, + 1001 => CertError::EE_KEY_TOO_SMALL, // US_X509_V_ERR_EE_KEY_TOO_SMALL (libusockets.h) + 1002 => CertError::CA_KEY_TOO_SMALL, // US_X509_V_ERR_CA_KEY_TOO_SMALL (libusockets.h) _ => CertError::UNKNOWN_CERTIFICATE_VERIFICATION_ERROR, }) } diff --git a/src/runtime/webcore/fetch/FetchTasklet.rs b/src/runtime/webcore/fetch/FetchTasklet.rs index 39e258c5d785..5b4b0a0172ea 100644 --- a/src/runtime/webcore/fetch/FetchTasklet.rs +++ b/src/runtime/webcore/fetch/FetchTasklet.rs @@ -1564,6 +1564,12 @@ impl FetchTasklet { http::Error::Cert(http::CertError::NAME_CONSTRAINTS_WITHOUT_SANS) => { BunString::static_("Issuer has name constraints but leaf has no SANs") } + http::Error::Cert(http::CertError::EE_KEY_TOO_SMALL) => { + BunString::static_("EE certificate key too weak") + } + http::Error::Cert(http::CertError::CA_KEY_TOO_SMALL) => { + BunString::static_("CA certificate key too weak") + } http::Error::Cert(http::CertError::UNKNOWN_CERTIFICATE_VERIFICATION_ERROR) => { BunString::static_("unknown certificate verification error") } diff --git a/test/js/node/tls/fetch-tls-cert.test.ts b/test/js/node/tls/fetch-tls-cert.test.ts index 84f278f33c46..765d93001df8 100644 --- a/test/js/node/tls/fetch-tls-cert.test.ts +++ b/test/js/node/tls/fetch-tls-cert.test.ts @@ -1,4 +1,4 @@ -import { expect, it } from "bun:test"; +import { describe, expect, it } from "bun:test"; import { readFileSync } from "fs"; import { once } from "node:events"; import tls from "node:tls"; @@ -277,6 +277,45 @@ it("Server sent their CA, wrongly, but its OK since we know the CA locally.", as }); }); +// Same chains as the "weak public key" tests in node-tls-cert.test.ts (which +// documents the fixtures): fetch names the failing certificate in its code where +// node:tls mirrors node's UNSPECIFIED. +describe("certificate chains containing a weak public key", () => { + const fixture = (name: string) => readFileSync(join(import.meta.dir, "fixtures", name), "utf8"); + const root = fixture("weak-key-root-cert.pem"); + const leafKey = fixture("weak-key-leaf-key.pem"); + + it("still fetches from a server whose chain is all RSA-2048", async () => { + await connect({ + client: { ca: root }, + server: { key: leafKey, cert: fixture("weak-key-ok-chain.pem") }, + }); + }); + + it.each([ + [ + "an RSA-512 intermediate CA", + { key: leafKey, cert: fixture("weak-key-ca512-chain.pem") }, + root, + { code: "CA_KEY_TOO_SMALL", message: "CA certificate key too weak" }, + ], + [ + "an RSA-1024 end-entity certificate", + { key: fixture("weak-key-ee1024-key.pem"), cert: fixture("weak-key-ee1024-cert.pem") }, + root, + { code: "EE_KEY_TOO_SMALL", message: "EE certificate key too weak" }, + ], + [ + "an RSA-1024 trust anchor", + { key: leafKey, cert: fixture("weak-key-under-root1024-cert.pem") }, + fixture("weak-key-root1024-cert.pem"), + { code: "CA_KEY_TOO_SMALL", message: "CA certificate key too weak" }, + ], + ])("rejects a server chain with %s", async (_, identity, ca, error) => { + await expect(connect({ client: { ca }, server: identity })).rejects.toMatchObject(error); + }); +}); + // Known gap: "BEGIN TRUSTED CERTIFICATE" PEM blocks aren't parsed as CA input, so // the client cannot verify the server (UNABLE_TO_GET_ISSUER_CERT_LOCALLY). it.todo('Confirm client support for "BEGIN TRUSTED CERTIFICATE".', async () => { diff --git a/test/js/node/tls/fixtures/agent10-cert.pem b/test/js/node/tls/fixtures/agent10-cert.pem index ce0e515e823d..59bb0705757d 100644 --- a/test/js/node/tls/fixtures/agent10-cert.pem +++ b/test/js/node/tls/fixtures/agent10-cert.pem @@ -1,41 +1,47 @@ -----BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgITMVaZ0eX5Kp8NI4vaKFVI592wTjANBgkqhkiG9w0BAQsF -ADCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEfMB0G -A1UECgwWVGhlIE5vZGUuanMgRm91bmRhdGlvbjEQMA4GA1UECwwHTm9kZS5qczEM -MAoGA1UEAwwDY2E0MR4wHAYJKoZIhvcNAQkBFg9jYTRAZXhhbXBsZS5vcmcwIBcN -MjIwOTAzMjE0MDM3WhgPMjI5NjA2MTcyMTQwMzdaMHgxCzAJBgNVBAYTAlVTMQsw -CQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxHzAdBgNVBAoMFlRoZSBOb2RlLmpzIEZv -dW5kYXRpb24xEDAOBgNVBAsMB05vZGUuanMxHDAaBgNVBAMME2FnZW50MTAuZXhh -bXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP49yjMES5 -1sfYG4ac06jR7DnSizMDgW+0V6CFPguv6p1D08aBA60mhY8+tjsbin3DYRiTB2HN -7C9svZ2cAffKK9W/40G6+jfJuB6I8g+LtdZ9hViw2RC0k4PFLzpG3VsJRpM4Wfos -/ubZqBuNGLN+K68sAFU0jbUra4dtJQXMi7SlFlJIUx2g10OF312uJcREfFVgNAw4 -EIZ2H7bmGtpE0p3UfBir4HTy5nz4ruYCbbzNWDuX7RIGZSXtqaQc7P9QPvuLzspl -feI8S2oRTLRIgDEatXJFlIWzGu1kF7XjftOrnFHwRWICK6joqSzdLhSS02qfqIRF -JFVZ8QNq11bhAgMBAAEwDQYJKoZIhvcNAQELBQADggEBACenzaglCUisBHiI7H/v -tOF/75jxDUO8FmV3mksh33EpTmzoBiQD1DiTFQu/EEJ/iAbdTRJ1PVnJsMTFH0Bm -7SmkYOCpETleXjU1MwHZIvh/gGa/CjLZhop26FkK2oqENl7iaM9vvqxxQ8H4Niit -ay3cn+aB9o8MjTH9Ki9iH0LS6bwtqqRimXXX0sx3HTUnFxD/7tzE7s6t7ayk+rIJ -6mBeQAw3UjNzjtLTvSxHoPFto7z5imF+6/v236UlOTdQpkbRS1KlxA8wm/NisWeq -TLjPh5BkZof+CwTUoAFK+WILsIHuvVY9SZBNcsQvsBao/whRR2Z8bU1HDAh8jHnk -4wo= +MIIDijCCAnICFAa1gku/rBMKem53dr6+kaDTIvSCMA0GCSqGSIb3DQEBCwUAMIGI +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMR8wHQYDVQQK +DBZUaGUgTm9kZS5qcyBGb3VuZGF0aW9uMRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYD +VQQDDANjYTQxHjAcBgkqhkiG9w0BCQEWD2NhNEBleGFtcGxlLm9yZzAgFw0yNDA4 +MjcyMjU4NDRaGA8yMjk4MDYxMTIyNTg0NFoweDELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQswCQYDVQQHDAJTRjEfMB0GA1UECgwWVGhlIE5vZGUuanMgRm91bmRh +dGlvbjEQMA4GA1UECwwHTm9kZS5qczEcMBoGA1UEAwwTYWdlbnQxMC5leGFtcGxl +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM/j3KMwRLnWx9gb +hpzTqNHsOdKLMwOBb7RXoIU+C6/qnUPTxoEDrSaFjz62OxuKfcNhGJMHYc3sL2y9 +nZwB98or1b/jQbr6N8m4HojyD4u11n2FWLDZELSTg8UvOkbdWwlGkzhZ+iz+5tmo +G40Ys34rrywAVTSNtStrh20lBcyLtKUWUkhTHaDXQ4XfXa4lxER8VWA0DDgQhnYf +tuYa2kTSndR8GKvgdPLmfPiu5gJtvM1YO5ftEgZlJe2ppBzs/1A++4vOymV94jxL +ahFMtEiAMRq1ckWUhbMa7WQXteN+06ucUfBFYgIrqOipLN0uFJLTap+ohEUkVVnx +A2rXVuECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAy0rm8E+PR+ZuaQsz8Q3s0Y7I +fNICuwEyByMcwiwCjvMM2FwNZbnmagmSQ2eo+jD0GMAcBLS61AWhC8tPqO6DfFOj +7L07NYJWTKQMqAsv3n6Nl0uXd8Aa4iGDhsMeTZXXk4E/GsZZ8T4pDmE8TtY6285Y +ONU7uKKFcnIfQwtcEUnpwqSAYmQxKa+rhQ974rW3hBCxvtrwNRXsMjCoPyfkIuOz +9P6ThZfMWlmuKg852Yi2VglaOrxakQInQGz4Q0JHyROd/e9m3J+t/QFR9VqtRnX8 +UEOlxD8iazk//VFd7WrO2jzqjXFIzBNrdvmsNsP+8uIjrGJtHdKeHL7v5V687A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDFzCCAoCgAwIBAgIJAJHwBmNgafKfMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV -BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBkpveWVu -dDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZIhvcNAQkB -FhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yMjA5MDMxNDQ2NTFaGA8yMjk2MDYxNzE0 -NDY1MVowgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0Yx -HzAdBgNVBAoMFlRoZSBOb2RlLmpzIEZvdW5kYXRpb24xEDAOBgNVBAsMB05vZGUu -anMxDDAKBgNVBAMMA2NhNDEeMBwGCSqGSIb3DQEJARYPY2E0QGV4YW1wbGUub3Jn -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0HnUahyfA25t8kaziu0i -vVMkTWntm0pJ8oemeO7yCGaY4QHEwN+QUzrzO7y7ngl2Dt76eEvj0mrgaW8Ao7Ns -ePfp3663g8RrBsb4cR1da2Tc8kpXCqgwbcTlm8HI/7OAdHGA2YDLNv7iyVk9meHM -gYfO9dVgrZ7RxfnGwNMJdNjYJrd02xeU6euoKl9j/ZWCG5xHAM2xAXOKHGm8toIm -+Ss6iZXY8kypy7Fjwyv7jMT8V+pzIWu24xd3Y3s07r59nkFmQ29nHMTaLP7Tf3TY -MBI5mp8fet732aBoywpQ/w05LR9gdM1jpUvIlmhj4qGskv17AMEmRecwic3opq/b -yQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBADsFOR+N -Bcm2FyHOutoFpQn70qAFg0xlO3NTH87uubbs6rf3LDrsskhjskfs6wpUk56IJOoU -H7+F7aDDtSrnxzxxC5eZeGyaN05T5N01OdK3xvqUnr7mg/Ce0jnxrZhxHI8SHOqs -Kwrg4fRasUHGhH286Y13xOj2pLSrVoSbkXsA +MIIEaDCCA1CgAwIBAgIUDxaIwCfB2vttbQL/LlnVg4mwMUAwDQYJKoZIhvcNAQEL +BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G +A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAe +BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTI0MDgyNzIyNTg0NFoY +DzIyOTgwNjExMjI1ODQ0WjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQsw +CQYDVQQHDAJTRjEfMB0GA1UECgwWVGhlIE5vZGUuanMgRm91bmRhdGlvbjEQMA4G +A1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2E0MR4wHAYJKoZIhvcNAQkBFg9jYTRA +ZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQedRq +HJ8Dbm3yRrOK7SK9UyRNae2bSknyh6Z47vIIZpjhAcTA35BTOvM7vLueCXYO3vp4 +S+PSauBpbwCjs2x49+nfrreDxGsGxvhxHV1rZNzySlcKqDBtxOWbwcj/s4B0cYDZ +gMs2/uLJWT2Z4cyBh8711WCtntHF+cbA0wl02Ngmt3TbF5Tp66gqX2P9lYIbnEcA +zbEBc4ocaby2gib5KzqJldjyTKnLsWPDK/uMxPxX6nMha7bjF3djezTuvn2eQWZD +b2ccxNos/tN/dNgwEjmanx963vfZoGjLClD/DTktH2B0zWOlS8iWaGPioayS/XsA +wSZF5zCJzeimr9vJAgMBAAGjgdQwgdEwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQU +Tc8o3KouldTCYNQHvW09ZBv9sW0wgaEGA1UdIwSBmTCBlqF+pHwwejELMAkGA1UE +BhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0GA1UECgwGSm95ZW50 +MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAeBgkqhkiG9w0BCQEW +EXJ5QHRpbnljbG91ZHMub3JnghRsoeMhBMOB34RpWIz6SD/UwaqquzANBgkqhkiG +9w0BAQsFAAOCAQEAKtd7q+5123jVDzpydg4o3FO84u/1gzlkQ9gAc0q48/ePD/0g +GTeTLz3fODq84l0Nx0g2XbcnrnH/07dzykZokAI6TFhv9qioeMmZa5UhwLSFynXJ +tqP26jA2/dpofGrVV2up/dJ9nw/jmvsRTigvIjkPyofFyxyssNmUIOXgEB6szthQ +mg0VKqgcF3yPDFiSMNh7YnxKd6Rsw1uujtRR+dbkLJs3m0sk+MNra7+LIfqVU5Iv +UyieguUmYYtW9rWTjxVCEl84teryIFJK81GlX/wiq1Nx3DZj+DCSwJMdl5DDzvH8 +EnE1L+MapqCnP0eAmNdWwF5SVxfKUwtt6uPpYw== -----END CERTIFICATE----- diff --git a/test/js/node/tls/fixtures/agent3-cert.pem b/test/js/node/tls/fixtures/agent3-cert.pem index 9a2b16b19f3d..e24a34c1bfd8 100644 --- a/test/js/node/tls/fixtures/agent3-cert.pem +++ b/test/js/node/tls/fixtures/agent3-cert.pem @@ -1,18 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIC9DCCAl0CCQCR8AZjYGnyoDANBgkqhkiG9w0BAQsFADB6MQswCQYDVQQGEwJV -UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ8wDQYDVQQKDAZKb3llbnQxEDAO -BgNVBAsMB05vZGUuanMxDDAKBgNVBAMMA2NhMjEgMB4GCSqGSIb3DQEJARYRcnlA -dGlueWNsb3Vkcy5vcmcwIBcNMjIwOTAzMTQ0NjUxWhgPMjI5NjA2MTcxNDQ2NTFa -MH0xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNV -BAoMBkpveWVudDEQMA4GA1UECwwHTm9kZS5qczEPMA0GA1UEAwwGYWdlbnQzMSAw -HgYJKoZIhvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMwdFX1RDh/WG1MyegBg2PqcmMSd3wKmO6QxSYpEdv2o -rhBJ8opfsdvMDvk66UfqBgMIryJhHWf1iznmAC2aT4hDYyKuqFuN7EDzHOWH7ta5 -E5+OXR/UvgYvsq5ptNKAUUbZ3MoOnQluEbNnJS0wqKSQWu1apnih8fUiqrTQjI/d -lnnN9A1aQwD2JMPy/GYD6bjx3psFcBjrPiSm/WuZxpcFg/r9cNW3mylEMMw2TUe2 -Wwaz92GfX6AbF/ENAS9DZSwz7UzVwaHzwv69TXTlskdvAvGA4j6FCvpbuTFNc03Y -YGUfnhO7WpiaS9lppj7UMAUOI0KLAIoYZYOCYarZeN0CAwEAATANBgkqhkiG9w0B -AQsFAAOBgQC3K2rmDobXHmAvKjQOndWY6xPUmmSzLPWr+WtFormgLG5UOiKAYa7K -ErG6aklZw2ZnYRSebotC+eVh1ZSuOdpFnLw36dt6XGe+ulp3jgc9nggTZGagCFB1 -yhgZ4y+7zx4u1t2oVqCbYn6mtw+AuwoszkdzHQqZIA42USnxUCLJPQ== +MIIDgDCCAmgCFHtnB1Iw05rTKjL+Xc+x+pXi6jGdMA0GCSqGSIb3DQEBCwUAMHox +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoM +BkpveWVudDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZI +hvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yNDA4MjcyMjU4NDRaGA8yMjk4 +MDYxMTIyNTg0NFowfTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQH +DAJTRjEPMA0GA1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQ8wDQYDVQQD +DAZhZ2VudDMxIDAeBgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzB0VfVEOH9YbUzJ6AGDY+pyYxJ3f +AqY7pDFJikR2/aiuEEnyil+x28wO+TrpR+oGAwivImEdZ/WLOeYALZpPiENjIq6o +W43sQPMc5Yfu1rkTn45dH9S+Bi+yrmm00oBRRtncyg6dCW4Rs2clLTCopJBa7Vqm +eKHx9SKqtNCMj92Wec30DVpDAPYkw/L8ZgPpuPHemwVwGOs+JKb9a5nGlwWD+v1w +1bebKUQwzDZNR7ZbBrP3YZ9foBsX8Q0BL0NlLDPtTNXBofPC/r1NdOWyR28C8YDi +PoUK+lu5MU1zTdhgZR+eE7tamJpL2WmmPtQwBQ4jQosAihhlg4Jhqtl43QIDAQAB +MA0GCSqGSIb3DQEBCwUAA4IBAQAfxPLKKEifOSGFXXFEa1Z2DXTxOc9YeY3dTVYa +py/ATdwnKhGDHknYmnHSUBzgvqRZqoZrG04S1HuatAdCifNx+ts2qrx3AmOdYrMH +A6PYQIY8RVNKgEoel776FjCJta2ta2KNOkyrVwEhY7jgIgHcYIGwAgM0Gcq8j63R +IomOu0+FE9M6a+oU9Z0EZ646LU0GgMEz8cegxKwRoA+KKEQzmdwnblzWXqNWf+VC +nljA0ReLl484iBt1eMZQ9tGMvu2QW8v7k1nnyuRF6Zmfe+ELgAk3rHWGCcFqB5ri +tEjlIc055+AmBlbf6Ba5oVawjrowvd+3BtlM0cx60DmC425T -----END CERTIFICATE----- diff --git a/test/js/node/tls/fixtures/ca2-cert.pem b/test/js/node/tls/fixtures/ca2-cert.pem index 0c72d6c64756..7ff23789d63e 100644 --- a/test/js/node/tls/fixtures/ca2-cert.pem +++ b/test/js/node/tls/fixtures/ca2-cert.pem @@ -1,16 +1,21 @@ -----BEGIN CERTIFICATE----- -MIICbTCCAdYCCQDRrfgRk8tC1zANBgkqhkiG9w0BAQsFADB6MQswCQYDVQQGEwJV -UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ8wDQYDVQQKDAZKb3llbnQxEDAO -BgNVBAsMB05vZGUuanMxDDAKBgNVBAMMA2NhMjEgMB4GCSqGSIb3DQEJARYRcnlA -dGlueWNsb3Vkcy5vcmcwIBcNMTgxMTE2MTg0MjIwWhgPMjI5MjA4MzAxODQyMjBa -MHoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNV -BAoMBkpveWVudDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJ -KoZIhvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEAv61gNiLff+zxCdAwdzlVoucGu5L+LFFN9TXzcT3ZD8U1H6CiLp3Q -02IlbK1JRHwpJBXgYOFvMWd9LD6JiJgJsp61kpZShl2qZSUIfhzeExWH7kkuPHWC -IEkiP/aDp5wuqbFBkNUJu8opYr0E6/t9sIzl4IK7WNDXWgQvv8cqin8CAwEAATAN -BgkqhkiG9w0BAQsFAAOBgQB80WTJ9neA5yVaDVV+hZtOasLiZlUT8m49ImQMnInA -jdoAkxgySNOJP8IrsilleAGeHF+JPy042z8NZ5C+xL9REaB1/OaQ7+nwHP0O0f+l -kXHgZATQ3YVf6db5euK3R1mdO1Vv++R4Nu4NYBu0cmfMpdl/uKdYpXMjPVn21iB7 -5w== +MIIDfTCCAmUCFGyh4yEEw4HfhGlYjPpIP9TBqqq7MA0GCSqGSIb3DQEBCwUAMHox +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoM +BkpveWVudDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZI +hvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yNDA4MjcyMjU4NDRaGA8yMjk4 +MDYxMTIyNTg0NFowejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQH +DAJTRjEPMA0GA1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQD +DANjYTIxIDAeBgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoq6k9bq0BgvZDesrfPPzYyA2PbxTA3hI +ziKAmglvuF1lbHVdG/7jOZV7JQpdViCRpcoO6uz1BmGnvd3UDS6Q/y/mkjE96E/y +O3h8gcn+CBzniKIYhB9QtrrVHDy5e/tOJGhGifLtver3iLf5kgiJPy4cGAD663oT +Vlzvo4U6E2j3vJw4l18pi9gpL7shU8QJka0/0F8BbhoaQK1ZqvD4p9bOMRDztfhZ +Gb5qJ+664bx80dck9a5UoLCid8tQIlOCnr9IrAwTPNpnk/xCC7nsbE0+CkMsI3+U +g+3gO0zApWy6DzSawYh6VVijFe6Q0N12duspxdpgt7Kk+8ejrAAOjwIDAQABMA0G +CSqGSIb3DQEBCwUAA4IBAQCSsx31ivZnnpAJqsF8yncin8kAvgy8YG1itguKO9sG +KQ5AIWpSRjhZjJ0JRMj2hxhoob2vZ68QbP8iEufByBJ7G1CkyHvBODaMSdydXWga +wBSKFpsiPt+Gj6rzb5yn0MuH577tWzVLi4C1KW8sFx9rtjDUHTqwf3i7/iuTA5Yo +yruWRmIXqFoIs3lnKC1f8CYmcZMT2hox8imQI8hIMjalB30WGrDudoqd67rDGWn7 +IKC12pRdgaADILx0vhdniieUwTq85r/6BaKFCJsZIaRd3aAoo3bl4qBA5Bt0uoCB +x6pEPQeypvU8qBmKKD+XQdY0Pf9Vh9Wq6g/iiw79IsY0 -----END CERTIFICATE----- diff --git a/test/js/node/tls/fixtures/weak-key-ca512-chain.pem b/test/js/node/tls/fixtures/weak-key-ca512-chain.pem new file mode 100644 index 000000000000..799014694dc5 --- /dev/null +++ b/test/js/node/tls/fixtures/weak-key-ca512-chain.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIICmzCCAkWgAwIBAgIJAJMBQOP4DnTBMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNV +BAMMIldlYWsgS2V5IFRlc3QgSW50ZXJtZWRpYXRlIFJTQS01MTIwIBcNMjYwODE0 +MTU1NzIxWhgPMjEyNjA3MjExNTU3MjFaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANrWFwSNmJ6dYNNxS8wvpN3o +mLhNQFFHldFWzKM5g6by5qJB/2n4Hj/uM+HWVviOBCDNoTiQCHD7zZkpJxEMeDxt +x8qXgqpL3oIXcyG2e3Ny5+WJ15BOyZzViXoBfy2OvPu3mN5wmiCazZR3xmYdhNtQ +Kel1/i47Ne/2RgOdaewPPEn6MJspzbzRHrZm5ykK+U4LR1ze1WE0ONBCXEhpPb5f +Z08263xmV1Wy8mcl8Uigh+/iaZgboSdNBT5T4NWyRpUZFAk7aQkh/IZpLrDyEAPc +4Cnw/E4ZPwcWfHpffJ1A1wJT+cNdkb9VMSOdMxfJWpGhGJpVI0t7z1xLustqxhEC +AwEAAaOBljCBkzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUE +FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwFAYDVR0RBA0wC4IJbG9jYWxob3N0MB0G +A1UdDgQWBBRjo1TqA4pJ5A/6LE9Qpycv/3cNNTAfBgNVHSMEGDAWgBSZYmLXCq1f +J8yXOe/5wZnms1Y15TANBgkqhkiG9w0BAQsFAANBALsXk1uvIkaVP5btJcEDJB8/ +uuuKeFrQeZMutLbT/TVy2hJq+guzx719am2GUayZCpq+xj4ieC3KEvPYGnHfau8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICajCCAVKgAwIBAgIJAOVfsNwjF7olMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNV +BAMMEldlYWsgS2V5IFRlc3QgUm9vdDAgFw0yNjA4MTQxNTU3MjFaGA8yMTI2MDcy +MTE1NTcyMVowLTErMCkGA1UEAwwiV2VhayBLZXkgVGVzdCBJbnRlcm1lZGlhdGUg +UlNBLTUxMjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDvYRYwBR6WMGj0Ctto1meF +nDkqD69U7BCbq8+K8Cs09KtP5xdPJm9i0qTcLjaurlC36DoJNRWTkVJuEu+zGv4R +AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBSZYmLXCq1fJ8yXOe/5wZnms1Y15TAfBgNVHSMEGDAWgBQ5sA5dM3P0d962 +nVqyELsJL1Sk1zANBgkqhkiG9w0BAQsFAAOCAQEASe5/As7WAJm9UkYJ6R4gWPI8 +jJ5mukbf/f5JOmyRgZc0YWbSZoX41xiR2joykwD6amtU5iusAmkRY8LSL1La2S6V +Q8CkFa6QjEOooGiYT8x1Bc779nygqGJzXGVS86yIhjlwAacXPQctKjD4ZqEWe06a +dNcMKo618CF9pNdeFnl5ZYaxJKqT4KWdu/6Kx2W6q5a1xZqWoqLzekQlUhdNKJwj +cjXxtmAa9TnFU3OC5ueI7e+0Dm0TVxZFHo7+zNvA4EJcLxnrZAHwXWQ8LIJuBMYe +tgfodSKjDYNG8UKx8WbIIWtYABCjTqV16qxdK3ta1rIO32l6kKnFuv2gyB2jLA== +-----END CERTIFICATE----- diff --git a/test/js/node/tls/fixtures/weak-key-ee1024-cert.pem b/test/js/node/tls/fixtures/weak-key-ee1024-cert.pem new file mode 100644 index 000000000000..6fe4c0b2bb3e --- /dev/null +++ b/test/js/node/tls/fixtures/weak-key-ee1024-cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICyTCCAbGgAwIBAgIJAIYTbbK8QdI4MA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNV +BAMMEldlYWsgS2V5IFRlc3QgUm9vdDAgFw0yNjA4MTQxNTU3MjFaGA8yMTI2MDcy +MTE1NTcyMVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDLaSIamOZbZefnfoPxb34RrRt0Hfzoj1mbCgDoz8MsqAv+5iPh +J0b2fPqLvh5CdnVYATofMIaFuNYQM5KgX7zU7Jdybogpr27IyMlsDCVc+yLto54v +93OmigRpGHiNdHhYmwRhxbtv0u0KmB40227ZwhfMFpOorDCGOcoHvQoO8QIDAQAB +o4GWMIGTMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAjAUBgNVHREEDTALgglsb2NhbGhvc3QwHQYDVR0O +BBYEFAEG3L7fhWswjWC2eG/d6qLAl7ACMB8GA1UdIwQYMBaAFDmwDl0zc/R33rad +WrIQuwkvVKTXMA0GCSqGSIb3DQEBCwUAA4IBAQAvNeTeTlK7KOlsavzbk/VMAnX6 +mfWvN4UcV/TYdTzw7tYfXzvimhLWH1aQmLbHeceIwnxJYwuElgCtowAphl4i8DpE +20cbpEVhMCjGjHQ+zilUEYQlwf7e7um4qT8cGbbrq4LfAVjpEu/UfDlalL3gY+4n +SuTWIJ4Hag4bJRFcd8r5EfbEvtIIrFJ11FOILZ0WOK36LWH5Bs0LqJqy5BT6FWYE +AVnIv6hHDSr2WgLJErW1I6j+papwku1+e/Tpx1y3drQ4MS1Ux7inWphuX+V3/hsv +MGHoA98qo/BzYfuD/O9bUK8dKAgY4YaThtVxAah4xsGT/uIihAc2jN/E5T7K +-----END CERTIFICATE----- diff --git a/test/js/node/tls/fixtures/weak-key-ee1024-key.pem b/test/js/node/tls/fixtures/weak-key-ee1024-key.pem new file mode 100644 index 000000000000..02976d4f2c34 --- /dev/null +++ b/test/js/node/tls/fixtures/weak-key-ee1024-key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMtpIhqY5ltl5+d+ +g/FvfhGtG3Qd/OiPWZsKAOjPwyyoC/7mI+EnRvZ8+ou+HkJ2dVgBOh8whoW41hAz +kqBfvNTsl3JuiCmvbsjIyWwMJVz7Iu2jni/3c6aKBGkYeI10eFibBGHFu2/S7QqY +HjTbbtnCF8wWk6isMIY5yge9Cg7xAgMBAAECgYEAu2IFZcUW6HmvMcWNnNudooD6 +unRpqH9uB3ImtlG2tau1KUMvKFo7eBRX5mXkkEt5+/FdbqAQPJ2yrUglOhIX69W0 +8fD1Gbd18ABpYFpvHvrHUI9pOJETW3LPTnnWp797+r2zeU9sgFi2Znhijefosf3e +sAcVQSGEow1JFwxJPAUCQQDsqwlzvfTQvcW+i9LqwYS3Yg25P6ez8bjAZMcOw0AQ +7nPyEnXwbfWQQ4QOO7oxYSz+GGkaBDviMpFpUwGCLVX7AkEA3AamjJ9PCNDtPCBP +tdhpzQYKhfScCgsRDbLPhv3ip83y/Cw+CluwFOokjfWiuHFFh1qmtZ97ajEXjAew +f3GXAwJBAKZPkvbY1/8QPLOoQnFhyEeuCgLR7qGPDct1hkSjhJPhXW0Q9/wa6WOV +bmkqI6+roBh3QvRbYVGVQ4YGJJs8DJ0CQHObnvk2X62vMWetRpSywGy0puTZsP9p +7yz2bipsziIDiY/Mo1CH+o4StOBOV5B4G+NR01SNFqimYMv34lokUgcCQQCTUSKZ +IcjgE/tROIZG1wQ54n5CE+MGkmwyv0nn02AJD7gJa2kjxPN57iNnSmcTEShIrbCe +BiA7//UjJHr3Bx5T +-----END PRIVATE KEY----- diff --git a/test/js/node/tls/fixtures/weak-key-leaf-key.pem b/test/js/node/tls/fixtures/weak-key-leaf-key.pem new file mode 100644 index 000000000000..8d1f707713c7 --- /dev/null +++ b/test/js/node/tls/fixtures/weak-key-leaf-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDa1hcEjZienWDT +cUvML6Td6Ji4TUBRR5XRVsyjOYOm8uaiQf9p+B4/7jPh1lb4jgQgzaE4kAhw+82Z +KScRDHg8bcfKl4KqS96CF3MhtntzcuflideQTsmc1Yl6AX8tjrz7t5jecJogms2U +d8ZmHYTbUCnpdf4uOzXv9kYDnWnsDzxJ+jCbKc280R62ZucpCvlOC0dc3tVhNDjQ +QlxIaT2+X2dPNut8ZldVsvJnJfFIoIfv4mmYG6EnTQU+U+DVskaVGRQJO2kJIfyG +aS6w8hAD3OAp8PxOGT8HFnx6X3ydQNcCU/nDXZG/VTEjnTMXyVqRoRiaVSNLe89c +S7rLasYRAgMBAAECggEAMgJeYL0+DTNgYvmfbYJOziJ/MhD/W4O9LkmEeuGkHyUf +xSFJbe1Udl4ob5n0ppkHwvpS91LdBvrYPYHcymXb3U1mLLtKkkHDz91tg10JIbU2 +3usM/s6ufr+CywWoC2B0+h43GlBHvJ87z0u+5GunBppvdYlwJJ8F4LhaQC27PMVD +XPaEFrsV+XisPoSr8Sov5DitKK6VY7WdDOIaum1SeAYGrEcApy68tfZ4bbmief23 +P5B0jAt4bMvNjt/Ti4xXa3HphnEGKXjyuPcgY+RDHV1Q2l5ODlI5o0p2TBnbJPAo +XFlk00xs8IrLYoj0uRgiH6U+byyYQNABShorZyoo9QKBgQDvjh/5PvbOMKqmUfh/ +nLt50HDnDXPBkgmXwXZVNRsW9/oAg/A2e4YCFnWl24wVQmUk2ozGEeDwZ9i2xy77 +qel040ieQVmjgtNots5O2F+QWBeNynLWNEvsocEHWSenDWMCtbLb7kX7KGyjUw5w +NmyEe5R/6hbYFOwJBv6LFwQDNQKBgQDp29tt0atCB8P3niKLs/KHABhn+Gsht9Nk +3loxnqgKuk2Cr1WdDGhS4E86MUVoQj4m7GbG64TNd+cZHm/WVzCwxtz1wFE+LCj1 +5stf2zpGypQAAJAt2+LEE/Fp/hOC5ykQYs2quDAF6vSsnGV1sxbyeR1pFMSJQ0zX +J8MCaSBW7QKBgGLAK94LXqJQ3YgCcnXonj/w9RnKKdW55cpxLd6iLbCiOKTNvtA2 +y19A8u6UOoLpA9jVXwKnjBqONH/kTDHiMSLGLsFOHy2QWKXp9dH60Coopk0FD6HN +nR7G71OgJQBwPEh5rmmLJ74JQ/9v1ZvcU4+pgeXZEeGxfjuaboPX0QehAoGAK7OZ +Otl+rnUzCtfzTrYO8Wl0JiHHK2Llzyi6JCGo93A/QdewIQwLhslCJPbGKKiQYse0 +oSGsDJWGiywj7CMZBz/yVL5esEaiVOmPQdd++XGr3KA+UUORCeFMMOl5DfJSuywr +kOagmsqAdK05TJhuBlvZwiROYfRArMhSaeXpVDUCgYBWpzlWkxgvlwU1q4xqycQ3 +lX54Q3ctEzvg5brXXIg33IiBTXraTIIRoJBHY3+o5s6POMwUFhE2ictOtKhD4J08 +eozUN6pufYOzrC9I0CU9Bg3xuAOn3aYBHKaLuCnWps8Ntg19SY4YZC+xawMRK8t1 +DWf+TJEZkvz8NX7hYb4xaQ== +-----END PRIVATE KEY----- diff --git a/test/js/node/tls/fixtures/weak-key-ok-chain.pem b/test/js/node/tls/fixtures/weak-key-ok-chain.pem new file mode 100644 index 000000000000..f52f407c61ec --- /dev/null +++ b/test/js/node/tls/fixtures/weak-key-ok-chain.pem @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIIKv4eDCQcmYIwDQYJKoZIhvcNAQELBQAwLjEsMCoGA1UE +AwwjV2VhayBLZXkgVGVzdCBJbnRlcm1lZGlhdGUgUlNBLTIwNDgwIBcNMjYwODE0 +MTU1NzIxWhgPMjEyNjA3MjExNTU3MjFaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANrWFwSNmJ6dYNNxS8wvpN3o +mLhNQFFHldFWzKM5g6by5qJB/2n4Hj/uM+HWVviOBCDNoTiQCHD7zZkpJxEMeDxt +x8qXgqpL3oIXcyG2e3Ny5+WJ15BOyZzViXoBfy2OvPu3mN5wmiCazZR3xmYdhNtQ +Kel1/i47Ne/2RgOdaewPPEn6MJspzbzRHrZm5ykK+U4LR1ze1WE0ONBCXEhpPb5f +Z08263xmV1Wy8mcl8Uigh+/iaZgboSdNBT5T4NWyRpUZFAk7aQkh/IZpLrDyEAPc +4Cnw/E4ZPwcWfHpffJ1A1wJT+cNdkb9VMSOdMxfJWpGhGJpVI0t7z1xLustqxhEC +AwEAAaOBljCBkzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUE +FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwFAYDVR0RBA0wC4IJbG9jYWxob3N0MB0G +A1UdDgQWBBRjo1TqA4pJ5A/6LE9Qpycv/3cNNTAfBgNVHSMEGDAWgBQMCT3goW/D +fWsR2JfFQsvv8BsXFTANBgkqhkiG9w0BAQsFAAOCAQEAVnrAKA64EGYl89mCDCpv +phVQVOjJDR+FAgXsNE6ZqBrqxFJ3XgzVtFLszYRSvYuggXbWhdNeUBR1Kcs3RTbN +1YKc1+XiOqgHnuEQE6GO2hSafx1wp/YooR+1DRv9jG0fsjedjNFFGBlbWudwjqRu +P5Z7Om2MbzXs0vj667lxAKnDsu1bztvXgcdSvCzzXKZ/O+QnLXcDOKDlcsYTwjeL +ogCZ/A5hIfsRgpUOe3+TXPi8vy/wMHY+xEBhrjJb3NDqQpLr8b036s+XHl2vSpya +IGDDYNIJPoqtCDK1hINu+MsOEt/oKcUu8UuapAdVl7/rgvOsmqfth0Rugw9Tlc3p +3A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDMzCCAhugAwIBAgIJAIR060UYOpWrMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNV +BAMMEldlYWsgS2V5IFRlc3QgUm9vdDAgFw0yNjA4MTQxNTU3MjFaGA8yMTI2MDcy +MTE1NTcyMVowLjEsMCoGA1UEAwwjV2VhayBLZXkgVGVzdCBJbnRlcm1lZGlhdGUg +UlNBLTIwNDgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCocMeslNcI +KvwD0/0rePj/WpuBaN4hl9H11muvBKhYQvlkSUjsA7kijLanM9vYzqrHQumxUO+4 +j3pp1G/KgvwSix9C0kI1X3qjeyDHeebZrO0sbxxVhnrpc3SyZiy6e45pOwlWyAgU +qTfgaMb53xAz6oqmESKJCPgsl0/qo1ZnZRaB1VoXLUF089sHsWC0ixCYJ/rtSkww +3eHsgmwMb3GLhAvFYurv6uCm914DAp1YfjK6bKKKHXYvd3is0c+WB3Jw0Xm34rM9 +p+f1m8fXadyS2xh3oeWqQfgYjt3eIF61VGhis+t6+7/f6rqN+319a98QMLCk+7oT +CEDs9sD6h/FLAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQMCT3goW/DfWsR2JfFQsvv8BsXFTAfBgNVHSMEGDAWgBQ5 +sA5dM3P0d962nVqyELsJL1Sk1zANBgkqhkiG9w0BAQsFAAOCAQEAkBkFIpHZOv9K +EtuTtCPc293MWPPL2Qu3KGIoBlw/chS2oAWh+E+IXifUHqkxhreHHySHuPv2kmZ9 +bla3nUBujKdh2lH3QaOdGrvZnKEn0WEjlGFizVidYn+Qpc5OYDq4v/bJwlcmoW/Z +LywQLwYL2fTJFQK/WldAKElzj7UyTrgsW2H3TnbpGt5WlgQSyaqIPhpVKMYGNDVU +qHY2V6ODGFkRbpBSOd1otmMBxZrQhRms6a5EZTbHD4c6NxpnUAuQrAu2VCU6EzgE +dvsbzwwNoDQ9QznpI0b5jR2kp0Wcwlfi4f9ALZ9pKrCVhEwAdMr0Cw+WOGWLMymr +UuI5rdA46A== +-----END CERTIFICATE----- diff --git a/test/js/node/tls/fixtures/weak-key-root-cert.pem b/test/js/node/tls/fixtures/weak-key-root-cert.pem new file mode 100644 index 000000000000..546731c48453 --- /dev/null +++ b/test/js/node/tls/fixtures/weak-key-root-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLTCCAhWgAwIBAgIUARv/VZiHj9zHU26VlT4v4nX3IYIwDQYJKoZIhvcNAQEL +BQAwHTEbMBkGA1UEAwwSV2VhayBLZXkgVGVzdCBSb290MCAXDTI2MDgxNDE1NTcy +MVoYDzIxMjYwNzIxMTU1NzIxWjAdMRswGQYDVQQDDBJXZWFrIEtleSBUZXN0IFJv +b3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6ODlJCxo4ICkkov0L +DoBSp1Fu6cUHmBw0FS0PfgVxmksoUgdtOOVvcIC2MgrDU1S6vq21XWZD/RmlNFun +aSH7U2wpROZyMToFFJ0qiTJJXQSXWGqzt9ELzN0XONy8w1+SFE9iJ4d/nkbWxAzN +rYlB374JuqLtumtFQRBjHXV55emyRcp138PwO/s6fQZKPsMgI/NzCO0cc8Atmsy/ +0x3XXzcVzCirkHcUhMFkAnzlJbhDMCXVWiiT5FoDZKJZ5put9YIE11e7zT/4cuMB +4MRbxKQc8yLdYiRdOX6JxxQMs+JB16vJGygu7wzZEpRrX6biB+qqulC51zW0RqgG +0ISLAgMBAAGjYzBhMB0GA1UdDgQWBBQ5sA5dM3P0d962nVqyELsJL1Sk1zAfBgNV +HSMEGDAWgBQ5sA5dM3P0d962nVqyELsJL1Sk1zAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAldqAKImBhqqkbTeUUkya +pUhLCgUypVFSZ4sPtUbUlsapI1EjVFF9f951BANCAFnu0p0rqYM9H4HOlGfNHEjK +cNLTCvKUUDOOA6MB18zqwcth4pmdChBV3eXZKsCaH5PWq2okv6lIzKhfMP5Q/D4e +XvAAL9AlWV7zAODGtx7zOfF+4ivUU0eo1JAwemb15K38OGe44Dtl+arUzb0lRvKl +UsYvJgzVibKqeCuHrzTydUl5P0tU2R7WzfvlAaZ8bVnDBKkPwHQQ2iFx+xhjOGcn +QhbEX1dQwLsmrqPR8YL7L1S/AbMzV4vVp2EmG0fbRqTuD4uYBeu6Inxm1pcrckEj +eg== +-----END CERTIFICATE----- diff --git a/test/js/node/tls/fixtures/weak-key-root1024-cert.pem b/test/js/node/tls/fixtures/weak-key-root1024-cert.pem new file mode 100644 index 000000000000..c65bb9541848 --- /dev/null +++ b/test/js/node/tls/fixtures/weak-key-root1024-cert.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICOjCCAaOgAwIBAgIUecXllek8/ZZ6+SDSTIMo/Utw4XwwDQYJKoZIhvcNAQEL +BQAwJjEkMCIGA1UEAwwbV2VhayBLZXkgVGVzdCBSb290IFJTQS0xMDI0MCAXDTI2 +MDgxNDE1NTcyMVoYDzIxMjYwNzIxMTU1NzIxWjAmMSQwIgYDVQQDDBtXZWFrIEtl +eSBUZXN0IFJvb3QgUlNBLTEwMjQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +ALMjuy4HMBKtBhRO95EV6SCEBdibO9c353NLMKvCz4UfoxpMjrXck9AMTX9ksHEu +a/04Hc/S2YH2SDzk8vUQhNkK6lkNsJsrNPFDDuqR+Frqd0Dd2EyFVoRgAaaYxlVF +OFu1zEbAZDlZeeaUN+tyXpmi1NQ44QO+IVjwqGzW2IP/AgMBAAGjYzBhMB0GA1Ud +DgQWBBRXKE12qmBx5rstDYSmPtQegDLuODAfBgNVHSMEGDAWgBRXKE12qmBx5rst +DYSmPtQegDLuODAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkq +hkiG9w0BAQsFAAOBgQCGTTEmDzlYqklr+yREArdVntTXx8X4cp9ob5gq9gVPpUq+ +1SyJ3gYpsV5nppy3r+DbZV87YChPzFn+faGl4IJWXTutCot8SzXlk6En5xPBgGTM +AFyn+SZIPvcgtuan2gK97NxNRT0QJftP7TElhVzgJxtHRDXabnb3ZQs48THMcQ== +-----END CERTIFICATE----- diff --git a/test/js/node/tls/fixtures/weak-key-under-root1024-cert.pem b/test/js/node/tls/fixtures/weak-key-under-root1024-cert.pem new file mode 100644 index 000000000000..d9ed9fc05514 --- /dev/null +++ b/test/js/node/tls/fixtures/weak-key-under-root1024-cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgIJAPfL0ZRa4I4SMA0GCSqGSIb3DQEBCwUAMCYxJDAiBgNV +BAMMG1dlYWsgS2V5IFRlc3QgUm9vdCBSU0EtMTAyNDAgFw0yNjA4MTQxNTU3MjJa +GA8yMTI2MDcyMTE1NTcyMlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2tYXBI2Ynp1g03FLzC+k3eiYuE1AUUeV +0VbMozmDpvLmokH/afgeP+4z4dZW+I4EIM2hOJAIcPvNmSknEQx4PG3HypeCqkve +ghdzIbZ7c3Ln5YnXkE7JnNWJegF/LY68+7eY3nCaIJrNlHfGZh2E21Ap6XX+Ljs1 +7/ZGA51p7A88SfowmynNvNEetmbnKQr5TgtHXN7VYTQ40EJcSGk9vl9nTzbrfGZX +VbLyZyXxSKCH7+JpmBuhJ00FPlPg1bJGlRkUCTtpCSH8hmkusPIQA9zgKfD8Thk/ +BxZ8el98nUDXAlP5w12Rv1UxI50zF8lakaEYmlUjS3vPXEu6y2rGEQIDAQABo4GW +MIGTMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsG +AQUFBwMBBggrBgEFBQcDAjAUBgNVHREEDTALgglsb2NhbGhvc3QwHQYDVR0OBBYE +FGOjVOoDiknkD/osT1CnJy//dw01MB8GA1UdIwQYMBaAFFcoTXaqYHHmuy0NhKY+ +1B6AMu44MA0GCSqGSIb3DQEBCwUAA4GBAIPPljdaEgADBIr/LxtbYFB8/Pmm/eFd +veU06eSBr5pm0cOoeWn8NHoKo/JBbRWjHUnCwTLQu+hv3142LPPE02XTp/yI2JNa +u4tuDrr5EjYm9R6Ysn5d1emLXXbHtn/14SXdg3m4egUSDs7FSiqWE32LsqwLKGRM +f3UmUzCWKg1P +-----END CERTIFICATE----- diff --git a/test/js/node/tls/node-tls-cert.test.ts b/test/js/node/tls/node-tls-cert.test.ts index 7717ae5949ad..c083480a1351 100644 --- a/test/js/node/tls/node-tls-cert.test.ts +++ b/test/js/node/tls/node-tls-cert.test.ts @@ -687,6 +687,105 @@ it("tls.connect should ignore NODE_EXTRA_CA_CERTS if it contains invalid cert", expect(exitCode).toBe(1); } }); + +// Node (OpenSSL at its default security level) refuses a chain in which any +// certificate, the trust anchor included, carries an RSA key below 2048 bits, +// reporting code UNSPECIFIED with OpenSSL's reason string. BoringSSL's verifier +// has no such floor, so Bun enforces it in uSockets (us_internal_x509_verify_cert). +// +// Fixtures (fixtures/weak-key-*.pem) were generated with: +// printf '[ca]\nbasicConstraints=critical,CA:TRUE\nkeyUsage=critical,keyCertSign,cRLSign\n[leaf]\nbasicConstraints=critical,CA:FALSE\nkeyUsage=critical,digitalSignature\nextendedKeyUsage=serverAuth,clientAuth\nsubjectAltName=DNS:localhost\n' > ext.cnf +// issue() { openssl req -new -key $1 -subj "$2" -out req.csr && openssl x509 -req -in req.csr -sha256 -days 36500 -CA $4 -CAkey $5 -set_serial 0x$(openssl rand -hex 8) -extfile ext.cnf -extensions $3 -out $6; } +// openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 36500 -keyout root.key -out weak-key-root-cert.pem -subj /CN="Weak Key Test Root" -addext basicConstraints=critical,CA:TRUE -addext keyUsage=critical,keyCertSign,cRLSign +// openssl genrsa -out weak-key-leaf-key.pem 2048 +// openssl genrsa -out inter2048.key 2048; issue inter2048.key /CN="Weak Key Test Intermediate RSA-2048" ca weak-key-root-cert.pem root.key inter2048.pem +// issue weak-key-leaf-key.pem /CN=localhost leaf inter2048.pem inter2048.key leaf.pem; cat leaf.pem inter2048.pem > weak-key-ok-chain.pem +// openssl genrsa -out inter512.key 512; issue inter512.key /CN="Weak Key Test Intermediate RSA-512" ca weak-key-root-cert.pem root.key inter512.pem +// issue weak-key-leaf-key.pem /CN=localhost leaf inter512.pem inter512.key leaf.pem; cat leaf.pem inter512.pem > weak-key-ca512-chain.pem +// openssl genrsa -out weak-key-ee1024-key.pem 1024; issue weak-key-ee1024-key.pem /CN=localhost leaf weak-key-root-cert.pem root.key weak-key-ee1024-cert.pem +// openssl req -x509 -newkey rsa:1024 -nodes -sha256 -days 36500 -keyout root1024.key -out weak-key-root1024-cert.pem -subj /CN="Weak Key Test Root RSA-1024" -addext basicConstraints=critical,CA:TRUE -addext keyUsage=critical,keyCertSign,cRLSign +// issue weak-key-leaf-key.pem /CN=localhost leaf weak-key-root1024-cert.pem root1024.key weak-key-under-root1024-cert.pem +describe("certificate chains containing a weak public key", () => { + const fixture = (name: string) => readFileSync(join(import.meta.dir, "fixtures", name), "utf8"); + const root = fixture("weak-key-root-cert.pem"); + const leafKey = fixture("weak-key-leaf-key.pem"); + // RSA-2048 leaf issued by an RSA-2048 intermediate under `root`. + const strong = { key: leafKey, cert: fixture("weak-key-ok-chain.pem") }; + + const weakChains = [ + { + name: "an RSA-512 intermediate CA", + identity: { key: leafKey, cert: fixture("weak-key-ca512-chain.pem") }, + ca: root, + message: "CA certificate key too weak", + }, + { + name: "an RSA-1024 end-entity certificate", + identity: { key: fixture("weak-key-ee1024-key.pem"), cert: fixture("weak-key-ee1024-cert.pem") }, + ca: root, + message: "EE certificate key too weak", + }, + { + name: "an RSA-1024 trust anchor", + identity: { key: leafKey, cert: fixture("weak-key-under-root1024-cert.pem") }, + ca: fixture("weak-key-root1024-cert.pem"), + message: "CA certificate key too weak", + }, + ]; + + it("authorizes a chain whose keys are all RSA-2048", async () => { + const { client } = await connect({ + client: { ca: root, servername: "localhost", rejectUnauthorized: false }, + server: strong, + }); + expect({ authorized: client.conn.authorized, authorizationError: client.conn.authorizationError }).toEqual({ + authorized: true, + authorizationError: null, + }); + }); + + it("accepts a client certificate whose keys are all RSA-2048", async () => { + const { server } = await connect({ + client: { ...strong, ca: root, servername: "localhost" }, + server: { ...strong, ca: root, requestCert: true }, + }); + expect(server.conn.authorized).toBe(true); + }); + + for (const { name, identity, ca, message } of weakChains) { + describe(name, () => { + it("is reported through authorizationError when rejectUnauthorized is false", async () => { + const { client } = await connect({ + client: { ca, servername: "localhost", rejectUnauthorized: false }, + server: identity, + }); + expect({ authorized: client.conn.authorized, authorizationError: client.conn.authorizationError }).toEqual({ + authorized: false, + authorizationError: "UNSPECIFIED", + }); + }); + + it("fails tls.connect by default", async () => { + await expect( + connect({ + client: { ca, servername: "localhost" }, + server: identity, + }), + ).rejects.toMatchObject({ code: "UNSPECIFIED", message }); + }); + + it("is rejected as a client certificate", async () => { + await expect( + connect({ + client: { ...identity, ca: root, servername: "localhost" }, + server: { ...strong, ca, requestCert: true }, + }), + ).rejects.toMatchObject({ code: "UNSPECIFIED", message }); + }); + }); + } +}); + describe("tls ciphers should work", () => { [ "", // when using BoringSSL we cannot set the cipher suites directly in this case, but we can set empty ciphers