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