mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 22:38:08 +00:00
slip39: cstyle and documentation.
This commit is contained in:
parent
cd08c6937b
commit
f06416eeff
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "py/objstr.h"
|
|
||||||
|
|
||||||
#include "embed/extmod/trezorobj.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)).
|
/// Returns f(x) given the Shamir shares (x_1, f(x_1)), ... , (x_k, f(x_k)).
|
||||||
/// :param shares: The Shamir shares.
|
/// :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
|
/// :type shares: A list of pairs (x_i, y_i), where x_i is an integer and
|
||||||
/// bytes representing the evaluations of the polynomials in x_i.
|
/// 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.
|
/// :param int x: The x coordinate of the result.
|
||||||
/// :return: Evaluations of the polynomials in x.
|
/// :return: Evaluations of the polynomials in x.
|
||||||
/// :rtype: Array of bytes.
|
/// :rtype: Array of bytes.
|
||||||
@ -39,10 +39,7 @@
|
|||||||
mp_obj_t mod_trezorcrypto_shamir_interpolate(mp_obj_t shares, mp_obj_t x) {
|
mp_obj_t mod_trezorcrypto_shamir_interpolate(mp_obj_t shares, mp_obj_t x) {
|
||||||
size_t share_count;
|
size_t share_count;
|
||||||
mp_obj_t *share_items;
|
mp_obj_t *share_items;
|
||||||
if (!MP_OBJ_IS_TYPE(shares, &mp_type_list)) {
|
mp_obj_get_array(shares, &share_count, &share_items);
|
||||||
mp_raise_TypeError("Expected a list.");
|
|
||||||
}
|
|
||||||
mp_obj_list_get(shares, &share_count, &share_items);
|
|
||||||
if (share_count < 1 || share_count > MAX_SHARE_COUNT) {
|
if (share_count < 1 || share_count > MAX_SHARE_COUNT) {
|
||||||
mp_raise_ValueError("Invalid number of shares.");
|
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];
|
const uint8_t *share_values[MAX_SHARE_COUNT];
|
||||||
size_t value_len = 0;
|
size_t value_len = 0;
|
||||||
for (int i = 0; i < share_count; ++i) {
|
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_t *share;
|
||||||
mp_obj_tuple_get(share_items[i], &tuple_len, &share);
|
mp_obj_get_array_fixed_n(share_items[i], 2, &share);
|
||||||
if (tuple_len != 2) {
|
|
||||||
mp_raise_ValueError("Expected a tuple of length 2.");
|
|
||||||
}
|
|
||||||
share_indices[i] = trezor_obj_get_uint8(share[0]);
|
share_indices[i] = trezor_obj_get_uint8(share[0]);
|
||||||
mp_buffer_info_t value;
|
mp_buffer_info_t value;
|
||||||
mp_get_buffer_raise(share[1], &value, MP_BUFFER_READ);
|
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_t vstr;
|
||||||
vstr_init_len(&vstr, value_len);
|
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);
|
vstr_cut_tail_bytes(&vstr, vstr_len(&vstr) - value_len);
|
||||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
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[] = {
|
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___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,
|
STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_shamir_globals,
|
||||||
mod_trezorcrypto_shamir_globals_table);
|
mod_trezorcrypto_shamir_globals_table);
|
||||||
|
@ -35,292 +35,265 @@
|
|||||||
* lookup operations, as all proper crypto code must be.
|
* lookup operations, as all proper crypto code must be.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "shamir.h"
|
#include "shamir.h"
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static void
|
static void bitslice(uint32_t r[8], const uint8_t *x, size_t len) {
|
||||||
bitslice(uint32_t r[8], const uint8_t *x, size_t len)
|
size_t bit_idx, arr_idx;
|
||||||
{
|
uint32_t cur;
|
||||||
size_t bit_idx, arr_idx;
|
|
||||||
uint32_t cur;
|
|
||||||
|
|
||||||
memset(r, 0, sizeof(uint32_t[8]));
|
memset(r, 0, sizeof(uint32_t[8]));
|
||||||
for (arr_idx = 0; arr_idx < len; arr_idx++) {
|
for (arr_idx = 0; arr_idx < len; arr_idx++) {
|
||||||
cur = (uint32_t) x[arr_idx];
|
cur = (uint32_t)x[arr_idx];
|
||||||
for (bit_idx = 0; bit_idx < 8; bit_idx++) {
|
for (bit_idx = 0; bit_idx < 8; bit_idx++) {
|
||||||
r[bit_idx] |= ((cur & (1 << bit_idx)) >> bit_idx) << arr_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
|
memset(r, 0, sizeof(uint8_t) * len);
|
||||||
unbitslice(uint8_t *r, const uint32_t x[8], size_t len)
|
for (bit_idx = 0; bit_idx < 8; bit_idx++) {
|
||||||
{
|
cur = (uint32_t)x[bit_idx];
|
||||||
size_t bit_idx, arr_idx;
|
for (arr_idx = 0; arr_idx < len; arr_idx++) {
|
||||||
uint32_t cur;
|
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) {
|
||||||
static void
|
size_t idx;
|
||||||
bitslice_setall(uint32_t r[8], const uint8_t x)
|
for (idx = 0; idx < 8; idx++) {
|
||||||
{
|
r[idx] = ((int32_t)((x & (1 << idx)) << (31 - idx))) >> 31;
|
||||||
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`.
|
* Add (XOR) `r` with `x` and store the result in `r`.
|
||||||
*/
|
*/
|
||||||
static void
|
static void gf256_add(uint32_t r[8], const uint32_t x[8]) {
|
||||||
gf256_add(uint32_t r[8], const uint32_t x[8])
|
size_t idx;
|
||||||
{
|
for (idx = 0; idx < 8; idx++) r[idx] ^= x[idx];
|
||||||
size_t idx;
|
|
||||||
for (idx = 0; idx < 8; idx++) r[idx] ^= x[idx];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Safely multiply two bitsliced polynomials in GF(2^8) reduced by
|
* 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`
|
* 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
|
* and `b` will produce an incorrect result! If you need to square a polynomial
|
||||||
* use `gf256_square` instead.
|
* use `gf256_square` instead.
|
||||||
*/
|
*/
|
||||||
static void
|
static void gf256_mul(uint32_t r[8], const uint32_t a[8], const uint32_t b[8]) {
|
||||||
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.
|
||||||
/* 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
|
||||||
* I personally think that these kinds of long lists of operations
|
* take up a lot less lines of code.
|
||||||
* are often a bit ugly. A double for loop would be nicer and would
|
* However, some compilers seem to fail in optimizing these kinds of
|
||||||
* take up a lot less lines of code.
|
* loops. So we will just have to do this by hand.
|
||||||
* 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]));
|
||||||
uint32_t a2[8];
|
|
||||||
memcpy(a2, a, sizeof(uint32_t[8]));
|
|
||||||
|
|
||||||
r[0] = a2[0] & b[0]; /* add (assignment, because r is 0) */
|
r[0] = a2[0] & b[0]; /* add (assignment, because r is 0) */
|
||||||
r[1] = a2[1] & b[0];
|
r[1] = a2[1] & b[0];
|
||||||
r[2] = a2[2] & b[0];
|
r[2] = a2[2] & b[0];
|
||||||
r[3] = a2[3] & b[0];
|
r[3] = a2[3] & b[0];
|
||||||
r[4] = a2[4] & b[0];
|
r[4] = a2[4] & b[0];
|
||||||
r[5] = a2[5] & b[0];
|
r[5] = a2[5] & b[0];
|
||||||
r[6] = a2[6] & b[0];
|
r[6] = a2[6] & b[0];
|
||||||
r[7] = a2[7] & b[0];
|
r[7] = a2[7] & b[0];
|
||||||
a2[0] ^= a2[7]; /* reduce */
|
a2[0] ^= a2[7]; /* reduce */
|
||||||
a2[2] ^= a2[7];
|
a2[2] ^= a2[7];
|
||||||
a2[3] ^= a2[7];
|
a2[3] ^= a2[7];
|
||||||
|
|
||||||
r[0] ^= a2[7] & b[1]; /* add */
|
r[0] ^= a2[7] & b[1]; /* add */
|
||||||
r[1] ^= a2[0] & b[1];
|
r[1] ^= a2[0] & b[1];
|
||||||
r[2] ^= a2[1] & b[1];
|
r[2] ^= a2[1] & b[1];
|
||||||
r[3] ^= a2[2] & b[1];
|
r[3] ^= a2[2] & b[1];
|
||||||
r[4] ^= a2[3] & b[1];
|
r[4] ^= a2[3] & b[1];
|
||||||
r[5] ^= a2[4] & b[1];
|
r[5] ^= a2[4] & b[1];
|
||||||
r[6] ^= a2[5] & b[1];
|
r[6] ^= a2[5] & b[1];
|
||||||
r[7] ^= a2[6] & b[1];
|
r[7] ^= a2[6] & b[1];
|
||||||
a2[7] ^= a2[6]; /* reduce */
|
a2[7] ^= a2[6]; /* reduce */
|
||||||
a2[1] ^= a2[6];
|
a2[1] ^= a2[6];
|
||||||
a2[2] ^= a2[6];
|
a2[2] ^= a2[6];
|
||||||
|
|
||||||
r[0] ^= a2[6] & b[2]; /* add */
|
r[0] ^= a2[6] & b[2]; /* add */
|
||||||
r[1] ^= a2[7] & b[2];
|
r[1] ^= a2[7] & b[2];
|
||||||
r[2] ^= a2[0] & b[2];
|
r[2] ^= a2[0] & b[2];
|
||||||
r[3] ^= a2[1] & b[2];
|
r[3] ^= a2[1] & b[2];
|
||||||
r[4] ^= a2[2] & b[2];
|
r[4] ^= a2[2] & b[2];
|
||||||
r[5] ^= a2[3] & b[2];
|
r[5] ^= a2[3] & b[2];
|
||||||
r[6] ^= a2[4] & b[2];
|
r[6] ^= a2[4] & b[2];
|
||||||
r[7] ^= a2[5] & b[2];
|
r[7] ^= a2[5] & b[2];
|
||||||
a2[6] ^= a2[5]; /* reduce */
|
a2[6] ^= a2[5]; /* reduce */
|
||||||
a2[0] ^= a2[5];
|
a2[0] ^= a2[5];
|
||||||
a2[1] ^= a2[5];
|
a2[1] ^= a2[5];
|
||||||
|
|
||||||
r[0] ^= a2[5] & b[3]; /* add */
|
r[0] ^= a2[5] & b[3]; /* add */
|
||||||
r[1] ^= a2[6] & b[3];
|
r[1] ^= a2[6] & b[3];
|
||||||
r[2] ^= a2[7] & b[3];
|
r[2] ^= a2[7] & b[3];
|
||||||
r[3] ^= a2[0] & b[3];
|
r[3] ^= a2[0] & b[3];
|
||||||
r[4] ^= a2[1] & b[3];
|
r[4] ^= a2[1] & b[3];
|
||||||
r[5] ^= a2[2] & b[3];
|
r[5] ^= a2[2] & b[3];
|
||||||
r[6] ^= a2[3] & b[3];
|
r[6] ^= a2[3] & b[3];
|
||||||
r[7] ^= a2[4] & b[3];
|
r[7] ^= a2[4] & b[3];
|
||||||
a2[5] ^= a2[4]; /* reduce */
|
a2[5] ^= a2[4]; /* reduce */
|
||||||
a2[7] ^= a2[4];
|
a2[7] ^= a2[4];
|
||||||
a2[0] ^= a2[4];
|
a2[0] ^= a2[4];
|
||||||
|
|
||||||
r[0] ^= a2[4] & b[4]; /* add */
|
r[0] ^= a2[4] & b[4]; /* add */
|
||||||
r[1] ^= a2[5] & b[4];
|
r[1] ^= a2[5] & b[4];
|
||||||
r[2] ^= a2[6] & b[4];
|
r[2] ^= a2[6] & b[4];
|
||||||
r[3] ^= a2[7] & b[4];
|
r[3] ^= a2[7] & b[4];
|
||||||
r[4] ^= a2[0] & b[4];
|
r[4] ^= a2[0] & b[4];
|
||||||
r[5] ^= a2[1] & b[4];
|
r[5] ^= a2[1] & b[4];
|
||||||
r[6] ^= a2[2] & b[4];
|
r[6] ^= a2[2] & b[4];
|
||||||
r[7] ^= a2[3] & b[4];
|
r[7] ^= a2[3] & b[4];
|
||||||
a2[4] ^= a2[3]; /* reduce */
|
a2[4] ^= a2[3]; /* reduce */
|
||||||
a2[6] ^= a2[3];
|
a2[6] ^= a2[3];
|
||||||
a2[7] ^= a2[3];
|
a2[7] ^= a2[3];
|
||||||
|
|
||||||
r[0] ^= a2[3] & b[5]; /* add */
|
r[0] ^= a2[3] & b[5]; /* add */
|
||||||
r[1] ^= a2[4] & b[5];
|
r[1] ^= a2[4] & b[5];
|
||||||
r[2] ^= a2[5] & b[5];
|
r[2] ^= a2[5] & b[5];
|
||||||
r[3] ^= a2[6] & b[5];
|
r[3] ^= a2[6] & b[5];
|
||||||
r[4] ^= a2[7] & b[5];
|
r[4] ^= a2[7] & b[5];
|
||||||
r[5] ^= a2[0] & b[5];
|
r[5] ^= a2[0] & b[5];
|
||||||
r[6] ^= a2[1] & b[5];
|
r[6] ^= a2[1] & b[5];
|
||||||
r[7] ^= a2[2] & b[5];
|
r[7] ^= a2[2] & b[5];
|
||||||
a2[3] ^= a2[2]; /* reduce */
|
a2[3] ^= a2[2]; /* reduce */
|
||||||
a2[5] ^= a2[2];
|
a2[5] ^= a2[2];
|
||||||
a2[6] ^= a2[2];
|
a2[6] ^= a2[2];
|
||||||
|
|
||||||
r[0] ^= a2[2] & b[6]; /* add */
|
r[0] ^= a2[2] & b[6]; /* add */
|
||||||
r[1] ^= a2[3] & b[6];
|
r[1] ^= a2[3] & b[6];
|
||||||
r[2] ^= a2[4] & b[6];
|
r[2] ^= a2[4] & b[6];
|
||||||
r[3] ^= a2[5] & b[6];
|
r[3] ^= a2[5] & b[6];
|
||||||
r[4] ^= a2[6] & b[6];
|
r[4] ^= a2[6] & b[6];
|
||||||
r[5] ^= a2[7] & b[6];
|
r[5] ^= a2[7] & b[6];
|
||||||
r[6] ^= a2[0] & b[6];
|
r[6] ^= a2[0] & b[6];
|
||||||
r[7] ^= a2[1] & b[6];
|
r[7] ^= a2[1] & b[6];
|
||||||
a2[2] ^= a2[1]; /* reduce */
|
a2[2] ^= a2[1]; /* reduce */
|
||||||
a2[4] ^= a2[1];
|
a2[4] ^= a2[1];
|
||||||
a2[5] ^= a2[1];
|
a2[5] ^= a2[1];
|
||||||
|
|
||||||
r[0] ^= a2[1] & b[7]; /* add */
|
r[0] ^= a2[1] & b[7]; /* add */
|
||||||
r[1] ^= a2[2] & b[7];
|
r[1] ^= a2[2] & b[7];
|
||||||
r[2] ^= a2[3] & b[7];
|
r[2] ^= a2[3] & b[7];
|
||||||
r[3] ^= a2[4] & b[7];
|
r[3] ^= a2[4] & b[7];
|
||||||
r[4] ^= a2[5] & b[7];
|
r[4] ^= a2[5] & b[7];
|
||||||
r[5] ^= a2[6] & b[7];
|
r[5] ^= a2[6] & b[7];
|
||||||
r[6] ^= a2[7] & b[7];
|
r[6] ^= a2[7] & b[7];
|
||||||
r[7] ^= a2[0] & 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.
|
* Square `x` in GF(2^8) and write the result to `r`. `r` and `x` may overlap.
|
||||||
*/
|
*/
|
||||||
static void
|
static void gf256_square(uint32_t r[8], const uint32_t x[8]) {
|
||||||
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
|
||||||
uint32_t r8, r10, r12, r14;
|
* Assignments are done from 7 downto 0, because this allows the user
|
||||||
/* Use the Freshman's Dream rule to square the polynomial
|
* to execute this function in-place (e.g. `gf256_square(r, r);`).
|
||||||
* 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];
|
||||||
r14 = x[7];
|
r10 = x[5];
|
||||||
r12 = x[6];
|
r8 = x[4];
|
||||||
r10 = x[5];
|
r[6] = x[3];
|
||||||
r8 = x[4];
|
r[4] = x[2];
|
||||||
r[6] = x[3];
|
r[2] = x[1];
|
||||||
r[4] = x[2];
|
r[0] = x[0];
|
||||||
r[2] = x[1];
|
|
||||||
r[0] = x[0];
|
|
||||||
|
|
||||||
/* Reduce with x^8 + x^4 + x^3 + x + 1 until order is less than 8 */
|
/* Reduce with x^8 + x^4 + x^3 + x + 1 until order is less than 8 */
|
||||||
r[7] = r14; /* r[7] was 0 */
|
r[7] = r14; /* r[7] was 0 */
|
||||||
r[6] ^= r14;
|
r[6] ^= r14;
|
||||||
r10 ^= r14;
|
r10 ^= r14;
|
||||||
/* Skip, because r13 is always 0 */
|
/* Skip, because r13 is always 0 */
|
||||||
r[4] ^= r12;
|
r[4] ^= r12;
|
||||||
r[5] = r12; /* r[5] was 0 */
|
r[5] = r12; /* r[5] was 0 */
|
||||||
r[7] ^= r12;
|
r[7] ^= r12;
|
||||||
r8 ^= r12;
|
r8 ^= r12;
|
||||||
/* Skip, because r11 is always 0 */
|
/* Skip, because r11 is always 0 */
|
||||||
r[2] ^= r10;
|
r[2] ^= r10;
|
||||||
r[3] = r10; /* r[3] was 0 */
|
r[3] = r10; /* r[3] was 0 */
|
||||||
r[5] ^= r10;
|
r[5] ^= r10;
|
||||||
r[6] ^= r10;
|
r[6] ^= r10;
|
||||||
r[1] = r14; /* r[1] was 0 */
|
r[1] = r14; /* r[1] was 0 */
|
||||||
r[2] ^= r14; /* Substitute r9 by r14 because they will always be equal*/
|
r[2] ^= r14; /* Substitute r9 by r14 because they will always be equal*/
|
||||||
r[4] ^= r14;
|
r[4] ^= r14;
|
||||||
r[5] ^= r14;
|
r[5] ^= r14;
|
||||||
r[0] ^= r8;
|
r[0] ^= r8;
|
||||||
r[1] ^= r8;
|
r[1] ^= r8;
|
||||||
r[3] ^= r8;
|
r[3] ^= r8;
|
||||||
r[4] ^= r8;
|
r[4] ^= r8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invert `x` in GF(2^8) and write the result to `r`
|
* Invert `x` in GF(2^8) and write the result to `r`
|
||||||
*/
|
*/
|
||||||
static void
|
static void gf256_inv(uint32_t r[8], uint32_t x[8]) {
|
||||||
gf256_inv(uint32_t r[8], uint32_t x[8])
|
uint32_t y[8], z[8];
|
||||||
{
|
|
||||||
uint32_t y[8], z[8];
|
|
||||||
|
|
||||||
gf256_square(y, x); // y = x^2
|
gf256_square(y, x); // y = x^2
|
||||||
gf256_square(y, y); // y = x^4
|
gf256_square(y, y); // y = x^4
|
||||||
gf256_square(r, y); // r = x^8
|
gf256_square(r, y); // r = x^8
|
||||||
gf256_mul(z, r, x); // z = x^9
|
gf256_mul(z, r, x); // z = x^9
|
||||||
gf256_square(r, r); // r = x^16
|
gf256_square(r, r); // r = x^16
|
||||||
gf256_mul(r, r, z); // r = x^25
|
gf256_mul(r, r, z); // r = x^25
|
||||||
gf256_square(r, r); // r = x^50
|
gf256_square(r, r); // r = x^50
|
||||||
gf256_square(z, r); // z = x^100
|
gf256_square(z, r); // z = x^100
|
||||||
gf256_square(z, z); // z = x^200
|
gf256_square(z, z); // z = x^200
|
||||||
gf256_mul(r, r, z); // r = x^250
|
gf256_mul(r, r, z); // r = x^250
|
||||||
gf256_mul(r, r, y); // r = x^254
|
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_indices,
|
||||||
const uint8_t **share_values,
|
const uint8_t **share_values, uint8_t share_count,
|
||||||
uint8_t share_count,
|
size_t len) {
|
||||||
size_t len)
|
size_t i, j;
|
||||||
{
|
uint32_t xs[share_count][8], ys[share_count][8];
|
||||||
size_t i, j;
|
uint32_t x[8];
|
||||||
uint32_t xs[share_count][8], ys[share_count][8];
|
uint32_t denom[8], tmp[8];
|
||||||
uint32_t x[8];
|
uint32_t num[8] = {~0}; /* num is the numerator (=1) */
|
||||||
uint32_t denom[8], tmp[8];
|
uint32_t secret[8] = {0};
|
||||||
uint32_t num[8] = {~0}; /* num is the numerator (=1) */
|
|
||||||
uint32_t secret[8] = {0};
|
|
||||||
|
|
||||||
if (len > SHAMIR_MAX_LEN)
|
if (len > SHAMIR_MAX_LEN) return;
|
||||||
return;
|
|
||||||
|
|
||||||
/* Collect the x and y values */
|
/* Collect the x and y values */
|
||||||
for (i = 0; i < share_count; i++) {
|
for (i = 0; i < share_count; i++) {
|
||||||
bitslice_setall(xs[i], share_indices[i]);
|
bitslice_setall(xs[i], share_indices[i]);
|
||||||
bitslice(ys[i], share_values[i], len);
|
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);
|
gf256_inv(tmp, denom); /* inverted denominator */
|
||||||
|
gf256_mul(tmp, tmp, num); /* basis polynomial */
|
||||||
for (i = 0; i < share_count; i++) {
|
gf256_mul(tmp, tmp, ys[i]); /* scaled coefficient */
|
||||||
memcpy(tmp, x, sizeof(uint32_t[8]));
|
gf256_add(secret, tmp);
|
||||||
gf256_add(tmp, xs[i]);
|
}
|
||||||
gf256_mul(num, num, tmp);
|
unbitslice(result, secret, len);
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
* intermediate level API. You have been warned!
|
* intermediate level API. You have been warned!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __SHAMIR_H__
|
#ifndef __SHAMIR_H__
|
||||||
#define __SHAMIR_H__
|
#define __SHAMIR_H__
|
||||||
|
|
||||||
@ -36,12 +35,19 @@
|
|||||||
#define SHAMIR_MAX_LEN 32
|
#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.
|
* Computes f(x) given the Shamir shares (x_1, f(x_1)), ... , (x_m, f(x_m)).
|
||||||
The x coordinate of the result.
|
* result: Array of length len where the evaluations of the polynomials in x
|
||||||
Evaluations of the polynomials in x.
|
* will be written.
|
||||||
* Interpolate the `m` shares provided in `shares` and write the evaluation at
|
* result_index: The x coordinate of the result.
|
||||||
* point `x` to `result`. The number of shares used to compute the result may
|
* share_indices: Points to an array of integers x_1, ... , x_m.
|
||||||
* be larger than the threshold needed to .
|
* 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
|
* 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.
|
* 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*
|
* the shares that were provided as input were incorrect, the result *still*
|
||||||
* allows an attacker to gain information about the correct result.
|
* allows an attacker to gain information about the correct result.
|
||||||
*
|
*
|
||||||
* This function treats `shares` and `result` as secret values. `m` is treated as
|
* This function treats `shares_values`, `share_indices` and `result` as secret
|
||||||
* a public value (for performance reasons).
|
* values. `share_count` is treated as a public value (for performance reasons).
|
||||||
*/
|
*/
|
||||||
void shamir_interpolate(uint8_t *result,
|
void shamir_interpolate(uint8_t *result, uint8_t result_index,
|
||||||
uint8_t result_index,
|
|
||||||
const uint8_t *share_indices,
|
const uint8_t *share_indices,
|
||||||
const uint8_t **share_values,
|
const uint8_t **share_values, uint8_t share_count,
|
||||||
uint8_t share_count,
|
|
||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
#endif /* __SHAMIR_H__ */
|
#endif /* __SHAMIR_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user