NTRU_IoT/legacy-code/test/check_internal_key.c

306 lines
9.0 KiB
C
Raw Permalink Normal View History

2022-02-01 11:45:47 -05:00
#include <check.h>
#include "ntru_crypto.h"
#include "ntru_crypto_ntru_convert.h"
#include "ntru_crypto_ntru_encrypt_key.h"
#include "ntru_crypto_ntru_encrypt_param_sets.h"
#include "ntru_crypto_ntru_poly.h"
#include "test_common.h"
#include "check_common.h"
/*
* test_key_form
*
* For all parameter sets:
* Check that keys satisfy h = pf/g with f and g of the
* correct form by computing f*h.
*/
START_TEST(test_key_form)
{
uint32_t i;
uint32_t rc;
NTRU_CK_MEM pubkey_blob;
NTRU_CK_MEM privkey_blob;
NTRU_CK_MEM F_buf;
NTRU_CK_MEM h_poly;
NTRU_CK_MEM g_poly;
NTRU_CK_MEM scratch;
uint8_t *pubkey_blob_p;
uint8_t *privkey_blob_p;
uint8_t const *pubkey_pack_p;
uint8_t const *privkey_pack_p;
uint16_t *F_buf_p;
uint16_t *h_poly_p;
uint16_t *g_poly_p;
uint16_t *scratch_p;
uint16_t pubkey_blob_len = 0;
uint16_t privkey_blob_len = 0;
uint16_t pubkey_pack_len = 0;
uint8_t pubkey_pack_type = 0x00;
uint8_t privkey_pack_type = 0x00;
uint16_t mod_q_mask;
uint16_t h1;
uint32_t dF;
uint16_t scratch_polys;
uint16_t pad_deg;
NTRU_ENCRYPT_PARAM_SET *params = NULL;
NTRU_ENCRYPT_PARAM_SET_ID param_set_id;
param_set_id = PARAM_SET_IDS[_i];
params = ntru_encrypt_get_params_with_id(param_set_id);
ck_assert_ptr_ne(params, NULL);
mod_q_mask = params->q - 1;
ntru_ring_mult_indices_memreq(params->N, &scratch_polys, &pad_deg);
ck_assert_uint_ge(scratch_polys, 1);
ck_assert_uint_ge(pad_deg, params->N);
if(params->is_product_form)
{
scratch_polys += 1;
}
/* Generate a key */
rc = ntru_crypto_ntru_encrypt_keygen(drbg, param_set_id, &pubkey_blob_len,
NULL, &privkey_blob_len, NULL);
ck_assert_uint_eq(rc, NTRU_RESULT(NTRU_OK));
pubkey_blob_p = ntru_ck_malloc(&pubkey_blob,
pubkey_blob_len*sizeof(*pubkey_blob_p));
privkey_blob_p = ntru_ck_malloc(&privkey_blob,
privkey_blob_len*sizeof(*privkey_blob_p));
rc = ntru_crypto_ntru_encrypt_keygen(drbg, param_set_id,
&pubkey_blob_len, pubkey_blob_p,
&privkey_blob_len, privkey_blob_p);
ck_assert_uint_eq(rc, NTRU_RESULT(NTRU_OK));
rc = ntru_crypto_ntru_encrypt_key_parse(FALSE,
privkey_blob_len,
privkey_blob_p, &pubkey_pack_type,
&privkey_pack_type, &params,
&pubkey_pack_p, &privkey_pack_p);
ck_assert_int_eq(rc, TRUE);
h_poly_p = (uint16_t*) ntru_ck_malloc(&h_poly, pad_deg*sizeof(*h_poly_p));
/* Unpack public key, h */
pubkey_pack_len = (params->N * params->q_bits + 7) >> 3;
ntru_octets_2_elements(pubkey_pack_len, pubkey_pack_p,
params->q_bits, h_poly_p);
/* Check that h(1) = p * f(1)/g(1) = 3 */
h1 = 0;
for(i=0; i<params->N; i++)
{
h1 += h_poly_p[i];
}
h1 &= mod_q_mask;
ck_assert_uint_eq(h1, 3);
/* Unpack private key, F */
dF = params->dF_r;
if (params->is_product_form)
{
dF = (dF + (dF >> 8) + (dF >> 16)) & 0xff;
}
F_buf_p = (uint16_t*)ntru_ck_malloc(&F_buf, 2*dF*sizeof(*F_buf_p));
if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS)
{
ntru_packed_trits_2_indices(privkey_pack_p, params->N, F_buf_p,
F_buf_p + dF);
}
else if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_INDICES)
{
ntru_octets_2_elements(
(2 * dF * params->N_bits + 7) >> 3,
privkey_pack_p, params->N_bits, F_buf_p);
}
g_poly_p = (uint16_t*) ntru_ck_malloc(&g_poly, pad_deg*sizeof(*g_poly_p));
scratch_p = (uint16_t*) ntru_ck_malloc(&scratch,
scratch_polys*pad_deg*sizeof(*scratch_p));
/* Check that (1 + p*F)*h = p*g */
/* Our h = p*g/f when generated properly. f = 1 + pF */
/* First compute g' = F*h */
if (params->is_product_form)
{
ntru_ring_mult_product_indices(h_poly_p,
(uint16_t)(params->dF_r & 0xff),
(uint16_t)((params->dF_r >> 8) & 0xff),
(uint16_t)((params->dF_r >> 16) & 0xff),
F_buf_p, params->N, params->q,
scratch_p, g_poly_p);
}
else
{
ntru_ring_mult_indices(h_poly_p, (uint16_t)dF, (uint16_t)dF,
F_buf_p, params->N, params->q,
scratch_p, g_poly_p);
}
/* Then g = 3*g' + h */
for(i=0; i<params->N; i++)
{
g_poly_p[i] = (3*g_poly_p[i] + h_poly_p[i]) & mod_q_mask;
}
/* Ensure g is of the right form: dg+1 coeffs = +3 and dg coeffs = -3 */
uint16_t g_p1 = 0;
uint16_t g_m1 = 0;
for(i=0; i<params->N; i++)
{
if(g_poly_p[i] == 3)
{
g_p1 += 1;
}
else if(g_poly_p[i] == params->q - 3)
{
g_m1 += 1;
}
else
{
ck_assert_uint_eq(g_poly_p[i], 0);
}
}
ck_assert_uint_eq(g_p1, params->dg + 1);
ck_assert_uint_eq(g_m1, params->dg);
ntru_ck_mem_ok(&scratch);
ntru_ck_mem_ok(&g_poly);
ntru_ck_mem_ok(&h_poly);
ntru_ck_mem_ok(&F_buf);
ntru_ck_mem_ok(&privkey_blob);
ntru_ck_mem_ok(&pubkey_blob);
ntru_ck_mem_free(&scratch);
ntru_ck_mem_free(&g_poly);
ntru_ck_mem_free(&h_poly);
ntru_ck_mem_free(&F_buf);
ntru_ck_mem_free(&privkey_blob);
ntru_ck_mem_free(&pubkey_blob);
}
END_TEST
START_TEST(test_key_encoding)
{
uint32_t rc;
NTRU_CK_MEM pubkey_mem;
NTRU_CK_MEM privkey_mem;
uint8_t *pubkey_blob = NULL;
uint8_t *privkey_blob = NULL;
uint16_t pubkey_blob_len = 0;
uint16_t privkey_blob_len = 0;
uint8_t tag = 0;
uint8_t pubkey_pack_type;
uint8_t privkey_pack_type;
uint8_t const *pubkey_packed;
uint8_t const *privkey_packed;
NTRU_ENCRYPT_PARAM_SET *params = NULL;
NTRU_ENCRYPT_PARAM_SET_ID param_set_id;
param_set_id = PARAM_SET_IDS[_i];
params = ntru_encrypt_get_params_with_id(param_set_id);
/* Generate a key */
rc = ntru_crypto_ntru_encrypt_keygen(drbg, param_set_id, &pubkey_blob_len,
NULL, &privkey_blob_len, NULL);
ck_assert_uint_eq(rc, NTRU_RESULT(NTRU_OK));
ck_assert_uint_gt(pubkey_blob_len, 0);
ck_assert_uint_gt(privkey_blob_len, 0);
pubkey_blob = (uint8_t *)ntru_ck_malloc(&pubkey_mem, pubkey_blob_len);
privkey_blob = (uint8_t *)ntru_ck_malloc(&privkey_mem, privkey_blob_len);
rc = ntru_crypto_ntru_encrypt_keygen(drbg, param_set_id,
&pubkey_blob_len, pubkey_blob,
&privkey_blob_len, privkey_blob);
ck_assert_uint_eq(rc, NTRU_RESULT(NTRU_OK));
/* Mangle private key tag */
if(params->is_product_form)
{
/* Product form with trits encoding is not allowed */
tag = privkey_blob[0];
privkey_blob[0] = NTRU_ENCRYPT_PRIVKEY_TRITS_TAG;
rc = ntru_crypto_ntru_encrypt_key_parse(FALSE,
privkey_blob_len, privkey_blob, &pubkey_pack_type,
&privkey_pack_type, &params, &pubkey_packed, &privkey_packed);
ck_assert_uint_eq(rc, FALSE);
privkey_blob[0] = tag;
}
else
{
/* Tag doesn't match encoding type */
tag = privkey_blob[0];
uint16_t packed_trits_len = (params->N + 4) / 5;
uint16_t packed_indices_len;
packed_indices_len = ((params->dF_r << 1) * params->N_bits + 7) >> 3;
/* TODO: add test parameter suite violating the following constraint */
ck_assert_uint_ne(packed_trits_len, packed_indices_len);
if(packed_indices_len <= packed_trits_len)
{
/* Would normally use trits encoding */
privkey_blob[0] = NTRU_ENCRYPT_PRIVKEY_TRITS_TAG;
}
else /* Would normally use indices encoding */
{
privkey_blob[0] = NTRU_ENCRYPT_PRIVKEY_INDICES_TAG;
}
rc = ntru_crypto_ntru_encrypt_key_parse(FALSE,
privkey_blob_len, privkey_blob, &pubkey_pack_type,
&privkey_pack_type, &params, &pubkey_packed, &privkey_packed);
ck_assert_uint_eq(rc, FALSE);
privkey_blob[0] = tag;
}
ntru_ck_mem_ok(&pubkey_mem);
ntru_ck_mem_ok(&privkey_mem);
ntru_ck_mem_free(&pubkey_mem);
ntru_ck_mem_free(&privkey_mem);
}
END_TEST
Suite *
ntruencrypt_internal_key_suite(void)
{
Suite *s;
TCase *tc_key;
s = suite_create("NTRUEncrypt.Internal.Key");
tc_key = tcase_create("Key");
tcase_add_unchecked_fixture(tc_key, test_drbg_setup, test_drbg_teardown);
tcase_add_loop_test(tc_key, test_key_form, 0, NUM_PARAM_SETS);
tcase_add_loop_test(tc_key, test_key_encoding, 0, NUM_PARAM_SETS);
suite_add_tcase(s, tc_key);
return s;
}