Skip to content

Commit

Permalink
Add test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
babelouest committed Nov 15, 2023
1 parent f9d8c06 commit 29e63f7
Showing 1 changed file with 259 additions and 0 deletions.
259 changes: 259 additions & 0 deletions test/glewlwyd_scheme_webauthn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3673,6 +3673,264 @@ START_TEST(test_glwd_scheme_webauthn_irl_register_error_invalid_data_cose_key_ke
}
END_TEST

START_TEST(test_glwd_scheme_webauthn_irl_register_error_invalid_data_cose_key_key_x_length)
{
json_t * j_params = json_pack("{sssssss{ss}}",
"username", USERNAME,
"scheme_type", MODULE_MODULE,
"scheme_name", MODULE_NAME,
"value",
"register", "new-credential"),
* j_result, * j_client_data, * j_credential;
struct _u_response resp, resp_register;
unsigned char challenge_dec[WEBAUTHN_CHALLENGE_LEN], challenge_b64url[WEBAUTHN_CHALLENGE_LEN*2], * client_data_json_enc, credential_id_enc[WEBAUTHN_CREDENTIAL_ID_LEN*2], credential_id_enc_url[WEBAUTHN_CREDENTIAL_ID_LEN*2], auth_data[AUTH_DATA_SIZE], aaguid[AAGUID_LEN] = AAGUID, pubkey_id[128], cbor_cose_dump[512], cert_der[1024], verification_data[384], client_data_hash[32], * att_obj_ser = NULL, * att_obj_ser_enc = NULL, key_x_invalid[384] = {0};
size_t challenge_dec_len, challenge_b64url_len, client_data_json_enc_len, credential_id_enc_len, credential_id_enc_url_len, auth_data_len = 1024, pubkey_id_len = 128, cbor_cose_dump_max_len = 512, cbor_cose_dump_len, cert_der_len = 1024, verification_data_offset = 0, client_data_hash_len = 32, att_obj_ser_len = 0, att_obj_ser_enc_len = 0, rp_id_len = 0;
const char * session, * challenge, * user_id, * username, * rpid;
char * client_data_json;
gnutls_datum_t key_data, key_x, key_y, signature;
gnutls_pubkey_t pubkey = NULL;
gnutls_x509_crt_t cert = NULL;
gnutls_x509_privkey_t key = NULL;
gnutls_privkey_t privkey = NULL;
gnutls_ecc_curve_t curve;
cbor_item_t * cbor_cose, * att_stmt, * att_obj, * bs_obj;
struct cbor_pair cose_pair;

ulfius_init_response(&resp);
ulfius_init_response(&resp_register);

o_free(user_req.http_verb);
user_req.http_verb = o_strdup("POST");
o_free(user_req.http_url);
user_req.http_url = o_strdup(SERVER_URI "profile/scheme/register/");
ck_assert_int_eq(ulfius_set_json_body_request(&user_req, j_params), U_OK);

ck_assert_int_eq(ulfius_send_http_request(&user_req, &resp), U_OK);
ck_assert_int_eq(resp.status, 200);
ck_assert_ptr_ne((j_result = ulfius_get_json_body_response(&resp, NULL)), NULL);
ck_assert_ptr_ne((session = json_string_value(json_object_get(j_result, "session"))), NULL);
ck_assert_ptr_ne((challenge = json_string_value(json_object_get(j_result, "challenge"))), NULL);
ck_assert_ptr_ne((rpid = json_string_value(json_object_get(j_result, "rpId"))), NULL);
ck_assert_ptr_ne((user_id = json_string_value(json_object_get(json_object_get(j_result, "user"), "id"))), NULL);
ck_assert_ptr_ne((username = json_string_value(json_object_get(json_object_get(j_result, "user"), "name"))), NULL);
ck_assert_int_eq(o_base64_decode((unsigned char *)json_string_value(json_object_get(j_result, "challenge")), json_string_length(json_object_get(j_result, "challenge")), challenge_dec, &challenge_dec_len), 1);

// Generate clientDataJSON
ck_assert_int_eq(o_base64_2_base64url((unsigned char *)challenge, o_strlen(challenge), challenge_b64url, &challenge_b64url_len), 1);
j_client_data = json_pack("{ss%s{}ssss}",
"challenge",
challenge_b64url,
challenge_b64url_len,
"clientExtensions",
"origin",
WEBAUTHN_RP_ORIGIN,
"type",
"webauthn.create");

client_data_json = json_dumps(j_client_data, JSON_COMPACT);
ck_assert_int_eq(oh_my_base64_encode((unsigned char *)client_data_json, o_strlen(client_data_json), NULL, &client_data_json_enc_len), 1);
client_data_json_enc = o_malloc(client_data_json_enc_len+1);
ck_assert_ptr_ne(client_data_json_enc, NULL);
ck_assert_int_eq(oh_my_base64_encode((unsigned char *)client_data_json, o_strlen(client_data_json), client_data_json_enc, &client_data_json_enc_len), 1);

// Generate credential_id
ck_assert_int_eq(oh_my_base64_encode(credential_id, WEBAUTHN_CREDENTIAL_ID_LEN, credential_id_enc, &credential_id_enc_len), 1);
ck_assert_int_eq(oh_my_base64url_encode(credential_id, WEBAUTHN_CREDENTIAL_ID_LEN, credential_id_enc_url, &credential_id_enc_url_len), 1);

// Let's build auth_data
memset(auth_data, 0, AUTH_DATA_SIZE);
// Set rpId hash
key_data.data = (unsigned char *)WEBAUTHN_RP_ID;
key_data.size = o_strlen(WEBAUTHN_RP_ID);
ck_assert_int_eq(gnutls_fingerprint(GNUTLS_DIG_SHA256, &key_data, auth_data, &auth_data_len), GNUTLS_E_SUCCESS);
rp_id_len = auth_data_len;
// Set flags
*(auth_data+auth_data_len) = FLAG_USER_PRESENT | FLAG_AT;
auth_data_len += 5;
// Set aaguid
memcpy((auth_data+auth_data_len), aaguid, AAGUID_LEN);
auth_data_len += AAGUID_LEN;
// Set Credential ID and Credential public key
ck_assert_int_eq(gnutls_pubkey_init(&pubkey), 0);
ck_assert_int_eq(gnutls_x509_privkey_init(&key), 0);
ck_assert_int_eq(gnutls_privkey_init(&privkey), 0);
key_data.data = (unsigned char *)CREDENTIAL_PUBLIC_KEY;
key_data.size = o_strlen(CREDENTIAL_PUBLIC_KEY);
ck_assert_int_eq(gnutls_pubkey_import(pubkey, &key_data, GNUTLS_X509_FMT_PEM), 0);
key_data.data = (unsigned char *)FIDO_KEY_FAKE;
key_data.size = o_strlen(FIDO_KEY_FAKE);
ck_assert_int_eq(gnutls_x509_privkey_import(key, &key_data, GNUTLS_X509_FMT_PEM), 0);
ck_assert_int_eq(gnutls_privkey_import_x509(privkey, key, 0), 0);
ck_assert_int_eq(gnutls_pubkey_get_key_id(pubkey, 0, pubkey_id, &pubkey_id_len), 0);
memset((auth_data+auth_data_len), WEBAUTHN_CREDENTIAL_ID_LEN>>8, 1);
memset((auth_data+auth_data_len+1), WEBAUTHN_CREDENTIAL_ID_LEN, 1);
auth_data_len += 2;
memcpy((auth_data+auth_data_len), credential_id, WEBAUTHN_CREDENTIAL_ID_LEN);
auth_data_len += WEBAUTHN_CREDENTIAL_ID_LEN;

memset(key_x_invalid, 1, 384);
ck_assert_int_eq(gnutls_pubkey_export_ecc_raw2(pubkey, &curve, &key_x, &key_y, GNUTLS_EXPORT_FLAG_NO_LZ), 0);
cbor_cose = cbor_new_definite_map(4);
ck_assert_ptr_ne(cbor_cose, NULL);

cose_pair.key = cbor_build_uint8(1);
cbor_mark_negint(cose_pair.key);
cose_pair.value = cbor_build_bytestring(key_x_invalid, 384);
ck_assert_int_eq(cbor_map_add(cbor_cose, cose_pair), true);
cbor_decref(&cose_pair.key);
cbor_decref(&cose_pair.value);

cose_pair.key = cbor_build_uint8(2);
cbor_mark_negint(cose_pair.key);
cose_pair.value = cbor_build_bytestring(key_y.data, key_y.size);
ck_assert_int_eq(cbor_map_add(cbor_cose, cose_pair), true);
cbor_decref(&cose_pair.key);
cbor_decref(&cose_pair.value);

cose_pair.key = cbor_build_uint8(1);
cose_pair.value = cbor_build_uint8(2);
ck_assert_int_eq(cbor_map_add(cbor_cose, cose_pair), true);
cbor_decref(&cose_pair.key);
cbor_decref(&cose_pair.value);

cose_pair.key = cbor_build_uint8(3);
cose_pair.value = cbor_build_uint8(6);
cbor_mark_negint(cose_pair.value);
ck_assert_int_eq(cbor_map_add(cbor_cose, cose_pair), true);
cbor_decref(&cose_pair.key);
cbor_decref(&cose_pair.value);

cbor_cose_dump_len = cbor_serialize(cbor_cose, cbor_cose_dump, cbor_cose_dump_max_len);
ck_assert_int_gt(cbor_cose_dump_len, 0);
memcpy((auth_data+auth_data_len), cbor_cose_dump, cbor_cose_dump_len);
auth_data_len += cbor_cose_dump_len;
// authData is properly built

// Let's build attStmt
att_stmt = cbor_new_definite_map(2);

ck_assert_int_eq(gnutls_x509_crt_init(&cert), 0);
key_data.data = (unsigned char *)FIDO_CERT_FAKE;
key_data.size = o_strlen(FIDO_CERT_FAKE);
ck_assert_int_ge(gnutls_x509_crt_import(cert, &key_data, GNUTLS_X509_FMT_PEM), 0);
ck_assert_int_eq(gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, cert_der, &cert_der_len), 0);
cose_pair.key = cbor_build_string("x5c");
cose_pair.value = cbor_new_definite_array(1);
bs_obj = cbor_build_bytestring(cert_der, cert_der_len);
ck_assert_int_eq(true, cbor_array_set(cose_pair.value, 0, bs_obj));
ck_assert_int_eq(cbor_map_add(att_stmt, cose_pair), true);
cbor_decref(&cose_pair.key);
cbor_decref(&cose_pair.value);

key_data.data = (unsigned char *)client_data_json;
key_data.size = o_strlen(client_data_json);
ck_assert_int_eq(gnutls_fingerprint(GNUTLS_DIG_SHA256, &key_data, client_data_hash, &client_data_hash_len), GNUTLS_E_SUCCESS);
verification_data[0] = 0;
verification_data_offset = 1;

memcpy(verification_data+verification_data_offset, auth_data, rp_id_len);
verification_data_offset += rp_id_len;

memcpy(verification_data+verification_data_offset, client_data_hash, client_data_hash_len);
verification_data_offset += client_data_hash_len;

memcpy(verification_data+verification_data_offset, credential_id, WEBAUTHN_CREDENTIAL_ID_LEN);
verification_data_offset += WEBAUTHN_CREDENTIAL_ID_LEN;

memset(verification_data+verification_data_offset, 0x04, 1);
verification_data_offset++;

memcpy(verification_data+verification_data_offset, key_x_invalid, 384);
verification_data_offset += 384;

memcpy(verification_data+verification_data_offset, key_y.data, key_y.size);
verification_data_offset += key_y.size;

key_data.data = verification_data;
key_data.size = verification_data_offset;

ck_assert_int_eq(gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0, &key_data, &signature), 0);

cose_pair.key = cbor_build_string("sig");
cose_pair.value = cbor_build_bytestring(signature.data, signature.size);
ck_assert_int_eq(cbor_map_add(att_stmt, cose_pair), true);
cbor_decref(&cose_pair.key);
cbor_decref(&cose_pair.value);
// attStmt is properly built

// Let's built the attestation object
att_obj = cbor_new_definite_map(3);
cose_pair.key = cbor_build_string("fmt");
cose_pair.value = cbor_build_string("fido-u2f");
ck_assert_int_eq(cbor_map_add(att_obj, cose_pair), true);
cbor_decref(&cose_pair.key);
cbor_decref(&cose_pair.value);

cose_pair.key = cbor_build_string("authData");
cose_pair.value = cbor_build_bytestring(auth_data, auth_data_len);
ck_assert_int_eq(cbor_map_add(att_obj, cose_pair), true);
cbor_decref(&cose_pair.key);
cbor_decref(&cose_pair.value);

cose_pair.key = cbor_build_string("attStmt");
cose_pair.value = att_stmt;
ck_assert_int_eq(cbor_map_add(att_obj, cose_pair), true);
cbor_decref(&cose_pair.key);

ck_assert_int_gt(cbor_serialize_alloc(att_obj, &att_obj_ser, &att_obj_ser_len), 0);
ck_assert_int_eq(oh_my_base64_encode(att_obj_ser, att_obj_ser_len, NULL, &att_obj_ser_enc_len), 1);
att_obj_ser_enc = o_malloc(att_obj_ser_enc_len+1);
att_obj_ser_enc_len = 0;
ck_assert_int_eq(oh_my_base64_encode(att_obj_ser, att_obj_ser_len, att_obj_ser_enc, &att_obj_ser_enc_len), 1);

j_credential = json_pack("{ss ss ss s{ss ss ss s{ss% ss% ss s{ss% ss%}}}}",
"username", USERNAME,
"scheme_type", MODULE_MODULE,
"scheme_name", MODULE_NAME,
"value",
"register", "register-credential",
"session", session,
"type", "public-key",
"credential",
"id", credential_id_enc_url, credential_id_enc_url_len,
"rawId", credential_id_enc, credential_id_enc_len,
"type", "public-key",
"response",
"attestationObject", att_obj_ser_enc, att_obj_ser_enc_len,
"clientDataJSON", client_data_json_enc, client_data_json_enc_len);

ck_assert_int_eq(run_simple_test(&user_req, "POST", SERVER_URI "profile/scheme/register/", NULL, NULL, j_credential, NULL, 400, NULL, NULL, NULL), 1);

/*ck_assert_int_eq(ulfius_set_json_body_request(&user_req, j_credential), U_OK);

ck_assert_int_eq(ulfius_send_http_request(&user_req, &resp_register), U_OK);
printf("body %.*s\n", (int)resp_register.binary_body_length, (char *)resp_register.binary_body);
ck_assert_int_eq(resp_register.status, 200);*/

gnutls_privkey_deinit(privkey);
gnutls_pubkey_deinit(pubkey);
gnutls_x509_crt_deinit(cert);
gnutls_x509_privkey_deinit(key);
gnutls_free(signature.data);
gnutls_free(key_x.data);
gnutls_free(key_y.data);
json_decref(j_params);
json_decref(j_result);
json_decref(j_client_data);
json_decref(j_credential);
ulfius_clean_response(&resp);
ulfius_clean_response(&resp_register);
o_free(client_data_json);
o_free(client_data_json_enc);
o_free(att_obj_ser_enc);
o_free(att_obj_ser);
cbor_decref(&att_obj);
cbor_decref(&cbor_cose);
cbor_decref(&att_stmt);
cbor_decref(&bs_obj);
}
END_TEST

START_TEST(test_glwd_scheme_webauthn_irl_register_error_invalid_data_cose_key_key_alg)
{
json_t * j_params = json_pack("{sssssss{ss}}",
Expand Down Expand Up @@ -20693,6 +20951,7 @@ static Suite *glewlwyd_suite(void)
tcase_add_test(tc_core, test_glwd_scheme_webauthn_irl_register_error_invalid_auth_data_cose_key_invalid_dump);
tcase_add_test(tc_core, test_glwd_scheme_webauthn_irl_register_error_invalid_data_cose_key_key_x_sign);
tcase_add_test(tc_core, test_glwd_scheme_webauthn_irl_register_error_invalid_data_cose_key_key_x_type);
tcase_add_test(tc_core, test_glwd_scheme_webauthn_irl_register_error_invalid_data_cose_key_key_x_length);
tcase_add_test(tc_core, test_glwd_scheme_webauthn_irl_register_error_invalid_data_cose_key_key_alg);
tcase_add_test(tc_core, test_glwd_scheme_webauthn_irl_register_error_u2f_invalid_att_stmt_map_size);
tcase_add_test(tc_core, test_glwd_scheme_webauthn_irl_register_error_u2f_invalid_att_stmt_cert_key);
Expand Down

0 comments on commit 29e63f7

Please sign in to comment.