Use public multi-scalar mults in Trust Tokens where applicable.
The input points are all public, so we can use a faster multi-scalar multiplication. This generalizes ec_point_mul_scalar_public to ec_point_mul_scalar_public_batch. To support the batched DLEQ construction, this function takes an arbirarily-length array of points and allocates some temporaries if necessary. First, to confirm that this doesn't affect the basic ECDSA verify case: Before: Did 6324 ECDSA P-384 verify operations in 3069342us (2060.4 ops/sec) After: Did 6324 ECDSA P-384 verify operations in 3063355us (2064.4 ops/sec) [+0.2%] Results for Trust Tokens issue (Exp1) and finish_issuance (both): Before: Did 147 TrustToken-Exp0-Batch1 finish_issuance operations in 2059145us (71.4 ops/sec) Did 14 TrustToken-Exp0-Batch10 finish_issuance operations in 2085888us (6.7 ops/sec) Did 357 TrustToken-Exp1-Batch1 issue operations in 2068238us (172.6 ops/sec) Did 286 TrustToken-Exp1-Batch1 finish_issuance operations in 2090932us (136.8 ops/sec) Did 63 TrustToken-Exp1-Batch10 issue operations in 2068201us (30.5 ops/sec) Did 56 TrustToken-Exp1-Batch10 finish_issuance operations in 2064796us (27.1 ops/sec) After: Did 168 TrustToken-Exp0-Batch1 finish_issuance operations in 2058891us (81.6 ops/sec) [+14.3%] Did 16 TrustToken-Exp0-Batch10 finish_issuance operations in 2075742us (7.7 ops/sec) [+14.8%] Did 378 TrustToken-Exp1-Batch1 issue operations in 2067956us (182.8 ops/sec) [+5.9%] Did 336 TrustToken-Exp1-Batch1 finish_issuance operations in 2097757us (160.2 ops/sec) [+17.1%] Did 105 TrustToken-Exp1-Batch10 issue operations in 2069934us (50.7 ops/sec) [+66.5%] Did 88 TrustToken-Exp1-Batch10 finish_issuance operations in 2014621us (43.7 ops/sec) [+61.1%] (This CL doesn't affect other operations.) Change-Id: Ie643b06f44990ab52bf892a007732fde61cdffe5 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41285 Reviewed-by: Steven Valdez <svaldez@google.com> Commit-Queue: David Benjamin <davidben@google.com>
This commit is contained in:
committed by
CQ bot account: commit-bot@chromium.org
parent
b55a8c1580
commit
a810d82575
@@ -1006,10 +1006,27 @@ int ec_point_mul_scalar_public(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (group->meth->mul_public == NULL) {
|
||||
return group->meth->mul_public_batch(group, r, g_scalar, p, p_scalar, 1);
|
||||
}
|
||||
|
||||
group->meth->mul_public(group, r, g_scalar, p, p_scalar);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ec_point_mul_scalar_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num) {
|
||||
if (group->meth->mul_public_batch == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return group->meth->mul_public_batch(group, r, g_scalar, points, scalars,
|
||||
num);
|
||||
}
|
||||
|
||||
int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p, const EC_SCALAR *scalar) {
|
||||
if (p == NULL || scalar == NULL) {
|
||||
|
||||
@@ -508,7 +508,7 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_mont_method) {
|
||||
out->mul = ec_GFp_mont_mul;
|
||||
out->mul_base = ec_GFp_mont_mul_base;
|
||||
out->mul_batch = ec_GFp_mont_mul_batch;
|
||||
out->mul_public = ec_GFp_mont_mul_public;
|
||||
out->mul_public_batch = ec_GFp_mont_mul_public_batch;
|
||||
out->init_precomp = ec_GFp_mont_init_precomp;
|
||||
out->mul_precomp = ec_GFp_mont_mul_precomp;
|
||||
out->felem_mul = ec_GFp_mont_felem_mul;
|
||||
|
||||
@@ -389,6 +389,19 @@ OPENSSL_EXPORT int ec_point_mul_scalar_public(const EC_GROUP *group,
|
||||
const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar);
|
||||
|
||||
// ec_point_mul_scalar_public_batch sets |r| to the sum of generator *
|
||||
// |g_scalar| and |points[i]| * |scalars[i]| where |points| and |scalars| have
|
||||
// |num| elements. It assumes that the inputs are public so there is no concern
|
||||
// about leaking their values through timing. |g_scalar| may be NULL to skip
|
||||
// that term.
|
||||
//
|
||||
// This function is not implemented for all curves. Add implementations as
|
||||
// needed.
|
||||
int ec_point_mul_scalar_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num);
|
||||
|
||||
// ec_point_select, in constant time, sets |out| to |a| if |mask| is all ones
|
||||
// and |b| if |mask| is all zeros.
|
||||
void ec_point_select(const EC_GROUP *group, EC_RAW_POINT *out, BN_ULONG mask,
|
||||
@@ -483,9 +496,15 @@ struct ec_method_st {
|
||||
// mul_public sets |r| to |g_scalar|*generator + |p_scalar|*|p|. It assumes
|
||||
// that the inputs are public so there is no concern about leaking their
|
||||
// values through timing.
|
||||
//
|
||||
// This function may be omitted if |mul_public_batch| is provided.
|
||||
void (*mul_public)(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar);
|
||||
// mul_public_batch implements |ec_point_mul_scalar_public_batch|.
|
||||
int (*mul_public_batch)(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar, const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num);
|
||||
|
||||
// init_precomp implements |ec_init_precomp|.
|
||||
int (*init_precomp)(const EC_GROUP *group, EC_PRECOMP *out,
|
||||
@@ -632,9 +651,10 @@ void ec_GFp_mont_mul_precomp(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
void ec_compute_wNAF(const EC_GROUP *group, int8_t *out,
|
||||
const EC_SCALAR *scalar, size_t bits, int w);
|
||||
|
||||
void ec_GFp_mont_mul_public(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar);
|
||||
int ec_GFp_mont_mul_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num);
|
||||
|
||||
// method functions in simple.c
|
||||
int ec_GFp_simple_group_init(EC_GROUP *);
|
||||
|
||||
+60
-18
@@ -174,24 +174,57 @@ static void lookup_precomp(const EC_GROUP *group, EC_RAW_POINT *out,
|
||||
// EC_WNAF_TABLE_SIZE is the table size to use for |ec_GFp_mont_mul_public|.
|
||||
#define EC_WNAF_TABLE_SIZE (1 << (EC_WNAF_WINDOW_BITS - 1))
|
||||
|
||||
void ec_GFp_mont_mul_public(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar) {
|
||||
// EC_WNAF_STACK is the number of points worth of data to stack-allocate and
|
||||
// avoid a malloc.
|
||||
#define EC_WNAF_STACK 3
|
||||
|
||||
int ec_GFp_mont_mul_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num) {
|
||||
size_t bits = BN_num_bits(&group->order);
|
||||
size_t wNAF_len = bits + 1;
|
||||
|
||||
int ret = 0;
|
||||
int8_t wNAF_stack[EC_WNAF_STACK][EC_MAX_BYTES * 8 + 1];
|
||||
int8_t (*wNAF_alloc)[EC_MAX_BYTES * 8 + 1] = NULL;
|
||||
int8_t (*wNAF)[EC_MAX_BYTES * 8 + 1];
|
||||
EC_RAW_POINT precomp_stack[EC_WNAF_STACK][EC_WNAF_TABLE_SIZE];
|
||||
EC_RAW_POINT (*precomp_alloc)[EC_WNAF_TABLE_SIZE] = NULL;
|
||||
EC_RAW_POINT (*precomp)[EC_WNAF_TABLE_SIZE];
|
||||
if (num <= EC_WNAF_STACK) {
|
||||
wNAF = wNAF_stack;
|
||||
precomp = precomp_stack;
|
||||
} else {
|
||||
if (num >= ((size_t)-1) / sizeof(wNAF_alloc[0]) ||
|
||||
num >= ((size_t)-1) / sizeof(precomp_alloc[0])) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_OVERFLOW);
|
||||
goto err;
|
||||
}
|
||||
wNAF_alloc = OPENSSL_malloc(num * sizeof(wNAF_alloc[0]));
|
||||
precomp_alloc = OPENSSL_malloc(num * sizeof(precomp_alloc[0]));
|
||||
if (wNAF_alloc == NULL || precomp_alloc == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
wNAF = wNAF_alloc;
|
||||
precomp = precomp_alloc;
|
||||
}
|
||||
|
||||
int8_t g_wNAF[EC_MAX_BYTES * 8 + 1];
|
||||
EC_RAW_POINT g_precomp[EC_WNAF_TABLE_SIZE];
|
||||
assert(wNAF_len <= OPENSSL_ARRAY_SIZE(g_wNAF));
|
||||
const EC_RAW_POINT *g = &group->generator->raw;
|
||||
ec_compute_wNAF(group, g_wNAF, g_scalar, bits, EC_WNAF_WINDOW_BITS);
|
||||
compute_precomp(group, g_precomp, g, EC_WNAF_TABLE_SIZE);
|
||||
if (g_scalar != NULL) {
|
||||
ec_compute_wNAF(group, g_wNAF, g_scalar, bits, EC_WNAF_WINDOW_BITS);
|
||||
compute_precomp(group, g_precomp, g, EC_WNAF_TABLE_SIZE);
|
||||
}
|
||||
|
||||
int8_t p_wNAF[EC_MAX_BYTES * 8 + 1];
|
||||
EC_RAW_POINT p_precomp[EC_WNAF_TABLE_SIZE];
|
||||
assert(wNAF_len <= OPENSSL_ARRAY_SIZE(p_wNAF));
|
||||
ec_compute_wNAF(group, p_wNAF, p_scalar, bits, EC_WNAF_WINDOW_BITS);
|
||||
compute_precomp(group, p_precomp, p, EC_WNAF_TABLE_SIZE);
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
assert(wNAF_len <= OPENSSL_ARRAY_SIZE(wNAF[i]));
|
||||
ec_compute_wNAF(group, wNAF[i], &scalars[i], bits, EC_WNAF_WINDOW_BITS);
|
||||
compute_precomp(group, precomp[i], &points[i], EC_WNAF_TABLE_SIZE);
|
||||
}
|
||||
|
||||
EC_RAW_POINT tmp;
|
||||
int r_is_at_infinity = 1;
|
||||
@@ -200,7 +233,7 @@ void ec_GFp_mont_mul_public(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
ec_GFp_mont_dbl(group, r, r);
|
||||
}
|
||||
|
||||
if (g_wNAF[k] != 0) {
|
||||
if (g_scalar != NULL && g_wNAF[k] != 0) {
|
||||
lookup_precomp(group, &tmp, g_precomp, g_wNAF[k]);
|
||||
if (r_is_at_infinity) {
|
||||
ec_GFp_simple_point_copy(r, &tmp);
|
||||
@@ -210,13 +243,15 @@ void ec_GFp_mont_mul_public(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
}
|
||||
}
|
||||
|
||||
if (p_wNAF[k] != 0) {
|
||||
lookup_precomp(group, &tmp, p_precomp, p_wNAF[k]);
|
||||
if (r_is_at_infinity) {
|
||||
ec_GFp_simple_point_copy(r, &tmp);
|
||||
r_is_at_infinity = 0;
|
||||
} else {
|
||||
ec_GFp_mont_add(group, r, r, &tmp);
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
if (wNAF[i][k] != 0) {
|
||||
lookup_precomp(group, &tmp, precomp[i], wNAF[i][k]);
|
||||
if (r_is_at_infinity) {
|
||||
ec_GFp_simple_point_copy(r, &tmp);
|
||||
r_is_at_infinity = 0;
|
||||
} else {
|
||||
ec_GFp_mont_add(group, r, r, &tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,4 +259,11 @@ void ec_GFp_mont_mul_public(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
if (r_is_at_infinity) {
|
||||
ec_GFp_simple_point_set_to_infinity(group, r);
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(wNAF_alloc);
|
||||
OPENSSL_free(precomp_alloc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -128,6 +128,16 @@ static int cbs_get_prefixed_point(CBS *cbs, const EC_GROUP *group,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mul_public_3(const EC_GROUP *group, EC_RAW_POINT *out,
|
||||
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
|
||||
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
|
||||
const EC_RAW_POINT *p2, const EC_SCALAR *scalar2) {
|
||||
EC_RAW_POINT points[3] = {*p0, *p1, *p2};
|
||||
EC_SCALAR scalars[3] = {*scalar0, *scalar1, *scalar2};
|
||||
return ec_point_mul_scalar_public_batch(group, out, /*g_scalar=*/NULL, points,
|
||||
scalars, 3);
|
||||
}
|
||||
|
||||
void PMBTOKEN_PRETOKEN_free(PMBTOKEN_PRETOKEN *pretoken) {
|
||||
OPENSSL_free(pretoken);
|
||||
}
|
||||
@@ -594,7 +604,9 @@ static int dleq_verify(const PMBTOKEN_METHOD *method, CBS *cbs,
|
||||
|
||||
// We verify a DLEQ proof for the validity token and a DLEQOR2 proof for the
|
||||
// private metadata token. To allow amortizing Jacobian-to-affine conversions,
|
||||
// we compute Ki for both proofs first.
|
||||
// we compute Ki for both proofs first. Additionally, all inputs to this
|
||||
// function are public, so we can use the faster variable-time
|
||||
// multiplications.
|
||||
enum {
|
||||
idx_T,
|
||||
idx_S,
|
||||
@@ -620,17 +632,14 @@ static int dleq_verify(const PMBTOKEN_METHOD *method, CBS *cbs,
|
||||
}
|
||||
|
||||
// Ks = us*(G;T) + vs*(H;S) - cs*(pubs;Ws)
|
||||
//
|
||||
// TODO(davidben): The multiplications in this function are public and can be
|
||||
// switched to a public batch multiplication function if we add one.
|
||||
EC_RAW_POINT pubs;
|
||||
ec_affine_to_jacobian(group, &pubs, &pub->pubs);
|
||||
EC_SCALAR minus_cs;
|
||||
ec_scalar_neg(group, &minus_cs, &cs);
|
||||
if (!ec_point_mul_scalar_batch(group, &jacobians[idx_Ks0], g, &us, &method->h,
|
||||
&vs, &pubs, &minus_cs) ||
|
||||
!ec_point_mul_scalar_batch(group, &jacobians[idx_Ks1], T, &us, S, &vs, Ws,
|
||||
&minus_cs)) {
|
||||
if (!mul_public_3(group, &jacobians[idx_Ks0], g, &us, &method->h, &vs, &pubs,
|
||||
&minus_cs) ||
|
||||
!mul_public_3(group, &jacobians[idx_Ks1], T, &us, S, &vs, Ws,
|
||||
&minus_cs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -653,15 +662,13 @@ static int dleq_verify(const PMBTOKEN_METHOD *method, CBS *cbs,
|
||||
ec_scalar_neg(group, &minus_c0, &c0);
|
||||
ec_scalar_neg(group, &minus_c1, &c1);
|
||||
if (// K0 = u0*(G;T) + v0*(H;S) - c0*(pub0;W)
|
||||
!ec_point_mul_scalar_batch(group, &jacobians[idx_K00], g, &u0, &method->h,
|
||||
&v0, &pub0, &minus_c0) ||
|
||||
!ec_point_mul_scalar_batch(group, &jacobians[idx_K01], T, &u0, S, &v0, W,
|
||||
&minus_c0) ||
|
||||
!mul_public_3(group, &jacobians[idx_K00], g, &u0, &method->h, &v0, &pub0,
|
||||
&minus_c0) ||
|
||||
!mul_public_3(group, &jacobians[idx_K01], T, &u0, S, &v0, W, &minus_c0) ||
|
||||
// K1 = u1*(G;T) + v1*(H;S) - c1*(pub1;W)
|
||||
!ec_point_mul_scalar_batch(group, &jacobians[idx_K10], g, &u1, &method->h,
|
||||
&v1, &pub1, &minus_c1) ||
|
||||
!ec_point_mul_scalar_batch(group, &jacobians[idx_K11], T, &u1, S, &v1, W,
|
||||
&minus_c1)) {
|
||||
!mul_public_3(group, &jacobians[idx_K10], g, &u1, &method->h, &v1, &pub1,
|
||||
&minus_c1) ||
|
||||
!mul_public_3(group, &jacobians[idx_K11], T, &u1, S, &v1, W, &minus_c1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -722,10 +729,12 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
|
||||
EC_RAW_POINT *Sps = NULL;
|
||||
EC_RAW_POINT *Wps = NULL;
|
||||
EC_RAW_POINT *Wsps = NULL;
|
||||
EC_SCALAR *es = NULL;
|
||||
CBB batch_cbb;
|
||||
CBB_zero(&batch_cbb);
|
||||
if (method->batched_proof) {
|
||||
if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT)) {
|
||||
if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
|
||||
num_to_issue > ((size_t)-1) / sizeof(EC_SCALAR)) {
|
||||
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
|
||||
goto err;
|
||||
}
|
||||
@@ -733,10 +742,12 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
|
||||
Sps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
|
||||
Wps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
|
||||
Wsps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
|
||||
es = OPENSSL_malloc(num_to_issue * sizeof(EC_SCALAR));
|
||||
if (!Tps ||
|
||||
!Sps ||
|
||||
!Wps ||
|
||||
!Wsps ||
|
||||
!es ||
|
||||
!CBB_init(&batch_cbb, 0) ||
|
||||
!point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
|
||||
!point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
|
||||
@@ -808,35 +819,29 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
|
||||
}
|
||||
|
||||
// The DLEQ batching construction is described in appendix B of
|
||||
// https://eprint.iacr.org/2020/072/20200324:214215.
|
||||
// https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
|
||||
// computations all act on public inputs.
|
||||
if (method->batched_proof) {
|
||||
EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
|
||||
for (size_t i = 0; i < num_to_issue; i++) {
|
||||
EC_SCALAR e;
|
||||
if (!hash_c_batch(method, &e, &batch_cbb, i)) {
|
||||
if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
EC_RAW_POINT Tp_e, Sp_e, Wp_e, Wsp_e;
|
||||
if (!ec_point_mul_scalar(group, &Tp_e, &Tps[i], &e) ||
|
||||
!ec_point_mul_scalar(group, &Sp_e, &Sps[i], &e) ||
|
||||
!ec_point_mul_scalar(group, &Wp_e, &Wps[i], &e) ||
|
||||
!ec_point_mul_scalar(group, &Wsp_e, &Wsps[i], &e)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// TODO: Switch this to a multi-scalar multiplication.
|
||||
if (i == 0) {
|
||||
Tp_batch = Tp_e;
|
||||
Sp_batch = Sp_e;
|
||||
Wp_batch = Wp_e;
|
||||
Wsp_batch = Wsp_e;
|
||||
} else {
|
||||
group->meth->add(group, &Tp_batch, &Tp_batch, &Tp_e);
|
||||
group->meth->add(group, &Sp_batch, &Sp_batch, &Sp_e);
|
||||
group->meth->add(group, &Wp_batch, &Wp_batch, &Wp_e);
|
||||
group->meth->add(group, &Wsp_batch, &Wsp_batch, &Wsp_e);
|
||||
}
|
||||
EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
|
||||
if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
|
||||
/*g_scalar=*/NULL, Tps, es,
|
||||
num_to_issue) ||
|
||||
!ec_point_mul_scalar_public_batch(group, &Sp_batch,
|
||||
/*g_scalar=*/NULL, Sps, es,
|
||||
num_to_issue) ||
|
||||
!ec_point_mul_scalar_public_batch(group, &Wp_batch,
|
||||
/*g_scalar=*/NULL, Wps, es,
|
||||
num_to_issue) ||
|
||||
!ec_point_mul_scalar_public_batch(group, &Wsp_batch,
|
||||
/*g_scalar=*/NULL, Wsps, es,
|
||||
num_to_issue)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBB proof;
|
||||
@@ -862,6 +867,7 @@ err:
|
||||
OPENSSL_free(Sps);
|
||||
OPENSSL_free(Wps);
|
||||
OPENSSL_free(Wsps);
|
||||
OPENSSL_free(es);
|
||||
CBB_cleanup(&batch_cbb);
|
||||
return ret;
|
||||
}
|
||||
@@ -888,10 +894,12 @@ static STACK_OF(TRUST_TOKEN) *
|
||||
EC_RAW_POINT *Sps = NULL;
|
||||
EC_RAW_POINT *Wps = NULL;
|
||||
EC_RAW_POINT *Wsps = NULL;
|
||||
EC_SCALAR *es = NULL;
|
||||
CBB batch_cbb;
|
||||
CBB_zero(&batch_cbb);
|
||||
if (method->batched_proof) {
|
||||
if (count > ((size_t)-1) / sizeof(EC_RAW_POINT)) {
|
||||
if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
|
||||
count > ((size_t)-1) / sizeof(EC_SCALAR)) {
|
||||
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
|
||||
goto err;
|
||||
}
|
||||
@@ -899,10 +907,12 @@ static STACK_OF(TRUST_TOKEN) *
|
||||
Sps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
|
||||
Wps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
|
||||
Wsps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
|
||||
es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
|
||||
if (!Tps ||
|
||||
!Sps ||
|
||||
!Wps ||
|
||||
!Wsps ||
|
||||
!es ||
|
||||
!CBB_init(&batch_cbb, 0) ||
|
||||
!point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
|
||||
!point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
|
||||
@@ -1006,35 +1016,25 @@ static STACK_OF(TRUST_TOKEN) *
|
||||
}
|
||||
|
||||
// The DLEQ batching construction is described in appendix B of
|
||||
// https://eprint.iacr.org/2020/072/20200324:214215.
|
||||
// https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
|
||||
// computations all act on public inputs.
|
||||
if (method->batched_proof) {
|
||||
EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
EC_SCALAR e;
|
||||
if (!hash_c_batch(method, &e, &batch_cbb, i)) {
|
||||
if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
EC_RAW_POINT Tp_e, Sp_e, Wp_e, Wsp_e;
|
||||
if (!ec_point_mul_scalar(group, &Tp_e, &Tps[i], &e) ||
|
||||
!ec_point_mul_scalar(group, &Sp_e, &Sps[i], &e) ||
|
||||
!ec_point_mul_scalar(group, &Wp_e, &Wps[i], &e) ||
|
||||
!ec_point_mul_scalar(group, &Wsp_e, &Wsps[i], &e)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// TODO: Switch this to a multi-scalar multiplication.
|
||||
if (i == 0) {
|
||||
Tp_batch = Tp_e;
|
||||
Sp_batch = Sp_e;
|
||||
Wp_batch = Wp_e;
|
||||
Wsp_batch = Wsp_e;
|
||||
} else {
|
||||
group->meth->add(group, &Tp_batch, &Tp_batch, &Tp_e);
|
||||
group->meth->add(group, &Sp_batch, &Sp_batch, &Sp_e);
|
||||
group->meth->add(group, &Wp_batch, &Wp_batch, &Wp_e);
|
||||
group->meth->add(group, &Wsp_batch, &Wsp_batch, &Wsp_e);
|
||||
}
|
||||
EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
|
||||
if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
|
||||
/*g_scalar=*/NULL, Tps, es, count) ||
|
||||
!ec_point_mul_scalar_public_batch(group, &Sp_batch,
|
||||
/*g_scalar=*/NULL, Sps, es, count) ||
|
||||
!ec_point_mul_scalar_public_batch(group, &Wp_batch,
|
||||
/*g_scalar=*/NULL, Wps, es, count) ||
|
||||
!ec_point_mul_scalar_public_batch(group, &Wsp_batch,
|
||||
/*g_scalar=*/NULL, Wsps, es, count)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBS proof;
|
||||
@@ -1053,6 +1053,7 @@ err:
|
||||
OPENSSL_free(Sps);
|
||||
OPENSSL_free(Wps);
|
||||
OPENSSL_free(Wsps);
|
||||
OPENSSL_free(es);
|
||||
CBB_cleanup(&batch_cbb);
|
||||
if (!ok) {
|
||||
sk_TRUST_TOKEN_pop_free(ret, TRUST_TOKEN_free);
|
||||
|
||||
Reference in New Issue
Block a user