summaryrefslogtreecommitdiff
path: root/src/irmd/oap/tests/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd/oap/tests/common.c')
-rw-r--r--src/irmd/oap/tests/common.c286
1 files changed, 273 insertions, 13 deletions
diff --git a/src/irmd/oap/tests/common.c b/src/irmd/oap/tests/common.c
index 0a1af100..16d52c63 100644
--- a/src/irmd/oap/tests/common.c
+++ b/src/irmd/oap/tests/common.c
@@ -29,39 +29,47 @@
#include <string.h>
#include <stdio.h>
-int load_srv_kex_config(const struct name_info * info,
+int load_srv_sec_config(const struct name_info * info,
struct sec_config * cfg)
{
(void) info;
memset(cfg, 0, sizeof(*cfg));
+ cfg->a.req = test_cfg.srv.req_auth;
+
+ /* Digest is kept without kex, as in parse_sec_config */
+ SET_KEX_DIGEST_NID(cfg, test_cfg.srv.md);
+
if (test_cfg.srv.kex == NID_undef)
return 0;
SET_KEX_ALGO_NID(cfg, test_cfg.srv.kex);
SET_KEX_CIPHER_NID(cfg, test_cfg.srv.cipher);
SET_KEX_KDF_NID(cfg, test_cfg.srv.kdf);
- SET_KEX_DIGEST_NID(cfg, test_cfg.srv.md);
SET_KEX_KEM_MODE(cfg, test_cfg.srv.kem_mode);
return 0;
}
-int load_cli_kex_config(const struct name_info * info,
+int load_cli_sec_config(const struct name_info * info,
struct sec_config * cfg)
{
(void) info;
memset(cfg, 0, sizeof(*cfg));
+ cfg->a.req = test_cfg.cli.req_auth;
+
+ /* Digest is kept without kex, as in parse_sec_config */
+ SET_KEX_DIGEST_NID(cfg, test_cfg.cli.md);
+
if (test_cfg.cli.kex == NID_undef)
return 0;
SET_KEX_ALGO_NID(cfg, test_cfg.cli.kex);
SET_KEX_CIPHER_NID(cfg, test_cfg.cli.cipher);
SET_KEX_KDF_NID(cfg, test_cfg.cli.kdf);
- SET_KEX_DIGEST_NID(cfg, test_cfg.cli.md);
SET_KEX_KEM_MODE(cfg, test_cfg.cli.kem_mode);
return 0;
@@ -152,13 +160,15 @@ void oap_test_teardown(struct oap_test_ctx * ctx)
if (ctx->cli.state != NULL) {
res.key = ctx->cli.key;
oap_cli_complete(ctx->cli.state, &ctx->cli.info, dummy,
- &ctx->data, &res);
+ &ctx->data, &res, NULL, NULL);
ctx->cli.state = NULL;
}
freebuf(ctx->data);
freebuf(ctx->resp_hdr);
freebuf(ctx->req_hdr);
+ freebuf(ctx->srv_crt);
+ freebuf(ctx->cli_crt);
crypt_free_crt(ctx->im_ca);
crypt_free_crt(ctx->root_ca);
@@ -170,7 +180,7 @@ void oap_test_teardown(struct oap_test_ctx * ctx)
int oap_cli_prepare_ctx(struct oap_test_ctx * ctx)
{
return oap_cli_prepare(&ctx->cli.state, &ctx->cli.info, &ctx->req_hdr,
- ctx->data);
+ ctx->data, ctx->rekey);
}
int oap_srv_process_ctx(struct oap_test_ctx * ctx)
@@ -179,7 +189,9 @@ int oap_srv_process_ctx(struct oap_test_ctx * ctx)
int ret;
ret = oap_srv_process(&ctx->srv.info, ctx->req_hdr,
- &ctx->resp_hdr, &ctx->data, &res);
+ &ctx->resp_hdr, &ctx->data, &res, ctx->rekey,
+ ctx->rekey ? &ctx->srv_crt : NULL,
+ ctx->rekey ? NULL : &ctx->srv_crt);
if (ret == 0)
ctx->srv.nid = res.nid;
@@ -192,7 +204,9 @@ int oap_cli_complete_ctx(struct oap_test_ctx * ctx)
int ret;
ret = oap_cli_complete(ctx->cli.state, &ctx->cli.info, ctx->resp_hdr,
- &ctx->data, &res);
+ &ctx->data, &res,
+ ctx->rekey ? &ctx->cli_crt : NULL,
+ ctx->rekey ? NULL : &ctx->cli_crt);
ctx->cli.state = NULL;
if (ret == 0)
@@ -243,6 +257,249 @@ int roundtrip_auth_only(const char * root_ca,
return TEST_RC_FAIL;
}
+static const char * rekey_mode(bool srv_auth,
+ bool cli_auth)
+{
+ if (srv_auth && cli_auth)
+ return "mutual";
+
+ if (srv_auth)
+ return "srv-only";
+
+ if (cli_auth)
+ return "cli-only";
+
+ return "none";
+}
+
+int roundtrip_rekey(const char * root_ca,
+ const char * im_ca_str,
+ bool srv_auth,
+ bool cli_auth)
+{
+ struct oap_test_ctx ctx;
+ uint8_t key0[SYMMKEYSZ];
+ const char * mode = rekey_mode(srv_auth, cli_auth);
+
+ TEST_START("(%s)", mode);
+
+ if (oap_test_setup(&ctx, root_ca, im_ca_str) < 0)
+ goto fail;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Initial client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_srv_process_ctx(&ctx) < 0) {
+ printf("Initial server process failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_cli_complete_ctx(&ctx) < 0) {
+ printf("Initial client complete failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (memcmp(ctx.cli.key, ctx.srv.key, SYMMKEYSZ) != 0) {
+ printf("Initial keys do not match.\n");
+ goto fail_cleanup;
+ }
+
+ /* The client caches the server cert only if the server authed. */
+ if (srv_auth && ctx.cli_crt.len == 0) {
+ printf("Server cert was not cached for re-key.\n");
+ goto fail_cleanup;
+ }
+
+ /* The server caches the client cert only if the client authed. */
+ if (cli_auth && ctx.srv_crt.len == 0) {
+ printf("Client cert was not cached by the server.\n");
+ goto fail_cleanup;
+ }
+
+ memcpy(key0, ctx.cli.key, SYMMKEYSZ);
+
+ /* Re-key: cert dropped on the wire, verified against the cache. */
+ freebuf(ctx.req_hdr);
+ freebuf(ctx.resp_hdr);
+ freebuf(ctx.data);
+
+ ctx.rekey = true;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Re-key client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_srv_process_ctx(&ctx) < 0) {
+ printf("Re-key server process failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_cli_complete_ctx(&ctx) < 0) {
+ printf("Re-key client complete failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (memcmp(ctx.cli.key, ctx.srv.key, SYMMKEYSZ) != 0) {
+ printf("Re-key keys do not match.\n");
+ goto fail_cleanup;
+ }
+
+ if (memcmp(ctx.cli.key, key0, SYMMKEYSZ) == 0) {
+ printf("Re-key did not produce a fresh key.\n");
+ goto fail_cleanup;
+ }
+
+ if (ctx.cli.nid == NID_undef || ctx.srv.nid == NID_undef) {
+ printf("Cipher not set after re-key.\n");
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS("(%s)", mode);
+
+ return TEST_RC_SUCCESS;
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL("(%s)", mode);
+ return TEST_RC_FAIL;
+}
+
+int roundtrip_rekey_badcache(const char * root_ca,
+ const char * im_ca_str,
+ bool cli_auth)
+{
+ struct oap_test_ctx ctx;
+ const char * mode = rekey_mode(true, cli_auth);
+
+ TEST_START("(%s)", mode);
+
+ if (oap_test_setup(&ctx, root_ca, im_ca_str) < 0)
+ goto fail;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Initial client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_srv_process_ctx(&ctx) < 0) {
+ printf("Initial server process failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_cli_complete_ctx(&ctx) < 0) {
+ printf("Initial client complete failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (ctx.cli_crt.len == 0) {
+ printf("Server cert was not cached.\n");
+ goto fail_cleanup;
+ }
+
+ /* Corrupt the client's cached server cert: re-key must fail closed. */
+ ctx.cli_crt.data[ctx.cli_crt.len / 2] ^= 0xFF;
+
+ freebuf(ctx.req_hdr);
+ freebuf(ctx.resp_hdr);
+ freebuf(ctx.data);
+
+ ctx.rekey = true;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Re-key client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_srv_process_ctx(&ctx) < 0) {
+ printf("Re-key server process failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_cli_complete_ctx(&ctx) == 0) {
+ printf("Re-key accepted a corrupted cached cert.\n");
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS("(%s)", mode);
+
+ return TEST_RC_SUCCESS;
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL("(%s)", mode);
+ return TEST_RC_FAIL;
+}
+
+int roundtrip_rekey_srv_badcache(const char * root_ca,
+ const char * im_ca_str,
+ bool srv_auth)
+{
+ struct oap_test_ctx ctx;
+ const char * mode = rekey_mode(srv_auth, true);
+
+ TEST_START("(%s)", mode);
+
+ if (oap_test_setup(&ctx, root_ca, im_ca_str) < 0)
+ goto fail;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Initial client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_srv_process_ctx(&ctx) < 0) {
+ printf("Initial server process failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_cli_complete_ctx(&ctx) < 0) {
+ printf("Initial client complete failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (ctx.srv_crt.len == 0) {
+ printf("Client cert was not cached by the server.\n");
+ goto fail_cleanup;
+ }
+
+ /* Corrupt the server's cached client cert: re-key must fail closed. */
+ ctx.srv_crt.data[ctx.srv_crt.len / 2] ^= 0xFF;
+
+ freebuf(ctx.req_hdr);
+ freebuf(ctx.resp_hdr);
+ freebuf(ctx.data);
+
+ ctx.rekey = true;
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Re-key client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ if (oap_srv_process_ctx(&ctx) == 0) {
+ printf("Server accepted a corrupted cached client cert.\n");
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS("(%s)", mode);
+
+ return TEST_RC_SUCCESS;
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL("(%s)", mode);
+ return TEST_RC_FAIL;
+}
+
int roundtrip_kex_only(void)
{
struct name_info cli_info;
@@ -271,14 +528,15 @@ int roundtrip_kex_only(void)
}
if (oap_cli_prepare(&cli_state, &cli_info, &req_hdr,
- data) < 0) {
+ data, false) < 0) {
printf("Client prepare failed.\n");
goto fail_cleanup;
}
res.key = srv_key;
- if (oap_srv_process(&srv_info, req_hdr, &resp_hdr, &data, &res) < 0) {
+ if (oap_srv_process(&srv_info, req_hdr, &resp_hdr, &data, &res,
+ false, NULL, NULL) < 0) {
printf("Server process failed.\n");
goto fail_cleanup;
}
@@ -287,7 +545,8 @@ int roundtrip_kex_only(void)
res.key = cli_key;
- if (oap_cli_complete(cli_state, &cli_info, resp_hdr, &data, &res) < 0) {
+ if (oap_cli_complete(cli_state, &cli_info, resp_hdr, &data, &res,
+ NULL, NULL) < 0) {
printf("Client complete failed.\n");
cli_state = NULL;
goto fail_cleanup;
@@ -316,7 +575,8 @@ int roundtrip_kex_only(void)
fail_cleanup:
if (cli_state != NULL) {
res.key = cli_key;
- oap_cli_complete(cli_state, &cli_info, resp_hdr, &data, &res);
+ oap_cli_complete(cli_state, &cli_info, resp_hdr, &data,
+ &res, NULL, NULL);
}
freebuf(resp_hdr);
freebuf(req_hdr);
@@ -396,7 +656,7 @@ int corrupted_response(const char * root_ca,
res.key = ctx.cli.key;
if (oap_cli_complete(ctx.cli.state, &ctx.cli.info, ctx.resp_hdr,
- &ctx.data, &res) == 0) {
+ &ctx.data, &res, NULL, NULL) == 0) {
printf("Client should reject corrupted response.\n");
ctx.cli.state = NULL;
goto fail_cleanup;