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