blob: f9132e66423d946ad944986231822da06953060e [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,
34 const uint8_t t[PMBTOKEN_NONCE_SIZE]);
35typedef int (*hash_s_func_t)(const EC_GROUP *group, EC_RAW_POINT *out,
36 const EC_AFFINE *t,
37 const uint8_t s[PMBTOKEN_NONCE_SIZE]);
38typedef 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
168void PMBTOKEN_PRETOKEN_free(PMBTOKEN_PRETOKEN *pretoken) {
169 OPENSSL_free(pretoken);
170}
171
172static int pmbtoken_generate_key(const PMBTOKEN_METHOD *method,
173 CBB *out_private, CBB *out_public) {
174 const EC_GROUP *group = method->group;
175 EC_RAW_POINT pub[3];
176 EC_SCALAR x0, y0, x1, y1, xs, ys;
177 if (!generate_keypair(method, &x0, &y0, &pub[0]) ||
178 !generate_keypair(method, &x1, &y1, &pub[1]) ||
179 !generate_keypair(method, &xs, &ys, &pub[2])) {
180 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_KEYGEN_FAILURE);
181 return 0;
182 }
183
184 const EC_SCALAR *scalars[] = {&x0, &y0, &x1, &y1, &xs, &ys};
185 size_t scalar_len = BN_num_bytes(&group->order);
186 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) {
187 uint8_t *buf;
188 if (!CBB_add_space(out_private, &buf, scalar_len)) {
189 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL);
190 return 0;
191 }
192 ec_scalar_to_bytes(group, buf, &scalar_len, scalars[i]);
193 }
194
195 EC_AFFINE pub_affine[3];
196 if (!ec_jacobian_to_affine_batch(group, pub_affine, pub, 3)) {
197 return 0;
198 }
199
200 if (!cbb_add_prefixed_point(out_public, group, &pub_affine[0],
201 method->prefix_point) ||
202 !cbb_add_prefixed_point(out_public, group, &pub_affine[1],
203 method->prefix_point) ||
204 !cbb_add_prefixed_point(out_public, group, &pub_affine[2],
205 method->prefix_point)) {
206 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL);
207 return 0;
208 }
209
210 return 1;
211}
212
213static int pmbtoken_client_key_from_bytes(const PMBTOKEN_METHOD *method,
214 PMBTOKEN_CLIENT_KEY *key,
215 const uint8_t *in, size_t len) {
216 CBS cbs;
217 CBS_init(&cbs, in, len);
218 if (!cbs_get_prefixed_point(&cbs, method->group, &key->pub0,
219 method->prefix_point) ||
220 !cbs_get_prefixed_point(&cbs, method->group, &key->pub1,
221 method->prefix_point) ||
222 !cbs_get_prefixed_point(&cbs, method->group, &key->pubs,
223 method->prefix_point) ||
224 CBS_len(&cbs) != 0) {
225 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
226 return 0;
227 }
228
229 return 1;
230}
231
232static int pmbtoken_issuer_key_from_bytes(const PMBTOKEN_METHOD *method,
233 PMBTOKEN_ISSUER_KEY *key,
234 const uint8_t *in, size_t len) {
235 const EC_GROUP *group = method->group;
236 CBS cbs, tmp;
237 CBS_init(&cbs, in, len);
238 size_t scalar_len = BN_num_bytes(&group->order);
239 EC_SCALAR *scalars[] = {&key->x0, &key->y0, &key->x1,
240 &key->y1, &key->xs, &key->ys};
241 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) {
242 if (!CBS_get_bytes(&cbs, &tmp, scalar_len) ||
243 !ec_scalar_from_bytes(group, scalars[i], CBS_data(&tmp),
244 CBS_len(&tmp))) {
245 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
246 return 0;
247 }
248 }
249
250 // Recompute the public key.
251 EC_RAW_POINT pub[3];
252 EC_AFFINE pub_affine[3];
253 if (!ec_point_mul_scalar_precomp(group, &pub[0], &method->g_precomp, &key->x0,
254 &method->h_precomp, &key->y0, NULL, NULL) ||
255 !ec_init_precomp(group, &key->pub0_precomp, &pub[0]) ||
256 !ec_point_mul_scalar_precomp(group, &pub[1], &method->g_precomp, &key->x1,
257 &method->h_precomp, &key->y1, NULL, NULL) ||
258 !ec_init_precomp(group, &key->pub1_precomp, &pub[1]) ||
259 !ec_point_mul_scalar_precomp(group, &pub[2], &method->g_precomp, &key->xs,
260 &method->h_precomp, &key->ys, NULL, NULL) ||
261 !ec_init_precomp(group, &key->pubs_precomp, &pub[2]) ||
262 !ec_jacobian_to_affine_batch(group, pub_affine, pub, 3)) {
263 return 0;
264 }
265
266 key->pub0 = pub_affine[0];
267 key->pub1 = pub_affine[1];
268 key->pubs = pub_affine[2];
269 return 1;
270}
271
272static STACK_OF(PMBTOKEN_PRETOKEN) *
273 pmbtoken_blind(const PMBTOKEN_METHOD *method, CBB *cbb, size_t count) {
274 const EC_GROUP *group = method->group;
275 STACK_OF(PMBTOKEN_PRETOKEN) *pretokens = sk_PMBTOKEN_PRETOKEN_new_null();
276 if (pretokens == NULL) {
277 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
278 goto err;
279 }
280
281 for (size_t i = 0; i < count; i++) {
282 // Insert |pretoken| into |pretokens| early to simplify error-handling.
283 PMBTOKEN_PRETOKEN *pretoken = OPENSSL_malloc(sizeof(PMBTOKEN_PRETOKEN));
284 if (pretoken == NULL ||
285 !sk_PMBTOKEN_PRETOKEN_push(pretokens, pretoken)) {
286 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
287 PMBTOKEN_PRETOKEN_free(pretoken);
288 goto err;
289 }
290
291 RAND_bytes(pretoken->t, sizeof(pretoken->t));
292
293 // We sample |pretoken->r| in Montgomery form to simplify inverting.
294 if (!ec_random_nonzero_scalar(group, &pretoken->r,
295 kDefaultAdditionalData)) {
296 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
297 goto err;
298 }
299
300 EC_SCALAR rinv;
301 ec_scalar_inv0_montgomery(group, &rinv, &pretoken->r);
302 // Convert both out of Montgomery form.
303 ec_scalar_from_montgomery(group, &pretoken->r, &pretoken->r);
304 ec_scalar_from_montgomery(group, &rinv, &rinv);
305
306 EC_RAW_POINT T, Tp;
307 if (!method->hash_t(group, &T, pretoken->t) ||
308 !ec_point_mul_scalar(group, &Tp, &T, &rinv) ||
309 !ec_jacobian_to_affine(group, &pretoken->Tp, &Tp)) {
310 goto err;
311 }
312
313 if (!cbb_add_prefixed_point(cbb, group, &pretoken->Tp,
314 method->prefix_point)) {
315 goto err;
316 }
317 }
318
319 return pretokens;
320
321err:
322 sk_PMBTOKEN_PRETOKEN_pop_free(pretokens, PMBTOKEN_PRETOKEN_free);
323 return NULL;
324}
325
326static int scalar_to_cbb(CBB *out, const EC_GROUP *group,
327 const EC_SCALAR *scalar) {
328 uint8_t *buf;
329 size_t scalar_len = BN_num_bytes(&group->order);
330 if (!CBB_add_space(out, &buf, scalar_len)) {
331 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
332 return 0;
333 }
334 ec_scalar_to_bytes(group, buf, &scalar_len, scalar);
335 return 1;
336}
337
338static int scalar_from_cbs(CBS *cbs, const EC_GROUP *group, EC_SCALAR *out) {
339 size_t scalar_len = BN_num_bytes(&group->order);
340 CBS tmp;
341 if (!CBS_get_bytes(cbs, &tmp, scalar_len)) {
342 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
343 return 0;
344 }
345
346 ec_scalar_from_bytes(group, out, CBS_data(&tmp), CBS_len(&tmp));
347 return 1;
348}
349
350static int hash_c_dleq(const PMBTOKEN_METHOD *method, EC_SCALAR *out,
351 const EC_AFFINE *X, const EC_AFFINE *T,
352 const EC_AFFINE *S, const EC_AFFINE *W,
353 const EC_AFFINE *K0, const EC_AFFINE *K1) {
354 static const uint8_t kDLEQ2Label[] = "DLEQ2";
355
356 int ok = 0;
357 CBB cbb;
358 CBB_zero(&cbb);
359 uint8_t *buf = NULL;
360 size_t len;
361 if (!CBB_init(&cbb, 0) ||
362 !CBB_add_bytes(&cbb, kDLEQ2Label, sizeof(kDLEQ2Label)) ||
363 !point_to_cbb(&cbb, method->group, X) ||
364 !point_to_cbb(&cbb, method->group, T) ||
365 !point_to_cbb(&cbb, method->group, S) ||
366 !point_to_cbb(&cbb, method->group, W) ||
367 !point_to_cbb(&cbb, method->group, K0) ||
368 !point_to_cbb(&cbb, method->group, K1) ||
369 !CBB_finish(&cbb, &buf, &len) ||
370 !method->hash_c(method->group, out, buf, len)) {
371 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
372 goto err;
373 }
374
375 ok = 1;
376
377err:
378 CBB_cleanup(&cbb);
379 OPENSSL_free(buf);
380 return ok;
381}
382
383static int hash_c_dleqor(const PMBTOKEN_METHOD *method, EC_SCALAR *out,
384 const EC_AFFINE *X0, const EC_AFFINE *X1,
385 const EC_AFFINE *T, const EC_AFFINE *S,
386 const EC_AFFINE *W, const EC_AFFINE *K00,
387 const EC_AFFINE *K01, const EC_AFFINE *K10,
388 const EC_AFFINE *K11) {
389 static const uint8_t kDLEQOR2Label[] = "DLEQOR2";
390
391 int ok = 0;
392 CBB cbb;
393 CBB_zero(&cbb);
394 uint8_t *buf = NULL;
395 size_t len;
396 if (!CBB_init(&cbb, 0) ||
397 !CBB_add_bytes(&cbb, kDLEQOR2Label, sizeof(kDLEQOR2Label)) ||
398 !point_to_cbb(&cbb, method->group, X0) ||
399 !point_to_cbb(&cbb, method->group, X1) ||
400 !point_to_cbb(&cbb, method->group, T) ||
401 !point_to_cbb(&cbb, method->group, S) ||
402 !point_to_cbb(&cbb, method->group, W) ||
403 !point_to_cbb(&cbb, method->group, K00) ||
404 !point_to_cbb(&cbb, method->group, K01) ||
405 !point_to_cbb(&cbb, method->group, K10) ||
406 !point_to_cbb(&cbb, method->group, K11) ||
407 !CBB_finish(&cbb, &buf, &len) ||
408 !method->hash_c(method->group, out, buf, len)) {
409 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
410 goto err;
411 }
412
413 ok = 1;
414
415err:
416 CBB_cleanup(&cbb);
417 OPENSSL_free(buf);
418 return ok;
419}
420
421static int hash_c_batch(const PMBTOKEN_METHOD *method, EC_SCALAR *out,
422 const CBB *points, size_t index) {
423 static const uint8_t kDLEQBatchLabel[] = "DLEQ BATCH";
424 if (index > 0xffff) {
425 // The protocol supports only two-byte batches.
426 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
427 return 0;
428 }
429
430 int ok = 0;
431 CBB cbb;
432 CBB_zero(&cbb);
433 uint8_t *buf = NULL;
434 size_t len;
435 if (!CBB_init(&cbb, 0) ||
436 !CBB_add_bytes(&cbb, kDLEQBatchLabel, sizeof(kDLEQBatchLabel)) ||
437 !CBB_add_bytes(&cbb, CBB_data(points), CBB_len(points)) ||
438 !CBB_add_u16(&cbb, (uint16_t)index) ||
439 !CBB_finish(&cbb, &buf, &len) ||
440 !method->hash_c(method->group, out, buf, len)) {
441 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
442 goto err;
443 }
444
445 ok = 1;
446
447err:
448 CBB_cleanup(&cbb);
449 OPENSSL_free(buf);
450 return ok;
451}
452
453// The DLEQ2 and DLEQOR2 constructions are described in appendix B of
454// https://eprint.iacr.org/2020/072/20200324:214215. DLEQ2 is an instance of
455// DLEQOR2 with only one value (n=1).
456
457static int dleq_generate(const PMBTOKEN_METHOD *method, CBB *cbb,
458 const PMBTOKEN_ISSUER_KEY *priv, const EC_RAW_POINT *T,
459 const EC_RAW_POINT *S, const EC_RAW_POINT *W,
460 const EC_RAW_POINT *Ws, uint8_t private_metadata) {
461 const EC_GROUP *group = method->group;
462
463 // We generate a DLEQ proof for the validity token and a DLEQOR2 proof for the
464 // private metadata token. To allow amortizing Jacobian-to-affine conversions,
465 // we compute Ki for both proofs first.
466 enum {
467 idx_T,
468 idx_S,
469 idx_W,
470 idx_Ws,
471 idx_Ks0,
472 idx_Ks1,
473 idx_Kb0,
474 idx_Kb1,
475 idx_Ko0,
476 idx_Ko1,
477 num_idx,
478 };
479 EC_RAW_POINT jacobians[num_idx];
480
481 // Setup the DLEQ proof.
482 EC_SCALAR ks0, ks1;
483 if (// ks0, ks1 <- Zp
484 !ec_random_nonzero_scalar(group, &ks0, kDefaultAdditionalData) ||
485 !ec_random_nonzero_scalar(group, &ks1, kDefaultAdditionalData) ||
486 // Ks = ks0*(G;T) + ks1*(H;S)
487 !ec_point_mul_scalar_precomp(group, &jacobians[idx_Ks0],
488 &method->g_precomp, &ks0, &method->h_precomp,
489 &ks1, NULL, NULL) ||
490 !ec_point_mul_scalar_batch(group, &jacobians[idx_Ks1], T, &ks0, S, &ks1,
491 NULL, NULL)) {
492 return 0;
493 }
494
495 // Setup the DLEQOR proof. First, select values of xb, yb (keys corresponding
496 // to the private metadata value) and pubo (public key corresponding to the
497 // other value) in constant time.
498 BN_ULONG mask = ((BN_ULONG)0) - (private_metadata & 1);
499 EC_PRECOMP pubo_precomp;
500 EC_SCALAR xb, yb;
501 ec_scalar_select(group, &xb, mask, &priv->x1, &priv->x0);
502 ec_scalar_select(group, &yb, mask, &priv->y1, &priv->y0);
503 ec_precomp_select(group, &pubo_precomp, mask, &priv->pub0_precomp,
504 &priv->pub1_precomp);
505
506 EC_SCALAR k0, k1, minus_co, uo, vo;
507 if (// k0, k1 <- Zp
508 !ec_random_nonzero_scalar(group, &k0, kDefaultAdditionalData) ||
509 !ec_random_nonzero_scalar(group, &k1, kDefaultAdditionalData) ||
510 // Kb = k0*(G;T) + k1*(H;S)
511 !ec_point_mul_scalar_precomp(group, &jacobians[idx_Kb0],
512 &method->g_precomp, &k0, &method->h_precomp,
513 &k1, NULL, NULL) ||
514 !ec_point_mul_scalar_batch(group, &jacobians[idx_Kb1], T, &k0, S, &k1,
515 NULL, NULL) ||
516 // co, uo, vo <- Zp
517 !ec_random_nonzero_scalar(group, &minus_co, kDefaultAdditionalData) ||
518 !ec_random_nonzero_scalar(group, &uo, kDefaultAdditionalData) ||
519 !ec_random_nonzero_scalar(group, &vo, kDefaultAdditionalData) ||
520 // Ko = uo*(G;T) + vo*(H;S) - co*(pubo;W)
521 !ec_point_mul_scalar_precomp(group, &jacobians[idx_Ko0],
522 &method->g_precomp, &uo, &method->h_precomp,
523 &vo, &pubo_precomp, &minus_co) ||
524 !ec_point_mul_scalar_batch(group, &jacobians[idx_Ko1], T, &uo, S, &vo, W,
525 &minus_co)) {
526 return 0;
527 }
528
529 EC_AFFINE affines[num_idx];
530 jacobians[idx_T] = *T;
531 jacobians[idx_S] = *S;
532 jacobians[idx_W] = *W;
533 jacobians[idx_Ws] = *Ws;
534 if (!ec_jacobian_to_affine_batch(group, affines, jacobians, num_idx)) {
535 return 0;
536 }
537
538 // Select the K corresponding to K0 and K1 in constant-time.
539 EC_AFFINE K00, K01, K10, K11;
540 ec_affine_select(group, &K00, mask, &affines[idx_Ko0], &affines[idx_Kb0]);
541 ec_affine_select(group, &K01, mask, &affines[idx_Ko1], &affines[idx_Kb1]);
542 ec_affine_select(group, &K10, mask, &affines[idx_Kb0], &affines[idx_Ko0]);
543 ec_affine_select(group, &K11, mask, &affines[idx_Kb1], &affines[idx_Ko1]);
544
545 // Compute c = Hc(...) for the two proofs.
546 EC_SCALAR cs, c;
547 if (!hash_c_dleq(method, &cs, &priv->pubs, &affines[idx_T], &affines[idx_S],
548 &affines[idx_Ws], &affines[idx_Ks0], &affines[idx_Ks1]) ||
549 !hash_c_dleqor(method, &c, &priv->pub0, &priv->pub1, &affines[idx_T],
550 &affines[idx_S], &affines[idx_W], &K00, &K01, &K10,
551 &K11)) {
552 return 0;
553 }
554
555 // Compute cb, ub, and ub for the two proofs. In each of these products, only
556 // one operand is in Montgomery form, so the product does not need to be
557 // converted.
558
559 EC_SCALAR cs_mont;
560 ec_scalar_to_montgomery(group, &cs_mont, &cs);
561
562 // us = ks0 + cs*xs
563 EC_SCALAR us, vs;
564 ec_scalar_mul_montgomery(group, &us, &priv->xs, &cs_mont);
565 ec_scalar_add(group, &us, &ks0, &us);
566
567 // vs = ks1 + cs*ys
568 ec_scalar_mul_montgomery(group, &vs, &priv->ys, &cs_mont);
569 ec_scalar_add(group, &vs, &ks1, &vs);
570
571 // Store DLEQ2 proof in transcript.
572 if (!scalar_to_cbb(cbb, group, &cs) ||
573 !scalar_to_cbb(cbb, group, &us) ||
574 !scalar_to_cbb(cbb, group, &vs)) {
575 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
576 return 0;
577 }
578
579 // cb = c - co
580 EC_SCALAR cb, ub, vb;
581 ec_scalar_add(group, &cb, &c, &minus_co);
582
583 EC_SCALAR cb_mont;
584 ec_scalar_to_montgomery(group, &cb_mont, &cb);
585
586 // ub = k0 + cb*xb
587 ec_scalar_mul_montgomery(group, &ub, &xb, &cb_mont);
588 ec_scalar_add(group, &ub, &k0, &ub);
589
590 // vb = k1 + cb*yb
591 ec_scalar_mul_montgomery(group, &vb, &yb, &cb_mont);
592 ec_scalar_add(group, &vb, &k1, &vb);
593
594 // Select c, u, v in constant-time.
595 EC_SCALAR co, c0, c1, u0, u1, v0, v1;
596 ec_scalar_neg(group, &co, &minus_co);
597 ec_scalar_select(group, &c0, mask, &co, &cb);
598 ec_scalar_select(group, &u0, mask, &uo, &ub);
599 ec_scalar_select(group, &v0, mask, &vo, &vb);
600 ec_scalar_select(group, &c1, mask, &cb, &co);
601 ec_scalar_select(group, &u1, mask, &ub, &uo);
602 ec_scalar_select(group, &v1, mask, &vb, &vo);
603
604 // Store DLEQOR2 proof in transcript.
605 if (!scalar_to_cbb(cbb, group, &c0) ||
606 !scalar_to_cbb(cbb, group, &c1) ||
607 !scalar_to_cbb(cbb, group, &u0) ||
608 !scalar_to_cbb(cbb, group, &u1) ||
609 !scalar_to_cbb(cbb, group, &v0) ||
610 !scalar_to_cbb(cbb, group, &v1)) {
611 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
612 return 0;
613 }
614
615 return 1;
616}
617
618static int dleq_verify(const PMBTOKEN_METHOD *method, CBS *cbs,
619 const PMBTOKEN_CLIENT_KEY *pub, const EC_RAW_POINT *T,
620 const EC_RAW_POINT *S, const EC_RAW_POINT *W,
621 const EC_RAW_POINT *Ws) {
622 const EC_GROUP *group = method->group;
623 const EC_RAW_POINT *g = &group->generator->raw;
624
625 // We verify a DLEQ proof for the validity token and a DLEQOR2 proof for the
626 // private metadata token. To allow amortizing Jacobian-to-affine conversions,
627 // we compute Ki for both proofs first. Additionally, all inputs to this
628 // function are public, so we can use the faster variable-time
629 // multiplications.
630 enum {
631 idx_T,
632 idx_S,
633 idx_W,
634 idx_Ws,
635 idx_Ks0,
636 idx_Ks1,
637 idx_K00,
638 idx_K01,
639 idx_K10,
640 idx_K11,
641 num_idx,
642 };
643 EC_RAW_POINT jacobians[num_idx];
644
645 // Decode the DLEQ proof.
646 EC_SCALAR cs, us, vs;
647 if (!scalar_from_cbs(cbs, group, &cs) ||
648 !scalar_from_cbs(cbs, group, &us) ||
649 !scalar_from_cbs(cbs, group, &vs)) {
650 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
651 return 0;
652 }
653
654 // Ks = us*(G;T) + vs*(H;S) - cs*(pubs;Ws)
655 EC_RAW_POINT pubs;
656 ec_affine_to_jacobian(group, &pubs, &pub->pubs);
657 EC_SCALAR minus_cs;
658 ec_scalar_neg(group, &minus_cs, &cs);
659 if (!mul_public_3(group, &jacobians[idx_Ks0], g, &us, &method->h, &vs, &pubs,
660 &minus_cs) ||
661 !mul_public_3(group, &jacobians[idx_Ks1], T, &us, S, &vs, Ws,
662 &minus_cs)) {
663 return 0;
664 }
665
666 // Decode the DLEQOR proof.
667 EC_SCALAR c0, c1, u0, u1, v0, v1;
668 if (!scalar_from_cbs(cbs, group, &c0) ||
669 !scalar_from_cbs(cbs, group, &c1) ||
670 !scalar_from_cbs(cbs, group, &u0) ||
671 !scalar_from_cbs(cbs, group, &u1) ||
672 !scalar_from_cbs(cbs, group, &v0) ||
673 !scalar_from_cbs(cbs, group, &v1)) {
674 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
675 return 0;
676 }
677
678 EC_RAW_POINT pub0, pub1;
679 ec_affine_to_jacobian(group, &pub0, &pub->pub0);
680 ec_affine_to_jacobian(group, &pub1, &pub->pub1);
681 EC_SCALAR minus_c0, minus_c1;
682 ec_scalar_neg(group, &minus_c0, &c0);
683 ec_scalar_neg(group, &minus_c1, &c1);
684 if (// K0 = u0*(G;T) + v0*(H;S) - c0*(pub0;W)
685 !mul_public_3(group, &jacobians[idx_K00], g, &u0, &method->h, &v0, &pub0,
686 &minus_c0) ||
687 !mul_public_3(group, &jacobians[idx_K01], T, &u0, S, &v0, W, &minus_c0) ||
688 // K1 = u1*(G;T) + v1*(H;S) - c1*(pub1;W)
689 !mul_public_3(group, &jacobians[idx_K10], g, &u1, &method->h, &v1, &pub1,
690 &minus_c1) ||
691 !mul_public_3(group, &jacobians[idx_K11], T, &u1, S, &v1, W, &minus_c1)) {
692 return 0;
693 }
694
695 EC_AFFINE affines[num_idx];
696 jacobians[idx_T] = *T;
697 jacobians[idx_S] = *S;
698 jacobians[idx_W] = *W;
699 jacobians[idx_Ws] = *Ws;
700 if (!ec_jacobian_to_affine_batch(group, affines, jacobians, num_idx)) {
701 return 0;
702 }
703
704 // Check the DLEQ proof.
705 EC_SCALAR calculated;
706 if (!hash_c_dleq(method, &calculated, &pub->pubs, &affines[idx_T],
707 &affines[idx_S], &affines[idx_Ws], &affines[idx_Ks0],
708 &affines[idx_Ks1])) {
709 return 0;
710 }
711
712 // cs == calculated
713 if (!ec_scalar_equal_vartime(group, &cs, &calculated)) {
714 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_PROOF);
715 return 0;
716 }
717
718 // Check the DLEQOR proof.
719 if (!hash_c_dleqor(method, &calculated, &pub->pub0, &pub->pub1,
720 &affines[idx_T], &affines[idx_S], &affines[idx_W],
721 &affines[idx_K00], &affines[idx_K01], &affines[idx_K10],
722 &affines[idx_K11])) {
723 return 0;
724 }
725
726 // c0 + c1 == calculated
727 EC_SCALAR c;
728 ec_scalar_add(group, &c, &c0, &c1);
729 if (!ec_scalar_equal_vartime(group, &c, &calculated)) {
730 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_PROOF);
731 return 0;
732 }
733
734 return 1;
735}
736
737static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
738 const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
739 size_t num_requested, size_t num_to_issue,
740 uint8_t private_metadata) {
741 const EC_GROUP *group = method->group;
742 if (num_requested < num_to_issue) {
743 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
744 return 0;
745 }
746
747 if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
748 num_to_issue > ((size_t)-1) / sizeof(EC_SCALAR)) {
749 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
750 return 0;
751 }
752
753 int ret = 0;
754 EC_RAW_POINT *Tps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
755 EC_RAW_POINT *Sps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
756 EC_RAW_POINT *Wps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
757 EC_RAW_POINT *Wsps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
758 EC_SCALAR *es = OPENSSL_malloc(num_to_issue * sizeof(EC_SCALAR));
759 CBB batch_cbb;
760 CBB_zero(&batch_cbb);
761 if (!Tps ||
762 !Sps ||
763 !Wps ||
764 !Wsps ||
765 !es ||
766 !CBB_init(&batch_cbb, 0) ||
767 !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
768 !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
769 !point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
770 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
771 goto err;
772 }
773
774 for (size_t i = 0; i < num_to_issue; i++) {
775 EC_AFFINE Tp_affine;
776 EC_RAW_POINT Tp;
777 if (!cbs_get_prefixed_point(cbs, group, &Tp_affine, method->prefix_point)) {
778 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
779 goto err;
780 }
781 ec_affine_to_jacobian(group, &Tp, &Tp_affine);
782
783 EC_SCALAR xb, yb;
784 BN_ULONG mask = ((BN_ULONG)0) - (private_metadata & 1);
785 ec_scalar_select(group, &xb, mask, &key->x1, &key->x0);
786 ec_scalar_select(group, &yb, mask, &key->y1, &key->y0);
787
788 uint8_t s[PMBTOKEN_NONCE_SIZE];
789 RAND_bytes(s, PMBTOKEN_NONCE_SIZE);
790 // The |jacobians| and |affines| contain Sp, Wp, and Wsp.
791 EC_RAW_POINT jacobians[3];
792 EC_AFFINE affines[3];
793 if (!method->hash_s(group, &jacobians[0], &Tp_affine, s) ||
794 !ec_point_mul_scalar_batch(group, &jacobians[1], &Tp, &xb,
795 &jacobians[0], &yb, NULL, NULL) ||
796 !ec_point_mul_scalar_batch(group, &jacobians[2], &Tp, &key->xs,
797 &jacobians[0], &key->ys, NULL, NULL) ||
798 !ec_jacobian_to_affine_batch(group, affines, jacobians, 3) ||
799 !CBB_add_bytes(cbb, s, PMBTOKEN_NONCE_SIZE) ||
800 !cbb_add_prefixed_point(cbb, group, &affines[1], method->prefix_point) ||
801 !cbb_add_prefixed_point(cbb, group, &affines[2], method->prefix_point)) {
802 goto err;
803 }
804
805 if (!point_to_cbb(&batch_cbb, group, &Tp_affine) ||
806 !point_to_cbb(&batch_cbb, group, &affines[0]) ||
807 !point_to_cbb(&batch_cbb, group, &affines[1]) ||
808 !point_to_cbb(&batch_cbb, group, &affines[2])) {
809 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
810 goto err;
811 }
812 Tps[i] = Tp;
813 Sps[i] = jacobians[0];
814 Wps[i] = jacobians[1];
815 Wsps[i] = jacobians[2];
816
817 if (!CBB_flush(cbb)) {
818 goto err;
819 }
820 }
821
822 // The DLEQ batching construction is described in appendix B of
823 // https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
824 // computations all act on public inputs.
825 for (size_t i = 0; i < num_to_issue; i++) {
826 if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
827 goto err;
828 }
829 }
830
831 EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
832 if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
833 /*g_scalar=*/NULL, Tps, es,
834 num_to_issue) ||
835 !ec_point_mul_scalar_public_batch(group, &Sp_batch,
836 /*g_scalar=*/NULL, Sps, es,
837 num_to_issue) ||
838 !ec_point_mul_scalar_public_batch(group, &Wp_batch,
839 /*g_scalar=*/NULL, Wps, es,
840 num_to_issue) ||
841 !ec_point_mul_scalar_public_batch(group, &Wsp_batch,
842 /*g_scalar=*/NULL, Wsps, es,
843 num_to_issue)) {
844 goto err;
845 }
846
847 CBB proof;
848 if (!CBB_add_u16_length_prefixed(cbb, &proof) ||
849 !dleq_generate(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
850 &Wsp_batch, private_metadata) ||
851 !CBB_flush(cbb)) {
852 goto err;
853 }
854
855 // Skip over any unused requests.
856 size_t point_len = 1 + 2 * BN_num_bytes(&group->field);
857 size_t token_len = point_len;
858 if (method->prefix_point) {
859 token_len += 2;
860 }
861 if (!CBS_skip(cbs, token_len * (num_requested - num_to_issue))) {
862 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
863 goto err;
864 }
865
866 ret = 1;
867
868err:
869 OPENSSL_free(Tps);
870 OPENSSL_free(Sps);
871 OPENSSL_free(Wps);
872 OPENSSL_free(Wsps);
873 OPENSSL_free(es);
874 CBB_cleanup(&batch_cbb);
875 return ret;
876}
877
878static STACK_OF(TRUST_TOKEN) *
879 pmbtoken_unblind(const PMBTOKEN_METHOD *method,
880 const PMBTOKEN_CLIENT_KEY *key,
881 const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens, CBS *cbs,
882 size_t count, uint32_t key_id) {
883 const EC_GROUP *group = method->group;
884 if (count > sk_PMBTOKEN_PRETOKEN_num(pretokens)) {
885 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
886 return NULL;
887 }
888
889 int ok = 0;
890 STACK_OF(TRUST_TOKEN) *ret = sk_TRUST_TOKEN_new_null();
891 if (ret == NULL) {
892 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
893 return NULL;
894 }
895
896 if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
897 count > ((size_t)-1) / sizeof(EC_SCALAR)) {
898 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
899 return 0;
900 }
901 EC_RAW_POINT *Tps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
902 EC_RAW_POINT *Sps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
903 EC_RAW_POINT *Wps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
904 EC_RAW_POINT *Wsps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
905 EC_SCALAR *es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
906 CBB batch_cbb;
907 CBB_zero(&batch_cbb);
908 if (!Tps ||
909 !Sps ||
910 !Wps ||
911 !Wsps ||
912 !es ||
913 !CBB_init(&batch_cbb, 0) ||
914 !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
915 !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
916 !point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
917 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
918 goto err;
919 }
920
921 for (size_t i = 0; i < count; i++) {
922 const PMBTOKEN_PRETOKEN *pretoken =
923 sk_PMBTOKEN_PRETOKEN_value(pretokens, i);
924
925 uint8_t s[PMBTOKEN_NONCE_SIZE];
926 EC_AFFINE Wp_affine, Wsp_affine;
927 if (!CBS_copy_bytes(cbs, s, PMBTOKEN_NONCE_SIZE) ||
928 !cbs_get_prefixed_point(cbs, group, &Wp_affine, method->prefix_point) ||
929 !cbs_get_prefixed_point(cbs, group, &Wsp_affine,
930 method->prefix_point)) {
931 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
932 goto err;
933 }
934
935 ec_affine_to_jacobian(group, &Tps[i], &pretoken->Tp);
936 ec_affine_to_jacobian(group, &Wps[i], &Wp_affine);
937 ec_affine_to_jacobian(group, &Wsps[i], &Wsp_affine);
938 if (!method->hash_s(group, &Sps[i], &pretoken->Tp, s)) {
939 goto err;
940 }
941
942 EC_AFFINE Sp_affine;
943 if (!point_to_cbb(&batch_cbb, group, &pretoken->Tp) ||
944 !ec_jacobian_to_affine(group, &Sp_affine, &Sps[i]) ||
945 !point_to_cbb(&batch_cbb, group, &Sp_affine) ||
946 !point_to_cbb(&batch_cbb, group, &Wp_affine) ||
947 !point_to_cbb(&batch_cbb, group, &Wsp_affine)) {
948 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
949 goto err;
950 }
951
952 // Unblind the token.
953 EC_RAW_POINT jacobians[3];
954 EC_AFFINE affines[3];
955 if (!ec_point_mul_scalar(group, &jacobians[0], &Sps[i], &pretoken->r) ||
956 !ec_point_mul_scalar(group, &jacobians[1], &Wps[i], &pretoken->r) ||
957 !ec_point_mul_scalar(group, &jacobians[2], &Wsps[i], &pretoken->r) ||
958 !ec_jacobian_to_affine_batch(group, affines, jacobians, 3)) {
959 goto err;
960 }
961
962 // Serialize the token. Include |key_id| to avoid an extra copy in the layer
963 // above.
964 CBB token_cbb;
965 size_t point_len = 1 + 2 * BN_num_bytes(&group->field);
966 if (!CBB_init(&token_cbb, 4 + PMBTOKEN_NONCE_SIZE + 3 * (2 + point_len)) ||
967 !CBB_add_u32(&token_cbb, key_id) ||
968 !CBB_add_bytes(&token_cbb, pretoken->t, PMBTOKEN_NONCE_SIZE) ||
969 !cbb_add_prefixed_point(&token_cbb, group, &affines[0],
970 method->prefix_point) ||
971 !cbb_add_prefixed_point(&token_cbb, group, &affines[1],
972 method->prefix_point) ||
973 !cbb_add_prefixed_point(&token_cbb, group, &affines[2],
974 method->prefix_point) ||
975 !CBB_flush(&token_cbb)) {
976 CBB_cleanup(&token_cbb);
977 goto err;
978 }
979
980 TRUST_TOKEN *token =
981 TRUST_TOKEN_new(CBB_data(&token_cbb), CBB_len(&token_cbb));
982 CBB_cleanup(&token_cbb);
983 if (token == NULL ||
984 !sk_TRUST_TOKEN_push(ret, token)) {
985 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
986 TRUST_TOKEN_free(token);
987 goto err;
988 }
989 }
990
991 // The DLEQ batching construction is described in appendix B of
992 // https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
993 // computations all act on public inputs.
994 for (size_t i = 0; i < count; i++) {
995 if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
996 goto err;
997 }
998 }
999
1000 EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
1001 if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
1002 /*g_scalar=*/NULL, Tps, es, count) ||
1003 !ec_point_mul_scalar_public_batch(group, &Sp_batch,
1004 /*g_scalar=*/NULL, Sps, es, count) ||
1005 !ec_point_mul_scalar_public_batch(group, &Wp_batch,
1006 /*g_scalar=*/NULL, Wps, es, count) ||
1007 !ec_point_mul_scalar_public_batch(group, &Wsp_batch,
1008 /*g_scalar=*/NULL, Wsps, es, count)) {
1009 goto err;
1010 }
1011
1012 CBS proof;
1013 if (!CBS_get_u16_length_prefixed(cbs, &proof) ||
1014 !dleq_verify(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
1015 &Wsp_batch) ||
1016 CBS_len(&proof) != 0) {
1017 goto err;
1018 }
1019
1020 ok = 1;
1021
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,
1037 const PMBTOKEN_ISSUER_KEY *key,
1038 uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
1039 uint8_t *out_private_metadata, const uint8_t *token,
1040 size_t token_len) {
1041 const EC_GROUP *group = method->group;
1042 CBS cbs;
1043 CBS_init(&cbs, token, token_len);
1044 EC_AFFINE S, W, Ws;
1045 if (!CBS_copy_bytes(&cbs, out_nonce, PMBTOKEN_NONCE_SIZE) ||
1046 !cbs_get_prefixed_point(&cbs, group, &S, method->prefix_point) ||
1047 !cbs_get_prefixed_point(&cbs, group, &W, method->prefix_point) ||
1048 !cbs_get_prefixed_point(&cbs, group, &Ws, method->prefix_point) ||
1049 CBS_len(&cbs) != 0) {
1050 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_TOKEN);
1051 return 0;
1052 }
1053
1054
1055 EC_RAW_POINT T;
1056 if (!method->hash_t(group, &T, out_nonce)) {
1057 return 0;
1058 }
1059
1060 // We perform three multiplications with S and T. This is enough that it is
1061 // worth using |ec_point_mul_scalar_precomp|.
1062 EC_RAW_POINT S_jacobian;
1063 EC_PRECOMP S_precomp, T_precomp;
1064 ec_affine_to_jacobian(group, &S_jacobian, &S);
1065 if (!ec_init_precomp(group, &S_precomp, &S_jacobian) ||
1066 !ec_init_precomp(group, &T_precomp, &T)) {
1067 return 0;
1068 }
1069
1070 EC_RAW_POINT Ws_calculated;
1071 // Check the validity of the token.
1072 if (!ec_point_mul_scalar_precomp(group, &Ws_calculated, &T_precomp, &key->xs,
1073 &S_precomp, &key->ys, NULL, NULL) ||
1074 !ec_affine_jacobian_equal(group, &Ws, &Ws_calculated)) {
1075 OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BAD_VALIDITY_CHECK);
1076 return 0;
1077 }
1078
1079 EC_RAW_POINT W0, W1;
1080 if (!ec_point_mul_scalar_precomp(group, &W0, &T_precomp, &key->x0, &S_precomp,
1081 &key->y0, NULL, NULL) ||
1082 !ec_point_mul_scalar_precomp(group, &W1, &T_precomp, &key->x1, &S_precomp,
1083 &key->y1, NULL, NULL)) {
1084 return 0;
1085 }
1086
1087 const int is_W0 = ec_affine_jacobian_equal(group, &W, &W0);
1088 const int is_W1 = ec_affine_jacobian_equal(group, &W, &W1);
1089 const int is_valid = is_W0 ^ is_W1;
1090 if (!is_valid) {
1091 // Invalid tokens will fail the validity check above.
1092 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
1093 return 0;
1094 }
1095
1096 *out_private_metadata = is_W1;
1097 return 1;
1098}
1099
1100
1101// PMBTokens experiment v1.
1102
1103static int pmbtoken_exp1_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
1104 const uint8_t t[PMBTOKEN_NONCE_SIZE]) {
1105 const uint8_t kHashTLabel[] = "PMBTokens Experiment V1 HashT";
1106 return ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
1107 group, out, kHashTLabel, sizeof(kHashTLabel), t, PMBTOKEN_NONCE_SIZE);
1108}
1109
1110static int pmbtoken_exp1_hash_s(const EC_GROUP *group, EC_RAW_POINT *out,
1111 const EC_AFFINE *t,
1112 const uint8_t s[PMBTOKEN_NONCE_SIZE]) {
1113 const uint8_t kHashSLabel[] = "PMBTokens Experiment V1 HashS";
1114 int ret = 0;
1115 CBB cbb;
1116 uint8_t *buf = NULL;
1117 size_t len;
1118 if (!CBB_init(&cbb, 0) ||
1119 !point_to_cbb(&cbb, group, t) ||
1120 !CBB_add_bytes(&cbb, s, PMBTOKEN_NONCE_SIZE) ||
1121 !CBB_finish(&cbb, &buf, &len) ||
1122 !ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
1123 group, out, kHashSLabel, sizeof(kHashSLabel), buf, len)) {
1124 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
1125 goto err;
1126 }
1127
1128 ret = 1;
1129
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
1185int pmbtoken_exp1_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
1186 const uint8_t *in, size_t len) {
1187 if (!pmbtoken_exp1_init_method()) {
1188 return 0;
1189 }
1190 return pmbtoken_client_key_from_bytes(&pmbtoken_exp1_method, key, in, len);
1191}
1192
1193int pmbtoken_exp1_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
1194 const uint8_t *in, size_t len) {
1195 if (!pmbtoken_exp1_init_method()) {
1196 return 0;
1197 }
1198 return pmbtoken_issuer_key_from_bytes(&pmbtoken_exp1_method, key, in, len);
1199}
1200
1201STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp1_blind(CBB *cbb, size_t count) {
1202 if (!pmbtoken_exp1_init_method()) {
1203 return NULL;
1204 }
1205 return pmbtoken_blind(&pmbtoken_exp1_method, cbb, count);
1206}
1207
1208int pmbtoken_exp1_sign(const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
1209 size_t num_requested, size_t num_to_issue,
1210 uint8_t private_metadata) {
1211 if (!pmbtoken_exp1_init_method()) {
1212 return 0;
1213 }
1214 return pmbtoken_sign(&pmbtoken_exp1_method, key, cbb, cbs, num_requested,
1215 num_to_issue, private_metadata);
1216}
1217
1218STACK_OF(TRUST_TOKEN) *
1219 pmbtoken_exp1_unblind(const PMBTOKEN_CLIENT_KEY *key,
1220 const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
1221 CBS *cbs, size_t count, uint32_t key_id) {
1222 if (!pmbtoken_exp1_init_method()) {
1223 return NULL;
1224 }
1225 return pmbtoken_unblind(&pmbtoken_exp1_method, key, pretokens, cbs, count,
1226 key_id);
1227}
1228
1229int pmbtoken_exp1_read(const PMBTOKEN_ISSUER_KEY *key,
1230 uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
1231 uint8_t *out_private_metadata, const uint8_t *token,
1232 size_t token_len) {
1233 if (!pmbtoken_exp1_init_method()) {
1234 return 0;
1235 }
1236 return pmbtoken_read(&pmbtoken_exp1_method, key, out_nonce,
1237 out_private_metadata, token, token_len);
1238}
1239
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,
1254 const uint8_t t[PMBTOKEN_NONCE_SIZE]) {
1255 const uint8_t kHashTLabel[] = "PMBTokens Experiment V2 HashT";
1256 return ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
1257 group, out, kHashTLabel, sizeof(kHashTLabel), t, PMBTOKEN_NONCE_SIZE);
1258}
1259
1260static int pmbtoken_exp2_hash_s(const EC_GROUP *group, EC_RAW_POINT *out,
1261 const EC_AFFINE *t,
1262 const uint8_t s[PMBTOKEN_NONCE_SIZE]) {
1263 const uint8_t kHashSLabel[] = "PMBTokens Experiment V2 HashS";
1264 int ret = 0;
1265 CBB cbb;
1266 uint8_t *buf = NULL;
1267 size_t len;
1268 if (!CBB_init(&cbb, 0) ||
1269 !point_to_cbb(&cbb, group, t) ||
1270 !CBB_add_bytes(&cbb, s, PMBTOKEN_NONCE_SIZE) ||
1271 !CBB_finish(&cbb, &buf, &len) ||
1272 !ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
1273 group, out, kHashSLabel, sizeof(kHashSLabel), buf, len)) {
1274 OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
1275 goto err;
1276 }
1277
1278 ret = 1;
1279
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
1335int pmbtoken_exp2_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
1336 const uint8_t *in, size_t len) {
1337 if (!pmbtoken_exp2_init_method()) {
1338 return 0;
1339 }
1340 return pmbtoken_client_key_from_bytes(&pmbtoken_exp2_method, key, in, len);
1341}
1342
1343int pmbtoken_exp2_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
1344 const uint8_t *in, size_t len) {
1345 if (!pmbtoken_exp2_init_method()) {
1346 return 0;
1347 }
1348 return pmbtoken_issuer_key_from_bytes(&pmbtoken_exp2_method, key, in, len);
1349}
1350
1351STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp2_blind(CBB *cbb, size_t count) {
1352 if (!pmbtoken_exp2_init_method()) {
1353 return NULL;
1354 }
1355 return pmbtoken_blind(&pmbtoken_exp2_method, cbb, count);
1356}
1357
1358int pmbtoken_exp2_sign(const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
1359 size_t num_requested, size_t num_to_issue,
1360 uint8_t private_metadata) {
1361 if (!pmbtoken_exp2_init_method()) {
1362 return 0;
1363 }
1364 return pmbtoken_sign(&pmbtoken_exp2_method, key, cbb, cbs, num_requested,
1365 num_to_issue, private_metadata);
1366}
1367
1368STACK_OF(TRUST_TOKEN) *
1369 pmbtoken_exp2_unblind(const PMBTOKEN_CLIENT_KEY *key,
1370 const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
1371 CBS *cbs, size_t count, uint32_t key_id) {
1372 if (!pmbtoken_exp2_init_method()) {
1373 return NULL;
1374 }
1375 return pmbtoken_unblind(&pmbtoken_exp2_method, key, pretokens, cbs, count,
1376 key_id);
1377}
1378
1379int pmbtoken_exp2_read(const PMBTOKEN_ISSUER_KEY *key,
1380 uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
1381 uint8_t *out_private_metadata, const uint8_t *token,
1382 size_t token_len) {
1383 if (!pmbtoken_exp2_init_method()) {
1384 return 0;
1385 }
1386 return pmbtoken_read(&pmbtoken_exp2_method, key, out_nonce,
1387 out_private_metadata, token, token_len);
1388}
1389
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}