The test considers a party that already has a private-public key pair and a party that provides a NULL key. The kernel will generate the private-public key pair for the latter, computes the shared secret on both ends and verifies if it's the same. The explicit private-public key pair was copied from the previous test vector. Signed-off-by: Tudor Ambarus <tudor.ambarus@xxxxxxxxxxxxx> --- crypto/testmgr.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-------- crypto/testmgr.h | 47 +++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 11 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 6f5f3ed..5f8e683 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1997,6 +1997,9 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, struct kpp_request *req; void *input_buf = NULL; void *output_buf = NULL; + void *a_public = NULL; + void *a_ss = NULL; + void *shared_secret = NULL; struct tcrypt_result result; unsigned int out_len_max; int err = -ENOMEM; @@ -2026,20 +2029,31 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, tcrypt_complete, &result); - /* Compute public key */ + /* Compute party A's public key */ err = wait_async_op(&result, crypto_kpp_generate_public_key(req)); if (err) { - pr_err("alg: %s: generate public key test failed. err %d\n", + pr_err("alg: %s: Party A: generate public key test failed. err %d\n", alg, err); goto free_output; } - /* Verify calculated public key */ - if (memcmp(vec->expected_a_public, sg_virt(req->dst), - vec->expected_a_public_size)) { - pr_err("alg: %s: generate public key test failed. Invalid output\n", - alg); - err = -EINVAL; - goto free_output; + + if (vec->genkey) { + /* Save party A's public key */ + a_public = kzalloc(out_len_max, GFP_KERNEL); + if (!a_public) { + err = -ENOMEM; + goto free_output; + } + memcpy(a_public, sg_virt(req->dst), out_len_max); + } else { + /* Verify calculated public key */ + if (memcmp(vec->expected_a_public, sg_virt(req->dst), + vec->expected_a_public_size)) { + pr_err("alg: %s: Party A: generate public key test failed. Invalid output\n", + alg); + err = -EINVAL; + goto free_output; + } } /* Calculate shared secret key by using counter part (b) public key. */ @@ -2058,15 +2072,53 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, tcrypt_complete, &result); err = wait_async_op(&result, crypto_kpp_compute_shared_secret(req)); if (err) { - pr_err("alg: %s: compute shard secret test failed. err %d\n", + pr_err("alg: %s: Party A: compute shared secret test failed. err %d\n", alg, err); goto free_all; } + + if (vec->genkey) { + /* Save the shared secret obtained by party A */ + a_ss = kzalloc(vec->expected_ss_size, GFP_KERNEL); + if (!a_ss) { + err = -ENOMEM; + goto free_all; + } + memcpy(a_ss, sg_virt(req->dst), vec->expected_ss_size); + + /* + * Calculate party B's shared secret by using party A's + * public key. + */ + err = crypto_kpp_set_secret(tfm, vec->b_secret, + vec->b_secret_size); + if (err < 0) + goto free_all; + + sg_init_one(&src, a_public, vec->expected_a_public_size); + sg_init_one(&dst, output_buf, out_len_max); + kpp_request_set_input(req, &src, vec->expected_a_public_size); + kpp_request_set_output(req, &dst, out_len_max); + kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, &result); + err = wait_async_op(&result, + crypto_kpp_compute_shared_secret(req)); + if (err) { + pr_err("alg: %s: Party B: compute shared secret failed. err %d\n", + alg, err); + goto free_all; + } + + shared_secret = a_ss; + } else { + shared_secret = (void *)vec->expected_ss; + } + /* * verify shared secret from which the user will derive * secret key by executing whatever hash it has chosen */ - if (memcmp(vec->expected_ss, sg_virt(req->dst), + if (memcmp(shared_secret, sg_virt(req->dst), vec->expected_ss_size)) { pr_err("alg: %s: compute shared secret test failed. Invalid output\n", alg); @@ -2074,8 +2126,10 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, } free_all: + kfree(a_ss); kfree(input_buf); free_output: + kfree(a_public); kfree(output_buf); free_req: kpp_request_free(req); diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 4293573..db2e26c 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -137,13 +137,16 @@ struct akcipher_testvec { struct kpp_testvec { const unsigned char *secret; + const unsigned char *b_secret; const unsigned char *b_public; const unsigned char *expected_a_public; const unsigned char *expected_ss; unsigned short secret_size; + unsigned short b_secret_size; unsigned short b_public_size; unsigned short expected_a_public_size; unsigned short expected_ss_size; + bool genkey; }; static const char zeroed_string[48]; @@ -840,6 +843,50 @@ static const struct kpp_testvec ecdh_tv_template[] = { .b_public_size = 64, .expected_a_public_size = 64, .expected_ss_size = 32 + }, { + .secret = +#ifdef __LITTLE_ENDIAN + "\x02\x00" /* type */ + "\x08\x00" /* len */ + "\x02\x00" /* curve_id */ + "\x00\x00", /* key_size */ +#else + "\x00\x02" /* type */ + "\x00\x08" /* len */ + "\x00\x02" /* curve_id */ + "\x00\x00", /* key_size */ +#endif + .b_secret = +#ifdef __LITTLE_ENDIAN + "\x02\x00" /* type */ + "\x28\x00" /* len */ + "\x02\x00" /* curve_id */ + "\x20\x00" /* key_size */ +#else + "\x00\x02" /* type */ + "\x00\x28" /* len */ + "\x00\x02" /* curve_id */ + "\x00\x20" /* key_size */ +#endif + "\x24\xd1\x21\xeb\xe5\xcf\x2d\x83" + "\xf6\x62\x1b\x6e\x43\x84\x3a\xa3" + "\x8b\xe0\x86\xc3\x20\x19\xda\x92" + "\x50\x53\x03\xe1\xc0\xea\xb8\x82", + .b_public = + "\x1a\x7f\xeb\x52\x00\xbd\x3c\x31" + "\x7d\xb6\x70\xc1\x86\xa6\xc7\xc4" + "\x3b\xc5\x5f\x6c\x6f\x58\x3c\xf5" + "\xb6\x63\x82\x77\x33\x24\xa1\x5f" + "\x6a\xca\x43\x6f\xf7\x7e\xff\x02" + "\x37\x08\xcc\x40\x5e\x7a\xfd\x6a" + "\x6a\x02\x6e\x41\x87\x68\x38\x77" + "\xfa\xa9\x44\x43\x2d\xef\x09\xdf", + .secret_size = 8, + .b_secret_size = 40, + .b_public_size = 64, + .expected_a_public_size = 64, + .expected_ss_size = 32, + .genkey = true, } }; -- 2.7.4