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