)
func init() {
- RegisterVethTests(EchoBuiltinTest, EchoBuiltinBandwidthTest, EchoBuiltinEchobytesTest, EchoBuiltinRoundtripTest, EchoBuiltinTestbytesTest, EchoBuiltinPeriodicReportTest, EchoBuiltinPeriodicReportTotalTest)
+ RegisterVethTests(EchoBuiltinTest, EchoBuiltinBandwidthTest, EchoBuiltinEchobytesTest, EchoBuiltinRoundtripTest, EchoBuiltinTestbytesTest, EchoBuiltinPeriodicReportTest, EchoBuiltinPeriodicReportTotalTest, TlsSingleConnectionTest)
RegisterVethMWTests(TcpWithLossTest)
RegisterSoloVeth6Tests(TcpWithLoss6Test)
}
s.AssertGreaterEqual(withLoss, uint64(float64(baseline)*0.15))
}
}
+
+func TlsSingleConnectionTest(s *VethsSuite) {
+ serverVpp := s.Containers.ServerVpp.VppInstance
+
+ serverVpp.Vppctl("test echo server " +
+ " uri tls://" + s.Interfaces.Server.Ip4AddressString() + "/" + s.Ports.Port1)
+
+ clientVpp := s.Containers.ClientVpp.VppInstance
+
+ o := clientVpp.Vppctl("test echo client uri tls://%s:%s verbose run-time 5", s.Interfaces.Server.Ip4AddressString(), s.Ports.Port1)
+
+ s.Log(o)
+ throughput, err := s.ParseEchoClientTransfer(o)
+ s.AssertNil(err)
+ s.AssertGreaterThan(throughput, uint64(0))
+}
--- /dev/null
+#!/usr/bin/bash
+
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2025 Cisco Systems, Inc.
+
+# Generate ca private key and certificate
+openssl genrsa -out ca-key.pem 2048
+openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -days 3650 -subj "/C=US/ST=CA/L=San Jose/O=Cisco/CN=Fd.io Test Root CA"
+
+# Generate intermediate CA key
+openssl genrsa -out intermediate-key.pem 2048
+
+# Create intermediate CA certificate request
+openssl req -new -key intermediate-key.pem -out intermediate.csr -subj "/C=US/ST=CA/L=San Jose/O=Cisco/CN=Fd.io Test Intermediate CA"
+
+# Sign intermediate certificate with root CA
+openssl x509 -req -in intermediate.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out intermediate-cert.pem -days 3650
+
+# Create a chain file (root + intermediate)
+cat ca-cert.pem intermediate-cert.pem > ca-chain.pem
+
+# Create CRL configuration
+cat > crl.conf << EOF
+[ ca ]
+default_ca = CA_default
+
+[ CA_default ]
+database = index.txt
+serial = serial
+crlnumber = crlnumber
+default_crl_days = 30
+default_md = sha256
+EOF
+
+# Initialize files
+touch index.txt
+echo 01 > serial
+echo 01 > crlnumber
+
+# Generate empty CRL
+openssl ca -config crl.conf -gencrl -keyfile ca-key.pem -cert ca-cert.pem -out ca-crl.pem
\ No newline at end of file
ec_attach ()
{
vnet_app_add_cert_key_pair_args_t _ck_pair, *ck_pair = &_ck_pair;
+ app_ca_trust_add_args_t _ca_args = {}, *ca_args = &_ca_args;
ec_main_t *ecm = &ec_main;
vnet_app_attach_args_t _a, *a = &_a;
u32 prealloc_fifos;
vnet_app_add_cert_key_pair (ck_pair);
ecm->ckpair_index = ck_pair->index;
+ vec_validate (ca_args->ca_chain, test_ca_chain_rsa_len - 1);
+ clib_memcpy (ca_args->ca_chain, test_ca_chain_rsa, test_ca_chain_rsa_len);
+ vec_validate (ca_args->crl, test_ca_crl_len - 1);
+ clib_memcpy (ca_args->crl, test_ca_crl, test_ca_crl_len);
+ app_crypto_add_ca_trust (ecm->app_index, ca_args);
+ ecm->ca_trust_index = ca_args->index;
+
ecm->test_client_attached = 1;
return 0;
&a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_CRYPTO,
sizeof (transport_endpt_crypto_cfg_t));
ext_cfg->crypto.ckpair_index = ecm->ckpair_index;
+ ext_cfg->crypto.ca_trust_index = ecm->ca_trust_index;
}
rv = vnet_connect (a);
u32 no_copy; /**< Don't memcpy data to tx fifo */
u32 quic_streams; /**< QUIC streams per connection */
u32 ckpair_index; /**< Cert key pair for tls/quic */
+ u32 ca_trust_index; /**< CA trust chain to be used */
u64 attach_flags; /**< App attach flags */
u8 *appns_id; /**< App namespaces id */
u64 appns_secret; /**< App namespace secret */
app_cert_key_pair_t *ckpair;
app_certkey_int_ctx_t *cki;
- /* Configure a ckpair index only if non-default/test provided */
- if (ckpair_index == 0)
- return 0;
-
ckpair = app_cert_key_pair_get_if_valid (ckpair_index);
if (!ckpair)
return -1;
return 0;
}
+static void
+openssl_cleanup_ca_trust_int_ctx (app_crypto_ca_trust_int_ctx_t *cki)
+{
+ X509_STORE_free (cki->ca_store);
+}
+
+static app_crypto_ca_trust_int_ctx_t *
+openssl_init_int_ca_trust_ctx (app_crypto_ca_trust_t *ca_trust,
+ clib_thread_index_t thread_index)
+{
+ app_crypto_ca_trust_int_ctx_t *cti = 0;
+ X509_STORE *store;
+ X509 *cert;
+ BIO *bio;
+
+ cti = app_crypto_alloc_int_ca_trust (ca_trust, thread_index);
+ store = X509_STORE_new ();
+ if (!store)
+ {
+ clib_warning ("unable to create x509 store");
+ return 0;
+ }
+
+ /* Create BIO from the single PEM string containing multiple certificates */
+ bio = BIO_new (BIO_s_mem ());
+ BIO_write (bio, ca_trust->ca_chain, vec_len (ca_trust->ca_chain));
+
+ /* Read all certificates from the PEM string */
+ while ((cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL)) != NULL)
+ {
+ if (X509_STORE_add_cert (store, cert) != 1)
+ {
+ char buf[512];
+ ERR_error_string (ERR_get_error (), buf);
+ clib_warning ("unable to add certificate to store: %s", buf);
+ X509_free (cert);
+ BIO_free (bio);
+ X509_STORE_free (store);
+ return 0;
+ }
+ X509_free (cert);
+ }
+
+ BIO_free (bio);
+
+ /* Parse and add CRL if present */
+ if (ca_trust->crl && vec_len (ca_trust->crl) > 0)
+ {
+ X509_CRL *crl;
+ bio = BIO_new (BIO_s_mem ());
+ BIO_write (bio, ca_trust->crl, vec_len (ca_trust->crl));
+
+ /* Read all CRLs from the PEM string */
+ while ((crl = PEM_read_bio_X509_CRL (bio, NULL, NULL, NULL)) != NULL)
+ {
+ if (X509_STORE_add_crl (store, crl) != 1)
+ {
+ char buf[512];
+ ERR_error_string (ERR_get_error (), buf);
+ clib_warning ("unable to add CRL to store: %s", buf);
+ X509_CRL_free (crl);
+ BIO_free (bio);
+ X509_STORE_free (store);
+ return 0;
+ }
+ X509_CRL_free (crl);
+ }
+
+ BIO_free (bio);
+
+ /* Enable CRL checking */
+ X509_STORE_set_flags (store,
+ X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+ }
+
+ cti->ca_store = store;
+ cti->cleanup_cb = openssl_cleanup_ca_trust_int_ctx;
+
+ return cti;
+}
+
+static int
+openssl_set_ca_trust (tls_ctx_t *ctx)
+{
+ openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
+ app_crypto_ca_trust_int_ctx_t *cti;
+ app_crypto_ca_trust_t *ca_trust;
+
+ ca_trust = app_crypto_get_wrk_ca_trust (ctx->parent_app_wrk_index,
+ ctx->ca_trust_index);
+ if (!ca_trust)
+ return -1;
+
+ cti = app_crypto_get_int_ca_trust (ca_trust, ctx->c_thread_index);
+ if (!cti || !cti->ca_store)
+ {
+ cti = openssl_init_int_ca_trust_ctx (ca_trust, ctx->c_thread_index);
+ if (!cti)
+ {
+ clib_warning ("unable to initialize certificate/key pair");
+ return -1;
+ }
+ }
+
+ if (SSL_set1_verify_cert_store (oc->ssl, cti->ca_store) != 1)
+ {
+ char buf[512];
+ ERR_error_string (ERR_get_error (), buf);
+ clib_warning ("Failed to set CA trust store: %s", buf);
+ return -1;
+ }
+
+ return 0;
+}
+
static int
openssl_init_client_ctx (clib_thread_index_t thread_index,
transport_proto_t proto)
}
}
- if (openssl_set_ckpair (oc->ssl, ctx->ckpair_index, ctx->c_thread_index))
+ /* Configure a ckpair index only if non-default/test provided */
+ if (ctx->ckpair_index)
{
- TLS_DBG (1, "Couldn't set client certificate-key pair");
+ if (openssl_set_ckpair (oc->ssl, ctx->ckpair_index, ctx->c_thread_index))
+ {
+ TLS_DBG (1, "Couldn't set client certificate-key pair");
+ }
+ }
+
+ /* Configure trusted ca only if non-default*/
+ if (ctx->ca_trust_index)
+ {
+ if (openssl_set_ca_trust (ctx))
+ {
+ TLS_DBG (1, "Couldn't set trusted CA");
+ return -1;
+ }
}
if (ctx->tls_type == TRANSPORT_PROTO_TLS)
return vec_elt_at_index (app->crypto_ctx.wrk, thread_index);
}
+static inline app_crypto_ca_trust_t *
+app_get_crypto_ca_trust (application_t *app, u32 ca_trust_index)
+{
+ if (pool_is_free_index (app->crypto_ctx.ca_trust_stores, ca_trust_index))
+ return 0;
+ return pool_elt_at_index (app->crypto_ctx.ca_trust_stores, ca_trust_index);
+}
+
typedef struct app_rx_mq_handle_
{
union
pool_get (app_crypto_main.cert_key_pair_store, ckpair);
clib_memset (ckpair, 0, sizeof (*ckpair));
ckpair->cert_key_index = ckpair - app_crypto_main.cert_key_pair_store;
+ /* Avoid need for locks when used by workers */
+ vec_validate (ckpair->cki, vlib_num_workers ());
return ckpair;
}
return app_cert_key_pair_get (0);
}
+static app_crypto_ca_trust_t *
+app_crypto_alloc_ca_trust (application_t *app)
+{
+ app_crypto_ca_trust_t *ca_trust;
+
+ /* first element not used */
+ if (!pool_elts (app->crypto_ctx.ca_trust_stores))
+ pool_get_zero (app->crypto_ctx.ca_trust_stores, ca_trust);
+ pool_get_zero (app->crypto_ctx.ca_trust_stores, ca_trust);
+ ca_trust->ca_trust_index = ca_trust - app->crypto_ctx.ca_trust_stores;
+ /* Avoid need for locks when used by workers */
+ vec_validate (ca_trust->cti, vlib_num_workers ());
+
+ return ca_trust;
+}
+
+int
+app_crypto_add_ca_trust (u32 app_index, app_ca_trust_add_args_t *args)
+{
+ application_t *app;
+ app_crypto_ca_trust_t *ca_trust;
+
+ app = application_get (app_index);
+ ca_trust = app_crypto_alloc_ca_trust (app);
+ ca_trust->ca_chain = args->ca_chain;
+ ca_trust->crl = args->crl;
+ args->index = ca_trust->ca_trust_index;
+
+ return 0;
+}
+
+app_crypto_ca_trust_t *
+app_crypto_get_wrk_ca_trust (u32 app_wrk_index, u32 ca_trust_index)
+{
+ app_worker_t *app_wrk;
+ application_t *app;
+
+ app_wrk = app_worker_get (app_wrk_index);
+ app = application_get (app_wrk->app_index);
+
+ return app_get_crypto_ca_trust (app, ca_trust_index);
+}
+
+app_crypto_ca_trust_int_ctx_t *
+app_crypto_alloc_int_ca_trust (app_crypto_ca_trust_t *ct,
+ clib_thread_index_t thread_index)
+{
+ return vec_elt_at_index (ct->cti, thread_index);
+}
+
+app_crypto_ca_trust_int_ctx_t *
+app_crypto_get_int_ca_trust (app_crypto_ca_trust_t *ct,
+ clib_thread_index_t thread_index)
+{
+ if (vec_len (ct->cti) <= thread_index)
+ return 0;
+ return vec_elt_at_index (ct->cti, thread_index);
+}
+
int
vnet_app_add_cert_key_pair (vnet_app_add_cert_key_pair_args_t *a)
{
vec_validate (crypto_ctx->wrk, vlib_num_workers ());
}
+static void
+app_crypto_ca_stores_cleanup (app_crypto_ca_trust_t *ca_stores)
+{
+ app_crypto_ca_trust_int_ctx_t *cti;
+ app_crypto_ca_trust_t *ct;
+
+ pool_foreach (ct, ca_stores)
+ {
+ vec_foreach (cti, ct->cti)
+ {
+ if (cti->cleanup_cb)
+ (cti->cleanup_cb) (cti);
+ cti->ca_store = 0;
+ }
+ vec_free (ct->cti);
+ vec_free (ct->ca_chain);
+ vec_free (ct->crl);
+ }
+}
+
void
app_crypto_ctx_free (app_crypto_ctx_t *crypto_ctx)
{
app_crypto_wrk_t *crypto_wrk;
+ if (crypto_ctx->ca_trust_stores)
+ {
+ app_crypto_ca_stores_cleanup (crypto_ctx->ca_trust_stores);
+ pool_free (crypto_ctx->ca_trust_stores);
+ }
+
vec_foreach (crypto_wrk, crypto_ctx->wrk)
pool_free (crypto_wrk->reqs);
vec_free (crypto_ctx->wrk);
typedef struct certificate_
{
- u32 *app_interests; /* vec of application index asking for deletion cb */
- u32 cert_key_index; /* index in cert & key pool */
- u8 *key;
- u8 *cert;
+ u32 *app_interests; /**< vec of application index asking for deletion cb */
+ u32 cert_key_index; /**< index in cert & key pool */
+ u8 *key; /**< PEM encoded key */
+ u8 *cert; /**< PEM encoded cert */
app_certkey_int_ctx_t *cki; /**< per-thread internal cert/key */
} app_cert_key_pair_t;
+struct app_crypto_ca_trust_int_ctx_;
+
+typedef void (*app_crypto_ca_cleanup_it_ctx_fn) (
+ struct app_crypto_ca_trust_int_ctx_ *cti);
+
+typedef struct app_crypto_ca_trust_int_ctx_
+{
+ void *ca_store; /**< trusted ca, possible format X509_STORE */
+ app_crypto_ca_cleanup_it_ctx_fn cleanup_cb; /**< cleanup callback */
+} app_crypto_ca_trust_int_ctx_t;
+
+typedef struct app_crypto_ca_trust_
+{
+ u8 *ca_chain; /**< PEM encoded CA chain */
+ u8 *crl; /**< PEM encoded CRL */
+ u32 ca_trust_index; /**< index in the CA trust pool */
+ app_crypto_ca_trust_int_ctx_t *cti; /**< per-thread internal ca trust */
+} app_crypto_ca_trust_t;
+
typedef enum crypto_engine_type_
{
CRYPTO_ENGINE_NONE,
u32 index;
} vnet_app_add_cert_key_pair_args_t;
+typedef struct app_ca_trust_add_args_
+{
+ u8 *ca_chain;
+ u8 *crl;
+ u32 index;
+} app_ca_trust_add_args_t;
+
typedef struct crypto_ctx_
{
u32 ctx_index; /**< index in crypto context pool */
typedef struct app_crypto_ctx_
{
app_crypto_wrk_t *wrk;
+ app_crypto_ca_trust_t *ca_trust_stores;
} app_crypto_ctx_t;
void app_crypto_ctx_init (app_crypto_ctx_t *crypto_ctx);
app_cert_key_pair_t *app_cert_key_pair_get_if_valid (u32 index);
app_cert_key_pair_t *app_cert_key_pair_get_default ();
+int app_crypto_add_ca_trust (u32 app_index, app_ca_trust_add_args_t *args);
+app_crypto_ca_trust_t *app_crypto_get_wrk_ca_trust (u32 app_wrk_index,
+ u32 ca_trust_index);
+app_crypto_ca_trust_int_ctx_t *
+app_crypto_alloc_int_ca_trust (app_crypto_ca_trust_t *ct,
+ clib_thread_index_t thread_index);
+app_crypto_ca_trust_int_ctx_t *
+app_crypto_get_int_ca_trust (app_crypto_ca_trust_t *ct,
+ clib_thread_index_t thread_index);
+
int vnet_app_add_cert_key_pair (vnet_app_add_cert_key_pair_args_t *a);
int vnet_app_add_cert_key_interest (u32 index, u32 app_index);
int vnet_app_del_cert_key_pair (u32 index);
app_certkey_alloc_int_ctx (app_cert_key_pair_t *ck,
clib_thread_index_t thread_index)
{
- if (!ck->cki)
- vec_validate (ck->cki, vlib_num_workers () + 1);
return vec_elt_at_index (ck->cki, thread_index);
}
typedef struct transport_endpt_crypto_cfg_
{
- u32 ckpair_index; /**< index of ck pair in application crypto layer */
- u8 alpn_protos[4]; /**< ordered by preference for server */
- u8 crypto_engine; /**< crypto engine requested */
+ u32 ckpair_index; /**< index of ck pair in application crypto layer */
+ u32 ca_trust_index; /**< index of ca trust in application crypto layer */
+ u8 alpn_protos[4]; /**< ordered by preference for server */
+ u8 crypto_engine; /**< crypto engine requested */
tls_verify_cfg_t verify_cfg; /**< cert verification mode */
u8 hostname[256]; /**< full domain len is 255 as per rfc 3986 */
} transport_endpt_crypto_cfg_t;
ctx->tcp_is_ip4 = sep->is_ip4;
ctx->tls_type = sep->transport_proto;
ctx->ckpair_index = ccfg->ckpair_index;
+ ctx->ca_trust_index = ccfg->ca_trust_index;
ctx->c_proto = TRANSPORT_PROTO_TLS;
ctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
if (ccfg->hostname[0])
tls_conn_flags_t flags;
u8 *srv_hostname;
u32 ckpair_index;
+ u32 ca_trust_index;
transport_proto_t tls_type;
u8 *alpn_list;
tls_alpn_proto_t alpn_selected;
"oEjPLVNtx8SOj/M4rhaPT3I=\r\n" "-----END PRIVATE KEY-----\r\n";
static const u32 test_srv_key_rsa_len = sizeof (test_srv_key_rsa);
+/*
+ * TLS test CA to used for testing only
+ */
+static const char test_ca_chain_rsa[] =
+ "-----BEGIN CERTIFICATE-----\r\n"
+ "MIIDlTCCAn2gAwIBAgIUMZO3VeOey8A1oB6tp8gx4FXw62gwDQYJKoZIhvcNAQEL\r\n"
+ "BQAwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhTYW4gSm9z\r\n"
+ "ZTEOMAwGA1UECgwFQ2lzY28xGzAZBgNVBAMMEkZkLmlvIFRlc3QgUm9vdCBDQTAe\r\n"
+ "Fw0yNTA5MTEwNjI1MTVaFw0zNTA5MDkwNjI1MTVaMFoxCzAJBgNVBAYTAlVTMQsw\r\n"
+ "CQYDVQQIDAJDQTERMA8GA1UEBwwIU2FuIEpvc2UxDjAMBgNVBAoMBUNpc2NvMRsw\r\n"
+ "GQYDVQQDDBJGZC5pbyBUZXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\r\n"
+ "DwAwggEKAoIBAQDHiQEu2NeUzmhTuPAFoJdRs8EyWmLUbu1HCaBGrmRUqLoPbAms\r\n"
+ "GSowFSHJSE/jQ8d84dMZAzHQxybEzlg14eM6JgpMkzUITZj0IhZB58FiPqEOK7hT\r\n"
+ "pV9nKGJkWJMm9srHo5oUwx3L8L3JZu1uaRj00c9GyD5ApvF+vmHnZv88XidR1f+m\r\n"
+ "yIiuw6Pkb2GrbdGaX08WdUXVv5PrRqFAJaqXMgXCijRucbpXRBYwX1oPdrE7U+Ho\r\n"
+ "uIVA6XyTp+3HwkGsV64oH3WTTIDZksgZMVQq8o9CF9eEXRjoPa5PtDRPs9LyGBid\r\n"
+ "tdrHwB+++HdQU2dNbdS08KdMD/UFg4MAJpqvAgMBAAGjUzBRMB0GA1UdDgQWBBRy\r\n"
+ "XX+uRpAbb8FB70rXIxWHbkAt6jAfBgNVHSMEGDAWgBRyXX+uRpAbb8FB70rXIxWH\r\n"
+ "bkAt6jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAEv8yK7WGJ\r\n"
+ "Zinpi5w736eCaCoSJDnIFZlQ6MHI5Jn9SSKudsGaEBSvicGcD5dkJLIdMEqFBJ6/\r\n"
+ "bm8XfiDa9HUR87LfWA0qVO7hiQ0Xvvf9e1lOM/+e0JTcS2nqNajFBzuWD5OA8s8w\r\n"
+ "6BdOerk7IxMw2cpwDmJ+7Nsc0yd7XRgUSyooyo3YcsvhPCg0v/pmGSbVu0nhG7sE\r\n"
+ "M8DaebCc7JVpsKVfY676IwDQejte35H3jzbMOOLlHKaXDhU9Xf3eEDEfSYyM7shK\r\n"
+ "5QHEw0X14TSO29Y832m3rwAizZOwLy0CpVPjIVju4qkGAzEdk4kg06NQHYlHhDA1\r\n"
+ "0WNb4tBLb2N2\r\n"
+ "-----END CERTIFICATE-----\r\n"
+ "-----BEGIN CERTIFICATE-----\r\n"
+ "MIIDQzCCAisCFCfFYwTSvtLo+7AhR/fDRFffGmTaMA0GCSqGSIb3DQEBCwUAMFox\r\n"
+ "CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTERMA8GA1UEBwwIU2FuIEpvc2UxDjAM\r\n"
+ "BgNVBAoMBUNpc2NvMRswGQYDVQQDDBJGZC5pbyBUZXN0IFJvb3QgQ0EwHhcNMjUw\r\n"
+ "OTExMDYyNzM5WhcNMzUwOTA5MDYyNzM5WjBiMQswCQYDVQQGEwJVUzELMAkGA1UE\r\n"
+ "CAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQKDAVDaXNjbzEjMCEGA1UE\r\n"
+ "AwwaRmQuaW8gVGVzdCBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUA\r\n"
+ "A4IBDwAwggEKAoIBAQCrfov0g9Ls1zV0c5tp6oxf+zGIgrd6Jg45KxKZwrRA0EN5\r\n"
+ "kHtyso1OZdQbJETUIj0cs7qLenjCO4r6c0T7cA5a/VqJUgvFhH4N0oMiH5wcL9yZ\r\n"
+ "m1SX5zdz7PhwBAzCyMkbvrz95243D5KLbYAMizMGx0KyHXzrqL6M+Tr1xYs2kjNj\r\n"
+ "6zq2I04FXbyJnwIj+D7yQ7fyvbKiZNWNstbcDhS3DvyHbAsaCv2NiB5Gelp0iEP3\r\n"
+ "HI6D1WEJiEWa8rgOtAP42WKFbjF1N7UbFUINpYvzckBIH0h7x9f/+Ocs2R4KNQLu\r\n"
+ "r8Lj+NGSQkb+KkRwPF9rOy94IViUyp/yfz1B2l4ZAgMBAAEwDQYJKoZIhvcNAQEL\r\n"
+ "BQADggEBAD6Dw0Kv+nnu6I4lmj50zTsArAwlQDfy+pwD3QBByvUVIkGOwWpKrMUC\r\n"
+ "rAb4sNi3LYoAaGCjrFgcArpuAgireirU0ilfovDipwiXKUGLtTzOL0ZqCqi4wynR\r\n"
+ "7UYh3eaHPQ0LkH+WFrrLCfRu/3TngQHDEiKaL7aug7/q/ZXQ88hTWobws7oHBnKc\r\n"
+ "m5ykWmmD2JRRKu7Mg5dyzlqlI2AkMnQMrX0voTR/KE16qhbMyovNSsH+PuwvhbVl\r\n"
+ "vFTyeC/o7Rm+U+JkaFA/wyP/6gzfT1XFSsNY2WAWNzrsWtCf2gVWNxPvGHg6G0Yz\r\n"
+ "TiCarwFKR1qNpR+qibWDni6b2gRZcs0=\r\n"
+ "-----END CERTIFICATE-----\r\n";
+static const u32 test_ca_chain_rsa_len = sizeof (test_ca_chain_rsa);
+
+static const char test_ca_crl[] =
+ "-----BEGIN X509 CRL-----\r\n"
+ "MIIBszCBnAIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzELMAkGA1UE\r\n"
+ "CAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQKDAVDaXNjbzEbMBkGA1UE\r\n"
+ "AwwSRmQuaW8gVGVzdCBSb290IENBFw0yNTA5MTEwNjI4NDhaFw0yNTEwMTEwNjI4\r\n"
+ "NDhaoA4wDDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAe8YmRs+VOw3M\r\n"
+ "xofJCI40bt6La/1knBd3KSM91pSBAfmZReztoHHxiM0ymViv6ZnKIymn+F1JhhqU\r\n"
+ "OLV7S28oCVkpB2O1zsCv8FyfAegLrvu/ipFGsemRos+YxXtC9mam8WuGFRMFXzjB\r\n"
+ "PBoyZsaWspXoHlMpUqPBfagjciiJdyxCWoCwd8jVA9swgG6dxCLUup98du88ikgA\r\n"
+ "huoi90QF+/qztjwoE8rngGWKdR7Re6qYrZIwGgLupxA3pGonCsTRwPKE/qrbNhMi\r\n"
+ "Pqmuu8zyeaqq/EoKNmuE22AeIn2BsYslJKMKOwQ022CAAtIDjB0boBI6+IeFrStJ\r\n"
+ "41u0xwNSyA==\r\n"
+ "-----END X509 CRL-----\r\n";
+static const u32 test_ca_crl_len = sizeof (test_ca_crl);
+
#endif /* SRC_VNET_TLS_TLS_TEST_H_ */
/*