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