Skip to content
Open
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
2 changes: 2 additions & 0 deletions docs/runtime/networking/fetch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
75 changes: 74 additions & 1 deletion packages/bun-usockets/src/crypto/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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};
}
Expand Down
5 changes: 5 additions & 0 deletions packages/bun-usockets/src/internal/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 8 additions & 0 deletions packages/bun-usockets/src/libusockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions packages/bun-usockets/src/quic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions src/http/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
2 changes: 2 additions & 0 deletions src/http/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
}
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/webcore/fetch/FetchTasklet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down
41 changes: 40 additions & 1 deletion test/js/node/tls/fetch-tls-cert.test.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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 () => {
Expand Down
80 changes: 43 additions & 37 deletions test/js/node/tls/fixtures/agent10-cert.pem
Original file line number Diff line number Diff line change
@@ -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-----
35 changes: 19 additions & 16 deletions test/js/node/tls/fixtures/agent3-cert.pem
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
Loading
Loading