/* * After the test case has been processed by the DUT, the results * need to be JSON formated to be included in the vector set results * file that will be uploaded to the server. This routine handles * the JSON processing for a single test case. */ static ACVP_RESULT acvp_cmac_output_tc(ACVP_CTX *ctx, ACVP_CMAC_TC *stc, JSON_Object *tc_rsp) { ACVP_RESULT rv = ACVP_SUCCESS; char *tmp = NULL; tmp = calloc(ACVP_CMAC_MACLEN_MAX + 1, sizeof(char)); if (!tmp) { ACVP_LOG_ERR("Unable to malloc in acvp_cmac_output_tc"); return ACVP_MALLOC_FAIL; } if (stc->verify) { json_object_set_boolean(tc_rsp, "testPassed", stc->ver_disposition); } else { rv = acvp_bin_to_hexstr(stc->mac, stc->mac_len, tmp, ACVP_CMAC_MACLEN_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (mac)"); goto end; } json_object_set_string(tc_rsp, "mac", tmp); } end: if (tmp) free(tmp); return rv; }
/* * This is the internal send function that takes the URI as an extra * parameter. This removes repeated code without having to change the * API that the library uses to send registrations */ static ACVP_RESULT acvp_network_action(ACVP_CTX *ctx, ACVP_NET_ACTION action, char *url, char *data, int data_len) { ACVP_RESULT rv = ACVP_SUCCESS; ACVP_NET_ACTION generic_action = 0; int check_data = 0; int curl_code = 0; if (!ctx) { ACVP_LOG_ERR("Missing ctx"); return ACVP_NO_CTX; } if (!url) { ACVP_LOG_ERR("URL required for transmission"); return ACVP_MISSING_ARG; } switch (action) { case ACVP_NET_GET: case ACVP_NET_GET_VS: case ACVP_NET_GET_VS_RESULT: case ACVP_NET_GET_VS_SAMPLE: generic_action = ACVP_NET_GET; break; case ACVP_NET_POST: case ACVP_NET_POST_REG: check_data = 1; generic_action = ACVP_NET_POST; break; case ACVP_NET_POST_LOGIN: /* Clear jwt if logging in */ if (ctx->jwt_token) free(ctx->jwt_token); ctx->jwt_token = NULL; check_data = 1; generic_action = ACVP_NET_POST_LOGIN; break; case ACVP_NET_POST_VS_RESP: generic_action = ACVP_NET_POST_VS_RESP; break; } if (check_data && (!data || !data_len)) { ACVP_LOG_ERR("POST action requires non-zero data/data_len"); return ACVP_NO_DATA; } rv = execute_network_action(ctx, generic_action, url, data, data_len, &curl_code); /* Log to the console */ log_network_status(ctx, action, curl_code, url); return rv; }
static ACVP_RESULT sanity_check_ctx(ACVP_CTX *ctx) { if (!ctx) { ACVP_LOG_ERR("Missing ctx"); return ACVP_NO_CTX; } if (!ctx->server_port || !ctx->server_name) { ACVP_LOG_ERR("Call acvp_set_server to fill in server name and port"); return ACVP_MISSING_ARG; } return ACVP_SUCCESS; }
static struct curl_slist *acvp_add_auth_hdr(ACVP_CTX *ctx, struct curl_slist *slist) { char *bearer = NULL; char bearer_title[] = "Authorization: Bearer "; int bearer_title_size = (int)sizeof(bearer_title) - 1; int bearer_size = 0; if (!ctx->jwt_token && !(ctx->tmp_jwt && ctx->use_tmp_jwt)) { /* * We don't have a token to embed */ return slist; } if (ctx->use_tmp_jwt && !ctx->tmp_jwt) { ACVP_LOG_ERR("Trying to use tmp_jwt, but it is NULL"); return slist; } if (ctx->use_tmp_jwt) { bearer_size = strnlen_s(ctx->tmp_jwt, ACVP_JWT_TOKEN_MAX) + bearer_title_size; } else { bearer_size = strnlen_s(ctx->jwt_token, ACVP_JWT_TOKEN_MAX) + bearer_title_size; } bearer = calloc(bearer_size + 1, sizeof(char)); if (!bearer) { ACVP_LOG_ERR("unable to allocate memory."); goto end; } if (ctx->use_tmp_jwt) { snprintf(bearer, bearer_size + 1, "%s%s", bearer_title, ctx->tmp_jwt); } else { snprintf(bearer, bearer_size + 1, "%s%s", bearer_title, ctx->jwt_token); } slist = curl_slist_append(slist, bearer); free(bearer); end: if (ctx->use_tmp_jwt) { /* * This was a single-use token. * Turn it off now... the library might turn it back on later. */ ctx->use_tmp_jwt = 0; } return slist; }
static ACVP_RESULT inspect_http_code(ACVP_CTX *ctx, int code) { ACVP_RESULT result = ACVP_TRANSPORT_FAIL; /* Generic failure */ JSON_Value *root_value = NULL; const JSON_Object *obj = NULL; const char *err_str = NULL; if (code == HTTP_OK) { /* 200 */ return ACVP_SUCCESS; } if (code == HTTP_UNAUTH) { int diff = 1; root_value = json_parse_string(ctx->curl_buf); obj = json_value_get_object(root_value); if (!obj) { ACVP_LOG_ERR("HTTP body doesn't contain top-level JSON object"); goto end; } err_str = json_object_get_string(obj, "error"); if (!err_str) { ACVP_LOG_ERR("JSON object doesn't contain 'error'"); goto end; } strncmp_s(JWT_EXPIRED_STR, JWT_EXPIRED_STR_LEN, err_str, JWT_EXPIRED_STR_LEN, &diff); if (!diff) { result = ACVP_JWT_EXPIRED; goto end; } strncmp_s(JWT_INVALID_STR, JWT_INVALID_STR_LEN, err_str, JWT_INVALID_STR_LEN, &diff); if (!diff) { result = ACVP_JWT_INVALID; goto end; } } end: if (root_value) json_value_free(root_value); return result; }
/* * Forward prototypes for local functions */ static ACVP_RESULT acvp_kdf135_ikev1_output_tc(ACVP_CTX *ctx, ACVP_KDF135_IKEV1_TC *stc, JSON_Object *tc_rsp) { ACVP_RESULT rv; char *tmp = NULL; tmp = calloc(ACVP_KDF135_IKEV1_SKEY_STR_MAX + 1, sizeof(char)); if (!tmp) { ACVP_LOG_ERR("Unable to malloc in acvp_kdf135 tpm_output_tc"); return ACVP_MALLOC_FAIL; } rv = acvp_bin_to_hexstr(stc->s_key_id, stc->s_key_id_len, tmp, ACVP_KDF135_IKEV1_SKEY_STR_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (s_key_id)"); goto err; } json_object_set_string(tc_rsp, "sKeyId", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_IKEV1_SKEY_STR_MAX); rv = acvp_bin_to_hexstr(stc->s_key_id_d, stc->s_key_id_d_len, tmp, ACVP_KDF135_IKEV1_SKEY_STR_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (s_key_id_d)"); goto err; } json_object_set_string(tc_rsp, "sKeyIdD", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_IKEV1_SKEY_STR_MAX); rv = acvp_bin_to_hexstr(stc->s_key_id_a, stc->s_key_id_a_len, tmp, ACVP_KDF135_IKEV1_SKEY_STR_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (s_key_id_a)"); goto err; } json_object_set_string(tc_rsp, "sKeyIdA", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_IKEV1_SKEY_STR_MAX); rv = acvp_bin_to_hexstr(stc->s_key_id_e, stc->s_key_id_e_len, tmp, ACVP_KDF135_IKEV1_SKEY_STR_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (s_key_id_e)"); goto err; } json_object_set_string(tc_rsp, "sKeyIdE", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_IKEV1_SKEY_STR_MAX); err: free(tmp); return rv; }
/* * After the test case has been processed by the DUT, the results * need to be JSON formated to be included in the vector set results * file that will be uploaded to the server. This routine handles * the JSON processing for a single test case. */ static ACVP_RESULT acvp_kdf135_srtp_output_tc(ACVP_CTX *ctx, ACVP_KDF135_SRTP_TC *stc, JSON_Object *tc_rsp) { ACVP_RESULT rv = ACVP_SUCCESS; char *tmp = NULL; tmp = calloc(ACVP_KDF135_SRTP_OUTPUT_MAX + 1, sizeof(char)); if (!tmp) { return ACVP_MALLOC_FAIL; } rv = acvp_bin_to_hexstr(stc->srtp_ke, stc->aes_keylen / 8, tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (srtp_ke)"); goto err; } json_object_set_string(tc_rsp, "srtpKe", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); rv = acvp_bin_to_hexstr(stc->srtp_ka, 160 / 8, tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (srtp_ka)"); goto err; } json_object_set_string(tc_rsp, "srtpKa", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); rv = acvp_bin_to_hexstr(stc->srtp_ks, 112 / 8, tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (srtp_ks)"); goto err; } json_object_set_string(tc_rsp, "srtpKs", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); rv = acvp_bin_to_hexstr(stc->srtcp_ke, stc->aes_keylen / 8, tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (srtcp_ke)"); goto err; } json_object_set_string(tc_rsp, "srtcpKe", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); rv = acvp_bin_to_hexstr(stc->srtcp_ka, 160 / 8, tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (srtcp_ka)"); goto err; } json_object_set_string(tc_rsp, "srtcpKa", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); rv = acvp_bin_to_hexstr(stc->srtcp_ks, 112 / 8, tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("hex conversion failure (srtcp_ks)"); goto err; } json_object_set_string(tc_rsp, "srtcpKs", (const char *)tmp); memzero_s(tmp, ACVP_KDF135_SRTP_OUTPUT_MAX); err: free(tmp); return rv; }
/* * Test KAT handler API. * The ctx is NULL, expecting failure. */ Test(CMAC_API, null_ctx) { val = json_parse_file("json/cmac/cmac_aes.json"); obj = ut_get_obj_from_rsp(val); if (!obj) { ACVP_LOG_ERR("JSON obj parse error"); return; } /* Test with NULL JSON object */ rv = acvp_cmac_kat_handler(NULL, obj); cr_assert(rv == ACVP_NO_CTX); json_value_free(val); }
ACVP_RESULT acvp_transport_get(ACVP_CTX *ctx, const char *url) { ACVP_RESULT rv = 0; char constructed_url[ACVP_ATTR_URL_MAX] = {0}; rv = sanity_check_ctx(ctx); if (ACVP_SUCCESS != rv) return rv; if (!url) { ACVP_LOG_ERR("Missing url"); return ACVP_MISSING_ARG; } snprintf(constructed_url, ACVP_ATTR_URL_MAX - 1, "https://%s:%d/%s", ctx->server_name, ctx->server_port, url); return acvp_network_action(ctx, ACVP_NET_GET, constructed_url, NULL, 0); }
ACVP_RESULT acvp_retrieve_expected_result(ACVP_CTX *ctx, char *api_url) { ACVP_RESULT rv = 0; char url[ACVP_ATTR_URL_MAX] = {0}; rv = sanity_check_ctx(ctx); if (ACVP_SUCCESS != rv) return rv; if (!api_url) { ACVP_LOG_ERR("Missing api_url"); return ACVP_MISSING_ARG; } snprintf(url, ACVP_ATTR_URL_MAX - 1, "https://%s:%d/%s/expected", ctx->server_name, ctx->server_port, api_url); return acvp_network_action(ctx, ACVP_NET_GET_VS_SAMPLE, url, NULL, 0); }
/* * This is the top level function used within libacvp to retrieve * a KAT vector set from the ACVP server. */ ACVP_RESULT acvp_retrieve_vector_set(ACVP_CTX *ctx, char *vsid_url) { ACVP_RESULT rv = 0; char url[ACVP_ATTR_URL_MAX] = {0}; rv = sanity_check_ctx(ctx); if (ACVP_SUCCESS != rv) return rv; if (!vsid_url) { ACVP_LOG_ERR("Missing vsid_url"); return ACVP_MISSING_ARG; } snprintf(url, ACVP_ATTR_URL_MAX - 1, "https://%s:%d/%s", ctx->server_name, ctx->server_port, vsid_url); return acvp_network_action(ctx, ACVP_NET_GET_VS, url, NULL, 0); }
ACVP_RESULT acvp_send_test_session_registration(ACVP_CTX *ctx, char *reg, int len) { ACVP_RESULT rv = 0; char url[ACVP_ATTR_URL_MAX] = {0}; rv = sanity_check_ctx(ctx); if (ACVP_SUCCESS != rv) return rv; if (!ctx->path_segment) { ACVP_LOG_ERR("No path segment, need to call acvp_set_path_segment first"); return ACVP_MISSING_ARG; } snprintf(url, ACVP_ATTR_URL_MAX - 1, "https://%s:%d/%s%s", ctx->server_name, ctx->server_port, ctx->path_segment, ACVP_TEST_SESSIONS_URI); return acvp_network_action(ctx, ACVP_NET_POST_REG, url, reg, len); }
/* * Test the KAT handler API. * The ctx is empty (no capabilities), expecting failure. */ Test(CMAC_API, empty_ctx) { setup_empty_ctx(&ctx); val = json_parse_file("json/cmac/cmac_aes.json"); obj = ut_get_obj_from_rsp(val); if (!obj) { ACVP_LOG_ERR("JSON obj parse error"); goto end; } rv = acvp_cmac_kat_handler(ctx, obj); cr_assert(rv == ACVP_UNSUPPORTED_OP); json_value_free(val); end: if (ctx) teardown_ctx(&ctx); }
ACVP_RESULT acvp_transport_post(ACVP_CTX *ctx, const char *uri, char *data, int data_len) { ACVP_RESULT rv = 0; char constructed_url[ACVP_ATTR_URL_MAX] = {0}; rv = sanity_check_ctx(ctx); if (ACVP_SUCCESS != rv) return rv; if (!uri) { ACVP_LOG_ERR("Missing uri"); return ACVP_MISSING_ARG; } snprintf(constructed_url, ACVP_ATTR_URL_MAX - 1, "https://%s:%d/%s%s", ctx->server_name, ctx->server_port, ctx->path_segment, uri); return acvp_network_action(ctx, ACVP_NET_POST, constructed_url, data, data_len); }
static ACVP_RESULT acvp_kdf135_ikev1_init_tc(ACVP_CTX *ctx, ACVP_KDF135_IKEV1_TC *stc, unsigned int tc_id, ACVP_HASH_ALG hash_alg, ACVP_KDF135_IKEV1_AUTH_METHOD auth_method, int init_nonce_len, int resp_nonce_len, int dh_secret_len, int psk_len, char *init_nonce, char *resp_nonce, char *init_ckey, char *resp_ckey, char *gxy, char *psk) { ACVP_RESULT rv = ACVP_SUCCESS; memzero_s(stc, sizeof(ACVP_KDF135_IKEV1_TC)); stc->tc_id = tc_id; stc->hash_alg = hash_alg; stc->auth_method = auth_method; stc->init_nonce_len = ACVP_BIT2BYTE(init_nonce_len); stc->resp_nonce_len = ACVP_BIT2BYTE(resp_nonce_len); stc->dh_secret_len = ACVP_BIT2BYTE(dh_secret_len); stc->psk_len = ACVP_BIT2BYTE(psk_len); stc->init_nonce = calloc(ACVP_KDF135_IKEV1_INIT_NONCE_BYTE_MAX, sizeof(unsigned char)); if (!stc->init_nonce) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(init_nonce, stc->init_nonce, ACVP_KDF135_IKEV1_INIT_NONCE_BYTE_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (init_nonce)"); return rv; } stc->resp_nonce = calloc(ACVP_KDF135_IKEV1_RESP_NONCE_BYTE_MAX, sizeof(unsigned char)); if (!stc->resp_nonce) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(resp_nonce, stc->resp_nonce, ACVP_KDF135_IKEV1_RESP_NONCE_BYTE_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (resp_nonce)"); return rv; } stc->init_ckey = calloc(ACVP_KDF135_IKEV1_COOKIE_BYTE_MAX, sizeof(unsigned char)); if (!stc->init_ckey) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(init_ckey, stc->init_ckey, ACVP_KDF135_IKEV1_COOKIE_BYTE_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (init_ckey)"); return rv; } stc->resp_ckey = calloc(ACVP_KDF135_IKEV1_COOKIE_BYTE_MAX, sizeof(unsigned char)); if (!stc->resp_ckey) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(resp_ckey, stc->resp_ckey, ACVP_KDF135_IKEV1_COOKIE_BYTE_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (resp_ckey)"); return rv; } stc->gxy = calloc(ACVP_KDF135_IKEV1_DH_SHARED_SECRET_BYTE_MAX, sizeof(unsigned char)); if (!stc->gxy) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(gxy, stc->gxy, ACVP_KDF135_IKEV1_DH_SHARED_SECRET_BYTE_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (gxy)"); return rv; } if (psk != NULL) { /* Only for PSK authentication method */ stc->psk = calloc(ACVP_KDF135_IKEV1_PSK_BYTE_MAX, sizeof(unsigned char)); if (!stc->psk) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(psk, stc->psk, ACVP_KDF135_IKEV1_PSK_BYTE_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (psk)"); return rv; } } stc->s_key_id = calloc(ACVP_KDF135_IKEV1_SKEY_BYTE_MAX, sizeof(unsigned char)); if (!stc->s_key_id) { return ACVP_MALLOC_FAIL; } stc->s_key_id_a = calloc(ACVP_KDF135_IKEV1_SKEY_BYTE_MAX, sizeof(unsigned char)); if (!stc->s_key_id_a) { return ACVP_MALLOC_FAIL; } stc->s_key_id_d = calloc(ACVP_KDF135_IKEV1_SKEY_BYTE_MAX, sizeof(unsigned char)); if (!stc->s_key_id_d) { return ACVP_MALLOC_FAIL; } stc->s_key_id_e = calloc(ACVP_KDF135_IKEV1_SKEY_BYTE_MAX, sizeof(unsigned char)); if (!stc->s_key_id_e) { return ACVP_MALLOC_FAIL; } return rv; }
static ACVP_RESULT execute_network_action(ACVP_CTX *ctx, ACVP_NET_ACTION action, char *url, char *data, int data_len, int *curl_code) { ACVP_RESULT result = 0; char *resp = NULL; char large_url[ACVP_ATTR_URL_MAX + 1] = {0}; int large_submission = 0; int resp_len = 0; int rc = 0; switch(action) { case ACVP_NET_GET: case ACVP_NET_GET_VS: case ACVP_NET_GET_VS_RESULT: case ACVP_NET_GET_VS_SAMPLE: rc = acvp_curl_http_get(ctx, url); break; case ACVP_NET_POST: case ACVP_NET_POST_LOGIN: case ACVP_NET_POST_REG: rc = acvp_curl_http_post(ctx, url, data, data_len); break; case ACVP_NET_POST_VS_RESP: resp = json_serialize_to_string(ctx->kat_resp, &resp_len); if (!resp) { ACVP_LOG_ERR("Faled to serialize JSON to string"); return ACVP_JSON_ERR; } json_value_free(ctx->kat_resp); ctx->kat_resp = NULL; if (ctx->post_size_constraint && resp_len > ctx->post_size_constraint) { /* Determine if this POST body goes over the "constraint" */ large_submission = 1; } if (large_submission) { /* * Need to tell the server about this large submission. * The server will supply us with a one-time "large" URL; */ result = acvp_notify_large(ctx, url, large_url, resp_len); if (result != ACVP_SUCCESS) goto end; rc = acvp_curl_http_post(ctx, large_url, resp, resp_len); } else { rc = acvp_curl_http_post(ctx, url, resp, resp_len); } break; default: ACVP_LOG_ERR("Unknown ACVP_NET_ACTION"); return ACVP_INVALID_ARG; } /* Peek at the HTTP code */ result = inspect_http_code(ctx, rc); if (result != ACVP_SUCCESS) { if (result == ACVP_JWT_EXPIRED && action != ACVP_NET_POST_LOGIN) { /* * Expired JWT * We are going to refresh the session * and try to obtain a new JWT! * This should not ever happen during "login"... * and we need to avoid an infinite loop (via acvp_refesh). */ ACVP_LOG_ERR("JWT authorization has timed out, curl rc=%d.\n" "Refreshing session...", rc); result = acvp_refresh(ctx); if (result != ACVP_SUCCESS) { ACVP_LOG_ERR("JWT refresh failed."); goto end; } /* Try action again after the refresh */ switch(action) { case ACVP_NET_GET: case ACVP_NET_GET_VS: case ACVP_NET_GET_VS_RESULT: case ACVP_NET_GET_VS_SAMPLE: rc = acvp_curl_http_get(ctx, url); break; case ACVP_NET_POST: case ACVP_NET_POST_REG: rc = acvp_curl_http_post(ctx, url, data, data_len); break; case ACVP_NET_POST_VS_RESP: if (large_submission) { rc = acvp_curl_http_post(ctx, large_url, resp, resp_len); } else { rc = acvp_curl_http_post(ctx, url, resp, resp_len); } break; case ACVP_NET_POST_LOGIN: ACVP_LOG_ERR("We should never be here!"); break; } result = inspect_http_code(ctx, rc); if (result != ACVP_SUCCESS) { ACVP_LOG_ERR("Refreshed + retried, HTTP transport fails. curl rc=%d\n", rc); goto end; } } else if (result == ACVP_JWT_INVALID) { /* * Invalid JWT */ ACVP_LOG_ERR("JWT invalid. curl rc=%d.\n", rc); goto end; } /* Generic error */ goto end; } result = ACVP_SUCCESS; end: if (resp) json_free_serialized_string(resp); *curl_code = rc; return result; }
ACVP_RESULT acvp_kdf135_ikev1_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { unsigned int tc_id; JSON_Value *groupval; JSON_Object *groupobj = NULL; JSON_Value *testval; JSON_Object *testobj = NULL; JSON_Array *groups; JSON_Array *tests; JSON_Value *reg_arry_val = NULL; JSON_Object *reg_obj = NULL; JSON_Array *reg_arry = NULL; int i, g_cnt; int j, t_cnt; JSON_Value *r_vs_val = NULL; JSON_Object *r_vs = NULL; JSON_Array *r_tarr = NULL, *r_garr = NULL; /* Response testarray, grouparray */ JSON_Value *r_tval = NULL, *r_gval = NULL; /* Response testval, groupval */ JSON_Object *r_tobj = NULL, *r_gobj = NULL; /* Response testobj, groupobj */ ACVP_CAPS_LIST *cap; ACVP_KDF135_IKEV1_TC stc; ACVP_TEST_CASE tc; ACVP_RESULT rv; const char *alg_str = json_object_get_string(obj, "algorithm"); const char *mode_str = NULL; ACVP_CIPHER alg_id; char *json_result; ACVP_HASH_ALG hash_alg = 0; ACVP_KDF135_IKEV1_AUTH_METHOD auth_method = 0; const char *hash_alg_str = NULL, *auth_method_str = NULL; char *init_ckey = NULL, *resp_ckey = NULL, *gxy = NULL, *psk = NULL, *init_nonce = NULL, *resp_nonce = NULL; int init_nonce_len = 0, resp_nonce_len = 0, dh_secret_len = 0, psk_len = 0; if (!ctx) { ACVP_LOG_ERR("No ctx for handler operation"); return ACVP_NO_CTX; } if (!alg_str) { ACVP_LOG_ERR("unable to parse 'algorithm' from JSON."); return ACVP_MALFORMED_JSON; } mode_str = json_object_get_string(obj, "mode"); if (!mode_str) { ACVP_LOG_ERR("unable to parse 'mode' from JSON."); return ACVP_MALFORMED_JSON; } alg_id = acvp_lookup_cipher_w_mode_index(alg_str, mode_str); if (alg_id != ACVP_KDF135_IKEV1) { ACVP_LOG_ERR("Server JSON invalid 'algorithm' or 'mode'"); return ACVP_INVALID_ARG; } /* * Get a reference to the abstracted test case */ tc.tc.kdf135_ikev1 = &stc; stc.cipher = alg_id; cap = acvp_locate_cap_entry(ctx, alg_id); if (!cap) { ACVP_LOG_ERR("ACVP server requesting unsupported capability %s : %d.", alg_str, alg_id); return ACVP_UNSUPPORTED_OP; } /* * Create ACVP array for response */ rv = acvp_create_array(®_obj, ®_arry_val, ®_arry); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Failed to create JSON response struct. "); return rv; } /* * Start to build the JSON response */ rv = acvp_setup_json_rsp_group(&ctx, ®_arry_val, &r_vs_val, &r_vs, alg_str, &r_garr); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Failed to setup json response"); return rv; } groups = json_object_get_array(obj, "testGroups"); g_cnt = json_array_get_count(groups); for (i = 0; i < g_cnt; i++) { int tgId = 0; groupval = json_array_get_value(groups, i); groupobj = json_value_get_object(groupval); /* * Create a new group in the response with the tgid * and an array of tests */ r_gval = json_value_init_object(); r_gobj = json_value_get_object(r_gval); tgId = json_object_get_number(groupobj, "tgId"); if (!tgId) { ACVP_LOG_ERR("Missing tgid from server JSON groub obj"); rv = ACVP_MALFORMED_JSON; goto err; } json_object_set_number(r_gobj, "tgId", tgId); json_object_set_value(r_gobj, "tests", json_value_init_array()); r_tarr = json_object_get_array(r_gobj, "tests"); hash_alg_str = json_object_get_string(groupobj, "hashAlg"); if (!hash_alg_str) { ACVP_LOG_ERR("Failed to include hashAlg"); rv = ACVP_MISSING_ARG; goto err; } hash_alg = acvp_lookup_hash_alg(hash_alg_str); if (hash_alg != ACVP_SHA1 && hash_alg != ACVP_SHA224 && hash_alg != ACVP_SHA256 && hash_alg != ACVP_SHA384 && hash_alg != ACVP_SHA512) { ACVP_LOG_ERR("ACVP server requesting invalid hashAlg"); rv = ACVP_INVALID_ARG; goto err; } auth_method_str = json_object_get_string(groupobj, "authenticationMethod"); if (!auth_method_str) { ACVP_LOG_ERR("Failed to include authenticationMethod"); rv = ACVP_MISSING_ARG; goto err; } auth_method = read_auth_method(auth_method_str); if (!auth_method) { ACVP_LOG_ERR("ACVP server requesting invalid authenticationMethod"); rv = ACVP_INVALID_ARG; goto err; } init_nonce_len = json_object_get_number(groupobj, "nInitLength"); if (!(init_nonce_len >= ACVP_KDF135_IKEV1_INIT_NONCE_BIT_MIN && init_nonce_len <= ACVP_KDF135_IKEV1_INIT_NONCE_BIT_MAX)) { ACVP_LOG_ERR("nInitLength incorrect, %d", init_nonce_len); rv = ACVP_INVALID_ARG; goto err; } resp_nonce_len = json_object_get_number(groupobj, "nRespLength"); if (!(resp_nonce_len >= ACVP_KDF135_IKEV1_RESP_NONCE_BIT_MIN && resp_nonce_len <= ACVP_KDF135_IKEV1_RESP_NONCE_BIT_MAX)) { ACVP_LOG_ERR("nRespLength incorrect, %d", resp_nonce_len); rv = ACVP_INVALID_ARG; goto err; } dh_secret_len = json_object_get_number(groupobj, "dhLength"); if (!(dh_secret_len >= ACVP_KDF135_IKEV1_DH_SHARED_SECRET_BIT_MIN && dh_secret_len <= ACVP_KDF135_IKEV1_DH_SHARED_SECRET_BIT_MAX)) { ACVP_LOG_ERR("dhLength incorrect, %d", dh_secret_len); rv = ACVP_INVALID_ARG; goto err; } if (auth_method == ACVP_KDF135_IKEV1_AMETH_PSK) { /* Only for PSK authentication method */ psk_len = json_object_get_number(groupobj, "preSharedKeyLength"); if (!(psk_len >= ACVP_KDF135_IKEV1_PSK_BIT_MIN && psk_len <= ACVP_KDF135_IKEV1_PSK_BIT_MAX)) { ACVP_LOG_ERR("preSharedKeyLength incorrect, %d", psk_len); rv = ACVP_INVALID_ARG; goto err; } } ACVP_LOG_INFO("\n Test group: %d", i); ACVP_LOG_INFO(" hash alg: %s", hash_alg_str); ACVP_LOG_INFO(" auth method: %s", auth_method_str); ACVP_LOG_INFO(" init nonce len: %d", init_nonce_len); ACVP_LOG_INFO(" resp nonce len: %d", resp_nonce_len); ACVP_LOG_INFO(" dh secret len: %d", dh_secret_len); ACVP_LOG_INFO(" psk len: %d", psk_len); tests = json_object_get_array(groupobj, "tests"); t_cnt = json_array_get_count(tests); for (j = 0; j < t_cnt; j++) { ACVP_LOG_INFO("Found new KDF IKEv1 test vector..."); testval = json_array_get_value(tests, j); testobj = json_value_get_object(testval); tc_id = (unsigned int)json_object_get_number(testobj, "tcId"); init_nonce = (char *)json_object_get_string(testobj, "nInit"); if (!init_nonce) { ACVP_LOG_ERR("Failed to include nInit"); rv = ACVP_MISSING_ARG; goto err; } if (strnlen_s((char *)init_nonce, ACVP_KDF135_IKEV1_INIT_NONCE_STR_MAX + 1) != ((init_nonce_len + 7) / 8) * 2) { ACVP_LOG_ERR("nInit length(%d) incorrect, expected(%d)", strnlen_s((char *)init_nonce, ACVP_KDF135_IKEV1_INIT_NONCE_STR_MAX + 1), ((init_nonce_len + 7) / 8) * 2); rv = ACVP_INVALID_ARG; goto err; } resp_nonce = (char *)json_object_get_string(testobj, "nResp"); if (!resp_nonce) { ACVP_LOG_ERR("Failed to include nResp"); rv = ACVP_MISSING_ARG; goto err; } if (strnlen_s((char *)resp_nonce, ACVP_KDF135_IKEV1_RESP_NONCE_STR_MAX + 1) != ((resp_nonce_len + 7) / 8) * 2) { ACVP_LOG_ERR("nResp length(%d) incorrect, expected(%d)", strnlen_s((char *)resp_nonce, ACVP_KDF135_IKEV1_RESP_NONCE_STR_MAX + 1), ((resp_nonce_len + 7) / 8) * 2); rv = ACVP_INVALID_ARG; goto err; } init_ckey = (char *)json_object_get_string(testobj, "ckyInit"); if (!init_ckey) { ACVP_LOG_ERR("Failed to include ckyInit"); rv = ACVP_MISSING_ARG; goto err; } if (strnlen_s((char *)init_ckey, ACVP_KDF135_IKEV1_COOKIE_STR_MAX + 1) > ACVP_KDF135_IKEV1_COOKIE_STR_MAX) { ACVP_LOG_ERR("ckyInit too long, max allowed=(%d)", ACVP_KDF135_IKEV1_COOKIE_STR_MAX); rv = ACVP_INVALID_ARG; goto err; } resp_ckey = (char *)json_object_get_string(testobj, "ckyResp"); if (!resp_ckey) { ACVP_LOG_ERR("Failed to include ckyResp"); rv = ACVP_MISSING_ARG; goto err; } if (strnlen_s((char *)resp_ckey, ACVP_KDF135_IKEV1_COOKIE_STR_MAX + 1) > ACVP_KDF135_IKEV1_COOKIE_STR_MAX) { ACVP_LOG_ERR("ckyResp too long, max allowed=(%d)", ACVP_KDF135_IKEV1_COOKIE_STR_MAX); rv = ACVP_INVALID_ARG; goto err; } gxy = (char *)json_object_get_string(testobj, "gxy"); if (!gxy) { ACVP_LOG_ERR("Failed to include gxy"); rv = ACVP_MISSING_ARG; goto err; } if (strnlen_s((char *)gxy, ACVP_KDF135_IKEV1_DH_SHARED_SECRET_STR_MAX + 1) > ACVP_KDF135_IKEV1_DH_SHARED_SECRET_STR_MAX) { ACVP_LOG_ERR("gxy too long, max allowed=(%d)", ACVP_KDF135_IKEV1_DH_SHARED_SECRET_STR_MAX); rv = ACVP_INVALID_ARG; goto err; } if (auth_method == ACVP_KDF135_IKEV1_AMETH_PSK) { /* Only for PSK authentication method */ psk = (char *)json_object_get_string(testobj, "preSharedKey"); if (!psk) { ACVP_LOG_ERR("Failed to include preSharedKey"); rv = ACVP_MISSING_ARG; goto err; } if (strnlen_s((char *)psk, ACVP_KDF135_IKEV1_PSK_STR_MAX + 1) > ACVP_KDF135_IKEV1_PSK_STR_MAX) { ACVP_LOG_ERR("preSharedKey too long, max allowed=(%d)", ACVP_KDF135_IKEV1_PSK_STR_MAX); rv = ACVP_INVALID_ARG; goto err; } } ACVP_LOG_INFO(" Test case: %d", j); ACVP_LOG_INFO(" tcId: %d", tc_id); /* * Create a new test case in the response */ r_tval = json_value_init_object(); r_tobj = json_value_get_object(r_tval); json_object_set_number(r_tobj, "tcId", tc_id); /* * Setup the test case data that will be passed down to * the crypto module2 */ rv = acvp_kdf135_ikev1_init_tc(ctx, &stc, tc_id, hash_alg, auth_method, init_nonce_len, resp_nonce_len, dh_secret_len, psk_len, init_nonce, resp_nonce, init_ckey, resp_ckey, gxy, psk); if (rv != ACVP_SUCCESS) { acvp_kdf135_ikev1_release_tc(&stc); json_value_free(r_tval); goto err; } /* Process the current test vector... */ if ((cap->crypto_handler)(&tc)) { ACVP_LOG_ERR("crypto module failed the KDF IKEv1 operation"); acvp_kdf135_ikev1_release_tc(&stc); rv = ACVP_CRYPTO_MODULE_FAIL; json_value_free(r_tval); goto err; } /* * Output the test case results using JSON */ rv = acvp_kdf135_ikev1_output_tc(ctx, &stc, r_tobj); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("JSON output failure in hash module"); acvp_kdf135_ikev1_release_tc(&stc); json_value_free(r_tval); goto err; } /* * Release all the memory associated with the test case */ acvp_kdf135_ikev1_release_tc(&stc); /* Append the test response value to array */ json_array_append_value(r_tarr, r_tval); } json_array_append_value(r_garr, r_gval); } json_array_append_value(reg_arry, r_vs_val); json_result = json_serialize_to_string_pretty(ctx->kat_resp, NULL); if (ctx->debug == ACVP_LOG_LVL_VERBOSE) { printf("\n\n%s\n\n", json_result); } else { ACVP_LOG_INFO("\n\n%s\n\n", json_result); } json_free_serialized_string(json_result); rv = ACVP_SUCCESS; err: if (rv != ACVP_SUCCESS) { acvp_release_json(r_vs_val, r_gval); } return rv; }
ACVP_RESULT acvp_kdf135_srtp_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { unsigned int tc_id; JSON_Value *groupval; JSON_Object *groupobj = NULL; JSON_Value *testval; JSON_Object *testobj = NULL; JSON_Array *groups; JSON_Array *tests; JSON_Value *reg_arry_val = NULL; JSON_Object *reg_obj = NULL; JSON_Array *reg_arry = NULL; int i, g_cnt; int j, t_cnt; JSON_Value *r_vs_val = NULL; JSON_Object *r_vs = NULL; JSON_Array *r_tarr = NULL, *r_garr = NULL; /* Response testarray, grouparray */ JSON_Value *r_tval = NULL, *r_gval = NULL; /* Response testval, groupval */ JSON_Object *r_tobj = NULL, *r_gobj = NULL; /* Response testobj, groupobj */ ACVP_CAPS_LIST *cap; ACVP_KDF135_SRTP_TC stc; ACVP_TEST_CASE tc; ACVP_RESULT rv; const char *alg_str = json_object_get_string(obj, "algorithm"); const char *mode_str = NULL; ACVP_CIPHER alg_id; char *json_result; int aes_key_length; char *kdr = NULL, *master_key = NULL, *master_salt = NULL, *index = NULL, *srtcp_index = NULL; if (!ctx) { ACVP_LOG_ERR("No ctx for handler operation"); return ACVP_NO_CTX; } if (!alg_str) { ACVP_LOG_ERR("unable to parse 'algorithm' from JSON."); return ACVP_MALFORMED_JSON; } mode_str = json_object_get_string(obj, "mode"); if (!mode_str) { ACVP_LOG_ERR("unable to parse 'mode' from JSON."); return ACVP_MALFORMED_JSON; } alg_id = acvp_lookup_cipher_w_mode_index(alg_str, mode_str); if (alg_id != ACVP_KDF135_SRTP) { ACVP_LOG_ERR("Server JSON invalid 'algorithm' or 'mode'"); return ACVP_INVALID_ARG; } /* * Get a reference to the abstracted test case */ tc.tc.kdf135_srtp = &stc; stc.cipher = alg_id; cap = acvp_locate_cap_entry(ctx, alg_id); if (!cap) { ACVP_LOG_ERR("ACVP server requesting unsupported capability %s : %d.", alg_str, alg_id); return ACVP_UNSUPPORTED_OP; } /* * Create ACVP array for response */ rv = acvp_create_array(®_obj, ®_arry_val, ®_arry); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Failed to create JSON response struct. "); return rv; } /* * Start to build the JSON response */ rv = acvp_setup_json_rsp_group(&ctx, ®_arry_val, &r_vs_val, &r_vs, alg_str, &r_garr); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Failed to setup json response"); goto err; } groups = json_object_get_array(obj, "testGroups"); g_cnt = json_array_get_count(groups); for (i = 0; i < g_cnt; i++) { int tgId = 0; groupval = json_array_get_value(groups, i); groupobj = json_value_get_object(groupval); /* * Create a new group in the response with the tgid * and an array of tests */ r_gval = json_value_init_object(); r_gobj = json_value_get_object(r_gval); tgId = json_object_get_number(groupobj, "tgId"); if (!tgId) { ACVP_LOG_ERR("Missing tgid from server JSON groub obj"); rv = ACVP_MALFORMED_JSON; goto err; } json_object_set_number(r_gobj, "tgId", tgId); json_object_set_value(r_gobj, "tests", json_value_init_array()); r_tarr = json_object_get_array(r_gobj, "tests"); aes_key_length = (unsigned int)json_object_get_number(groupobj, "aesKeyLength"); if (!aes_key_length) { ACVP_LOG_ERR("aesKeyLength incorrect, %d", aes_key_length); rv = ACVP_INVALID_ARG; goto err; } kdr = (char *)json_object_get_string(groupobj, "kdr"); if (!kdr) { ACVP_LOG_ERR("Failed to include kdr"); rv = ACVP_MISSING_ARG; goto err; } ACVP_LOG_INFO("\n Test group: %d", i); ACVP_LOG_INFO(" kdr: %s", kdr); ACVP_LOG_INFO(" key length: %d", aes_key_length); tests = json_object_get_array(groupobj, "tests"); t_cnt = json_array_get_count(tests); for (j = 0; j < t_cnt; j++) { ACVP_LOG_INFO("Found new KDF SRTP test vector..."); testval = json_array_get_value(tests, j); testobj = json_value_get_object(testval); tc_id = (unsigned int)json_object_get_number(testobj, "tcId"); master_key = (char *)json_object_get_string(testobj, "masterKey"); if (!master_key) { ACVP_LOG_ERR("Failed to include JSON key:\"masterKey\""); rv = ACVP_MISSING_ARG; goto err; } master_salt = (char *)json_object_get_string(testobj, "masterSalt"); if (!master_salt) { ACVP_LOG_ERR("Failed to include JSON key:\"masterSalt\""); rv = ACVP_MISSING_ARG; goto err; } index = (char *)json_object_get_string(testobj, "index"); if (!index) { ACVP_LOG_ERR("Failed to include JSON key:\"index\""); rv = ACVP_MISSING_ARG; goto err; } srtcp_index = (char *)json_object_get_string(testobj, "srtcpIndex"); if (!srtcp_index) { ACVP_LOG_ERR("Failed to include JSON key:\"srtcpIndex\""); rv = ACVP_MISSING_ARG; goto err; } ACVP_LOG_INFO(" Test case: %d", j); ACVP_LOG_INFO(" tcId: %d", tc_id); ACVP_LOG_INFO(" masterKey: %s", master_key); ACVP_LOG_INFO(" masterSalt: %s", master_salt); ACVP_LOG_INFO(" index: %s", index); ACVP_LOG_INFO(" srtcpIndex: %s", srtcp_index); /* * Create a new test case in the response */ r_tval = json_value_init_object(); r_tobj = json_value_get_object(r_tval); json_object_set_number(r_tobj, "tcId", tc_id); /* * Setup the test case data that will be passed down to * the crypto module. */ rv = acvp_kdf135_srtp_init_tc(ctx, &stc, tc_id, aes_key_length, kdr, master_key, master_salt, index, srtcp_index); if (rv != ACVP_SUCCESS) { acvp_kdf135_srtp_release_tc(&stc); json_value_free(r_tval); goto err; } /* Process the current test vector... */ if ((cap->crypto_handler)(&tc)) { ACVP_LOG_ERR("crypto module failed"); acvp_kdf135_srtp_release_tc(&stc); rv = ACVP_CRYPTO_MODULE_FAIL; json_value_free(r_tval); goto err; } /* * Output the test case results using JSON */ rv = acvp_kdf135_srtp_output_tc(ctx, &stc, r_tobj); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("JSON output failure"); acvp_kdf135_srtp_release_tc(&stc); json_value_free(r_tval); goto err; } /* * Release all the memory associated with the test case */ acvp_kdf135_srtp_release_tc(&stc); /* Append the test response value to array */ json_array_append_value(r_tarr, r_tval); } json_array_append_value(r_garr, r_gval); } json_array_append_value(reg_arry, r_vs_val); json_result = json_serialize_to_string_pretty(ctx->kat_resp, NULL); if (ctx->debug == ACVP_LOG_LVL_VERBOSE) { printf("\n\n%s\n\n", json_result); } else { ACVP_LOG_INFO("\n\n%s\n\n", json_result); } json_free_serialized_string(json_result); rv = ACVP_SUCCESS; err: if (rv != ACVP_SUCCESS) { acvp_release_json(r_vs_val, r_gval); } return rv; }
static ACVP_RESULT acvp_kdf135_srtp_init_tc(ACVP_CTX *ctx, ACVP_KDF135_SRTP_TC *stc, unsigned int tc_id, int aes_keylen, char *kdr, char *master_key, char *master_salt, char *index, char *srtcp_index) { ACVP_RESULT rv = ACVP_SUCCESS; memzero_s(stc, sizeof(ACVP_KDF135_SRTP_TC)); if (!kdr || !master_key || !master_salt || !index || !srtcp_index) { ACVP_LOG_ERR("Missing parameters - initalize KDF SRTP test case"); return ACVP_INVALID_ARG; } stc->tc_id = tc_id; stc->aes_keylen = aes_keylen; stc->kdr = calloc(ACVP_KDF135_SRTP_KDR_STR_MAX, sizeof(char)); if (!stc->kdr) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(kdr, stc->kdr, ACVP_KDF135_SRTP_KDR_STR_MAX, &(stc->kdr_len)); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (kdr)"); return rv; } stc->master_key = calloc(ACVP_KDF135_SRTP_MASTER_MAX, sizeof(char)); if (!stc->master_key) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(master_key, (unsigned char *)stc->master_key, ACVP_KDF135_SRTP_MASTER_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (master_key)"); return rv; } stc->master_salt = calloc(ACVP_KDF135_SRTP_MASTER_MAX, sizeof(char)); if (!stc->master_salt) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(master_salt, (unsigned char *)stc->master_salt, ACVP_KDF135_SRTP_MASTER_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (master_salt)"); return rv; } stc->index = calloc(ACVP_KDF135_SRTP_INDEX_MAX, sizeof(char)); if (!stc->index) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(index, (unsigned char *)stc->index, ACVP_KDF135_SRTP_INDEX_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (index)"); return rv; } stc->srtcp_index = calloc(ACVP_KDF135_SRTP_INDEX_MAX, sizeof(char)); if (!stc->srtcp_index) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(srtcp_index, (unsigned char *)stc->srtcp_index, ACVP_KDF135_SRTP_INDEX_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex conversion failure (srtcp_index)"); return rv; } stc->srtp_ka = calloc(ACVP_KDF135_SRTP_OUTPUT_MAX, sizeof(char)); if (!stc->srtp_ka) { return ACVP_MALLOC_FAIL; } stc->srtp_ke = calloc(ACVP_KDF135_SRTP_OUTPUT_MAX, sizeof(char)); if (!stc->srtp_ke) { return ACVP_MALLOC_FAIL; } stc->srtp_ks = calloc(ACVP_KDF135_SRTP_OUTPUT_MAX, sizeof(char)); if (!stc->srtp_ks) { return ACVP_MALLOC_FAIL; } stc->srtcp_ka = calloc(ACVP_KDF135_SRTP_OUTPUT_MAX, sizeof(char)); if (!stc->srtcp_ka) { return ACVP_MALLOC_FAIL; } stc->srtcp_ke = calloc(ACVP_KDF135_SRTP_OUTPUT_MAX, sizeof(char)); if (!stc->srtcp_ke) { return ACVP_MALLOC_FAIL; } stc->srtcp_ks = calloc(ACVP_KDF135_SRTP_OUTPUT_MAX, sizeof(char)); if (!stc->srtcp_ks) { return ACVP_MALLOC_FAIL; } return ACVP_SUCCESS; }
static ACVP_RESULT acvp_cmac_init_tc(ACVP_CTX *ctx, ACVP_CMAC_TC *stc, unsigned int tc_id, char *msg, unsigned int msg_len, unsigned int key_len, char *key, char *key2, char *key3, int direction_verify, char *mac, unsigned int mac_len, ACVP_CIPHER alg_id) { ACVP_RESULT rv; if (!ctx) { return ACVP_NO_CTX; } if (alg_id != ACVP_CMAC_TDES && alg_id != ACVP_CMAC_AES) { return ACVP_INVALID_ARG; } if (!msg || !stc || !tc_id || !key) { return ACVP_INVALID_ARG; } if (alg_id == ACVP_CMAC_TDES && (!key2 || !key3)) { return ACVP_INVALID_ARG; } if (direction_verify) { if (!mac_len || !mac) { return ACVP_INVALID_ARG; } } memzero_s(stc, sizeof(ACVP_CMAC_TC)); stc->msg = calloc(1, ACVP_CMAC_MSGLEN_MAX_STR); if (!stc->msg) { return ACVP_MALLOC_FAIL; } stc->mac = calloc(ACVP_CMAC_MACLEN_MAX, sizeof(char)); if (!stc->mac) { return ACVP_MALLOC_FAIL; } stc->key = calloc(1, ACVP_CMAC_KEY_MAX); if (!stc->key) { return ACVP_MALLOC_FAIL; } stc->mac_len = mac_len; if (direction_verify) { rv = acvp_hexstr_to_bin(mac, stc->mac, ACVP_CMAC_MACLEN_MAX, (int *)&(stc->mac_len)); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex converstion failure (mac)"); return rv; } } stc->key2 = calloc(1, ACVP_CMAC_KEY_MAX); if (!stc->key2) { return ACVP_MALLOC_FAIL; } stc->key3 = calloc(1, ACVP_CMAC_KEY_MAX); if (!stc->key3) { return ACVP_MALLOC_FAIL; } rv = acvp_hexstr_to_bin(msg, stc->msg, ACVP_CMAC_MSGLEN_MAX_STR, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex converstion failure (msg)"); return rv; } if (alg_id == ACVP_CMAC_AES) { rv = acvp_hexstr_to_bin(key, stc->key, ACVP_CMAC_KEY_MAX, (int *)&(stc->key_len)); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex converstion failure (key)"); return rv; } } else if (alg_id == ACVP_CMAC_TDES) { rv = acvp_hexstr_to_bin(key, stc->key, ACVP_CMAC_KEY_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex converstion failure (key1)"); return rv; } rv = acvp_hexstr_to_bin(key2, stc->key2, ACVP_CMAC_KEY_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex converstion failure (key2)"); return rv; } rv = acvp_hexstr_to_bin(key3, stc->key3, ACVP_CMAC_KEY_MAX, NULL); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Hex converstion failure (key3)"); return rv; } } if (direction_verify) { stc->verify = 1; } stc->tc_id = tc_id; stc->msg_len = msg_len; stc->cipher = alg_id; return ACVP_SUCCESS; }
ACVP_RESULT acvp_cmac_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { unsigned int tc_id, msglen, keyLen = 0, keyingOption = 0, maclen, verify = 0; char *msg = NULL, *key1 = NULL, *key2 = NULL, *key3 = NULL, *mac = NULL; JSON_Value *groupval; JSON_Object *groupobj = NULL; JSON_Value *testval; JSON_Object *testobj = NULL; JSON_Array *groups; JSON_Array *tests; JSON_Value *reg_arry_val = NULL; JSON_Object *reg_obj = NULL; JSON_Array *reg_arry = NULL; int i, g_cnt; int j, t_cnt; JSON_Value *r_vs_val = NULL; JSON_Object *r_vs = NULL; JSON_Array *r_tarr = NULL, *r_garr = NULL; /* Response testarray, grouparray */ JSON_Value *r_tval = NULL, *r_gval = NULL; /* Response testval, groupval */ JSON_Object *r_tobj = NULL, *r_gobj = NULL; /* Response testobj, groupobj */ ACVP_CAPS_LIST *cap; ACVP_CMAC_TC stc; ACVP_TEST_CASE tc; ACVP_RESULT rv; const char *alg_str = json_object_get_string(obj, "algorithm"); ACVP_CIPHER alg_id; char *json_result, *direction = NULL; int key1_len, key2_len, key3_len, json_msglen; if (!ctx) { ACVP_LOG_ERR("No ctx for handler operation"); return ACVP_NO_CTX; } if (!obj) { ACVP_LOG_ERR("No obj for handler operation"); return ACVP_MALFORMED_JSON; } if (!alg_str) { ACVP_LOG_ERR("ERROR: unable to parse 'algorithm' from JSON"); return ACVP_MALFORMED_JSON; } /* * Get a reference to the abstracted test case */ tc.tc.cmac = &stc; /* * Get the crypto module handler for this hash algorithm */ alg_id = acvp_lookup_cipher_index(alg_str); if (alg_id < ACVP_CIPHER_START) { ACVP_LOG_ERR("ERROR: unsupported algorithm (%s)", alg_str); return ACVP_UNSUPPORTED_OP; } cap = acvp_locate_cap_entry(ctx, alg_id); if (!cap) { ACVP_LOG_ERR("ERROR: ACVP server requesting unsupported capability"); return ACVP_UNSUPPORTED_OP; } /* * Create ACVP array for response */ rv = acvp_create_array(®_obj, ®_arry_val, ®_arry); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("ERROR: Failed to create JSON response struct. "); return rv; } /* * Start to build the JSON response */ rv = acvp_setup_json_rsp_group(&ctx, ®_arry_val, &r_vs_val, &r_vs, alg_str, &r_garr); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Failed to setup json response"); return rv; } groups = json_object_get_array(obj, "testGroups"); g_cnt = json_array_get_count(groups); for (i = 0; i < g_cnt; i++) { int tgId = 0; int diff = 0; groupval = json_array_get_value(groups, i); groupobj = json_value_get_object(groupval); /* * Create a new group in the response with the tgid * and an array of tests */ r_gval = json_value_init_object(); r_gobj = json_value_get_object(r_gval); tgId = json_object_get_number(groupobj, "tgId"); if (!tgId) { ACVP_LOG_ERR("Missing tgid from server JSON groub obj"); rv = ACVP_MALFORMED_JSON; goto err; } json_object_set_number(r_gobj, "tgId", tgId); json_object_set_value(r_gobj, "tests", json_value_init_array()); r_tarr = json_object_get_array(r_gobj, "tests"); if (alg_id == ACVP_CMAC_AES) { keyLen = (unsigned int)json_object_get_number(groupobj, "keyLen"); if (!keyLen) { ACVP_LOG_ERR("keylen missing from cmac aes json"); rv = ACVP_MISSING_ARG; goto err; } } else if (alg_id == ACVP_CMAC_TDES) { keyingOption = (unsigned int)json_object_get_number(groupobj, "keyingOption"); if (keyingOption <= ACVP_CMAC_TDES_KEYING_OPTION_MIN || keyingOption >= ACVP_CMAC_TDES_KEYING_OPTION_MAX) { ACVP_LOG_ERR("keyingOption missing or wrong from cmac tdes json"); rv = ACVP_INVALID_ARG; goto err; } } direction = (char *)json_object_get_string(groupobj, "direction"); if (!direction) { ACVP_LOG_ERR("Unable to parse 'direction' from JSON."); rv = ACVP_MALFORMED_JSON; goto err; } strcmp_s("ver", 3, direction, &diff); if (!diff) { verify = 1; } else { strcmp_s("gen", 3, direction, &diff); if (diff) { ACVP_LOG_ERR("'direction' should be 'gen' or 'ver'"); rv = ACVP_UNSUPPORTED_OP; goto err; } } msglen = (unsigned int)json_object_get_number(groupobj, "msgLen") / 8; maclen = (unsigned int)json_object_get_number(groupobj, "macLen") / 8; if (!maclen) { ACVP_LOG_ERR("Server JSON missing 'macLen'"); rv = ACVP_MISSING_ARG; goto err; } ACVP_LOG_INFO("\n\n Test group: %d", i); tests = json_object_get_array(groupobj, "tests"); t_cnt = json_array_get_count(tests); for (j = 0; j < t_cnt; j++) { ACVP_LOG_INFO("Found new cmac test vector..."); testval = json_array_get_value(tests, j); testobj = json_value_get_object(testval); tc_id = (unsigned int)json_object_get_number(testobj, "tcId"); msg = (char *)json_object_get_string(testobj, "message"); /* msg can be null if msglen is 0 */ if (msg) { json_msglen = strnlen_s(msg, ACVP_CMAC_MSGLEN_MAX_STR + 1); if (json_msglen > ACVP_CMAC_MSGLEN_MAX_STR) { ACVP_LOG_ERR("'msg' too long"); rv = ACVP_INVALID_ARG; goto err; } if (!msglen && json_msglen > 0) { ACVP_LOG_ERR("Server JSON missing 'msgLen'"); rv = ACVP_MISSING_ARG; goto err; } } else if (msglen) { ACVP_LOG_ERR("msglen is nonzero, expected 'msg' in json"); rv = ACVP_MISSING_ARG; goto err; } if (alg_id == ACVP_CMAC_AES) { key1 = (char *)json_object_get_string(testobj, "key"); if (!key1) { ACVP_LOG_ERR("Server JSON missing 'key'"); rv = ACVP_MISSING_ARG; goto err; } key1_len = strnlen_s(key1, ACVP_CMAC_KEY_MAX + 1); if (key1_len > ACVP_CMAC_KEY_MAX) { ACVP_LOG_ERR("Invalid length for 'key' attribute in CMAC-AES test"); rv = ACVP_INVALID_ARG; goto err; } } else if (alg_id == ACVP_CMAC_TDES) { key1 = (char *)json_object_get_string(testobj, "key1"); key2 = (char *)json_object_get_string(testobj, "key2"); key3 = (char *)json_object_get_string(testobj, "key3"); if (!key1 || !key2 || !key3) { ACVP_LOG_ERR("Server JSON missing 'key(1,2,3)' value"); rv = ACVP_MISSING_ARG; goto err; } key1_len = strnlen_s(key1, ACVP_CMAC_KEY_MAX + 1); key2_len = strnlen_s(key2, ACVP_CMAC_KEY_MAX + 1); key3_len = strnlen_s(key3, ACVP_CMAC_KEY_MAX + 1); if (key1_len > ACVP_CMAC_KEY_MAX || key2_len > ACVP_CMAC_KEY_MAX || key3_len > ACVP_CMAC_KEY_MAX) { ACVP_LOG_ERR("Invalid length for 'key(1|2|3)' attribute in CMAC-TDES test"); rv = ACVP_INVALID_ARG; goto err; } } if (verify) { mac = (char *)json_object_get_string(testobj, "mac"); if (!mac) { ACVP_LOG_ERR("Server JSON missing 'mac'"); rv = ACVP_MISSING_ARG; goto err; } } ACVP_LOG_INFO("\n Test case: %d", j); ACVP_LOG_INFO(" tcId: %d", tc_id); ACVP_LOG_INFO(" direction: %s", direction); ACVP_LOG_INFO(" msgLen: %d", msglen); ACVP_LOG_INFO(" msg: %s", msg); if (alg_id == ACVP_CMAC_AES) { ACVP_LOG_INFO(" keyLen: %d", keyLen); ACVP_LOG_INFO(" key: %s", key1); } else if (alg_id == ACVP_CMAC_TDES) { ACVP_LOG_INFO(" keyingOption: %d", keyingOption); ACVP_LOG_INFO(" key1: %s", key1); ACVP_LOG_INFO(" key2: %s", key2); ACVP_LOG_INFO(" key3: %s", key3); } if (verify) { ACVP_LOG_INFO(" mac: %s", mac); } /* * Create a new test case in the response */ r_tval = json_value_init_object(); r_tobj = json_value_get_object(r_tval); json_object_set_number(r_tobj, "tcId", tc_id); /* * Setup the test case data that will be passed down to * the crypto module. */ rv = acvp_cmac_init_tc(ctx, &stc, tc_id, msg, msglen, keyLen, key1, key2, key3, verify, mac, maclen, alg_id); if (rv != ACVP_SUCCESS) { acvp_cmac_release_tc(&stc); json_value_free(r_tval); goto err; } /* Process the current test vector... */ if ((cap->crypto_handler)(&tc)) { ACVP_LOG_ERR("ERROR: crypto module failed the operation"); acvp_cmac_release_tc(&stc); rv = ACVP_CRYPTO_MODULE_FAIL; json_value_free(r_tval); goto err; } /* * Output the test case results using JSON */ rv = acvp_cmac_output_tc(ctx, &stc, r_tobj); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("ERROR: JSON output failure in hash module"); acvp_cmac_release_tc(&stc); json_value_free(r_tval); goto err; } /* * Release all the memory associated with the test case */ acvp_cmac_release_tc(&stc); /* Append the test response value to array */ json_array_append_value(r_tarr, r_tval); } json_array_append_value(r_garr, r_gval); } json_array_append_value(reg_arry, r_vs_val); json_result = json_serialize_to_string_pretty(ctx->kat_resp, NULL); if (ctx->debug == ACVP_LOG_LVL_VERBOSE) { printf("\n\n%s\n\n", json_result); } else { ACVP_LOG_INFO("\n\n%s\n\n", json_result); } json_free_serialized_string(json_result); rv = ACVP_SUCCESS; err: if (rv != ACVP_SUCCESS) { acvp_release_json(r_vs_val, r_gval); } return rv; }
/* * After the test case has been processed by the DUT, the results * need to be JSON formated to be included in the vector set results * file that will be uploaded to the server. This routine handles * the JSON processing for a single test case. */ static ACVP_RESULT acvp_kdf135_ssh_output_tc(ACVP_CTX *ctx, ACVP_KDF135_SSH_TC *stc, JSON_Object *tc_rsp) { char *tmp = NULL; ACVP_RESULT rv = ACVP_SUCCESS; if ((stc->iv_len * 2) > ACVP_KDF135_SSH_STR_OUT_MAX || (stc->e_key_len * 2) > ACVP_KDF135_SSH_STR_OUT_MAX || (stc->i_key_len * 2) > ACVP_KDF135_SSH_STR_OUT_MAX) { ACVP_LOG_ERR("iv_len*2(%u) || e_key_len*2(%u) || i_key_len*2(%u) > ACVP_KDF135_SSH_STR_OUT_MAX(%u)", (stc->iv_len * 2), (stc->e_key_len * 2), (stc->i_key_len * 2), ACVP_KDF135_SSH_STR_OUT_MAX); ACVP_LOG_ERR("Hint, make sure user isn't modifying those field values"); return ACVP_DATA_TOO_LARGE; } tmp = calloc(ACVP_KDF135_SSH_STR_OUT_MAX + 1, sizeof(char)); if (!tmp) { ACVP_LOG_ERR("Unable to malloc"); return ACVP_MALLOC_FAIL; } rv = acvp_bin_to_hexstr(stc->cs_init_iv, stc->iv_len, tmp, ACVP_KDF135_SSH_STR_OUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("acvp_bin_to_hexstr() failure"); goto err; } json_object_set_string(tc_rsp, "initialIvClient", tmp); memzero_s(tmp, ACVP_KDF135_SSH_STR_OUT_MAX); rv = acvp_bin_to_hexstr(stc->cs_encrypt_key, stc->e_key_len, tmp, ACVP_KDF135_SSH_STR_OUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("acvp_bin_to_hexstr() failure"); goto err; } json_object_set_string(tc_rsp, "encryptionKeyClient", tmp); memzero_s(tmp, ACVP_KDF135_SSH_STR_OUT_MAX); rv = acvp_bin_to_hexstr(stc->cs_integrity_key, stc->i_key_len, tmp, ACVP_KDF135_SSH_STR_OUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("acvp_bin_to_hexstr() failure"); goto err; } json_object_set_string(tc_rsp, "integrityKeyClient", tmp); memzero_s(tmp, ACVP_KDF135_SSH_STR_OUT_MAX); rv = acvp_bin_to_hexstr(stc->sc_init_iv, stc->iv_len, tmp, ACVP_KDF135_SSH_STR_OUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("acvp_bin_to_hexstr() failure"); goto err; } json_object_set_string(tc_rsp, "initialIvServer", tmp); memzero_s(tmp, ACVP_KDF135_SSH_STR_OUT_MAX); rv = acvp_bin_to_hexstr(stc->sc_encrypt_key, stc->e_key_len, tmp, ACVP_KDF135_SSH_STR_OUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("acvp_bin_to_hexstr() failure"); goto err; } json_object_set_string(tc_rsp, "encryptionKeyServer", tmp); memzero_s(tmp, ACVP_KDF135_SSH_STR_OUT_MAX); rv = acvp_bin_to_hexstr(stc->sc_integrity_key, stc->i_key_len, tmp, ACVP_KDF135_SSH_STR_OUT_MAX); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("acvp_bin_to_hexstr() failure"); goto err; } json_object_set_string(tc_rsp, "integrityKeyServer", tmp); err: free(tmp); return rv; }
ACVP_RESULT acvp_kdf135_ssh_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { unsigned int tc_id; JSON_Value *groupval; JSON_Object *groupobj = NULL; JSON_Value *testval; JSON_Object *testobj = NULL; JSON_Array *groups; JSON_Array *tests; JSON_Value *reg_arry_val = NULL; JSON_Object *reg_obj = NULL; JSON_Array *reg_arry = NULL; int i, g_cnt; int j, t_cnt; JSON_Value *r_vs_val = NULL; JSON_Object *r_vs = NULL; JSON_Array *r_tarr = NULL, *r_garr = NULL; /* Response testarray, grouparray */ JSON_Value *r_tval = NULL, *r_gval = NULL; /* Response testval, groupval */ JSON_Object *r_tobj = NULL, *r_gobj = NULL; /* Response testobj, groupobj */ ACVP_CAPS_LIST *cap; ACVP_KDF135_SSH_TC stc; ACVP_TEST_CASE tc; ACVP_RESULT rv; ACVP_CIPHER alg_id; const char *alg_str = NULL; const char *mode_str = NULL; const char *cipher_str = NULL; const char *shared_secret_str = NULL; const char *session_id_str = NULL; const char *hash_str = NULL; char *json_result; if (!ctx) { ACVP_LOG_ERR("No ctx for handler operation"); return ACVP_NO_CTX; } if (!obj) { ACVP_LOG_ERR("No obj for handler operation"); return ACVP_MALFORMED_JSON; } alg_str = json_object_get_string(obj, "algorithm"); if (!alg_str) { ACVP_LOG_ERR("unable to parse 'algorithm' from JSON"); return ACVP_MALFORMED_JSON; } mode_str = json_object_get_string(obj, "mode"); if (!mode_str) { ACVP_LOG_ERR("unable to parse 'mode' from JSON"); return ACVP_MALFORMED_JSON; } alg_id = acvp_lookup_cipher_w_mode_index(alg_str, mode_str); if (alg_id != ACVP_KDF135_SSH) { ACVP_LOG_ERR("Server JSON invalid 'algorithm' or 'mode'"); return ACVP_INVALID_ARG; } /* * Get a reference to the abstracted test case */ tc.tc.kdf135_ssh = &stc; /* * Get the crypto module handler for this hash algorithm */ cap = acvp_locate_cap_entry(ctx, alg_id); if (!cap) { ACVP_LOG_ERR("ACVP server requesting unsupported capability %s : %d.", alg_str, alg_id); return ACVP_UNSUPPORTED_OP; } /* * Create ACVP array for response */ rv = acvp_create_array(®_obj, ®_arry_val, ®_arry); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Failed to create JSON response struct. "); return rv; } /* * Start to build the JSON response */ rv = acvp_setup_json_rsp_group(&ctx, ®_arry_val, &r_vs_val, &r_vs, alg_str, &r_garr); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("Failed to setup json response"); return rv; } groups = json_object_get_array(obj, "testGroups"); if (!groups) { ACVP_LOG_ERR("Failed to include testGroups. "); rv = ACVP_MISSING_ARG; goto err; } g_cnt = json_array_get_count(groups); for (i = 0; i < g_cnt; i++) { int tgId = 0; int diff = 1; unsigned int e_key_len = 0, i_key_len = 0, hash_len = 0, iv_len = 0; ACVP_HASH_ALG sha_type = 0; const char *sha_str = NULL; groupval = json_array_get_value(groups, i); groupobj = json_value_get_object(groupval); /* * Create a new group in the response with the tgid * and an array of tests */ r_gval = json_value_init_object(); r_gobj = json_value_get_object(r_gval); tgId = json_object_get_number(groupobj, "tgId"); if (!tgId) { ACVP_LOG_ERR("Missing tgid from server JSON groub obj"); rv = ACVP_MALFORMED_JSON; goto err; } json_object_set_number(r_gobj, "tgId", tgId); json_object_set_value(r_gobj, "tests", json_value_init_array()); r_tarr = json_object_get_array(r_gobj, "tests"); // Get the expected (user will generate) key and iv lengths cipher_str = json_object_get_string(groupobj, "cipher"); if (!cipher_str) { ACVP_LOG_ERR("Failed to include cipher. "); rv = ACVP_MISSING_ARG; goto err; } sha_str = json_object_get_string(groupobj, "hashAlg"); if (!sha_str) { ACVP_LOG_ERR("Failed to include hashAlg. "); rv = ACVP_MISSING_ARG; goto err; } sha_type = acvp_lookup_hash_alg(sha_str); if (sha_type == ACVP_SHA1) { i_key_len = hash_len = ACVP_SHA1_BYTE_LEN; } else if (sha_type == ACVP_SHA224) { i_key_len = hash_len = ACVP_SHA224_BYTE_LEN; } else if (sha_type == ACVP_SHA256) { i_key_len = hash_len = ACVP_SHA256_BYTE_LEN; } else if (sha_type == ACVP_SHA384) { i_key_len = hash_len = ACVP_SHA384_BYTE_LEN; } else if (sha_type == ACVP_SHA512) { i_key_len = hash_len = ACVP_SHA512_BYTE_LEN; } else { ACVP_LOG_ERR("ACVP server requesting invalid hashAlg"); rv = ACVP_NO_CAP; goto err; } /* * Determine the encrypt key_len, inferred from cipher. */ strcmp_s(ACVP_MODE_TDES, 4, cipher_str, &diff); if (!diff) { e_key_len = ACVP_KEY_LEN_TDES; iv_len = ACVP_BLOCK_LEN_TDES; } strcmp_s(ACVP_MODE_AES_128, 7, cipher_str, &diff); if (!diff) { e_key_len = ACVP_KEY_LEN_AES128; iv_len = ACVP_BLOCK_LEN_AES128; } strcmp_s(ACVP_MODE_AES_192, 7, cipher_str, &diff); if (!diff) { e_key_len = ACVP_KEY_LEN_AES192; iv_len = ACVP_BLOCK_LEN_AES192; } strcmp_s(ACVP_MODE_AES_256, 7, cipher_str, &diff); if (!diff) { e_key_len = ACVP_KEY_LEN_AES256; iv_len = ACVP_BLOCK_LEN_AES256; } if (!e_key_len || !iv_len) { ACVP_LOG_ERR("Unsupported cipher type"); rv = ACVP_NO_CAP; goto err; } /* * Log Test Group information... */ ACVP_LOG_INFO(" Test group: %d", i); ACVP_LOG_INFO(" cipher: %s", cipher_str); ACVP_LOG_INFO(" hashAlg: %s", sha_str); tests = json_object_get_array(groupobj, "tests"); if (!tests) { ACVP_LOG_ERR("Failed to include tests. "); rv = ACVP_MISSING_ARG; goto err; } t_cnt = json_array_get_count(tests); if (!t_cnt) { ACVP_LOG_ERR("Failed to include tests in array. "); rv = ACVP_MISSING_ARG; goto err; } for (j = 0; j < t_cnt; j++) { ACVP_LOG_INFO("Found new KDF SSH test vector..."); testval = json_array_get_value(tests, j); testobj = json_value_get_object(testval); tc_id = (unsigned int)json_object_get_number(testobj, "tcId"); if (!tc_id) { ACVP_LOG_ERR("Failed to include tc_id. "); rv = ACVP_MISSING_ARG; goto err; } shared_secret_str = json_object_get_string(testobj, "k"); if (!shared_secret_str) { ACVP_LOG_ERR("Failed to include k. "); rv = ACVP_MISSING_ARG; goto err; } hash_str = json_object_get_string(testobj, "h"); if (!hash_str) { ACVP_LOG_ERR("Failed to include h. "); rv = ACVP_MISSING_ARG; goto err; } session_id_str = json_object_get_string(testobj, "sessionId"); if (!session_id_str) { ACVP_LOG_ERR("Failed to include sessionId. "); rv = ACVP_MISSING_ARG; goto err; } ACVP_LOG_INFO(" Test case: %d", j); ACVP_LOG_INFO(" tcId: %d", tc_id); ACVP_LOG_INFO(" k: %s", shared_secret_str); ACVP_LOG_INFO(" h: %s", hash_str); ACVP_LOG_INFO(" session_id: %s", session_id_str); /* * Create a new test case in the response */ r_tval = json_value_init_object(); r_tobj = json_value_get_object(r_tval); json_object_set_number(r_tobj, "tcId", tc_id); /* * Setup the test case data that will be passed down to * the crypto module. */ rv = acvp_kdf135_ssh_init_tc(ctx, &stc, tc_id, alg_id, sha_type, e_key_len, i_key_len, iv_len, hash_len, shared_secret_str, hash_str, session_id_str); if (rv != ACVP_SUCCESS) { acvp_kdf135_ssh_release_tc(&stc); json_value_free(r_tval); goto err; } /* Process the current test vector... */ if ((cap->crypto_handler)(&tc)) { ACVP_LOG_ERR("crypto module failed the KDF SSH operation"); acvp_kdf135_ssh_release_tc(&stc); rv = ACVP_CRYPTO_MODULE_FAIL; json_value_free(r_tval); goto err; } /* * Output the test case results using JSON */ rv = acvp_kdf135_ssh_output_tc(ctx, &stc, r_tobj); if (rv != ACVP_SUCCESS) { ACVP_LOG_ERR("JSON output failure in hash module"); acvp_kdf135_ssh_release_tc(&stc); json_value_free(r_tval); goto err; } /* * Release all the memory associated with the test case */ acvp_kdf135_ssh_release_tc(&stc); /* Append the test response value to array */ json_array_append_value(r_tarr, r_tval); } json_array_append_value(r_garr, r_gval); } json_array_append_value(reg_arry, r_vs_val); json_result = json_serialize_to_string_pretty(ctx->kat_resp, NULL); if (ctx->debug == ACVP_LOG_LVL_VERBOSE) { printf("\n\n%s\n\n", json_result); } else { ACVP_LOG_INFO("\n\n%s\n\n", json_result); } json_free_serialized_string(json_result); rv = ACVP_SUCCESS; err: if (rv != ACVP_SUCCESS) { acvp_release_json(r_vs_val, r_gval); } return rv; }
/* * This function uses libcurl to send a simple HTTP POST * request with no Content-Type header. * TLS peer verification is enabled, but not HTTP authentication. * The parameters are: * * ctx: Ptr to ACVP_CTX, which contains the server name * url: URL to use for the GET request * data: data to POST to the server * writefunc: Function pointer to handle writing the data * from the HTTP body received from the server. * * Return value is the HTTP status value from the server * (e.g. 200 for HTTP OK) */ static long acvp_curl_http_post(ACVP_CTX *ctx, char *url, char *data, int data_len) { long http_code = 0; CURL *hnd; CURLcode crv; struct curl_slist *slist; char user_agent_str[USER_AGENT_STR_MAX + 1]; /* * Set the Content-Type header in the HTTP request */ slist = NULL; slist = curl_slist_append(slist, "Content-Type:application/json"); /* * Create the Authorzation header if needed */ slist = acvp_add_auth_hdr(ctx, slist); ctx->curl_read_ctr = 0; /* * Create the HTTP User Agent value */ snprintf(user_agent_str, USER_AGENT_STR_MAX, "libacvp/%s", ACVP_VERSION); /* * Setup Curl */ hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_URL, url); curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(hnd, CURLOPT_USERAGENT, user_agent_str); curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST"); curl_easy_setopt(hnd, CURLOPT_POST, 1L); curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, data); curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)data_len); curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(hnd, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); /* * Always verify the server */ curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 1L); if (ctx->cacerts_file) { curl_easy_setopt(hnd, CURLOPT_CAINFO, ctx->cacerts_file); curl_easy_setopt(hnd, CURLOPT_CERTINFO, 1L); } /* * Mutual-auth */ if (ctx->tls_cert && ctx->tls_key) { curl_easy_setopt(hnd, CURLOPT_SSLCERTTYPE, "PEM"); curl_easy_setopt(hnd, CURLOPT_SSLCERT, ctx->tls_cert); curl_easy_setopt(hnd, CURLOPT_SSLKEYTYPE, "PEM"); curl_easy_setopt(hnd, CURLOPT_SSLKEY, ctx->tls_key); } /* * To record the HTTP data recieved from the server, * set the callback function. */ curl_easy_setopt(hnd, CURLOPT_WRITEDATA, ctx); curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, &acvp_curl_write_callback); if (ctx->curl_buf) { /* Clear the HTTP buffer for next server response */ memzero_s(ctx->curl_buf, ACVP_CURL_BUF_MAX); } /* * Send the HTTP POST request */ crv = curl_easy_perform(hnd); if (crv != CURLE_OK) { ACVP_LOG_ERR("Curl failed with code %d (%s)\n", crv, curl_easy_strerror(crv)); } /* * Get the HTTP reponse status code from the server */ curl_easy_getinfo(hnd, CURLINFO_RESPONSE_CODE, &http_code); curl_easy_cleanup(hnd); hnd = NULL; curl_slist_free_all(slist); slist = NULL; return http_code; }