1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-28 18:38:39 +00:00

crypto/shamir: Improve error handling.

This commit is contained in:
Andrew Kozlik 2019-04-18 14:35:18 +02:00
parent 1b3c0e0243
commit c073d68a2d
4 changed files with 90 additions and 25 deletions

View File

@ -23,7 +23,7 @@
#include "shamir.h" #include "shamir.h"
#define MAX_SHARE_COUNT 16 #define SHAMIR_MAX_SHARE_COUNT 16
/// def interpolate(shares, x) -> bytes: /// def interpolate(shares, x) -> bytes:
/// ''' /// '''
@ -40,12 +40,12 @@ 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;
mp_obj_get_array(shares, &share_count, &share_items); mp_obj_get_array(shares, &share_count, &share_items);
if (share_count < 1 || share_count > MAX_SHARE_COUNT) { if (share_count < 1 || share_count > SHAMIR_MAX_SHARE_COUNT) {
mp_raise_ValueError("Invalid number of shares."); mp_raise_ValueError("Invalid number of shares.");
} }
uint8_t x_uint8 = trezor_obj_get_uint8(x); uint8_t x_uint8 = trezor_obj_get_uint8(x);
uint8_t share_indices[MAX_SHARE_COUNT]; uint8_t share_indices[SHAMIR_MAX_SHARE_COUNT];
const uint8_t *share_values[MAX_SHARE_COUNT]; const uint8_t *share_values[SHAMIR_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) {
mp_obj_t *share; mp_obj_t *share;
@ -66,9 +66,11 @@ 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, if (shamir_interpolate((uint8_t *)vstr.buf, x_uint8, share_indices,
share_count, value_len); share_values, share_count, value_len) != true) {
vstr_cut_tail_bytes(&vstr, vstr_len(&vstr) - value_len); vstr_clear(&vstr);
mp_raise_ValueError("Share indices must be pairwise distinct.");
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_shamir_interpolate_obj, STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_shamir_interpolate_obj,

View File

@ -36,8 +36,8 @@
*/ */
#include "shamir.h" #include "shamir.h"
#include <stdio.h>
#include <string.h> #include <string.h>
#include "memzero.h"
static void bitslice(uint32_t r[8], const uint8_t *x, size_t len) { static void bitslice(uint32_t r[8], const uint8_t *x, size_t len) {
size_t bit_idx, arr_idx; size_t bit_idx, arr_idx;
@ -254,18 +254,29 @@ static void gf256_inv(uint32_t r[8], uint32_t x[8]) {
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, bool shamir_interpolate(uint8_t *result, uint8_t result_index,
const uint8_t *share_indices, 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) { size_t len) {
size_t i, j; size_t i, j;
uint32_t xs[share_count][8], ys[share_count][8];
uint32_t x[8]; uint32_t x[8];
uint32_t denom[8], tmp[8]; uint32_t xs[share_count][8];
uint32_t ys[share_count][8];
uint32_t num[8] = {~0}; /* num is the numerator (=1) */ uint32_t num[8] = {~0}; /* num is the numerator (=1) */
uint32_t denom[8];
uint32_t tmp[8];
uint32_t secret[8] = {0}; uint32_t secret[8] = {0};
bool ret = true;
if (len > SHAMIR_MAX_LEN) return; if (len > SHAMIR_MAX_LEN) return false;
/* The code below assumes that none of the share_indices are equal to
* result_index. We need to treat that as a special case. */
for (i = 0; i < share_count; i++)
if (share_indices[i] == result_index) {
memcpy(result, share_values[i], len);
return true;
}
/* 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++) {
@ -290,10 +301,28 @@ void shamir_interpolate(uint8_t *result, uint8_t result_index,
gf256_add(tmp, xs[j]); gf256_add(tmp, xs[j]);
gf256_mul(denom, denom, tmp); gf256_mul(denom, denom, tmp);
} }
if ((denom[0] | denom[1] | denom[2] | denom[3] | denom[4] | denom[5] |
denom[6] | denom[7]) == 0) {
/* The share_indices are not unique. */
ret = false;
break;
}
gf256_inv(tmp, denom); /* inverted denominator */ gf256_inv(tmp, denom); /* inverted denominator */
gf256_mul(tmp, tmp, num); /* basis polynomial */ gf256_mul(tmp, tmp, num); /* basis polynomial */
gf256_mul(tmp, tmp, ys[i]); /* scaled coefficient */ gf256_mul(tmp, tmp, ys[i]); /* scaled coefficient */
gf256_add(secret, tmp); gf256_add(secret, tmp);
} }
if (ret == true) {
unbitslice(result, secret, len); unbitslice(result, secret, len);
}
memzero(x, sizeof(x));
memzero(xs, sizeof(xs));
memzero(ys, sizeof(ys));
memzero(num, sizeof(num));
memzero(denom, sizeof(denom));
memzero(tmp, sizeof(tmp));
memzero(secret, sizeof(secret));
return ret;
} }

View File

@ -29,6 +29,7 @@
#ifndef __SHAMIR_H__ #ifndef __SHAMIR_H__
#define __SHAMIR_H__ #define __SHAMIR_H__
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
@ -36,16 +37,18 @@
/* /*
* Computes f(x) given the Shamir shares (x_1, f(x_1)), ... , (x_m, f(x_m)). * Computes f(x) given the Shamir shares (x_1, f(x_1)), ... , (x_m, f(x_m)).
* The x coordinates of the shares must be pairwise distinct. Returns true on
* success, otherwise false.
* result: Array of length len where the evaluations of the polynomials in x * result: Array of length len where the evaluations of the polynomials in x
* will be written. * will be written.
* result_index: The x coordinate of the result. * result_index: The x coordinate of the result.
* share_indices: Points to an array of integers x_1, ... , x_m. * share_indices: Points to the array of integers x_1, ... , x_m.
* share_values: Points to an array of y_1, ... , y_m, where each y_i is an * share_values: Points to the array of y_1, ... , y_m, where each y_i is an
* array of bytes of length len representing the evaluations of the * array of bytes of length len representing the evaluations of the
* polynomials in x_i. * polynomials in x_i.
* share_count: The number of shares m. * share_count: The number of shares m.
* len: The length of the result array and each of the y_1, ... , y_m arrays. * len: The length of the result array and of each of the y_1, ... , y_m arrays.
*
* The number of shares used to compute the result may be larger than the * The number of shares used to compute the result may be larger than the
* required threshold. * required threshold.
* *
@ -58,7 +61,7 @@
* This function treats `shares_values`, `share_indices` and `result` as secret * This function treats `shares_values`, `share_indices` and `result` as secret
* values. `share_count` is treated as a public value (for performance reasons). * values. `share_count` is treated as a public value (for performance reasons).
*/ */
void shamir_interpolate(uint8_t *result, uint8_t result_index, bool shamir_interpolate(uint8_t *result, uint8_t result_index,
const uint8_t *share_indices, 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); size_t len);

View File

@ -5067,6 +5067,7 @@ START_TEST(test_shamir) {
const uint8_t share_values[SHAMIR_MAX_COUNT][SHAMIR_MAX_LEN]; const uint8_t share_values[SHAMIR_MAX_COUNT][SHAMIR_MAX_LEN];
uint8_t share_count; uint8_t share_count;
size_t len; size_t len;
bool ret;
} vectors[] = {{{7, 151, 168, 57, 186, 104, 218, 21, 209, 96, 106, } vectors[] = {{{7, 151, 168, 57, 186, 104, 218, 21, 209, 96, 106,
152, 252, 35, 210, 208, 43, 47, 13, 21, 142, 122, 152, 252, 35, 210, 208, 43, 47, 13, 21, 142, 122,
24, 42, 149, 192, 95, 24, 240, 24, 148, 110}, 24, 42, 149, 192, 95, 24, 240, 24, 148, 110},
@ -5078,7 +5079,8 @@ START_TEST(test_shamir) {
24, 42, 149, 192, 95, 24, 240, 24, 148, 110}, 24, 42, 149, 192, 95, 24, 240, 24, 148, 110},
}, },
1, 1,
32}, 32,
true},
{{53}, {{53},
255, 255,
@ -5102,7 +5104,32 @@ START_TEST(test_shamir) {
{175}, {175},
}, },
16, 16,
1}, 1,
true},
{{91, 188, 226, 91, 254, 197, 225},
1,
{5, 1, 10},
{
{129, 18, 104, 86, 236, 73, 176},
{91, 188, 226, 91, 254, 197, 225},
{69, 53, 151, 204, 224, 37, 19},
},
3,
7,
true},
{{0},
255,
{3, 12, 3},
{
{100, 176, 99, 142, 115, 192, 138},
{54, 139, 99, 172, 29, 137, 58},
{216, 119, 222, 40, 87, 25, 147},
},
3,
7,
false},
{{163, 120, 30, 243, 179, 172, 196, 137, 119, 17}, {{163, 120, 30, 243, 179, 172, 196, 137, 119, 17},
3, 3,
@ -5111,7 +5138,8 @@ START_TEST(test_shamir) {
{121, 9, 79, 98, 132, 164, 9, 165, 19, 230}, {121, 9, 79, 98, 132, 164, 9, 165, 19, 230},
{86, 52, 173, 138, 189, 223, 122, 102, 248, 157}}, {86, 52, 173, 138, 189, 223, 122, 102, 248, 157}},
3, 3,
10}}; 10,
true}};
for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); ++i) { for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); ++i) {
uint8_t result[SHAMIR_MAX_LEN]; uint8_t result[SHAMIR_MAX_LEN];
@ -5119,11 +5147,14 @@ START_TEST(test_shamir) {
for (size_t j = 0; j < vectors[i].share_count; ++j) { for (size_t j = 0; j < vectors[i].share_count; ++j) {
share_values[j] = vectors[i].share_values[j]; share_values[j] = vectors[i].share_values[j];
} }
shamir_interpolate(result, vectors[i].result_index, ck_assert_int_eq(shamir_interpolate(result, vectors[i].result_index,
vectors[i].share_indices, share_values, vectors[i].share_indices, share_values,
vectors[i].share_count, vectors[i].len); vectors[i].share_count, vectors[i].len),
vectors[i].ret);
if (vectors[i].ret == true) {
ck_assert_mem_eq(result, vectors[i].result, vectors[i].len); ck_assert_mem_eq(result, vectors[i].result, vectors[i].len);
} }
}
} }
END_TEST END_TEST