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