1 /* Copyright (c) 2020, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/trust_token.h>
16
17 #include <openssl/bn.h>
18 #include <openssl/bytestring.h>
19 #include <openssl/ec.h>
20 #include <openssl/err.h>
21 #include <openssl/mem.h>
22 #include <openssl/nid.h>
23 #include <openssl/rand.h>
24 #include <openssl/sha.h>
25
26 #include "../ec_extra/internal.h"
27 #include "../fipsmodule/bn/internal.h"
28 #include "../fipsmodule/ec/internal.h"
29
30 #include "internal.h"
31
32
33 typedef int (*hash_t_func_t)(const EC_GROUP *group, EC_RAW_POINT *out,
34 const uint8_t t[PMBTOKEN_NONCE_SIZE]);
35 typedef int (*hash_s_func_t)(const EC_GROUP *group, EC_RAW_POINT *out,
36 const EC_AFFINE *t,
37 const uint8_t s[PMBTOKEN_NONCE_SIZE]);
38 typedef int (*hash_c_func_t)(const EC_GROUP *group, EC_SCALAR *out,
39 uint8_t *buf, size_t len);
40
41 typedef struct {
42 const EC_GROUP *group;
43 EC_PRECOMP g_precomp;
44 EC_PRECOMP h_precomp;
45 EC_RAW_POINT h;
46 // hash_t implements the H_t operation in PMBTokens. It returns one on success
47 // and zero on error.
48 hash_t_func_t hash_t;
49 // hash_s implements the H_s operation in PMBTokens. It returns one on success
50 // and zero on error.
51 hash_s_func_t hash_s;
52 // hash_c implements the H_c operation in PMBTokens. It returns one on success
53 // and zero on error.
54 hash_c_func_t hash_c;
55 // batched_proof determines whether PMBToken uses a batched DLEQOR proof when
56 // signing tokens.
57 int batched_proof : 1;
58 } PMBTOKEN_METHOD;
59
60 static const uint8_t kDefaultAdditionalData[32] = {0};
61
pmbtoken_init_method(PMBTOKEN_METHOD * method,int curve_nid,const uint8_t * h_bytes,size_t h_len,hash_t_func_t hash_t,hash_s_func_t hash_s,hash_c_func_t hash_c,int batched_proof)62 static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid,
63 const uint8_t *h_bytes, size_t h_len,
64 hash_t_func_t hash_t, hash_s_func_t hash_s,
65 hash_c_func_t hash_c, int batched_proof) {
66 method->group = EC_GROUP_new_by_curve_name(curve_nid);
67 if (method->group == NULL) {
68 return 0;
69 }
70
71 method->hash_t = hash_t;
72 method->hash_s = hash_s;
73 method->hash_c = hash_c;
74 method->batched_proof = batched_proof;
75
76 EC_AFFINE h;
77 if (!ec_point_from_uncompressed(method->group, &h, h_bytes, h_len)) {
78 return 0;
79 }
80 ec_affine_to_jacobian(method->group, &method->h, &h);
81
82 if (!ec_init_precomp(method->group, &method->g_precomp,
83 &method->group->generator->raw) ||
84 !ec_init_precomp(method->group, &method->h_precomp, &method->h)) {
85 return 0;
86 }
87 return 1;
88 }
89
90 // generate_keypair generates a keypair for the PMBTokens construction.
91 // |out_x| and |out_y| are set to the secret half of the keypair, while
92 // |*out_pub| is set to the public half of the keypair. It returns one on
93 // success and zero on failure.
generate_keypair(const PMBTOKEN_METHOD * method,EC_SCALAR * out_x,EC_SCALAR * out_y,EC_RAW_POINT * out_pub)94 static int generate_keypair(const PMBTOKEN_METHOD *method, EC_SCALAR *out_x,
95 EC_SCALAR *out_y, EC_RAW_POINT *out_pub) {
96 if (!ec_random_nonzero_scalar(method->group, out_x, kDefaultAdditionalData) ||
97 !ec_random_nonzero_scalar(method->group, out_y, kDefaultAdditionalData) ||
98 !ec_point_mul_scalar_precomp(method->group, out_pub, &method->g_precomp,
99 out_x, &method->h_precomp, out_y, NULL,
100 NULL)) {
101 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
102 return 0;
103 }
104 return 1;
105 }
106
point_to_cbb(CBB * out,const EC_GROUP * group,const EC_AFFINE * point)107 static int point_to_cbb(CBB *out, const EC_GROUP *group,
108 const EC_AFFINE *point) {
109 size_t len =
110 ec_point_to_bytes(group, point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0);
111 if (len == 0) {
112 return 0;
113 }
114 uint8_t *p;
115 return CBB_add_space(out, &p, len) &&
116 ec_point_to_bytes(group, point, POINT_CONVERSION_UNCOMPRESSED, p,
117 len) == len;
118 }
119
cbs_get_prefixed_point(CBS * cbs,const EC_GROUP * group,EC_AFFINE * out)120 static int cbs_get_prefixed_point(CBS *cbs, const EC_GROUP *group,
121 EC_AFFINE *out) {
122 CBS child;
123 if (!CBS_get_u16_length_prefixed(cbs, &child) ||
124 !ec_point_from_uncompressed(group, out, CBS_data(&child),
125 CBS_len(&child))) {
126 return 0;
127 }
128 return 1;
129 }
130
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)131 static int mul_public_3(const EC_GROUP *group, EC_RAW_POINT *out,
132 const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
133 const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
134 const EC_RAW_POINT *p2, const EC_SCALAR *scalar2) {
135 EC_RAW_POINT points[3] = {*p0, *p1, *p2};
136 EC_SCALAR scalars[3] = {*scalar0, *scalar1, *scalar2};
137 return ec_point_mul_scalar_public_batch(group, out, /*g_scalar=*/NULL, points,
138 scalars, 3);
139 }
140
PMBTOKEN_PRETOKEN_free(PMBTOKEN_PRETOKEN * pretoken)141 void PMBTOKEN_PRETOKEN_free(PMBTOKEN_PRETOKEN *pretoken) {
142 OPENSSL_free(pretoken);
143 }
144
pmbtoken_generate_key(const PMBTOKEN_METHOD * method,CBB * out_private,CBB * out_public)145 static int pmbtoken_generate_key(const PMBTOKEN_METHOD *method,
146 CBB *out_private, CBB *out_public) {
147 const EC_GROUP *group = method->group;
148 EC_RAW_POINT pub[3];
149 EC_SCALAR x0, y0, x1, y1, xs, ys;
150 if (!generate_keypair(method, &x0, &y0, &pub[0]) ||
151 !generate_keypair(method, &x1, &y1, &pub[1]) ||
152 !generate_keypair(method, &xs, &ys, &pub[2])) {
153 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE);
154 return 0;
155 }
156
157 const EC_SCALAR *scalars[] = {&x0, &y0, &x1, &y1, &xs, &ys};
158 size_t scalar_len = BN_num_bytes(&group->order);
159 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) {
160 uint8_t *buf;
161 if (!CBB_add_space(out_private, &buf, scalar_len)) {
162 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL);
163 return 0;
164 }
165 ec_scalar_to_bytes(group, buf, &scalar_len, scalars[i]);
166 }
167
168 EC_AFFINE pub_affine[3];
169 if (!ec_jacobian_to_affine_batch(group, pub_affine, pub, 3)) {
170 return 0;
171 }
172
173 // TODO(https://crbug.com/boringssl/331): When updating the key format, remove
174 // the redundant length prefixes.
175 CBB child;
176 if (!CBB_add_u16_length_prefixed(out_public, &child) ||
177 !point_to_cbb(&child, group, &pub_affine[0]) ||
178 !CBB_add_u16_length_prefixed(out_public, &child) ||
179 !point_to_cbb(&child, group, &pub_affine[1]) ||
180 !CBB_add_u16_length_prefixed(out_public, &child) ||
181 !point_to_cbb(&child, group, &pub_affine[2]) ||
182 !CBB_flush(out_public)) {
183 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL);
184 return 0;
185 }
186
187 return 1;
188 }
189
pmbtoken_client_key_from_bytes(const PMBTOKEN_METHOD * method,PMBTOKEN_CLIENT_KEY * key,const uint8_t * in,size_t len)190 static int pmbtoken_client_key_from_bytes(const PMBTOKEN_METHOD *method,
191 PMBTOKEN_CLIENT_KEY *key,
192 const uint8_t *in, size_t len) {
193 // TODO(https://crbug.com/boringssl/331): When updating the key format, remove
194 // the redundant length prefixes.
195 CBS cbs;
196 CBS_init(&cbs, in, len);
197 if (!cbs_get_prefixed_point(&cbs, method->group, &key->pub0) ||
198 !cbs_get_prefixed_point(&cbs, method->group, &key->pub1) ||
199 !cbs_get_prefixed_point(&cbs, method->group, &key->pubs) ||
200 CBS_len(&cbs) != 0) {
201 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
202 return 0;
203 }
204
205 return 1;
206 }
207
pmbtoken_issuer_key_from_bytes(const PMBTOKEN_METHOD * method,PMBTOKEN_ISSUER_KEY * key,const uint8_t * in,size_t len)208 static int pmbtoken_issuer_key_from_bytes(const PMBTOKEN_METHOD *method,
209 PMBTOKEN_ISSUER_KEY *key,
210 const uint8_t *in, size_t len) {
211 const EC_GROUP *group = method->group;
212 CBS cbs, tmp;
213 CBS_init(&cbs, in, len);
214 size_t scalar_len = BN_num_bytes(&group->order);
215 EC_SCALAR *scalars[] = {&key->x0, &key->y0, &key->x1,
216 &key->y1, &key->xs, &key->ys};
217 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) {
218 if (!CBS_get_bytes(&cbs, &tmp, scalar_len) ||
219 !ec_scalar_from_bytes(group, scalars[i], CBS_data(&tmp),
220 CBS_len(&tmp))) {
221 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
222 return 0;
223 }
224 }
225
226 // Recompute the public key.
227 EC_RAW_POINT pub[3];
228 EC_AFFINE pub_affine[3];
229 if (!ec_point_mul_scalar_precomp(group, &pub[0], &method->g_precomp, &key->x0,
230 &method->h_precomp, &key->y0, NULL, NULL) ||
231 !ec_init_precomp(group, &key->pub0_precomp, &pub[0]) ||
232 !ec_point_mul_scalar_precomp(group, &pub[1], &method->g_precomp, &key->x1,
233 &method->h_precomp, &key->y1, NULL, NULL) ||
234 !ec_init_precomp(group, &key->pub1_precomp, &pub[1]) ||
235 !ec_point_mul_scalar_precomp(group, &pub[2], &method->g_precomp, &key->xs,
236 &method->h_precomp, &key->ys, NULL, NULL) ||
237 !ec_init_precomp(group, &key->pubs_precomp, &pub[2]) ||
238 !ec_jacobian_to_affine_batch(group, pub_affine, pub, 3)) {
239 return 0;
240 }
241
242 key->pub0 = pub_affine[0];
243 key->pub1 = pub_affine[1];
244 key->pubs = pub_affine[2];
245 return 1;
246 }
247
STACK_OF(PMBTOKEN_PRETOKEN)248 static STACK_OF(PMBTOKEN_PRETOKEN) *
249 pmbtoken_blind(const PMBTOKEN_METHOD *method, CBB *cbb, size_t count) {
250 const EC_GROUP *group = method->group;
251 STACK_OF(PMBTOKEN_PRETOKEN) *pretokens = sk_PMBTOKEN_PRETOKEN_new_null();
252 if (pretokens == NULL) {
253 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
254 goto err;
255 }
256
257 for (size_t i = 0; i < count; i++) {
258 // Insert |pretoken| into |pretokens| early to simplify error-handling.
259 PMBTOKEN_PRETOKEN *pretoken = OPENSSL_malloc(sizeof(PMBTOKEN_PRETOKEN));
260 if (pretoken == NULL ||
261 !sk_PMBTOKEN_PRETOKEN_push(pretokens, pretoken)) {
262 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
263 PMBTOKEN_PRETOKEN_free(pretoken);
264 goto err;
265 }
266
267 RAND_bytes(pretoken->t, sizeof(pretoken->t));
268
269 // We sample |pretoken->r| in Montgomery form to simplify inverting.
270 if (!ec_random_nonzero_scalar(group, &pretoken->r,
271 kDefaultAdditionalData)) {
272 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
273 goto err;
274 }
275
276 EC_SCALAR rinv;
277 ec_scalar_inv0_montgomery(group, &rinv, &pretoken->r);
278 // Convert both out of Montgomery form.
279 ec_scalar_from_montgomery(group, &pretoken->r, &pretoken->r);
280 ec_scalar_from_montgomery(group, &rinv, &rinv);
281
282 EC_RAW_POINT T, Tp;
283 if (!method->hash_t(group, &T, pretoken->t) ||
284 !ec_point_mul_scalar(group, &Tp, &T, &rinv) ||
285 !ec_jacobian_to_affine(group, &pretoken->Tp, &Tp)) {
286 goto err;
287 }
288
289 // TODO(https://crbug.com/boringssl/331): When updating the key format,
290 // remove the redundant length prefixes.
291 CBB child;
292 if (!CBB_add_u16_length_prefixed(cbb, &child) ||
293 !point_to_cbb(&child, group, &pretoken->Tp) ||
294 !CBB_flush(cbb)) {
295 goto err;
296 }
297 }
298
299 return pretokens;
300
301 err:
302 sk_PMBTOKEN_PRETOKEN_pop_free(pretokens, PMBTOKEN_PRETOKEN_free);
303 return NULL;
304 }
305
scalar_to_cbb(CBB * out,const EC_GROUP * group,const EC_SCALAR * scalar)306 static int scalar_to_cbb(CBB *out, const EC_GROUP *group,
307 const EC_SCALAR *scalar) {
308 uint8_t *buf;
309 size_t scalar_len = BN_num_bytes(&group->order);
310 if (!CBB_add_space(out, &buf, scalar_len)) {
311 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
312 return 0;
313 }
314 ec_scalar_to_bytes(group, buf, &scalar_len, scalar);
315 return 1;
316 }
317
scalar_from_cbs(CBS * cbs,const EC_GROUP * group,EC_SCALAR * out)318 static int scalar_from_cbs(CBS *cbs, const EC_GROUP *group, EC_SCALAR *out) {
319 size_t scalar_len = BN_num_bytes(&group->order);
320 CBS tmp;
321 if (!CBS_get_bytes(cbs, &tmp, scalar_len)) {
322 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
323 return 0;
324 }
325
326 ec_scalar_from_bytes(group, out, CBS_data(&tmp), CBS_len(&tmp));
327 return 1;
328 }
329
hash_c_dleq(const PMBTOKEN_METHOD * method,EC_SCALAR * out,const EC_AFFINE * X,const EC_AFFINE * T,const EC_AFFINE * S,const EC_AFFINE * W,const EC_AFFINE * K0,const EC_AFFINE * K1)330 static int hash_c_dleq(const PMBTOKEN_METHOD *method, EC_SCALAR *out,
331 const EC_AFFINE *X, const EC_AFFINE *T,
332 const EC_AFFINE *S, const EC_AFFINE *W,
333 const EC_AFFINE *K0, const EC_AFFINE *K1) {
334 static const uint8_t kDLEQ2Label[] = "DLEQ2";
335
336 int ok = 0;
337 CBB cbb;
338 CBB_zero(&cbb);
339 uint8_t *buf = NULL;
340 size_t len;
341 if (!CBB_init(&cbb, 0) ||
342 !CBB_add_bytes(&cbb, kDLEQ2Label, sizeof(kDLEQ2Label)) ||
343 !point_to_cbb(&cbb, method->group, X) ||
344 !point_to_cbb(&cbb, method->group, T) ||
345 !point_to_cbb(&cbb, method->group, S) ||
346 !point_to_cbb(&cbb, method->group, W) ||
347 !point_to_cbb(&cbb, method->group, K0) ||
348 !point_to_cbb(&cbb, method->group, K1) ||
349 !CBB_finish(&cbb, &buf, &len) ||
350 !method->hash_c(method->group, out, buf, len)) {
351 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
352 goto err;
353 }
354
355 ok = 1;
356
357 err:
358 CBB_cleanup(&cbb);
359 OPENSSL_free(buf);
360 return ok;
361 }
362
hash_c_dleqor(const PMBTOKEN_METHOD * method,EC_SCALAR * out,const EC_AFFINE * X0,const EC_AFFINE * X1,const EC_AFFINE * T,const EC_AFFINE * S,const EC_AFFINE * W,const EC_AFFINE * K00,const EC_AFFINE * K01,const EC_AFFINE * K10,const EC_AFFINE * K11)363 static int hash_c_dleqor(const PMBTOKEN_METHOD *method, EC_SCALAR *out,
364 const EC_AFFINE *X0, const EC_AFFINE *X1,
365 const EC_AFFINE *T, const EC_AFFINE *S,
366 const EC_AFFINE *W, const EC_AFFINE *K00,
367 const EC_AFFINE *K01, const EC_AFFINE *K10,
368 const EC_AFFINE *K11) {
369 static const uint8_t kDLEQOR2Label[] = "DLEQOR2";
370
371 int ok = 0;
372 CBB cbb;
373 CBB_zero(&cbb);
374 uint8_t *buf = NULL;
375 size_t len;
376 if (!CBB_init(&cbb, 0) ||
377 !CBB_add_bytes(&cbb, kDLEQOR2Label, sizeof(kDLEQOR2Label)) ||
378 !point_to_cbb(&cbb, method->group, X0) ||
379 !point_to_cbb(&cbb, method->group, X1) ||
380 !point_to_cbb(&cbb, method->group, T) ||
381 !point_to_cbb(&cbb, method->group, S) ||
382 !point_to_cbb(&cbb, method->group, W) ||
383 !point_to_cbb(&cbb, method->group, K00) ||
384 !point_to_cbb(&cbb, method->group, K01) ||
385 !point_to_cbb(&cbb, method->group, K10) ||
386 !point_to_cbb(&cbb, method->group, K11) ||
387 !CBB_finish(&cbb, &buf, &len) ||
388 !method->hash_c(method->group, out, buf, len)) {
389 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
390 goto err;
391 }
392
393 ok = 1;
394
395 err:
396 CBB_cleanup(&cbb);
397 OPENSSL_free(buf);
398 return ok;
399 }
400
hash_c_batch(const PMBTOKEN_METHOD * method,EC_SCALAR * out,const CBB * points,size_t index)401 static int hash_c_batch(const PMBTOKEN_METHOD *method, EC_SCALAR *out,
402 const CBB *points, size_t index) {
403 static const uint8_t kDLEQBatchLabel[] = "DLEQ BATCH";
404 if (index > 0xffff) {
405 // The protocol supports only two-byte batches.
406 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
407 return 0;
408 }
409
410 int ok = 0;
411 CBB cbb;
412 CBB_zero(&cbb);
413 uint8_t *buf = NULL;
414 size_t len;
415 if (!CBB_init(&cbb, 0) ||
416 !CBB_add_bytes(&cbb, kDLEQBatchLabel, sizeof(kDLEQBatchLabel)) ||
417 !CBB_add_bytes(&cbb, CBB_data(points), CBB_len(points)) ||
418 !CBB_add_u16(&cbb, (uint16_t)index) ||
419 !CBB_finish(&cbb, &buf, &len) ||
420 !method->hash_c(method->group, out, buf, len)) {
421 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
422 goto err;
423 }
424
425 ok = 1;
426
427 err:
428 CBB_cleanup(&cbb);
429 OPENSSL_free(buf);
430 return ok;
431 }
432
433 // The DLEQ2 and DLEQOR2 constructions are described in appendix B of
434 // https://eprint.iacr.org/2020/072/20200324:214215. DLEQ2 is an instance of
435 // DLEQOR2 with only one value (n=1).
436
dleq_generate(const PMBTOKEN_METHOD * method,CBB * cbb,const PMBTOKEN_ISSUER_KEY * priv,const EC_RAW_POINT * T,const EC_RAW_POINT * S,const EC_RAW_POINT * W,const EC_RAW_POINT * Ws,uint8_t private_metadata)437 static int dleq_generate(const PMBTOKEN_METHOD *method, CBB *cbb,
438 const PMBTOKEN_ISSUER_KEY *priv, const EC_RAW_POINT *T,
439 const EC_RAW_POINT *S, const EC_RAW_POINT *W,
440 const EC_RAW_POINT *Ws, uint8_t private_metadata) {
441 const EC_GROUP *group = method->group;
442
443 // We generate a DLEQ proof for the validity token and a DLEQOR2 proof for the
444 // private metadata token. To allow amortizing Jacobian-to-affine conversions,
445 // we compute Ki for both proofs first.
446 enum {
447 idx_T,
448 idx_S,
449 idx_W,
450 idx_Ws,
451 idx_Ks0,
452 idx_Ks1,
453 idx_Kb0,
454 idx_Kb1,
455 idx_Ko0,
456 idx_Ko1,
457 num_idx,
458 };
459 EC_RAW_POINT jacobians[num_idx];
460
461 // Setup the DLEQ proof.
462 EC_SCALAR ks0, ks1;
463 if (// ks0, ks1 <- Zp
464 !ec_random_nonzero_scalar(group, &ks0, kDefaultAdditionalData) ||
465 !ec_random_nonzero_scalar(group, &ks1, kDefaultAdditionalData) ||
466 // Ks = ks0*(G;T) + ks1*(H;S)
467 !ec_point_mul_scalar_precomp(group, &jacobians[idx_Ks0],
468 &method->g_precomp, &ks0, &method->h_precomp,
469 &ks1, NULL, NULL) ||
470 !ec_point_mul_scalar_batch(group, &jacobians[idx_Ks1], T, &ks0, S, &ks1,
471 NULL, NULL)) {
472 return 0;
473 }
474
475 // Setup the DLEQOR proof. First, select values of xb, yb (keys corresponding
476 // to the private metadata value) and pubo (public key corresponding to the
477 // other value) in constant time.
478 BN_ULONG mask = ((BN_ULONG)0) - (private_metadata & 1);
479 EC_PRECOMP pubo_precomp;
480 EC_SCALAR xb, yb;
481 ec_scalar_select(group, &xb, mask, &priv->x1, &priv->x0);
482 ec_scalar_select(group, &yb, mask, &priv->y1, &priv->y0);
483 ec_precomp_select(group, &pubo_precomp, mask, &priv->pub0_precomp,
484 &priv->pub1_precomp);
485
486 EC_SCALAR k0, k1, minus_co, uo, vo;
487 if (// k0, k1 <- Zp
488 !ec_random_nonzero_scalar(group, &k0, kDefaultAdditionalData) ||
489 !ec_random_nonzero_scalar(group, &k1, kDefaultAdditionalData) ||
490 // Kb = k0*(G;T) + k1*(H;S)
491 !ec_point_mul_scalar_precomp(group, &jacobians[idx_Kb0],
492 &method->g_precomp, &k0, &method->h_precomp,
493 &k1, NULL, NULL) ||
494 !ec_point_mul_scalar_batch(group, &jacobians[idx_Kb1], T, &k0, S, &k1,
495 NULL, NULL) ||
496 // co, uo, vo <- Zp
497 !ec_random_nonzero_scalar(group, &minus_co, kDefaultAdditionalData) ||
498 !ec_random_nonzero_scalar(group, &uo, kDefaultAdditionalData) ||
499 !ec_random_nonzero_scalar(group, &vo, kDefaultAdditionalData) ||
500 // Ko = uo*(G;T) + vo*(H;S) - co*(pubo;W)
501 !ec_point_mul_scalar_precomp(group, &jacobians[idx_Ko0],
502 &method->g_precomp, &uo, &method->h_precomp,
503 &vo, &pubo_precomp, &minus_co) ||
504 !ec_point_mul_scalar_batch(group, &jacobians[idx_Ko1], T, &uo, S, &vo, W,
505 &minus_co)) {
506 return 0;
507 }
508
509 EC_AFFINE affines[num_idx];
510 jacobians[idx_T] = *T;
511 jacobians[idx_S] = *S;
512 jacobians[idx_W] = *W;
513 jacobians[idx_Ws] = *Ws;
514 if (!ec_jacobian_to_affine_batch(group, affines, jacobians, num_idx)) {
515 return 0;
516 }
517
518 // Select the K corresponding to K0 and K1 in constant-time.
519 EC_AFFINE K00, K01, K10, K11;
520 ec_affine_select(group, &K00, mask, &affines[idx_Ko0], &affines[idx_Kb0]);
521 ec_affine_select(group, &K01, mask, &affines[idx_Ko1], &affines[idx_Kb1]);
522 ec_affine_select(group, &K10, mask, &affines[idx_Kb0], &affines[idx_Ko0]);
523 ec_affine_select(group, &K11, mask, &affines[idx_Kb1], &affines[idx_Ko1]);
524
525 // Compute c = Hc(...) for the two proofs.
526 EC_SCALAR cs, c;
527 if (!hash_c_dleq(method, &cs, &priv->pubs, &affines[idx_T], &affines[idx_S],
528 &affines[idx_Ws], &affines[idx_Ks0], &affines[idx_Ks1]) ||
529 !hash_c_dleqor(method, &c, &priv->pub0, &priv->pub1, &affines[idx_T],
530 &affines[idx_S], &affines[idx_W], &K00, &K01, &K10,
531 &K11)) {
532 return 0;
533 }
534
535 // Compute cb, ub, and ub for the two proofs. In each of these products, only
536 // one operand is in Montgomery form, so the product does not need to be
537 // converted.
538
539 EC_SCALAR cs_mont;
540 ec_scalar_to_montgomery(group, &cs_mont, &cs);
541
542 // us = ks0 + cs*xs
543 EC_SCALAR us, vs;
544 ec_scalar_mul_montgomery(group, &us, &priv->xs, &cs_mont);
545 ec_scalar_add(group, &us, &ks0, &us);
546
547 // vs = ks1 + cs*ys
548 ec_scalar_mul_montgomery(group, &vs, &priv->ys, &cs_mont);
549 ec_scalar_add(group, &vs, &ks1, &vs);
550
551 // Store DLEQ2 proof in transcript.
552 if (!scalar_to_cbb(cbb, group, &cs) ||
553 !scalar_to_cbb(cbb, group, &us) ||
554 !scalar_to_cbb(cbb, group, &vs)) {
555 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
556 return 0;
557 }
558
559 // cb = c - co
560 EC_SCALAR cb, ub, vb;
561 ec_scalar_add(group, &cb, &c, &minus_co);
562
563 EC_SCALAR cb_mont;
564 ec_scalar_to_montgomery(group, &cb_mont, &cb);
565
566 // ub = k0 + cb*xb
567 ec_scalar_mul_montgomery(group, &ub, &xb, &cb_mont);
568 ec_scalar_add(group, &ub, &k0, &ub);
569
570 // vb = k1 + cb*yb
571 ec_scalar_mul_montgomery(group, &vb, &yb, &cb_mont);
572 ec_scalar_add(group, &vb, &k1, &vb);
573
574 // Select c, u, v in constant-time.
575 EC_SCALAR co, c0, c1, u0, u1, v0, v1;
576 ec_scalar_neg(group, &co, &minus_co);
577 ec_scalar_select(group, &c0, mask, &co, &cb);
578 ec_scalar_select(group, &u0, mask, &uo, &ub);
579 ec_scalar_select(group, &v0, mask, &vo, &vb);
580 ec_scalar_select(group, &c1, mask, &cb, &co);
581 ec_scalar_select(group, &u1, mask, &ub, &uo);
582 ec_scalar_select(group, &v1, mask, &vb, &vo);
583
584 // Store DLEQOR2 proof in transcript.
585 if (!scalar_to_cbb(cbb, group, &c0) ||
586 !scalar_to_cbb(cbb, group, &c1) ||
587 !scalar_to_cbb(cbb, group, &u0) ||
588 !scalar_to_cbb(cbb, group, &u1) ||
589 !scalar_to_cbb(cbb, group, &v0) ||
590 !scalar_to_cbb(cbb, group, &v1)) {
591 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
592 return 0;
593 }
594
595 return 1;
596 }
597
dleq_verify(const PMBTOKEN_METHOD * method,CBS * cbs,const PMBTOKEN_CLIENT_KEY * pub,const EC_RAW_POINT * T,const EC_RAW_POINT * S,const EC_RAW_POINT * W,const EC_RAW_POINT * Ws)598 static int dleq_verify(const PMBTOKEN_METHOD *method, CBS *cbs,
599 const PMBTOKEN_CLIENT_KEY *pub, const EC_RAW_POINT *T,
600 const EC_RAW_POINT *S, const EC_RAW_POINT *W,
601 const EC_RAW_POINT *Ws) {
602 const EC_GROUP *group = method->group;
603 const EC_RAW_POINT *g = &group->generator->raw;
604
605 // We verify a DLEQ proof for the validity token and a DLEQOR2 proof for the
606 // private metadata token. To allow amortizing Jacobian-to-affine conversions,
607 // we compute Ki for both proofs first. Additionally, all inputs to this
608 // function are public, so we can use the faster variable-time
609 // multiplications.
610 enum {
611 idx_T,
612 idx_S,
613 idx_W,
614 idx_Ws,
615 idx_Ks0,
616 idx_Ks1,
617 idx_K00,
618 idx_K01,
619 idx_K10,
620 idx_K11,
621 num_idx,
622 };
623 EC_RAW_POINT jacobians[num_idx];
624
625 // Decode the DLEQ proof.
626 EC_SCALAR cs, us, vs;
627 if (!scalar_from_cbs(cbs, group, &cs) ||
628 !scalar_from_cbs(cbs, group, &us) ||
629 !scalar_from_cbs(cbs, group, &vs)) {
630 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
631 return 0;
632 }
633
634 // Ks = us*(G;T) + vs*(H;S) - cs*(pubs;Ws)
635 EC_RAW_POINT pubs;
636 ec_affine_to_jacobian(group, &pubs, &pub->pubs);
637 EC_SCALAR minus_cs;
638 ec_scalar_neg(group, &minus_cs, &cs);
639 if (!mul_public_3(group, &jacobians[idx_Ks0], g, &us, &method->h, &vs, &pubs,
640 &minus_cs) ||
641 !mul_public_3(group, &jacobians[idx_Ks1], T, &us, S, &vs, Ws,
642 &minus_cs)) {
643 return 0;
644 }
645
646 // Decode the DLEQOR proof.
647 EC_SCALAR c0, c1, u0, u1, v0, v1;
648 if (!scalar_from_cbs(cbs, group, &c0) ||
649 !scalar_from_cbs(cbs, group, &c1) ||
650 !scalar_from_cbs(cbs, group, &u0) ||
651 !scalar_from_cbs(cbs, group, &u1) ||
652 !scalar_from_cbs(cbs, group, &v0) ||
653 !scalar_from_cbs(cbs, group, &v1)) {
654 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
655 return 0;
656 }
657
658 EC_RAW_POINT pub0, pub1;
659 ec_affine_to_jacobian(group, &pub0, &pub->pub0);
660 ec_affine_to_jacobian(group, &pub1, &pub->pub1);
661 EC_SCALAR minus_c0, minus_c1;
662 ec_scalar_neg(group, &minus_c0, &c0);
663 ec_scalar_neg(group, &minus_c1, &c1);
664 if (// K0 = u0*(G;T) + v0*(H;S) - c0*(pub0;W)
665 !mul_public_3(group, &jacobians[idx_K00], g, &u0, &method->h, &v0, &pub0,
666 &minus_c0) ||
667 !mul_public_3(group, &jacobians[idx_K01], T, &u0, S, &v0, W, &minus_c0) ||
668 // K1 = u1*(G;T) + v1*(H;S) - c1*(pub1;W)
669 !mul_public_3(group, &jacobians[idx_K10], g, &u1, &method->h, &v1, &pub1,
670 &minus_c1) ||
671 !mul_public_3(group, &jacobians[idx_K11], T, &u1, S, &v1, W, &minus_c1)) {
672 return 0;
673 }
674
675 EC_AFFINE affines[num_idx];
676 jacobians[idx_T] = *T;
677 jacobians[idx_S] = *S;
678 jacobians[idx_W] = *W;
679 jacobians[idx_Ws] = *Ws;
680 if (!ec_jacobian_to_affine_batch(group, affines, jacobians, num_idx)) {
681 return 0;
682 }
683
684 // Check the DLEQ proof.
685 EC_SCALAR calculated;
686 if (!hash_c_dleq(method, &calculated, &pub->pubs, &affines[idx_T],
687 &affines[idx_S], &affines[idx_Ws], &affines[idx_Ks0],
688 &affines[idx_Ks1])) {
689 return 0;
690 }
691
692 // cs == calculated
693 if (!ec_scalar_equal_vartime(group, &cs, &calculated)) {
694 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_PROOF);
695 return 0;
696 }
697
698 // Check the DLEQOR proof.
699 if (!hash_c_dleqor(method, &calculated, &pub->pub0, &pub->pub1,
700 &affines[idx_T], &affines[idx_S], &affines[idx_W],
701 &affines[idx_K00], &affines[idx_K01], &affines[idx_K10],
702 &affines[idx_K11])) {
703 return 0;
704 }
705
706 // c0 + c1 == calculated
707 EC_SCALAR c;
708 ec_scalar_add(group, &c, &c0, &c1);
709 if (!ec_scalar_equal_vartime(group, &c, &calculated)) {
710 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_PROOF);
711 return 0;
712 }
713
714 return 1;
715 }
716
pmbtoken_sign(const PMBTOKEN_METHOD * method,const PMBTOKEN_ISSUER_KEY * key,CBB * cbb,CBS * cbs,size_t num_requested,size_t num_to_issue,uint8_t private_metadata)717 static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
718 const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
719 size_t num_requested, size_t num_to_issue,
720 uint8_t private_metadata) {
721 const EC_GROUP *group = method->group;
722 if (num_requested < num_to_issue) {
723 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
724 return 0;
725 }
726
727 int ret = 0;
728 EC_RAW_POINT *Tps = NULL;
729 EC_RAW_POINT *Sps = NULL;
730 EC_RAW_POINT *Wps = NULL;
731 EC_RAW_POINT *Wsps = NULL;
732 EC_SCALAR *es = NULL;
733 CBB batch_cbb;
734 CBB_zero(&batch_cbb);
735 if (method->batched_proof) {
736 if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
737 num_to_issue > ((size_t)-1) / sizeof(EC_SCALAR)) {
738 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
739 goto err;
740 }
741 Tps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
742 Sps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
743 Wps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
744 Wsps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
745 es = OPENSSL_malloc(num_to_issue * sizeof(EC_SCALAR));
746 if (!Tps ||
747 !Sps ||
748 !Wps ||
749 !Wsps ||
750 !es ||
751 !CBB_init(&batch_cbb, 0) ||
752 !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
753 !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
754 !point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
755 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
756 goto err;
757 }
758 }
759
760 for (size_t i = 0; i < num_to_issue; i++) {
761 EC_AFFINE Tp_affine;
762 EC_RAW_POINT Tp;
763 if (!cbs_get_prefixed_point(cbs, group, &Tp_affine)) {
764 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
765 goto err;
766 }
767 ec_affine_to_jacobian(group, &Tp, &Tp_affine);
768
769 EC_SCALAR xb, yb;
770 BN_ULONG mask = ((BN_ULONG)0) - (private_metadata & 1);
771 ec_scalar_select(group, &xb, mask, &key->x1, &key->x0);
772 ec_scalar_select(group, &yb, mask, &key->y1, &key->y0);
773
774 uint8_t s[PMBTOKEN_NONCE_SIZE];
775 RAND_bytes(s, PMBTOKEN_NONCE_SIZE);
776 // The |jacobians| and |affines| contain Sp, Wp, and Wsp.
777 EC_RAW_POINT jacobians[3];
778 EC_AFFINE affines[3];
779 CBB child;
780 if (!method->hash_s(group, &jacobians[0], &Tp_affine, s) ||
781 !ec_point_mul_scalar_batch(group, &jacobians[1], &Tp, &xb,
782 &jacobians[0], &yb, NULL, NULL) ||
783 !ec_point_mul_scalar_batch(group, &jacobians[2], &Tp, &key->xs,
784 &jacobians[0], &key->ys, NULL, NULL) ||
785 !ec_jacobian_to_affine_batch(group, affines, jacobians, 3) ||
786 !CBB_add_bytes(cbb, s, PMBTOKEN_NONCE_SIZE) ||
787 // TODO(https://crbug.com/boringssl/331): When updating the key format,
788 // remove the redundant length prefixes.
789 !CBB_add_u16_length_prefixed(cbb, &child) ||
790 !point_to_cbb(&child, group, &affines[1]) ||
791 !CBB_add_u16_length_prefixed(cbb, &child) ||
792 !point_to_cbb(&child, group, &affines[2])) {
793 goto err;
794 }
795
796 if (!method->batched_proof) {
797 if (!CBB_add_u16_length_prefixed(cbb, &child) ||
798 !dleq_generate(method, &child, key, &Tp, &jacobians[0], &jacobians[1],
799 &jacobians[2], private_metadata)) {
800 goto err;
801 }
802 } else {
803 if (!point_to_cbb(&batch_cbb, group, &Tp_affine) ||
804 !point_to_cbb(&batch_cbb, group, &affines[0]) ||
805 !point_to_cbb(&batch_cbb, group, &affines[1]) ||
806 !point_to_cbb(&batch_cbb, group, &affines[2])) {
807 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
808 goto err;
809 }
810 Tps[i] = Tp;
811 Sps[i] = jacobians[0];
812 Wps[i] = jacobians[1];
813 Wsps[i] = jacobians[2];
814 }
815
816 if (!CBB_flush(cbb)) {
817 goto err;
818 }
819 }
820
821 // The DLEQ batching construction is described in appendix B of
822 // https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
823 // computations all act on public inputs.
824 if (method->batched_proof) {
825 for (size_t i = 0; i < num_to_issue; i++) {
826 if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
827 goto err;
828 }
829 }
830
831 EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
832 if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
833 /*g_scalar=*/NULL, Tps, es,
834 num_to_issue) ||
835 !ec_point_mul_scalar_public_batch(group, &Sp_batch,
836 /*g_scalar=*/NULL, Sps, es,
837 num_to_issue) ||
838 !ec_point_mul_scalar_public_batch(group, &Wp_batch,
839 /*g_scalar=*/NULL, Wps, es,
840 num_to_issue) ||
841 !ec_point_mul_scalar_public_batch(group, &Wsp_batch,
842 /*g_scalar=*/NULL, Wsps, es,
843 num_to_issue)) {
844 goto err;
845 }
846
847 CBB proof;
848 if (!CBB_add_u16_length_prefixed(cbb, &proof) ||
849 !dleq_generate(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
850 &Wsp_batch, private_metadata) ||
851 !CBB_flush(cbb)) {
852 goto err;
853 }
854 }
855
856 // Skip over any unused requests.
857 size_t point_len = 1 + 2 * BN_num_bytes(&group->field);
858 if (!CBS_skip(cbs, (2 + point_len) * (num_requested - num_to_issue))) {
859 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
860 goto err;
861 }
862
863 ret = 1;
864
865 err:
866 OPENSSL_free(Tps);
867 OPENSSL_free(Sps);
868 OPENSSL_free(Wps);
869 OPENSSL_free(Wsps);
870 OPENSSL_free(es);
871 CBB_cleanup(&batch_cbb);
872 return ret;
873 }
874
STACK_OF(TRUST_TOKEN)875 static STACK_OF(TRUST_TOKEN) *
876 pmbtoken_unblind(const PMBTOKEN_METHOD *method,
877 const PMBTOKEN_CLIENT_KEY *key,
878 const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens, CBS *cbs,
879 size_t count, uint32_t key_id) {
880 const EC_GROUP *group = method->group;
881 if (count > sk_PMBTOKEN_PRETOKEN_num(pretokens)) {
882 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
883 return NULL;
884 }
885
886 int ok = 0;
887 STACK_OF(TRUST_TOKEN) *ret = sk_TRUST_TOKEN_new_null();
888 if (ret == NULL) {
889 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
890 return NULL;
891 }
892
893 EC_RAW_POINT *Tps = NULL;
894 EC_RAW_POINT *Sps = NULL;
895 EC_RAW_POINT *Wps = NULL;
896 EC_RAW_POINT *Wsps = NULL;
897 EC_SCALAR *es = NULL;
898 CBB batch_cbb;
899 CBB_zero(&batch_cbb);
900 if (method->batched_proof) {
901 if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
902 count > ((size_t)-1) / sizeof(EC_SCALAR)) {
903 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
904 goto err;
905 }
906 Tps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
907 Sps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
908 Wps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
909 Wsps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
910 es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
911 if (!Tps ||
912 !Sps ||
913 !Wps ||
914 !Wsps ||
915 !es ||
916 !CBB_init(&batch_cbb, 0) ||
917 !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
918 !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
919 !point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
920 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
921 goto err;
922 }
923 }
924
925 for (size_t i = 0; i < count; i++) {
926 const PMBTOKEN_PRETOKEN *pretoken =
927 sk_PMBTOKEN_PRETOKEN_value(pretokens, i);
928
929 uint8_t s[PMBTOKEN_NONCE_SIZE];
930 EC_AFFINE Wp_affine, Wsp_affine;
931 CBS proof;
932 if (!CBS_copy_bytes(cbs, s, PMBTOKEN_NONCE_SIZE) ||
933 !cbs_get_prefixed_point(cbs, group, &Wp_affine) ||
934 !cbs_get_prefixed_point(cbs, group, &Wsp_affine)) {
935 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
936 goto err;
937 }
938
939 EC_RAW_POINT Tp, Wp, Wsp, Sp;
940 ec_affine_to_jacobian(group, &Tp, &pretoken->Tp);
941 ec_affine_to_jacobian(group, &Wp, &Wp_affine);
942 ec_affine_to_jacobian(group, &Wsp, &Wsp_affine);
943 if (!method->hash_s(group, &Sp, &pretoken->Tp, s)) {
944 goto err;
945 }
946
947 if (!method->batched_proof) {
948 if(!CBS_get_u16_length_prefixed(cbs, &proof)) {
949 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
950 goto err;
951 }
952
953 if (!dleq_verify(method, &proof, key, &Tp, &Sp, &Wp, &Wsp)) {
954 goto err;
955 }
956
957 if (CBS_len(&proof) != 0) {
958 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
959 goto err;
960 }
961 } else {
962 EC_AFFINE Sp_affine;
963 if (!point_to_cbb(&batch_cbb, group, &pretoken->Tp) ||
964 !ec_jacobian_to_affine(group, &Sp_affine, &Sp) ||
965 !point_to_cbb(&batch_cbb, group, &Sp_affine) ||
966 !point_to_cbb(&batch_cbb, group, &Wp_affine) ||
967 !point_to_cbb(&batch_cbb, group, &Wsp_affine)) {
968 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
969 goto err;
970 }
971 Tps[i] = Tp;
972 Sps[i] = Sp;
973 Wps[i] = Wp;
974 Wsps[i] = Wsp;
975 }
976
977 // Unblind the token.
978 EC_RAW_POINT jacobians[3];
979 EC_AFFINE affines[3];
980 if (!ec_point_mul_scalar(group, &jacobians[0], &Sp, &pretoken->r) ||
981 !ec_point_mul_scalar(group, &jacobians[1], &Wp, &pretoken->r) ||
982 !ec_point_mul_scalar(group, &jacobians[2], &Wsp, &pretoken->r) ||
983 !ec_jacobian_to_affine_batch(group, affines, jacobians, 3)) {
984 goto err;
985 }
986
987 // Serialize the token. Include |key_id| to avoid an extra copy in the layer
988 // above.
989 CBB token_cbb, child;
990 size_t point_len = 1 + 2 * BN_num_bytes(&group->field);
991 if (!CBB_init(&token_cbb, 4 + PMBTOKEN_NONCE_SIZE + 3 * (2 + point_len)) ||
992 !CBB_add_u32(&token_cbb, key_id) ||
993 !CBB_add_bytes(&token_cbb, pretoken->t, PMBTOKEN_NONCE_SIZE) ||
994 // TODO(https://crbug.com/boringssl/331): When updating the key format,
995 // remove the redundant length prefixes.
996 !CBB_add_u16_length_prefixed(&token_cbb, &child) ||
997 !point_to_cbb(&child, group, &affines[0]) ||
998 !CBB_add_u16_length_prefixed(&token_cbb, &child) ||
999 !point_to_cbb(&child, group, &affines[1]) ||
1000 !CBB_add_u16_length_prefixed(&token_cbb, &child) ||
1001 !point_to_cbb(&child, group, &affines[2]) ||
1002 !CBB_flush(&token_cbb)) {
1003 CBB_cleanup(&token_cbb);
1004 goto err;
1005 }
1006
1007 TRUST_TOKEN *token =
1008 TRUST_TOKEN_new(CBB_data(&token_cbb), CBB_len(&token_cbb));
1009 CBB_cleanup(&token_cbb);
1010 if (token == NULL ||
1011 !sk_TRUST_TOKEN_push(ret, token)) {
1012 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
1013 TRUST_TOKEN_free(token);
1014 goto err;
1015 }
1016 }
1017
1018 // The DLEQ batching construction is described in appendix B of
1019 // https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
1020 // computations all act on public inputs.
1021 if (method->batched_proof) {
1022 for (size_t i = 0; i < count; i++) {
1023 if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
1024 goto err;
1025 }
1026 }
1027
1028 EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
1029 if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
1030 /*g_scalar=*/NULL, Tps, es, count) ||
1031 !ec_point_mul_scalar_public_batch(group, &Sp_batch,
1032 /*g_scalar=*/NULL, Sps, es, count) ||
1033 !ec_point_mul_scalar_public_batch(group, &Wp_batch,
1034 /*g_scalar=*/NULL, Wps, es, count) ||
1035 !ec_point_mul_scalar_public_batch(group, &Wsp_batch,
1036 /*g_scalar=*/NULL, Wsps, es, count)) {
1037 goto err;
1038 }
1039
1040 CBS proof;
1041 if (!CBS_get_u16_length_prefixed(cbs, &proof) ||
1042 !dleq_verify(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
1043 &Wsp_batch) ||
1044 CBS_len(&proof) != 0) {
1045 goto err;
1046 }
1047 }
1048
1049 ok = 1;
1050
1051 err:
1052 OPENSSL_free(Tps);
1053 OPENSSL_free(Sps);
1054 OPENSSL_free(Wps);
1055 OPENSSL_free(Wsps);
1056 OPENSSL_free(es);
1057 CBB_cleanup(&batch_cbb);
1058 if (!ok) {
1059 sk_TRUST_TOKEN_pop_free(ret, TRUST_TOKEN_free);
1060 ret = NULL;
1061 }
1062 return ret;
1063 }
1064
pmbtoken_read(const PMBTOKEN_METHOD * method,const PMBTOKEN_ISSUER_KEY * key,uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],uint8_t * out_private_metadata,const uint8_t * token,size_t token_len)1065 static int pmbtoken_read(const PMBTOKEN_METHOD *method,
1066 const PMBTOKEN_ISSUER_KEY *key,
1067 uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
1068 uint8_t *out_private_metadata, const uint8_t *token,
1069 size_t token_len) {
1070 const EC_GROUP *group = method->group;
1071 CBS cbs;
1072 CBS_init(&cbs, token, token_len);
1073 EC_AFFINE S, W, Ws;
1074 if (!CBS_copy_bytes(&cbs, out_nonce, PMBTOKEN_NONCE_SIZE) ||
1075 !cbs_get_prefixed_point(&cbs, group, &S) ||
1076 !cbs_get_prefixed_point(&cbs, group, &W) ||
1077 !cbs_get_prefixed_point(&cbs, group, &Ws) ||
1078 CBS_len(&cbs) != 0) {
1079 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_TOKEN);
1080 return 0;
1081 }
1082
1083
1084 EC_RAW_POINT T;
1085 if (!method->hash_t(group, &T, out_nonce)) {
1086 return 0;
1087 }
1088
1089 // We perform three multiplications with S and T. This is enough that it is
1090 // worth using |ec_point_mul_scalar_precomp|.
1091 EC_RAW_POINT S_jacobian;
1092 EC_PRECOMP S_precomp, T_precomp;
1093 ec_affine_to_jacobian(group, &S_jacobian, &S);
1094 if (!ec_init_precomp(group, &S_precomp, &S_jacobian) ||
1095 !ec_init_precomp(group, &T_precomp, &T)) {
1096 return 0;
1097 }
1098
1099 EC_RAW_POINT Ws_calculated;
1100 // Check the validity of the token.
1101 if (!ec_point_mul_scalar_precomp(group, &Ws_calculated, &T_precomp, &key->xs,
1102 &S_precomp, &key->ys, NULL, NULL) ||
1103 !ec_affine_jacobian_equal(group, &Ws, &Ws_calculated)) {
1104 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BAD_VALIDITY_CHECK);
1105 return 0;
1106 }
1107
1108 EC_RAW_POINT W0, W1;
1109 if (!ec_point_mul_scalar_precomp(group, &W0, &T_precomp, &key->x0, &S_precomp,
1110 &key->y0, NULL, NULL) ||
1111 !ec_point_mul_scalar_precomp(group, &W1, &T_precomp, &key->x1, &S_precomp,
1112 &key->y1, NULL, NULL)) {
1113 return 0;
1114 }
1115
1116 const int is_W0 = ec_affine_jacobian_equal(group, &W, &W0);
1117 const int is_W1 = ec_affine_jacobian_equal(group, &W, &W1);
1118 const int is_valid = is_W0 ^ is_W1;
1119 if (!is_valid) {
1120 // Invalid tokens will fail the validity check above.
1121 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
1122 return 0;
1123 }
1124
1125 *out_private_metadata = is_W1;
1126 return 1;
1127 }
1128
1129
1130 // PMBTokens experiment v0.
1131
pmbtoken_exp0_hash_t(const EC_GROUP * group,EC_RAW_POINT * out,const uint8_t t[PMBTOKEN_NONCE_SIZE])1132 static int pmbtoken_exp0_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
1133 const uint8_t t[PMBTOKEN_NONCE_SIZE]) {
1134 const uint8_t kHashTLabel[] = "PMBTokensV0 HashT";
1135 return ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
1136 group, out, kHashTLabel, sizeof(kHashTLabel), t, PMBTOKEN_NONCE_SIZE);
1137 }
1138
pmbtoken_exp0_hash_s(const EC_GROUP * group,EC_RAW_POINT * out,const EC_AFFINE * t,const uint8_t s[PMBTOKEN_NONCE_SIZE])1139 static int pmbtoken_exp0_hash_s(const EC_GROUP *group, EC_RAW_POINT *out,
1140 const EC_AFFINE *t,
1141 const uint8_t s[PMBTOKEN_NONCE_SIZE]) {
1142 const uint8_t kHashSLabel[] = "PMBTokensV0 HashS";
1143 int ret = 0;
1144 CBB cbb;
1145 uint8_t *buf = NULL;
1146 size_t len;
1147 if (!CBB_init(&cbb, 0) ||
1148 !point_to_cbb(&cbb, group, t) ||
1149 !CBB_add_bytes(&cbb, s, PMBTOKEN_NONCE_SIZE) ||
1150 !CBB_finish(&cbb, &buf, &len) ||
1151 !ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
1152 group, out, kHashSLabel, sizeof(kHashSLabel), buf, len)) {
1153 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
1154 goto err;
1155 }
1156
1157 ret = 1;
1158
1159 err:
1160 OPENSSL_free(buf);
1161 CBB_cleanup(&cbb);
1162 return ret;
1163 }
1164
pmbtoken_exp0_hash_c(const EC_GROUP * group,EC_SCALAR * out,uint8_t * buf,size_t len)1165 static int pmbtoken_exp0_hash_c(const EC_GROUP *group, EC_SCALAR *out,
1166 uint8_t *buf, size_t len) {
1167 const uint8_t kHashCLabel[] = "PMBTokensV0 HashC";
1168 return ec_hash_to_scalar_p521_xmd_sha512_draft06(
1169 group, out, kHashCLabel, sizeof(kHashCLabel), buf, len);
1170 }
1171
1172 // H for PMBTokens v0 was generated with the following Python code.
1173 /*
1174 import hashlib
1175
1176 SEED_H = 'PrivacyPass H'
1177
1178 A = -3
1179 B = 0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00
1180 P = 2**521 - 1
1181
1182 def get_y(x):
1183 y2 = (x**3 + A*x + B) % P
1184 y = pow(y2, (P+1)/4, P)
1185 if (y*y) % P != y2:
1186 raise ValueError("point not on curve")
1187 return y
1188
1189 def bit(h,i):
1190 return (ord(h[i/8]) >> (i%8)) & 1
1191
1192 b = 521
1193 def decode_point(so):
1194 s = hashlib.sha256(so + '0').digest() + hashlib.sha256(so + '1').digest() + \
1195 hashlib.sha256(so + '2').digest()
1196
1197 x = 0
1198 for i in range(0,b):
1199 x = x + (long(bit(s,i))<<i)
1200 if x >= P:
1201 raise ValueError("x out of range")
1202 y = get_y(x)
1203 if y & 1 != bit(s,b-1): y = P-y
1204 return (x, y)
1205
1206
1207 def gen_point(seed):
1208 v = hashlib.sha256(seed).digest()
1209 it = 1
1210 while True:
1211 try:
1212 x,y = decode_point(v)
1213 except Exception, e:
1214 print e
1215 it += 1
1216 v = hashlib.sha256(v).digest()
1217 continue
1218 print "Found in %d iterations:" % it
1219 print " x = %d" % x
1220 print " y = %d" % y
1221 print " Encoded (hex): (%x, %x)" % (x, y)
1222 return (x, y)
1223
1224 if __name__ == "__main__":
1225 gen_point(SEED_H)
1226 */
1227 static int pmbtoken_exp0_ok = 0;
1228 static PMBTOKEN_METHOD pmbtoken_exp0_method;
1229 static CRYPTO_once_t pmbtoken_exp0_method_once = CRYPTO_ONCE_INIT;
1230
pmbtoken_exp0_init_method_impl(void)1231 static void pmbtoken_exp0_init_method_impl(void) {
1232 static const uint8_t kH[] = {
1233 0x04, 0x01, 0xf0, 0xa9, 0xf7, 0x9e, 0xbc, 0x12, 0x6c, 0xef, 0xd1, 0xab,
1234 0x29, 0x10, 0x03, 0x6f, 0x4e, 0xf5, 0xbd, 0xeb, 0x0f, 0x6b, 0xc0, 0x5c,
1235 0x0e, 0xce, 0xfe, 0x59, 0x45, 0xd1, 0x3e, 0x25, 0x33, 0x7e, 0x4c, 0xda,
1236 0x64, 0x53, 0x54, 0x4e, 0xf9, 0x76, 0x0d, 0x6d, 0xc5, 0x39, 0x2a, 0xd4,
1237 0xce, 0x84, 0x6e, 0x31, 0xc2, 0x86, 0x21, 0xf9, 0x5c, 0x98, 0xb9, 0x3d,
1238 0x01, 0x74, 0x9f, 0xc5, 0x1e, 0x47, 0x24, 0x00, 0x5c, 0x17, 0x62, 0x51,
1239 0x7d, 0x32, 0x5e, 0x29, 0xac, 0x52, 0x14, 0x75, 0x6f, 0x36, 0xd9, 0xc7,
1240 0xfa, 0xbb, 0xa9, 0x3b, 0x9d, 0x70, 0x49, 0x1e, 0xb4, 0x53, 0xbc, 0x55,
1241 0xea, 0xad, 0x8f, 0x26, 0x1d, 0xe0, 0xbc, 0xf3, 0x50, 0x5c, 0x7e, 0x66,
1242 0x41, 0xb5, 0x61, 0x70, 0x12, 0x72, 0xac, 0x6a, 0xb0, 0x6e, 0x78, 0x3d,
1243 0x17, 0x08, 0xe3, 0xdf, 0x3c, 0xff, 0xa6, 0xa0, 0xea, 0x96, 0x67, 0x92,
1244 0xcd,
1245 };
1246
1247 pmbtoken_exp0_ok =
1248 pmbtoken_init_method(&pmbtoken_exp0_method, NID_secp521r1, kH, sizeof(kH),
1249 pmbtoken_exp0_hash_t, pmbtoken_exp0_hash_s,
1250 pmbtoken_exp0_hash_c, /*batched_proof=*/0);
1251 }
1252
pmbtoken_exp0_init_method(void)1253 static int pmbtoken_exp0_init_method(void) {
1254 CRYPTO_once(&pmbtoken_exp0_method_once, pmbtoken_exp0_init_method_impl);
1255 if (!pmbtoken_exp0_ok) {
1256 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
1257 return 0;
1258 }
1259 return 1;
1260 }
1261
pmbtoken_exp0_generate_key(CBB * out_private,CBB * out_public)1262 int pmbtoken_exp0_generate_key(CBB *out_private, CBB *out_public) {
1263 if (!pmbtoken_exp0_init_method()) {
1264 return 0;
1265 }
1266
1267 return pmbtoken_generate_key(&pmbtoken_exp0_method, out_private, out_public);
1268 }
1269
pmbtoken_exp0_client_key_from_bytes(PMBTOKEN_CLIENT_KEY * key,const uint8_t * in,size_t len)1270 int pmbtoken_exp0_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
1271 const uint8_t *in, size_t len) {
1272 if (!pmbtoken_exp0_init_method()) {
1273 return 0;
1274 }
1275 return pmbtoken_client_key_from_bytes(&pmbtoken_exp0_method, key, in, len);
1276 }
1277
pmbtoken_exp0_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY * key,const uint8_t * in,size_t len)1278 int pmbtoken_exp0_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
1279 const uint8_t *in, size_t len) {
1280 if (!pmbtoken_exp0_init_method()) {
1281 return 0;
1282 }
1283 return pmbtoken_issuer_key_from_bytes(&pmbtoken_exp0_method, key, in, len);
1284 }
1285
STACK_OF(PMBTOKEN_PRETOKEN)1286 STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp0_blind(CBB *cbb, size_t count) {
1287 if (!pmbtoken_exp0_init_method()) {
1288 return NULL;
1289 }
1290 return pmbtoken_blind(&pmbtoken_exp0_method, cbb, count);
1291 }
1292
pmbtoken_exp0_sign(const PMBTOKEN_ISSUER_KEY * key,CBB * cbb,CBS * cbs,size_t num_requested,size_t num_to_issue,uint8_t private_metadata)1293 int pmbtoken_exp0_sign(const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
1294 size_t num_requested, size_t num_to_issue,
1295 uint8_t private_metadata) {
1296 if (!pmbtoken_exp0_init_method()) {
1297 return 0;
1298 }
1299 return pmbtoken_sign(&pmbtoken_exp0_method, key, cbb, cbs, num_requested,
1300 num_to_issue, private_metadata);
1301 }
1302
STACK_OF(TRUST_TOKEN)1303 STACK_OF(TRUST_TOKEN) *
1304 pmbtoken_exp0_unblind(const PMBTOKEN_CLIENT_KEY *key,
1305 const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
1306 CBS *cbs, size_t count, uint32_t key_id) {
1307 if (!pmbtoken_exp0_init_method()) {
1308 return NULL;
1309 }
1310 return pmbtoken_unblind(&pmbtoken_exp0_method, key, pretokens, cbs, count,
1311 key_id);
1312 }
1313
pmbtoken_exp0_read(const PMBTOKEN_ISSUER_KEY * key,uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],uint8_t * out_private_metadata,const uint8_t * token,size_t token_len)1314 int pmbtoken_exp0_read(const PMBTOKEN_ISSUER_KEY *key,
1315 uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
1316 uint8_t *out_private_metadata, const uint8_t *token,
1317 size_t token_len) {
1318 if (!pmbtoken_exp0_init_method()) {
1319 return 0;
1320 }
1321 return pmbtoken_read(&pmbtoken_exp0_method, key, out_nonce,
1322 out_private_metadata, token, token_len);
1323 }
1324
1325
1326 // PMBTokens experiment v1.
1327
pmbtoken_exp1_hash_t(const EC_GROUP * group,EC_RAW_POINT * out,const uint8_t t[PMBTOKEN_NONCE_SIZE])1328 static int pmbtoken_exp1_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
1329 const uint8_t t[PMBTOKEN_NONCE_SIZE]) {
1330 const uint8_t kHashTLabel[] = "PMBTokens Experiment V1 HashT";
1331 return ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
1332 group, out, kHashTLabel, sizeof(kHashTLabel), t, PMBTOKEN_NONCE_SIZE);
1333 }
1334
pmbtoken_exp1_hash_s(const EC_GROUP * group,EC_RAW_POINT * out,const EC_AFFINE * t,const uint8_t s[PMBTOKEN_NONCE_SIZE])1335 static int pmbtoken_exp1_hash_s(const EC_GROUP *group, EC_RAW_POINT *out,
1336 const EC_AFFINE *t,
1337 const uint8_t s[PMBTOKEN_NONCE_SIZE]) {
1338 const uint8_t kHashSLabel[] = "PMBTokens Experiment V1 HashS";
1339 int ret = 0;
1340 CBB cbb;
1341 uint8_t *buf = NULL;
1342 size_t len;
1343 if (!CBB_init(&cbb, 0) ||
1344 !point_to_cbb(&cbb, group, t) ||
1345 !CBB_add_bytes(&cbb, s, PMBTOKEN_NONCE_SIZE) ||
1346 !CBB_finish(&cbb, &buf, &len) ||
1347 !ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
1348 group, out, kHashSLabel, sizeof(kHashSLabel), buf, len)) {
1349 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
1350 goto err;
1351 }
1352
1353 ret = 1;
1354
1355 err:
1356 OPENSSL_free(buf);
1357 CBB_cleanup(&cbb);
1358 return ret;
1359 }
1360
pmbtoken_exp1_hash_c(const EC_GROUP * group,EC_SCALAR * out,uint8_t * buf,size_t len)1361 static int pmbtoken_exp1_hash_c(const EC_GROUP *group, EC_SCALAR *out,
1362 uint8_t *buf, size_t len) {
1363 const uint8_t kHashCLabel[] = "PMBTokens Experiment V1 HashC";
1364 return ec_hash_to_scalar_p384_xmd_sha512_draft07(
1365 group, out, kHashCLabel, sizeof(kHashCLabel), buf, len);
1366 }
1367
1368 static int pmbtoken_exp1_ok = 0;
1369 static PMBTOKEN_METHOD pmbtoken_exp1_method;
1370 static CRYPTO_once_t pmbtoken_exp1_method_once = CRYPTO_ONCE_INIT;
1371
pmbtoken_exp1_init_method_impl(void)1372 static void pmbtoken_exp1_init_method_impl(void) {
1373 // This is the output of |ec_hash_to_scalar_p384_xmd_sha512_draft07| with DST
1374 // "PMBTokens Experiment V1 HashH" and message "generator".
1375 static const uint8_t kH[] = {
1376 0x04, 0x82, 0xd5, 0x68, 0xf5, 0x39, 0xf6, 0x08, 0x19, 0xa1, 0x75,
1377 0x9f, 0x98, 0xb5, 0x10, 0xf5, 0x0b, 0x9d, 0x2b, 0xe1, 0x64, 0x4d,
1378 0x02, 0x76, 0x18, 0x11, 0xf8, 0x2f, 0xd3, 0x33, 0x25, 0x1f, 0x2c,
1379 0xb8, 0xf6, 0xf1, 0x9e, 0x93, 0x85, 0x79, 0xb3, 0xb7, 0x81, 0xa3,
1380 0xe6, 0x23, 0xc3, 0x1c, 0xff, 0x03, 0xd9, 0x40, 0x6c, 0xec, 0xe0,
1381 0x4d, 0xea, 0xdf, 0x9d, 0x94, 0xd1, 0x87, 0xab, 0x27, 0xf7, 0x4f,
1382 0x53, 0xea, 0xa3, 0x18, 0x72, 0xb9, 0xd1, 0x56, 0xa0, 0x4e, 0x81,
1383 0xaa, 0xeb, 0x1c, 0x22, 0x6d, 0x39, 0x1c, 0x5e, 0xb1, 0x27, 0xfc,
1384 0x87, 0xc3, 0x95, 0xd0, 0x13, 0xb7, 0x0b, 0x5c, 0xc7,
1385 };
1386
1387 pmbtoken_exp1_ok =
1388 pmbtoken_init_method(&pmbtoken_exp1_method, NID_secp384r1, kH, sizeof(kH),
1389 pmbtoken_exp1_hash_t, pmbtoken_exp1_hash_s,
1390 pmbtoken_exp1_hash_c, /*batched_proof=*/1);
1391 }
1392
pmbtoken_exp1_init_method(void)1393 static int pmbtoken_exp1_init_method(void) {
1394 CRYPTO_once(&pmbtoken_exp1_method_once, pmbtoken_exp1_init_method_impl);
1395 if (!pmbtoken_exp1_ok) {
1396 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
1397 return 0;
1398 }
1399 return 1;
1400 }
1401
pmbtoken_exp1_generate_key(CBB * out_private,CBB * out_public)1402 int pmbtoken_exp1_generate_key(CBB *out_private, CBB *out_public) {
1403 if (!pmbtoken_exp1_init_method()) {
1404 return 0;
1405 }
1406
1407 return pmbtoken_generate_key(&pmbtoken_exp1_method, out_private, out_public);
1408 }
1409
pmbtoken_exp1_client_key_from_bytes(PMBTOKEN_CLIENT_KEY * key,const uint8_t * in,size_t len)1410 int pmbtoken_exp1_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
1411 const uint8_t *in, size_t len) {
1412 if (!pmbtoken_exp1_init_method()) {
1413 return 0;
1414 }
1415 return pmbtoken_client_key_from_bytes(&pmbtoken_exp1_method, key, in, len);
1416 }
1417
pmbtoken_exp1_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY * key,const uint8_t * in,size_t len)1418 int pmbtoken_exp1_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
1419 const uint8_t *in, size_t len) {
1420 if (!pmbtoken_exp1_init_method()) {
1421 return 0;
1422 }
1423 return pmbtoken_issuer_key_from_bytes(&pmbtoken_exp1_method, key, in, len);
1424 }
1425
STACK_OF(PMBTOKEN_PRETOKEN)1426 STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp1_blind(CBB *cbb, size_t count) {
1427 if (!pmbtoken_exp1_init_method()) {
1428 return NULL;
1429 }
1430 return pmbtoken_blind(&pmbtoken_exp1_method, cbb, count);
1431 }
1432
pmbtoken_exp1_sign(const PMBTOKEN_ISSUER_KEY * key,CBB * cbb,CBS * cbs,size_t num_requested,size_t num_to_issue,uint8_t private_metadata)1433 int pmbtoken_exp1_sign(const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
1434 size_t num_requested, size_t num_to_issue,
1435 uint8_t private_metadata) {
1436 if (!pmbtoken_exp1_init_method()) {
1437 return 0;
1438 }
1439 return pmbtoken_sign(&pmbtoken_exp1_method, key, cbb, cbs, num_requested,
1440 num_to_issue, private_metadata);
1441 }
1442
STACK_OF(TRUST_TOKEN)1443 STACK_OF(TRUST_TOKEN) *
1444 pmbtoken_exp1_unblind(const PMBTOKEN_CLIENT_KEY *key,
1445 const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
1446 CBS *cbs, size_t count, uint32_t key_id) {
1447 if (!pmbtoken_exp1_init_method()) {
1448 return NULL;
1449 }
1450 return pmbtoken_unblind(&pmbtoken_exp1_method, key, pretokens, cbs, count,
1451 key_id);
1452 }
1453
pmbtoken_exp1_read(const PMBTOKEN_ISSUER_KEY * key,uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],uint8_t * out_private_metadata,const uint8_t * token,size_t token_len)1454 int pmbtoken_exp1_read(const PMBTOKEN_ISSUER_KEY *key,
1455 uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
1456 uint8_t *out_private_metadata, const uint8_t *token,
1457 size_t token_len) {
1458 if (!pmbtoken_exp1_init_method()) {
1459 return 0;
1460 }
1461 return pmbtoken_read(&pmbtoken_exp1_method, key, out_nonce,
1462 out_private_metadata, token, token_len);
1463 }
1464
pmbtoken_exp1_get_h_for_testing(uint8_t out[97])1465 int pmbtoken_exp1_get_h_for_testing(uint8_t out[97]) {
1466 if (!pmbtoken_exp1_init_method()) {
1467 return 0;
1468 }
1469 EC_AFFINE h;
1470 return ec_jacobian_to_affine(pmbtoken_exp1_method.group, &h,
1471 &pmbtoken_exp1_method.h) &&
1472 ec_point_to_bytes(pmbtoken_exp1_method.group, &h,
1473 POINT_CONVERSION_UNCOMPRESSED, out, 97) == 97;
1474 }
1475