diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-shamir.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-shamir.h index 0a3db61c12..781e8ee3ca 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-shamir.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-shamir.h @@ -18,7 +18,6 @@ */ #include "py/obj.h" -#include "py/objstr.h" #include "embed/extmod/trezorobj.h" @@ -30,8 +29,9 @@ /// ''' /// Returns f(x) given the Shamir shares (x_1, f(x_1)), ... , (x_k, f(x_k)). /// :param shares: The Shamir shares. -/// :type shares: A list of pairs (x_i, y_i), where x_i is an integer and y_i is an array of -/// bytes representing the evaluations of the polynomials in x_i. +/// :type shares: A list of pairs (x_i, y_i), where x_i is an integer and +/// y_i is an array of bytes representing the evaluations of the +/// polynomials in x_i. /// :param int x: The x coordinate of the result. /// :return: Evaluations of the polynomials in x. /// :rtype: Array of bytes. @@ -39,10 +39,7 @@ mp_obj_t mod_trezorcrypto_shamir_interpolate(mp_obj_t shares, mp_obj_t x) { size_t share_count; mp_obj_t *share_items; - if (!MP_OBJ_IS_TYPE(shares, &mp_type_list)) { - mp_raise_TypeError("Expected a list."); - } - mp_obj_list_get(shares, &share_count, &share_items); + mp_obj_get_array(shares, &share_count, &share_items); if (share_count < 1 || share_count > MAX_SHARE_COUNT) { mp_raise_ValueError("Invalid number of shares."); } @@ -51,15 +48,8 @@ mp_obj_t mod_trezorcrypto_shamir_interpolate(mp_obj_t shares, mp_obj_t x) { const uint8_t *share_values[MAX_SHARE_COUNT]; size_t value_len = 0; for (int i = 0; i < share_count; ++i) { - if (!MP_OBJ_IS_TYPE(share_items[i], &mp_type_tuple)) { - mp_raise_TypeError("Expected a tuple."); - } - size_t tuple_len; mp_obj_t *share; - mp_obj_tuple_get(share_items[i], &tuple_len, &share); - if (tuple_len != 2) { - mp_raise_ValueError("Expected a tuple of length 2."); - } + mp_obj_get_array_fixed_n(share_items[i], 2, &share); share_indices[i] = trezor_obj_get_uint8(share[0]); mp_buffer_info_t value; mp_get_buffer_raise(share[1], &value, MP_BUFFER_READ); @@ -76,7 +66,8 @@ mp_obj_t mod_trezorcrypto_shamir_interpolate(mp_obj_t shares, mp_obj_t x) { } vstr_t vstr; vstr_init_len(&vstr, value_len); - shamir_interpolate((uint8_t*) vstr.buf, x_uint8, share_indices, share_values, share_count, value_len); + shamir_interpolate((uint8_t *)vstr.buf, x_uint8, share_indices, share_values, + share_count, value_len); vstr_cut_tail_bytes(&vstr, vstr_len(&vstr) - value_len); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } @@ -85,7 +76,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_shamir_interpolate_obj, STATIC const mp_rom_map_elem_t mod_trezorcrypto_shamir_globals_table[] = { {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_shamir)}, - {MP_ROM_QSTR(MP_QSTR_interpolate), MP_ROM_PTR(&mod_trezorcrypto_shamir_interpolate_obj)}, + {MP_ROM_QSTR(MP_QSTR_interpolate), + MP_ROM_PTR(&mod_trezorcrypto_shamir_interpolate_obj)}, }; STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_shamir_globals, mod_trezorcrypto_shamir_globals_table); diff --git a/embed/extmod/modtrezorcrypto/shamir.c b/embed/extmod/modtrezorcrypto/shamir.c index ed7b9d374b..21e712faf7 100644 --- a/embed/extmod/modtrezorcrypto/shamir.c +++ b/embed/extmod/modtrezorcrypto/shamir.c @@ -35,292 +35,265 @@ * lookup operations, as all proper crypto code must be. */ - #include "shamir.h" -#include #include +#include -static void -bitslice(uint32_t r[8], const uint8_t *x, size_t len) -{ - size_t bit_idx, arr_idx; - uint32_t cur; +static void bitslice(uint32_t r[8], const uint8_t *x, size_t len) { + size_t bit_idx, arr_idx; + uint32_t cur; - memset(r, 0, sizeof(uint32_t[8])); - for (arr_idx = 0; arr_idx < len; arr_idx++) { - cur = (uint32_t) x[arr_idx]; - for (bit_idx = 0; bit_idx < 8; bit_idx++) { - r[bit_idx] |= ((cur & (1 << bit_idx)) >> bit_idx) << arr_idx; - } - } + memset(r, 0, sizeof(uint32_t[8])); + for (arr_idx = 0; arr_idx < len; arr_idx++) { + cur = (uint32_t)x[arr_idx]; + for (bit_idx = 0; bit_idx < 8; bit_idx++) { + r[bit_idx] |= ((cur & (1 << bit_idx)) >> bit_idx) << arr_idx; + } + } } +static void unbitslice(uint8_t *r, const uint32_t x[8], size_t len) { + size_t bit_idx, arr_idx; + uint32_t cur; -static void -unbitslice(uint8_t *r, const uint32_t x[8], size_t len) -{ - size_t bit_idx, arr_idx; - uint32_t cur; - - memset(r, 0, sizeof(uint8_t) * len); - for (bit_idx = 0; bit_idx < 8; bit_idx++) { - cur = (uint32_t) x[bit_idx]; - for (arr_idx = 0; arr_idx < len; arr_idx++) { - r[arr_idx] |= ((cur & (1 << arr_idx)) >> arr_idx) << bit_idx; - } - } + memset(r, 0, sizeof(uint8_t) * len); + for (bit_idx = 0; bit_idx < 8; bit_idx++) { + cur = (uint32_t)x[bit_idx]; + for (arr_idx = 0; arr_idx < len; arr_idx++) { + r[arr_idx] |= ((cur & (1 << arr_idx)) >> arr_idx) << bit_idx; + } + } } - -static void -bitslice_setall(uint32_t r[8], const uint8_t x) -{ - size_t idx; - for (idx = 0; idx < 8; idx++) { - r[idx] = ((int32_t) ((x & (1 << idx)) << (31 - idx))) >> 31; - } +static void bitslice_setall(uint32_t r[8], const uint8_t x) { + size_t idx; + for (idx = 0; idx < 8; idx++) { + r[idx] = ((int32_t)((x & (1 << idx)) << (31 - idx))) >> 31; + } } - /* * Add (XOR) `r` with `x` and store the result in `r`. */ -static void -gf256_add(uint32_t r[8], const uint32_t x[8]) -{ - size_t idx; - for (idx = 0; idx < 8; idx++) r[idx] ^= x[idx]; +static void gf256_add(uint32_t r[8], const uint32_t x[8]) { + size_t idx; + for (idx = 0; idx < 8; idx++) r[idx] ^= x[idx]; } - /* * Safely multiply two bitsliced polynomials in GF(2^8) reduced by * x^8 + x^4 + x^3 + x + 1. `r` and `a` may overlap, but overlapping of `r` * and `b` will produce an incorrect result! If you need to square a polynomial * use `gf256_square` instead. */ -static void -gf256_mul(uint32_t r[8], const uint32_t a[8], const uint32_t b[8]) -{ - /* This function implements Russian Peasant multiplication on two - * bitsliced polynomials. - * - * I personally think that these kinds of long lists of operations - * are often a bit ugly. A double for loop would be nicer and would - * take up a lot less lines of code. - * However, some compilers seem to fail in optimizing these kinds of - * loops. So we will just have to do this by hand. - */ - uint32_t a2[8]; - memcpy(a2, a, sizeof(uint32_t[8])); +static void gf256_mul(uint32_t r[8], const uint32_t a[8], const uint32_t b[8]) { + /* This function implements Russian Peasant multiplication on two + * bitsliced polynomials. + * + * I personally think that these kinds of long lists of operations + * are often a bit ugly. A double for loop would be nicer and would + * take up a lot less lines of code. + * However, some compilers seem to fail in optimizing these kinds of + * loops. So we will just have to do this by hand. + */ + uint32_t a2[8]; + memcpy(a2, a, sizeof(uint32_t[8])); - r[0] = a2[0] & b[0]; /* add (assignment, because r is 0) */ - r[1] = a2[1] & b[0]; - r[2] = a2[2] & b[0]; - r[3] = a2[3] & b[0]; - r[4] = a2[4] & b[0]; - r[5] = a2[5] & b[0]; - r[6] = a2[6] & b[0]; - r[7] = a2[7] & b[0]; - a2[0] ^= a2[7]; /* reduce */ - a2[2] ^= a2[7]; - a2[3] ^= a2[7]; + r[0] = a2[0] & b[0]; /* add (assignment, because r is 0) */ + r[1] = a2[1] & b[0]; + r[2] = a2[2] & b[0]; + r[3] = a2[3] & b[0]; + r[4] = a2[4] & b[0]; + r[5] = a2[5] & b[0]; + r[6] = a2[6] & b[0]; + r[7] = a2[7] & b[0]; + a2[0] ^= a2[7]; /* reduce */ + a2[2] ^= a2[7]; + a2[3] ^= a2[7]; - r[0] ^= a2[7] & b[1]; /* add */ - r[1] ^= a2[0] & b[1]; - r[2] ^= a2[1] & b[1]; - r[3] ^= a2[2] & b[1]; - r[4] ^= a2[3] & b[1]; - r[5] ^= a2[4] & b[1]; - r[6] ^= a2[5] & b[1]; - r[7] ^= a2[6] & b[1]; - a2[7] ^= a2[6]; /* reduce */ - a2[1] ^= a2[6]; - a2[2] ^= a2[6]; + r[0] ^= a2[7] & b[1]; /* add */ + r[1] ^= a2[0] & b[1]; + r[2] ^= a2[1] & b[1]; + r[3] ^= a2[2] & b[1]; + r[4] ^= a2[3] & b[1]; + r[5] ^= a2[4] & b[1]; + r[6] ^= a2[5] & b[1]; + r[7] ^= a2[6] & b[1]; + a2[7] ^= a2[6]; /* reduce */ + a2[1] ^= a2[6]; + a2[2] ^= a2[6]; - r[0] ^= a2[6] & b[2]; /* add */ - r[1] ^= a2[7] & b[2]; - r[2] ^= a2[0] & b[2]; - r[3] ^= a2[1] & b[2]; - r[4] ^= a2[2] & b[2]; - r[5] ^= a2[3] & b[2]; - r[6] ^= a2[4] & b[2]; - r[7] ^= a2[5] & b[2]; - a2[6] ^= a2[5]; /* reduce */ - a2[0] ^= a2[5]; - a2[1] ^= a2[5]; + r[0] ^= a2[6] & b[2]; /* add */ + r[1] ^= a2[7] & b[2]; + r[2] ^= a2[0] & b[2]; + r[3] ^= a2[1] & b[2]; + r[4] ^= a2[2] & b[2]; + r[5] ^= a2[3] & b[2]; + r[6] ^= a2[4] & b[2]; + r[7] ^= a2[5] & b[2]; + a2[6] ^= a2[5]; /* reduce */ + a2[0] ^= a2[5]; + a2[1] ^= a2[5]; - r[0] ^= a2[5] & b[3]; /* add */ - r[1] ^= a2[6] & b[3]; - r[2] ^= a2[7] & b[3]; - r[3] ^= a2[0] & b[3]; - r[4] ^= a2[1] & b[3]; - r[5] ^= a2[2] & b[3]; - r[6] ^= a2[3] & b[3]; - r[7] ^= a2[4] & b[3]; - a2[5] ^= a2[4]; /* reduce */ - a2[7] ^= a2[4]; - a2[0] ^= a2[4]; + r[0] ^= a2[5] & b[3]; /* add */ + r[1] ^= a2[6] & b[3]; + r[2] ^= a2[7] & b[3]; + r[3] ^= a2[0] & b[3]; + r[4] ^= a2[1] & b[3]; + r[5] ^= a2[2] & b[3]; + r[6] ^= a2[3] & b[3]; + r[7] ^= a2[4] & b[3]; + a2[5] ^= a2[4]; /* reduce */ + a2[7] ^= a2[4]; + a2[0] ^= a2[4]; - r[0] ^= a2[4] & b[4]; /* add */ - r[1] ^= a2[5] & b[4]; - r[2] ^= a2[6] & b[4]; - r[3] ^= a2[7] & b[4]; - r[4] ^= a2[0] & b[4]; - r[5] ^= a2[1] & b[4]; - r[6] ^= a2[2] & b[4]; - r[7] ^= a2[3] & b[4]; - a2[4] ^= a2[3]; /* reduce */ - a2[6] ^= a2[3]; - a2[7] ^= a2[3]; + r[0] ^= a2[4] & b[4]; /* add */ + r[1] ^= a2[5] & b[4]; + r[2] ^= a2[6] & b[4]; + r[3] ^= a2[7] & b[4]; + r[4] ^= a2[0] & b[4]; + r[5] ^= a2[1] & b[4]; + r[6] ^= a2[2] & b[4]; + r[7] ^= a2[3] & b[4]; + a2[4] ^= a2[3]; /* reduce */ + a2[6] ^= a2[3]; + a2[7] ^= a2[3]; - r[0] ^= a2[3] & b[5]; /* add */ - r[1] ^= a2[4] & b[5]; - r[2] ^= a2[5] & b[5]; - r[3] ^= a2[6] & b[5]; - r[4] ^= a2[7] & b[5]; - r[5] ^= a2[0] & b[5]; - r[6] ^= a2[1] & b[5]; - r[7] ^= a2[2] & b[5]; - a2[3] ^= a2[2]; /* reduce */ - a2[5] ^= a2[2]; - a2[6] ^= a2[2]; + r[0] ^= a2[3] & b[5]; /* add */ + r[1] ^= a2[4] & b[5]; + r[2] ^= a2[5] & b[5]; + r[3] ^= a2[6] & b[5]; + r[4] ^= a2[7] & b[5]; + r[5] ^= a2[0] & b[5]; + r[6] ^= a2[1] & b[5]; + r[7] ^= a2[2] & b[5]; + a2[3] ^= a2[2]; /* reduce */ + a2[5] ^= a2[2]; + a2[6] ^= a2[2]; - r[0] ^= a2[2] & b[6]; /* add */ - r[1] ^= a2[3] & b[6]; - r[2] ^= a2[4] & b[6]; - r[3] ^= a2[5] & b[6]; - r[4] ^= a2[6] & b[6]; - r[5] ^= a2[7] & b[6]; - r[6] ^= a2[0] & b[6]; - r[7] ^= a2[1] & b[6]; - a2[2] ^= a2[1]; /* reduce */ - a2[4] ^= a2[1]; - a2[5] ^= a2[1]; + r[0] ^= a2[2] & b[6]; /* add */ + r[1] ^= a2[3] & b[6]; + r[2] ^= a2[4] & b[6]; + r[3] ^= a2[5] & b[6]; + r[4] ^= a2[6] & b[6]; + r[5] ^= a2[7] & b[6]; + r[6] ^= a2[0] & b[6]; + r[7] ^= a2[1] & b[6]; + a2[2] ^= a2[1]; /* reduce */ + a2[4] ^= a2[1]; + a2[5] ^= a2[1]; - r[0] ^= a2[1] & b[7]; /* add */ - r[1] ^= a2[2] & b[7]; - r[2] ^= a2[3] & b[7]; - r[3] ^= a2[4] & b[7]; - r[4] ^= a2[5] & b[7]; - r[5] ^= a2[6] & b[7]; - r[6] ^= a2[7] & b[7]; - r[7] ^= a2[0] & b[7]; + r[0] ^= a2[1] & b[7]; /* add */ + r[1] ^= a2[2] & b[7]; + r[2] ^= a2[3] & b[7]; + r[3] ^= a2[4] & b[7]; + r[4] ^= a2[5] & b[7]; + r[5] ^= a2[6] & b[7]; + r[6] ^= a2[7] & b[7]; + r[7] ^= a2[0] & b[7]; } - /* * Square `x` in GF(2^8) and write the result to `r`. `r` and `x` may overlap. */ -static void -gf256_square(uint32_t r[8], const uint32_t x[8]) -{ - uint32_t r8, r10, r12, r14; - /* Use the Freshman's Dream rule to square the polynomial - * Assignments are done from 7 downto 0, because this allows the user - * to execute this function in-place (e.g. `gf256_square(r, r);`). - */ - r14 = x[7]; - r12 = x[6]; - r10 = x[5]; - r8 = x[4]; - r[6] = x[3]; - r[4] = x[2]; - r[2] = x[1]; - r[0] = x[0]; +static void gf256_square(uint32_t r[8], const uint32_t x[8]) { + uint32_t r8, r10, r12, r14; + /* Use the Freshman's Dream rule to square the polynomial + * Assignments are done from 7 downto 0, because this allows the user + * to execute this function in-place (e.g. `gf256_square(r, r);`). + */ + r14 = x[7]; + r12 = x[6]; + r10 = x[5]; + r8 = x[4]; + r[6] = x[3]; + r[4] = x[2]; + r[2] = x[1]; + r[0] = x[0]; - /* Reduce with x^8 + x^4 + x^3 + x + 1 until order is less than 8 */ - r[7] = r14; /* r[7] was 0 */ - r[6] ^= r14; - r10 ^= r14; - /* Skip, because r13 is always 0 */ - r[4] ^= r12; - r[5] = r12; /* r[5] was 0 */ - r[7] ^= r12; - r8 ^= r12; - /* Skip, because r11 is always 0 */ - r[2] ^= r10; - r[3] = r10; /* r[3] was 0 */ - r[5] ^= r10; - r[6] ^= r10; - r[1] = r14; /* r[1] was 0 */ - r[2] ^= r14; /* Substitute r9 by r14 because they will always be equal*/ - r[4] ^= r14; - r[5] ^= r14; - r[0] ^= r8; - r[1] ^= r8; - r[3] ^= r8; - r[4] ^= r8; + /* Reduce with x^8 + x^4 + x^3 + x + 1 until order is less than 8 */ + r[7] = r14; /* r[7] was 0 */ + r[6] ^= r14; + r10 ^= r14; + /* Skip, because r13 is always 0 */ + r[4] ^= r12; + r[5] = r12; /* r[5] was 0 */ + r[7] ^= r12; + r8 ^= r12; + /* Skip, because r11 is always 0 */ + r[2] ^= r10; + r[3] = r10; /* r[3] was 0 */ + r[5] ^= r10; + r[6] ^= r10; + r[1] = r14; /* r[1] was 0 */ + r[2] ^= r14; /* Substitute r9 by r14 because they will always be equal*/ + r[4] ^= r14; + r[5] ^= r14; + r[0] ^= r8; + r[1] ^= r8; + r[3] ^= r8; + r[4] ^= r8; } - /* * Invert `x` in GF(2^8) and write the result to `r` */ -static void -gf256_inv(uint32_t r[8], uint32_t x[8]) -{ - uint32_t y[8], z[8]; +static void gf256_inv(uint32_t r[8], uint32_t x[8]) { + uint32_t y[8], z[8]; - gf256_square(y, x); // y = x^2 - gf256_square(y, y); // y = x^4 - gf256_square(r, y); // r = x^8 - gf256_mul(z, r, x); // z = x^9 - gf256_square(r, r); // r = x^16 - gf256_mul(r, r, z); // r = x^25 - gf256_square(r, r); // r = x^50 - gf256_square(z, r); // z = x^100 - gf256_square(z, z); // z = x^200 - gf256_mul(r, r, z); // r = x^250 - gf256_mul(r, r, y); // r = x^254 + gf256_square(y, x); // y = x^2 + gf256_square(y, y); // y = x^4 + gf256_square(r, y); // r = x^8 + gf256_mul(z, r, x); // z = x^9 + gf256_square(r, r); // r = x^16 + gf256_mul(r, r, z); // r = x^25 + gf256_square(r, r); // r = x^50 + gf256_square(z, r); // z = x^100 + gf256_square(z, z); // z = x^200 + gf256_mul(r, r, z); // r = x^250 + gf256_mul(r, r, y); // r = x^254 } - -void shamir_interpolate(uint8_t *result, - uint8_t result_index, +void shamir_interpolate(uint8_t *result, uint8_t result_index, const uint8_t *share_indices, - const uint8_t **share_values, - uint8_t share_count, - size_t len) -{ - size_t i, j; - uint32_t xs[share_count][8], ys[share_count][8]; - uint32_t x[8]; - uint32_t denom[8], tmp[8]; - uint32_t num[8] = {~0}; /* num is the numerator (=1) */ - uint32_t secret[8] = {0}; + const uint8_t **share_values, uint8_t share_count, + size_t len) { + size_t i, j; + uint32_t xs[share_count][8], ys[share_count][8]; + uint32_t x[8]; + uint32_t denom[8], tmp[8]; + uint32_t num[8] = {~0}; /* num is the numerator (=1) */ + uint32_t secret[8] = {0}; - if (len > SHAMIR_MAX_LEN) - return; + if (len > SHAMIR_MAX_LEN) return; - /* Collect the x and y values */ - for (i = 0; i < share_count; i++) { - bitslice_setall(xs[i], share_indices[i]); - bitslice(ys[i], share_values[i], len); + /* Collect the x and y values */ + for (i = 0; i < share_count; i++) { + bitslice_setall(xs[i], share_indices[i]); + bitslice(ys[i], share_values[i], len); + } + bitslice_setall(x, result_index); + + for (i = 0; i < share_count; i++) { + memcpy(tmp, x, sizeof(uint32_t[8])); + gf256_add(tmp, xs[i]); + gf256_mul(num, num, tmp); + } + + /* Use Lagrange basis polynomials to calculate the secret coefficient */ + for (i = 0; i < share_count; i++) { + memcpy(denom, x, sizeof(denom)); + gf256_add(denom, xs[i]); + for (j = 0; j < share_count; j++) { + if (i == j) continue; + memcpy(tmp, xs[i], sizeof(uint32_t[8])); + gf256_add(tmp, xs[j]); + gf256_mul(denom, denom, tmp); } - bitslice_setall(x, result_index); - - for (i = 0; i < share_count; i++) { - memcpy(tmp, x, sizeof(uint32_t[8])); - gf256_add(tmp, xs[i]); - gf256_mul(num, num, tmp); - } - - /* Use Lagrange basis polynomials to calculate the secret coefficient */ - for (i = 0; i < share_count; i++) { - memcpy(denom, x, sizeof(denom)); - gf256_add(denom, xs[i]); - for (j = 0; j < share_count; j++) { - if (i == j) continue; - memcpy(tmp, xs[i], sizeof(uint32_t[8])); - gf256_add(tmp, xs[j]); - gf256_mul(denom, denom, tmp); - } - gf256_inv(tmp, denom); /* inverted denominator */ - gf256_mul(tmp, tmp, num); /* basis polynomial */ - gf256_mul(tmp, tmp, ys[i]); /* scaled coefficient */ - gf256_add(secret, tmp); - } - unbitslice(result, secret, len); + gf256_inv(tmp, denom); /* inverted denominator */ + gf256_mul(tmp, tmp, num); /* basis polynomial */ + gf256_mul(tmp, tmp, ys[i]); /* scaled coefficient */ + gf256_add(secret, tmp); + } + unbitslice(result, secret, len); } - diff --git a/embed/extmod/modtrezorcrypto/shamir.h b/embed/extmod/modtrezorcrypto/shamir.h index 136172f852..16a37dc360 100644 --- a/embed/extmod/modtrezorcrypto/shamir.h +++ b/embed/extmod/modtrezorcrypto/shamir.h @@ -26,7 +26,6 @@ * intermediate level API. You have been warned! */ - #ifndef __SHAMIR_H__ #define __SHAMIR_H__ @@ -36,12 +35,19 @@ #define SHAMIR_MAX_LEN 32 /* -A list of pairs (x_i, y_i), where x_i is an integer and y_i is an array of bytes representing the evaluations of the polynomials in x_i. -The x coordinate of the result. -Evaluations of the polynomials in x. - * Interpolate the `m` shares provided in `shares` and write the evaluation at - * point `x` to `result`. The number of shares used to compute the result may - * be larger than the threshold needed to . + * Computes f(x) given the Shamir shares (x_1, f(x_1)), ... , (x_m, f(x_m)). + * result: Array of length len where the evaluations of the polynomials in x + * will be written. + * result_index: The x coordinate of the result. + * share_indices: Points to an array of integers x_1, ... , x_m. + * share_values: Points to an array of y_1, ... , y_m, where each y_i is an + * array of bytes of length len representing the evaluations of the + * polynomials in x_i. + * share_count: The number of shares m. + * len: The length of the result array and each of the y_1, ... , y_m arrays. + + * The number of shares used to compute the result may be larger than the + * required threshold. * * This function does *not* do *any* checking for integrity. If any of the * shares are not original, this will result in an invalid restored value. @@ -49,14 +55,12 @@ Evaluations of the polynomials in x. * the shares that were provided as input were incorrect, the result *still* * allows an attacker to gain information about the correct result. * - * This function treats `shares` and `result` as secret values. `m` is treated as - * a public value (for performance reasons). + * This function treats `shares_values`, `share_indices` and `result` as secret + * values. `share_count` is treated as a public value (for performance reasons). */ -void shamir_interpolate(uint8_t *result, - uint8_t result_index, +void shamir_interpolate(uint8_t *result, uint8_t result_index, const uint8_t *share_indices, - const uint8_t **share_values, - uint8_t share_count, + const uint8_t **share_values, uint8_t share_count, size_t len); #endif /* __SHAMIR_H__ */