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