Add TrustTokenV2.

Changes:
- Remove point prefixes.
- Don't verify SRR on the client.

TODO:
- Replace SRR generation with RR generation on issuer.
- Add finalized PrivacyPass version.

Change-Id: Ibfb04aaba2cf669639af77299da22ab668175edb
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42824
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
chromium-5359
Steven Valdez 5 years ago committed by CQ bot account: commit-bot@chromium.org
parent ee4af9e94e
commit 9adcb0aa7e
  1. 46
      crypto/trust_token/internal.h
  2. 270
      crypto/trust_token/pmbtoken.c
  3. 84
      crypto/trust_token/trust_token.c
  4. 123
      crypto/trust_token/trust_token_test.cc
  5. 32
      include/openssl/trust_token.h

@ -110,6 +110,39 @@ int pmbtoken_exp1_read(const PMBTOKEN_ISSUER_KEY *key,
// function is used to confirm H was computed as expected. // function is used to confirm H was computed as expected.
OPENSSL_EXPORT int pmbtoken_exp1_get_h_for_testing(uint8_t out[97]); OPENSSL_EXPORT int pmbtoken_exp1_get_h_for_testing(uint8_t out[97]);
// The following functions implement the corresponding |TRUST_TOKENS_METHOD|
// functions for |TRUST_TOKENS_experiment_v2|'s PMBTokens construction which
// uses P-384.
//
// We use P-384 instead of our usual choice of P-256. See Appendix I which
// describes two attacks which may affect smaller curves. In particular, p-1 for
// P-256 is smooth, giving a low complexity for the p-1 attack. P-384's p-1 has
// a 281-bit prime factor,
// 3055465788140352002733946906144561090641249606160407884365391979704929268480326390471.
// This lower-bounds the p-1 attack at O(2^140). The p+1 attack is lower-bounded
// by O(p^(1/3)) or O(2^128), so we do not need to check the smoothness of p+1.
int pmbtoken_exp2_generate_key(CBB *out_private, CBB *out_public);
int pmbtoken_exp2_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
const uint8_t *in, size_t len);
int pmbtoken_exp2_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
const uint8_t *in, size_t len);
STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp2_blind(CBB *cbb, size_t count);
int pmbtoken_exp2_sign(const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
size_t num_requested, size_t num_to_issue,
uint8_t private_metadata);
STACK_OF(TRUST_TOKEN) *
pmbtoken_exp2_unblind(const PMBTOKEN_CLIENT_KEY *key,
const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
CBS *cbs, size_t count, uint32_t key_id);
int pmbtoken_exp2_read(const PMBTOKEN_ISSUER_KEY *key,
uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
uint8_t *out_private_metadata, const uint8_t *token,
size_t token_len);
// pmbtoken_exp2_get_h_for_testing returns H in uncompressed coordinates. This
// function is used to confirm H was computed as expected.
OPENSSL_EXPORT int pmbtoken_exp2_get_h_for_testing(uint8_t out[97]);
// Trust Tokens internals. // Trust Tokens internals.
@ -172,6 +205,15 @@ struct trust_token_method_st {
uint8_t out_nonce[PMBTOKEN_NONCE_SIZE], uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
uint8_t *out_private_metadata, const uint8_t *token, uint8_t *out_private_metadata, const uint8_t *token,
size_t token_len); size_t token_len);
// whether the construction supports private metadata.
int has_private_metadata;
// max keys that can be configured.
size_t max_keys;
// whether the SRR is part of the protocol.
int has_srr;
}; };
// Structure representing a single Trust Token public key with the specified ID. // Structure representing a single Trust Token public key with the specified ID.
@ -195,7 +237,7 @@ struct trust_token_client_st {
// keys is the set of public keys that are supported by the client for // keys is the set of public keys that are supported by the client for
// issuance/redemptions. // issuance/redemptions.
struct trust_token_client_key_st keys[3]; struct trust_token_client_key_st keys[6];
// num_keys is the number of keys currently configured. // num_keys is the number of keys currently configured.
size_t num_keys; size_t num_keys;
@ -217,7 +259,7 @@ struct trust_token_issuer_st {
// keys is the set of private keys that are supported by the issuer for // keys is the set of private keys that are supported by the issuer for
// issuance/redemptions. The public metadata is an index into this list of // issuance/redemptions. The public metadata is an index into this list of
// keys. // keys.
struct trust_token_issuer_key_st keys[3]; struct trust_token_issuer_key_st keys[6];
// num_keys is the number of keys currently configured. // num_keys is the number of keys currently configured.
size_t num_keys; size_t num_keys;

@ -52,6 +52,7 @@ typedef struct {
// hash_c implements the H_c operation in PMBTokens. It returns one on success // hash_c implements the H_c operation in PMBTokens. It returns one on success
// and zero on error. // and zero on error.
hash_c_func_t hash_c; hash_c_func_t hash_c;
int prefix_point : 1;
} PMBTOKEN_METHOD; } PMBTOKEN_METHOD;
static const uint8_t kDefaultAdditionalData[32] = {0}; static const uint8_t kDefaultAdditionalData[32] = {0};
@ -59,7 +60,7 @@ static const uint8_t kDefaultAdditionalData[32] = {0};
static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid, static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid,
const uint8_t *h_bytes, size_t h_len, const uint8_t *h_bytes, size_t h_len,
hash_t_func_t hash_t, hash_s_func_t hash_s, hash_t_func_t hash_t, hash_s_func_t hash_s,
hash_c_func_t hash_c) { hash_c_func_t hash_c, int prefix_point) {
method->group = EC_GROUP_new_by_curve_name(curve_nid); method->group = EC_GROUP_new_by_curve_name(curve_nid);
if (method->group == NULL) { if (method->group == NULL) {
return 0; return 0;
@ -68,6 +69,7 @@ static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid,
method->hash_t = hash_t; method->hash_t = hash_t;
method->hash_s = hash_s; method->hash_s = hash_s;
method->hash_c = hash_c; method->hash_c = hash_c;
method->prefix_point = prefix_point;
EC_AFFINE h; EC_AFFINE h;
if (!ec_point_from_uncompressed(method->group, &h, h_bytes, h_len)) { if (!ec_point_from_uncompressed(method->group, &h, h_bytes, h_len)) {
@ -113,11 +115,40 @@ static int point_to_cbb(CBB *out, const EC_GROUP *group,
len) == len; len) == len;
} }
static int cbb_add_prefixed_point(CBB *out, const EC_GROUP *group,
const EC_AFFINE *point, int prefix_point) {
if (prefix_point) {
CBB child;
if (!CBB_add_u16_length_prefixed(out, &child) ||
!point_to_cbb(&child, group, point) ||
!CBB_flush(out)) {
return 0;
}
} else {
if (!point_to_cbb(out, group, point) ||
!CBB_flush(out)) {
return 0;
}
}
return 1;
}
static int cbs_get_prefixed_point(CBS *cbs, const EC_GROUP *group, static int cbs_get_prefixed_point(CBS *cbs, const EC_GROUP *group,
EC_AFFINE *out) { EC_AFFINE *out, int prefix_point) {
CBS child; CBS child;
if (!CBS_get_u16_length_prefixed(cbs, &child) || if (prefix_point) {
!ec_point_from_uncompressed(group, out, CBS_data(&child), if (!CBS_get_u16_length_prefixed(cbs, &child)) {
return 0;
}
} else {
size_t plen = 1 + 2 * BN_num_bytes(&group->field);
if (!CBS_get_bytes(cbs, &child, plen)) {
return 0;
}
}
if (!ec_point_from_uncompressed(group, out, CBS_data(&child),
CBS_len(&child))) { CBS_len(&child))) {
return 0; return 0;
} }
@ -166,16 +197,12 @@ static int pmbtoken_generate_key(const PMBTOKEN_METHOD *method,
return 0; return 0;
} }
// TODO(https://crbug.com/boringssl/331): When updating the key format, remove if (!cbb_add_prefixed_point(out_public, group, &pub_affine[0],
// the redundant length prefixes. method->prefix_point) ||
CBB child; !cbb_add_prefixed_point(out_public, group, &pub_affine[1],
if (!CBB_add_u16_length_prefixed(out_public, &child) || method->prefix_point) ||
!point_to_cbb(&child, group, &pub_affine[0]) || !cbb_add_prefixed_point(out_public, group, &pub_affine[2],
!CBB_add_u16_length_prefixed(out_public, &child) || method->prefix_point)) {
!point_to_cbb(&child, group, &pub_affine[1]) ||
!CBB_add_u16_length_prefixed(out_public, &child) ||
!point_to_cbb(&child, group, &pub_affine[2]) ||
!CBB_flush(out_public)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL);
return 0; return 0;
} }
@ -186,13 +213,14 @@ static int pmbtoken_generate_key(const PMBTOKEN_METHOD *method,
static int pmbtoken_client_key_from_bytes(const PMBTOKEN_METHOD *method, static int pmbtoken_client_key_from_bytes(const PMBTOKEN_METHOD *method,
PMBTOKEN_CLIENT_KEY *key, PMBTOKEN_CLIENT_KEY *key,
const uint8_t *in, size_t len) { const uint8_t *in, size_t len) {
// TODO(https://crbug.com/boringssl/331): When updating the key format, remove
// the redundant length prefixes.
CBS cbs; CBS cbs;
CBS_init(&cbs, in, len); CBS_init(&cbs, in, len);
if (!cbs_get_prefixed_point(&cbs, method->group, &key->pub0) || if (!cbs_get_prefixed_point(&cbs, method->group, &key->pub0,
!cbs_get_prefixed_point(&cbs, method->group, &key->pub1) || method->prefix_point) ||
!cbs_get_prefixed_point(&cbs, method->group, &key->pubs) || !cbs_get_prefixed_point(&cbs, method->group, &key->pub1,
method->prefix_point) ||
!cbs_get_prefixed_point(&cbs, method->group, &key->pubs,
method->prefix_point) ||
CBS_len(&cbs) != 0) { CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
return 0; return 0;
@ -282,12 +310,8 @@ static STACK_OF(PMBTOKEN_PRETOKEN) *
goto err; goto err;
} }
// TODO(https://crbug.com/boringssl/331): When updating the key format, if (!cbb_add_prefixed_point(cbb, group, &pretoken->Tp,
// remove the redundant length prefixes. method->prefix_point)) {
CBB child;
if (!CBB_add_u16_length_prefixed(cbb, &child) ||
!point_to_cbb(&child, group, &pretoken->Tp) ||
!CBB_flush(cbb)) {
goto err; goto err;
} }
} }
@ -750,7 +774,7 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
for (size_t i = 0; i < num_to_issue; i++) { for (size_t i = 0; i < num_to_issue; i++) {
EC_AFFINE Tp_affine; EC_AFFINE Tp_affine;
EC_RAW_POINT Tp; EC_RAW_POINT Tp;
if (!cbs_get_prefixed_point(cbs, group, &Tp_affine)) { if (!cbs_get_prefixed_point(cbs, group, &Tp_affine, method->prefix_point)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
goto err; goto err;
} }
@ -766,7 +790,6 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
// The |jacobians| and |affines| contain Sp, Wp, and Wsp. // The |jacobians| and |affines| contain Sp, Wp, and Wsp.
EC_RAW_POINT jacobians[3]; EC_RAW_POINT jacobians[3];
EC_AFFINE affines[3]; EC_AFFINE affines[3];
CBB child;
if (!method->hash_s(group, &jacobians[0], &Tp_affine, s) || if (!method->hash_s(group, &jacobians[0], &Tp_affine, s) ||
!ec_point_mul_scalar_batch(group, &jacobians[1], &Tp, &xb, !ec_point_mul_scalar_batch(group, &jacobians[1], &Tp, &xb,
&jacobians[0], &yb, NULL, NULL) || &jacobians[0], &yb, NULL, NULL) ||
@ -774,12 +797,8 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
&jacobians[0], &key->ys, NULL, NULL) || &jacobians[0], &key->ys, NULL, NULL) ||
!ec_jacobian_to_affine_batch(group, affines, jacobians, 3) || !ec_jacobian_to_affine_batch(group, affines, jacobians, 3) ||
!CBB_add_bytes(cbb, s, PMBTOKEN_NONCE_SIZE) || !CBB_add_bytes(cbb, s, PMBTOKEN_NONCE_SIZE) ||
// TODO(https://crbug.com/boringssl/331): When updating the key format, !cbb_add_prefixed_point(cbb, group, &affines[1], method->prefix_point) ||
// remove the redundant length prefixes. !cbb_add_prefixed_point(cbb, group, &affines[2], method->prefix_point)) {
!CBB_add_u16_length_prefixed(cbb, &child) ||
!point_to_cbb(&child, group, &affines[1]) ||
!CBB_add_u16_length_prefixed(cbb, &child) ||
!point_to_cbb(&child, group, &affines[2])) {
goto err; goto err;
} }
@ -835,7 +854,11 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
// Skip over any unused requests. // Skip over any unused requests.
size_t point_len = 1 + 2 * BN_num_bytes(&group->field); size_t point_len = 1 + 2 * BN_num_bytes(&group->field);
if (!CBS_skip(cbs, (2 + point_len) * (num_requested - num_to_issue))) { size_t token_len = point_len;
if (method->prefix_point) {
token_len += 2;
}
if (!CBS_skip(cbs, token_len * (num_requested - num_to_issue))) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
goto err; goto err;
} }
@ -902,8 +925,9 @@ static STACK_OF(TRUST_TOKEN) *
uint8_t s[PMBTOKEN_NONCE_SIZE]; uint8_t s[PMBTOKEN_NONCE_SIZE];
EC_AFFINE Wp_affine, Wsp_affine; EC_AFFINE Wp_affine, Wsp_affine;
if (!CBS_copy_bytes(cbs, s, PMBTOKEN_NONCE_SIZE) || if (!CBS_copy_bytes(cbs, s, PMBTOKEN_NONCE_SIZE) ||
!cbs_get_prefixed_point(cbs, group, &Wp_affine) || !cbs_get_prefixed_point(cbs, group, &Wp_affine, method->prefix_point) ||
!cbs_get_prefixed_point(cbs, group, &Wsp_affine)) { !cbs_get_prefixed_point(cbs, group, &Wsp_affine,
method->prefix_point)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
goto err; goto err;
} }
@ -937,19 +961,17 @@ static STACK_OF(TRUST_TOKEN) *
// Serialize the token. Include |key_id| to avoid an extra copy in the layer // Serialize the token. Include |key_id| to avoid an extra copy in the layer
// above. // above.
CBB token_cbb, child; CBB token_cbb;
size_t point_len = 1 + 2 * BN_num_bytes(&group->field); size_t point_len = 1 + 2 * BN_num_bytes(&group->field);
if (!CBB_init(&token_cbb, 4 + PMBTOKEN_NONCE_SIZE + 3 * (2 + point_len)) || if (!CBB_init(&token_cbb, 4 + PMBTOKEN_NONCE_SIZE + 3 * (2 + point_len)) ||
!CBB_add_u32(&token_cbb, key_id) || !CBB_add_u32(&token_cbb, key_id) ||
!CBB_add_bytes(&token_cbb, pretoken->t, PMBTOKEN_NONCE_SIZE) || !CBB_add_bytes(&token_cbb, pretoken->t, PMBTOKEN_NONCE_SIZE) ||
// TODO(https://crbug.com/boringssl/331): When updating the key format, !cbb_add_prefixed_point(&token_cbb, group, &affines[0],
// remove the redundant length prefixes. method->prefix_point) ||
!CBB_add_u16_length_prefixed(&token_cbb, &child) || !cbb_add_prefixed_point(&token_cbb, group, &affines[1],
!point_to_cbb(&child, group, &affines[0]) || method->prefix_point) ||
!CBB_add_u16_length_prefixed(&token_cbb, &child) || !cbb_add_prefixed_point(&token_cbb, group, &affines[2],
!point_to_cbb(&child, group, &affines[1]) || method->prefix_point) ||
!CBB_add_u16_length_prefixed(&token_cbb, &child) ||
!point_to_cbb(&child, group, &affines[2]) ||
!CBB_flush(&token_cbb)) { !CBB_flush(&token_cbb)) {
CBB_cleanup(&token_cbb); CBB_cleanup(&token_cbb);
goto err; goto err;
@ -1021,9 +1043,9 @@ static int pmbtoken_read(const PMBTOKEN_METHOD *method,
CBS_init(&cbs, token, token_len); CBS_init(&cbs, token, token_len);
EC_AFFINE S, W, Ws; EC_AFFINE S, W, Ws;
if (!CBS_copy_bytes(&cbs, out_nonce, PMBTOKEN_NONCE_SIZE) || if (!CBS_copy_bytes(&cbs, out_nonce, PMBTOKEN_NONCE_SIZE) ||
!cbs_get_prefixed_point(&cbs, group, &S) || !cbs_get_prefixed_point(&cbs, group, &S, method->prefix_point) ||
!cbs_get_prefixed_point(&cbs, group, &W) || !cbs_get_prefixed_point(&cbs, group, &W, method->prefix_point) ||
!cbs_get_prefixed_point(&cbs, group, &Ws) || !cbs_get_prefixed_point(&cbs, group, &Ws, method->prefix_point) ||
CBS_len(&cbs) != 0) { CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_TOKEN); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_TOKEN);
return 0; return 0;
@ -1140,7 +1162,7 @@ static void pmbtoken_exp1_init_method_impl(void) {
pmbtoken_exp1_ok = pmbtoken_exp1_ok =
pmbtoken_init_method(&pmbtoken_exp1_method, NID_secp384r1, kH, sizeof(kH), pmbtoken_init_method(&pmbtoken_exp1_method, NID_secp384r1, kH, sizeof(kH),
pmbtoken_exp1_hash_t, pmbtoken_exp1_hash_s, pmbtoken_exp1_hash_t, pmbtoken_exp1_hash_s,
pmbtoken_exp1_hash_c); pmbtoken_exp1_hash_c, 1);
} }
static int pmbtoken_exp1_init_method(void) { static int pmbtoken_exp1_init_method(void) {
@ -1225,3 +1247,153 @@ int pmbtoken_exp1_get_h_for_testing(uint8_t out[97]) {
ec_point_to_bytes(pmbtoken_exp1_method.group, &h, ec_point_to_bytes(pmbtoken_exp1_method.group, &h,
POINT_CONVERSION_UNCOMPRESSED, out, 97) == 97; POINT_CONVERSION_UNCOMPRESSED, out, 97) == 97;
} }
// PMBTokens experiment v2.
static int pmbtoken_exp2_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
const uint8_t t[PMBTOKEN_NONCE_SIZE]) {
const uint8_t kHashTLabel[] = "PMBTokens Experiment V2 HashT";
return ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
group, out, kHashTLabel, sizeof(kHashTLabel), t, PMBTOKEN_NONCE_SIZE);
}
static int pmbtoken_exp2_hash_s(const EC_GROUP *group, EC_RAW_POINT *out,
const EC_AFFINE *t,
const uint8_t s[PMBTOKEN_NONCE_SIZE]) {
const uint8_t kHashSLabel[] = "PMBTokens Experiment V2 HashS";
int ret = 0;
CBB cbb;
uint8_t *buf = NULL;
size_t len;
if (!CBB_init(&cbb, 0) ||
!point_to_cbb(&cbb, group, t) ||
!CBB_add_bytes(&cbb, s, PMBTOKEN_NONCE_SIZE) ||
!CBB_finish(&cbb, &buf, &len) ||
!ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
group, out, kHashSLabel, sizeof(kHashSLabel), buf, len)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
ret = 1;
err:
OPENSSL_free(buf);
CBB_cleanup(&cbb);
return ret;
}
static int pmbtoken_exp2_hash_c(const EC_GROUP *group, EC_SCALAR *out,
uint8_t *buf, size_t len) {
const uint8_t kHashCLabel[] = "PMBTokens Experiment V2 HashC";
return ec_hash_to_scalar_p384_xmd_sha512_draft07(
group, out, kHashCLabel, sizeof(kHashCLabel), buf, len);
}
static int pmbtoken_exp2_ok = 0;
static PMBTOKEN_METHOD pmbtoken_exp2_method;
static CRYPTO_once_t pmbtoken_exp2_method_once = CRYPTO_ONCE_INIT;
static void pmbtoken_exp2_init_method_impl(void) {
// This is the output of |ec_hash_to_scalar_p384_xmd_sha512_draft07| with DST
// "PMBTokens Experiment V2 HashH" and message "generator".
static const uint8_t kH[] = {
0x04, 0xbc, 0x27, 0x24, 0x99, 0xfa, 0xc9, 0xa4, 0x74, 0x6f, 0xf9,
0x07, 0x81, 0x55, 0xf8, 0x1f, 0x6f, 0xda, 0x09, 0xe7, 0x8c, 0x5d,
0x9e, 0x4e, 0x14, 0x7c, 0x53, 0x14, 0xbc, 0x7e, 0x29, 0x57, 0x92,
0x17, 0x94, 0x6e, 0xd2, 0xdf, 0xa5, 0x31, 0x1b, 0x4e, 0xb7, 0xfc,
0x93, 0xe3, 0x6e, 0x14, 0x1f, 0x4f, 0x14, 0xf3, 0xe5, 0x47, 0x61,
0x1c, 0x2c, 0x72, 0x25, 0xf0, 0x4a, 0x45, 0x23, 0x2d, 0x57, 0x93,
0x0e, 0xb2, 0x55, 0xb8, 0x57, 0x25, 0x4c, 0x1e, 0xdb, 0xfd, 0x58,
0x70, 0x17, 0x9a, 0xbb, 0x9e, 0x5e, 0x93, 0x9e, 0x92, 0xd3, 0xe8,
0x25, 0x62, 0xbf, 0x59, 0xb2, 0xd2, 0x3d, 0x71, 0xff
};
pmbtoken_exp2_ok =
pmbtoken_init_method(&pmbtoken_exp2_method, NID_secp384r1, kH, sizeof(kH),
pmbtoken_exp2_hash_t, pmbtoken_exp2_hash_s,
pmbtoken_exp2_hash_c, 0);
}
static int pmbtoken_exp2_init_method(void) {
CRYPTO_once(&pmbtoken_exp2_method_once, pmbtoken_exp2_init_method_impl);
if (!pmbtoken_exp2_ok) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int pmbtoken_exp2_generate_key(CBB *out_private, CBB *out_public) {
if (!pmbtoken_exp2_init_method()) {
return 0;
}
return pmbtoken_generate_key(&pmbtoken_exp2_method, out_private, out_public);
}
int pmbtoken_exp2_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
const uint8_t *in, size_t len) {
if (!pmbtoken_exp2_init_method()) {
return 0;
}
return pmbtoken_client_key_from_bytes(&pmbtoken_exp2_method, key, in, len);
}
int pmbtoken_exp2_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
const uint8_t *in, size_t len) {
if (!pmbtoken_exp2_init_method()) {
return 0;
}
return pmbtoken_issuer_key_from_bytes(&pmbtoken_exp2_method, key, in, len);
}
STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp2_blind(CBB *cbb, size_t count) {
if (!pmbtoken_exp2_init_method()) {
return NULL;
}
return pmbtoken_blind(&pmbtoken_exp2_method, cbb, count);
}
int pmbtoken_exp2_sign(const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
size_t num_requested, size_t num_to_issue,
uint8_t private_metadata) {
if (!pmbtoken_exp2_init_method()) {
return 0;
}
return pmbtoken_sign(&pmbtoken_exp2_method, key, cbb, cbs, num_requested,
num_to_issue, private_metadata);
}
STACK_OF(TRUST_TOKEN) *
pmbtoken_exp2_unblind(const PMBTOKEN_CLIENT_KEY *key,
const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
CBS *cbs, size_t count, uint32_t key_id) {
if (!pmbtoken_exp2_init_method()) {
return NULL;
}
return pmbtoken_unblind(&pmbtoken_exp2_method, key, pretokens, cbs, count,
key_id);
}
int pmbtoken_exp2_read(const PMBTOKEN_ISSUER_KEY *key,
uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
uint8_t *out_private_metadata, const uint8_t *token,
size_t token_len) {
if (!pmbtoken_exp2_init_method()) {
return 0;
}
return pmbtoken_read(&pmbtoken_exp2_method, key, out_nonce,
out_private_metadata, token, token_len);
}
int pmbtoken_exp2_get_h_for_testing(uint8_t out[97]) {
if (!pmbtoken_exp2_init_method()) {
return 0;
}
EC_AFFINE h;
return ec_jacobian_to_affine(pmbtoken_exp2_method.group, &h,
&pmbtoken_exp2_method.h) &&
ec_point_to_bytes(pmbtoken_exp2_method.group, &h,
POINT_CONVERSION_UNCOMPRESSED, out, 97) == 97;
}

@ -36,6 +36,41 @@ const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void) {
pmbtoken_exp1_sign, pmbtoken_exp1_sign,
pmbtoken_exp1_unblind, pmbtoken_exp1_unblind,
pmbtoken_exp1_read, pmbtoken_exp1_read,
1, /* has_private_metadata */
3, /* max_keys */
1, /* has_srr */
};
return &kMethod;
}
const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_pp(void) {
static const TRUST_TOKEN_METHOD kMethod = {
pmbtoken_exp2_generate_key,
pmbtoken_exp2_client_key_from_bytes,
pmbtoken_exp2_issuer_key_from_bytes,
pmbtoken_exp2_blind,
pmbtoken_exp2_sign,
pmbtoken_exp2_unblind,
pmbtoken_exp2_read,
0, /* has_private_metadata */
6, /* max_keys */
0, /* has_srr */
};
return &kMethod;
}
const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_pmb(void) {
static const TRUST_TOKEN_METHOD kMethod = {
pmbtoken_exp2_generate_key,
pmbtoken_exp2_client_key_from_bytes,
pmbtoken_exp2_issuer_key_from_bytes,
pmbtoken_exp2_blind,
pmbtoken_exp2_sign,
pmbtoken_exp2_unblind,
pmbtoken_exp2_read,
1, /* has_private_metadata */
3, /* max_keys */
0, /* has_srr */
}; };
return &kMethod; return &kMethod;
} }
@ -131,7 +166,8 @@ void TRUST_TOKEN_CLIENT_free(TRUST_TOKEN_CLIENT *ctx) {
int TRUST_TOKEN_CLIENT_add_key(TRUST_TOKEN_CLIENT *ctx, size_t *out_key_index, int TRUST_TOKEN_CLIENT_add_key(TRUST_TOKEN_CLIENT *ctx, size_t *out_key_index,
const uint8_t *key, size_t key_len) { const uint8_t *key, size_t key_len) {
if (ctx->num_keys == OPENSSL_ARRAY_SIZE(ctx->keys)) { if (ctx->num_keys == OPENSSL_ARRAY_SIZE(ctx->keys) ||
ctx->num_keys >= ctx->method->max_keys) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_TOO_MANY_KEYS); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_TOO_MANY_KEYS);
return 0; return 0;
} }
@ -153,6 +189,9 @@ int TRUST_TOKEN_CLIENT_add_key(TRUST_TOKEN_CLIENT *ctx, size_t *out_key_index,
} }
int TRUST_TOKEN_CLIENT_set_srr_key(TRUST_TOKEN_CLIENT *ctx, EVP_PKEY *key) { int TRUST_TOKEN_CLIENT_set_srr_key(TRUST_TOKEN_CLIENT *ctx, EVP_PKEY *key) {
if (!ctx->method->has_srr) {
return 1;
}
EVP_PKEY_free(ctx->srr_key); EVP_PKEY_free(ctx->srr_key);
EVP_PKEY_up_ref(key); EVP_PKEY_up_ref(key);
ctx->srr_key = key; ctx->srr_key = key;
@ -270,15 +309,10 @@ int TRUST_TOKEN_CLIENT_begin_redemption(TRUST_TOKEN_CLIENT *ctx, uint8_t **out,
} }
int TRUST_TOKEN_CLIENT_finish_redemption(TRUST_TOKEN_CLIENT *ctx, int TRUST_TOKEN_CLIENT_finish_redemption(TRUST_TOKEN_CLIENT *ctx,
uint8_t **out_srr, size_t *out_srr_len, uint8_t **out_rr, size_t *out_rr_len,
uint8_t **out_sig, size_t *out_sig_len, uint8_t **out_sig, size_t *out_sig_len,
const uint8_t *response, const uint8_t *response,
size_t response_len) { size_t response_len) {
if (ctx->srr_key == NULL) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_NO_SRR_KEY_CONFIGURED);
return 0;
}
CBS in, srr, sig; CBS in, srr, sig;
CBS_init(&in, response, response_len); CBS_init(&in, response, response_len);
if (!CBS_get_u16_length_prefixed(&in, &srr) || if (!CBS_get_u16_length_prefixed(&in, &srr) ||
@ -287,16 +321,24 @@ int TRUST_TOKEN_CLIENT_finish_redemption(TRUST_TOKEN_CLIENT *ctx,
return 0; return 0;
} }
EVP_MD_CTX md_ctx; if (ctx->method->has_srr) {
EVP_MD_CTX_init(&md_ctx); if (ctx->srr_key == NULL) {
int sig_ok = EVP_DigestVerifyInit(&md_ctx, NULL, NULL, NULL, ctx->srr_key) && OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_NO_SRR_KEY_CONFIGURED);
EVP_DigestVerify(&md_ctx, CBS_data(&sig), CBS_len(&sig), return 0;
CBS_data(&srr), CBS_len(&srr)); }
EVP_MD_CTX_cleanup(&md_ctx);
if (!sig_ok) { EVP_MD_CTX md_ctx;
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_SRR_SIGNATURE_ERROR); EVP_MD_CTX_init(&md_ctx);
return 0; int sig_ok =
EVP_DigestVerifyInit(&md_ctx, NULL, NULL, NULL, ctx->srr_key) &&
EVP_DigestVerify(&md_ctx, CBS_data(&sig), CBS_len(&sig), CBS_data(&srr),
CBS_len(&srr));
EVP_MD_CTX_cleanup(&md_ctx);
if (!sig_ok) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_SRR_SIGNATURE_ERROR);
return 0;
}
} }
uint8_t *srr_buf = NULL, *sig_buf = NULL; uint8_t *srr_buf = NULL, *sig_buf = NULL;
@ -309,8 +351,8 @@ int TRUST_TOKEN_CLIENT_finish_redemption(TRUST_TOKEN_CLIENT *ctx,
return 0; return 0;
} }
*out_srr = srr_buf; *out_rr = srr_buf;
*out_srr_len = srr_len; *out_rr_len = srr_len;
*out_sig = sig_buf; *out_sig = sig_buf;
*out_sig_len = sig_len; *out_sig_len = sig_len;
return 1; return 1;
@ -346,7 +388,8 @@ void TRUST_TOKEN_ISSUER_free(TRUST_TOKEN_ISSUER *ctx) {
int TRUST_TOKEN_ISSUER_add_key(TRUST_TOKEN_ISSUER *ctx, const uint8_t *key, int TRUST_TOKEN_ISSUER_add_key(TRUST_TOKEN_ISSUER *ctx, const uint8_t *key,
size_t key_len) { size_t key_len) {
if (ctx->num_keys == OPENSSL_ARRAY_SIZE(ctx->keys)) { if (ctx->num_keys == OPENSSL_ARRAY_SIZE(ctx->keys) ||
ctx->num_keys >= ctx->method->max_keys) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_TOO_MANY_KEYS); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_TOO_MANY_KEYS);
return 0; return 0;
} }
@ -411,7 +454,8 @@ int TRUST_TOKEN_ISSUER_issue(const TRUST_TOKEN_ISSUER *ctx, uint8_t **out,
const struct trust_token_issuer_key_st *key = const struct trust_token_issuer_key_st *key =
trust_token_issuer_get_key(ctx, public_metadata); trust_token_issuer_get_key(ctx, public_metadata);
if (key == NULL || private_metadata > 1) { if (key == NULL || private_metadata > 1 ||
(!ctx->method->has_private_metadata && private_metadata != 0)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_METADATA); OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_METADATA);
return 0; return 0;
} }

@ -56,6 +56,30 @@ TEST(TrustTokenTest, KeyGenExp1) {
ASSERT_EQ(301u, pub_key_len); ASSERT_EQ(301u, pub_key_len);
} }
TEST(TrustTokenTest, KeyGenExp2PP) {
uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
size_t priv_key_len, pub_key_len;
ASSERT_TRUE(TRUST_TOKEN_generate_key(
TRUST_TOKEN_experiment_v2_pp(), priv_key, &priv_key_len,
TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, pub_key, &pub_key_len,
TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001));
ASSERT_EQ(292u, priv_key_len);
ASSERT_EQ(295u, pub_key_len);
}
TEST(TrustTokenTest, KeyGenExp2PMB) {
uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
size_t priv_key_len, pub_key_len;
ASSERT_TRUE(TRUST_TOKEN_generate_key(
TRUST_TOKEN_experiment_v2_pmb(), priv_key, &priv_key_len,
TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, pub_key, &pub_key_len,
TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001));
ASSERT_EQ(292u, priv_key_len);
ASSERT_EQ(295u, pub_key_len);
}
// Test that H in |TRUST_TOKEN_experiment_v1| was computed correctly. // Test that H in |TRUST_TOKEN_experiment_v1| was computed correctly.
TEST(TrustTokenTest, HExp1) { TEST(TrustTokenTest, HExp1) {
const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1); const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
@ -78,8 +102,34 @@ TEST(TrustTokenTest, HExp1) {
EXPECT_EQ(Bytes(h), Bytes(expected_bytes, expected_len)); EXPECT_EQ(Bytes(h), Bytes(expected_bytes, expected_len));
} }
// Test that H in |TRUST_TOKEN_experiment_v2_pmb| was computed correctly.
TEST(TrustTokenTest, HExp2) {
const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
ASSERT_TRUE(group);
const uint8_t kHGen[] = "generator";
const uint8_t kHLabel[] = "PMBTokens Experiment V2 HashH";
bssl::UniquePtr<EC_POINT> expected_h(EC_POINT_new(group));
ASSERT_TRUE(expected_h);
ASSERT_TRUE(ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
group, &expected_h->raw, kHLabel, sizeof(kHLabel), kHGen, sizeof(kHGen)));
uint8_t expected_bytes[1 + 2 * EC_MAX_BYTES];
size_t expected_len =
EC_POINT_point2oct(group, expected_h.get(), POINT_CONVERSION_UNCOMPRESSED,
expected_bytes, sizeof(expected_bytes), nullptr);
uint8_t h[97];
ASSERT_TRUE(pmbtoken_exp2_get_h_for_testing(h));
EXPECT_EQ(Bytes(h), Bytes(expected_bytes, expected_len));
}
static std::vector<const TRUST_TOKEN_METHOD *> AllMethods() { static std::vector<const TRUST_TOKEN_METHOD *> AllMethods() {
return {TRUST_TOKEN_experiment_v1()}; return {
TRUST_TOKEN_experiment_v1(),
TRUST_TOKEN_experiment_v2_pp(),
TRUST_TOKEN_experiment_v2_pmb()
};
} }
class TrustTokenProtocolTestBase : public ::testing::Test { class TrustTokenProtocolTestBase : public ::testing::Test {
@ -102,7 +152,7 @@ class TrustTokenProtocolTestBase : public ::testing::Test {
issuer.reset(TRUST_TOKEN_ISSUER_new(method(), issuer_max_batchsize)); issuer.reset(TRUST_TOKEN_ISSUER_new(method(), issuer_max_batchsize));
ASSERT_TRUE(issuer); ASSERT_TRUE(issuer);
for (size_t i = 0; i < 3; i++) { for (size_t i = 0; i < method()->max_keys; i++) {
uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE]; uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE]; uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
size_t priv_key_len, pub_key_len, key_index; size_t priv_key_len, pub_key_len, key_index;
@ -163,7 +213,7 @@ TEST_P(TrustTokenProtocolTest, InvalidToken) {
bssl::UniquePtr<uint8_t> free_issue_msg(issue_msg); bssl::UniquePtr<uint8_t> free_issue_msg(issue_msg);
ASSERT_TRUE(TRUST_TOKEN_ISSUER_issue( ASSERT_TRUE(TRUST_TOKEN_ISSUER_issue(
issuer.get(), &issue_resp, &resp_len, &tokens_issued, issue_msg, msg_len, issuer.get(), &issue_resp, &resp_len, &tokens_issued, issue_msg, msg_len,
/*public_metadata=*/KeyID(0), /*private_metadata=*/1, /*public_metadata=*/KeyID(0), /*private_metadata=*/0,
/*max_issuance=*/10)); /*max_issuance=*/10));
bssl::UniquePtr<uint8_t> free_msg(issue_resp); bssl::UniquePtr<uint8_t> free_msg(issue_resp);
bssl::UniquePtr<STACK_OF(TRUST_TOKEN)> tokens( bssl::UniquePtr<STACK_OF(TRUST_TOKEN)> tokens(
@ -428,9 +478,14 @@ TEST_P(TrustTokenMetadataTest, SetAndGetMetadata) {
&msg_len, 10)); &msg_len, 10));
bssl::UniquePtr<uint8_t> free_issue_msg(issue_msg); bssl::UniquePtr<uint8_t> free_issue_msg(issue_msg);
size_t tokens_issued; size_t tokens_issued;
ASSERT_TRUE(TRUST_TOKEN_ISSUER_issue( bool result = TRUST_TOKEN_ISSUER_issue(
issuer.get(), &issue_resp, &resp_len, &tokens_issued, issue_msg, msg_len, issuer.get(), &issue_resp, &resp_len, &tokens_issued, issue_msg, msg_len,
public_metadata(), private_metadata(), /*max_issuance=*/1)); public_metadata(), private_metadata(), /*max_issuance=*/1);
if (!method()->has_private_metadata && private_metadata()) {
ASSERT_FALSE(result);
return;
}
ASSERT_TRUE(result);
bssl::UniquePtr<uint8_t> free_msg(issue_resp); bssl::UniquePtr<uint8_t> free_msg(issue_resp);
size_t key_index; size_t key_index;
bssl::UniquePtr<STACK_OF(TRUST_TOKEN)> tokens( bssl::UniquePtr<STACK_OF(TRUST_TOKEN)> tokens(
@ -510,6 +565,10 @@ TEST_P(TrustTokenMetadataTest, SetAndGetMetadata) {
} }
TEST_P(TrustTokenMetadataTest, TooManyRequests) { TEST_P(TrustTokenMetadataTest, TooManyRequests) {
if (!method()->has_private_metadata && private_metadata()) {
return;
}
issuer_max_batchsize = 1; issuer_max_batchsize = 1;
ASSERT_NO_FATAL_FAILURE(SetupContexts()); ASSERT_NO_FATAL_FAILURE(SetupContexts());
@ -534,6 +593,10 @@ TEST_P(TrustTokenMetadataTest, TooManyRequests) {
TEST_P(TrustTokenMetadataTest, TruncatedProof) { TEST_P(TrustTokenMetadataTest, TruncatedProof) {
if (!method()->has_private_metadata && private_metadata()) {
return;
}
ASSERT_NO_FATAL_FAILURE(SetupContexts()); ASSERT_NO_FATAL_FAILURE(SetupContexts());
uint8_t *issue_msg = NULL, *issue_resp = NULL; uint8_t *issue_msg = NULL, *issue_resp = NULL;
@ -558,19 +621,16 @@ TEST_P(TrustTokenMetadataTest, TruncatedProof) {
ASSERT_TRUE(CBS_get_u32(&real_response, &public_metadata)); ASSERT_TRUE(CBS_get_u32(&real_response, &public_metadata));
ASSERT_TRUE(CBB_add_u32(bad_response.get(), public_metadata)); ASSERT_TRUE(CBB_add_u32(bad_response.get(), public_metadata));
const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
size_t token_length =
PMBTOKEN_NONCE_SIZE + 2 * (1 + 2 * BN_num_bytes(&group->field));
if (method() == TRUST_TOKEN_experiment_v1()) {
token_length += 4;
}
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
uint8_t s[PMBTOKEN_NONCE_SIZE]; ASSERT_TRUE(CBB_add_bytes(bad_response.get(), CBS_data(&real_response),
CBS tmp; token_length));
ASSERT_TRUE(CBS_copy_bytes(&real_response, s, PMBTOKEN_NONCE_SIZE)); ASSERT_TRUE(CBS_skip(&real_response, token_length));
ASSERT_TRUE(CBB_add_bytes(bad_response.get(), s, PMBTOKEN_NONCE_SIZE));
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
ASSERT_TRUE(CBB_add_u16(bad_response.get(), CBS_len(&tmp)));
ASSERT_TRUE(
CBB_add_bytes(bad_response.get(), CBS_data(&tmp), CBS_len(&tmp)));
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
ASSERT_TRUE(CBB_add_u16(bad_response.get(), CBS_len(&tmp)));
ASSERT_TRUE(
CBB_add_bytes(bad_response.get(), CBS_data(&tmp), CBS_len(&tmp)));
} }
CBS tmp; CBS tmp;
@ -593,6 +653,10 @@ TEST_P(TrustTokenMetadataTest, TruncatedProof) {
} }
TEST_P(TrustTokenMetadataTest, ExcessDataProof) { TEST_P(TrustTokenMetadataTest, ExcessDataProof) {
if (!method()->has_private_metadata && private_metadata()) {
return;
}
ASSERT_NO_FATAL_FAILURE(SetupContexts()); ASSERT_NO_FATAL_FAILURE(SetupContexts());
uint8_t *issue_msg = NULL, *issue_resp = NULL; uint8_t *issue_msg = NULL, *issue_resp = NULL;
@ -617,19 +681,16 @@ TEST_P(TrustTokenMetadataTest, ExcessDataProof) {
ASSERT_TRUE(CBS_get_u32(&real_response, &public_metadata)); ASSERT_TRUE(CBS_get_u32(&real_response, &public_metadata));
ASSERT_TRUE(CBB_add_u32(bad_response.get(), public_metadata)); ASSERT_TRUE(CBB_add_u32(bad_response.get(), public_metadata));
const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
size_t token_length =
PMBTOKEN_NONCE_SIZE + 2 * (1 + 2 * BN_num_bytes(&group->field));
if (method() == TRUST_TOKEN_experiment_v1()) {
token_length += 4;
}
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
uint8_t s[PMBTOKEN_NONCE_SIZE]; ASSERT_TRUE(CBB_add_bytes(bad_response.get(), CBS_data(&real_response),
CBS tmp; token_length));
ASSERT_TRUE(CBS_copy_bytes(&real_response, s, PMBTOKEN_NONCE_SIZE)); ASSERT_TRUE(CBS_skip(&real_response, token_length));
ASSERT_TRUE(CBB_add_bytes(bad_response.get(), s, PMBTOKEN_NONCE_SIZE));
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
ASSERT_TRUE(CBB_add_u16(bad_response.get(), CBS_len(&tmp)));
ASSERT_TRUE(
CBB_add_bytes(bad_response.get(), CBS_data(&tmp), CBS_len(&tmp)));
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
ASSERT_TRUE(CBB_add_u16(bad_response.get(), CBS_len(&tmp)));
ASSERT_TRUE(
CBB_add_bytes(bad_response.get(), CBS_data(&tmp), CBS_len(&tmp)));
} }
CBS tmp; CBS tmp;
@ -673,6 +734,10 @@ class TrustTokenBadKeyTest
}; };
TEST_P(TrustTokenBadKeyTest, BadKey) { TEST_P(TrustTokenBadKeyTest, BadKey) {
if (!method()->has_private_metadata && private_metadata()) {
return;
}
ASSERT_NO_FATAL_FAILURE(SetupContexts()); ASSERT_NO_FATAL_FAILURE(SetupContexts());
uint8_t *issue_msg = NULL, *issue_resp = NULL; uint8_t *issue_msg = NULL, *issue_resp = NULL;

@ -40,6 +40,20 @@ extern "C" {
// PMBTokens and P-384. // PMBTokens and P-384.
OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void); OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void);
// TRUST_TOKEN_experiment_v2_pp is an experimental Trust Tokens protocol using
// PMBTokens (with no private metadata) and P-384 with up to 6 keys, without RR
// verification.
//
// This version is incomplete and should not be used.
// TODO(svaldez): Update to use the PrivacyPass primitive
OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_pp(void);
// TRUST_TOKEN_experiment_v2_pmb is an experimental Trust Tokens protocol using
// PMBTokens and P-384 with up to 3 keys, without RR verification.
//
// This version is incomplete and should not be used.
OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_pmb(void);
// trust_token_st represents a single-use token for the Trust Token protocol. // trust_token_st represents a single-use token for the Trust Token protocol.
// For the client, this is the token and its corresponding signature. For the // For the client, this is the token and its corresponding signature. For the
// issuer, this is the token itself. // issuer, this is the token itself.
@ -146,13 +160,19 @@ OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_begin_redemption(
const TRUST_TOKEN *token, const uint8_t *data, size_t data_len, const TRUST_TOKEN *token, const uint8_t *data, size_t data_len,
uint64_t time); uint64_t time);
// TRUST_TOKEN_CLIENT_finish_redemption consumes |response| from the issuer and // TRUST_TOKEN_CLIENT_finish_redemption consumes |response| from the issuer. In
// verifies the SRR. If valid, it returns one and sets |*out_srr| and // |TRUST_TOKEN_experiment_v1|, it then verifies the SRR and if valid sets
// |*out_srr_len| (respectively, |*out_sig| and |*out_sig_len|) to a // |*out_rr| and |*out_rr_len| (respectively, |*out_sig| and |*out_sig_len|)
// newly-allocated buffer containing the SRR (respectively, the SRR signature). // to a newly-allocated buffer containing the SRR (respectively, the SRR
// Otherwise, it returns zero. // signature). In other versions, it sets |*out_rr| and |*out_rr_len|
// (respectively, |*out_sig| and |*out_sig_len|) to a newly-allocated buffer
// containing the SRR (respectively, the SRR signature). It returns one on
// success or zero on failure.
//
// TODO(svaldez): Return the entire response in |*out_rr| and omit |*out_sig| in
// non-|TRUST_TOKEN_experiment_v1| versions.
OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_finish_redemption( OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_finish_redemption(
TRUST_TOKEN_CLIENT *ctx, uint8_t **out_srr, size_t *out_srr_len, TRUST_TOKEN_CLIENT *ctx, uint8_t **out_rr, size_t *out_rr_len,
uint8_t **out_sig, size_t *out_sig_len, const uint8_t *response, uint8_t **out_sig, size_t *out_sig_len, const uint8_t *response,
size_t response_len); size_t response_len);

Loading…
Cancel
Save