Remove TRUST_TOKEN_experiment_v0.

Update-Note: This gets rid of TRUST_TOKEN_experiment_v0. Existing callers
should be updated to call TRUST_TOKEN_experiment_v1.

Change-Id: I8ec9b808cbd35546425690d1548db671ff033e14
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41524
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
diff --git a/crypto/ec_extra/hash_to_curve.c b/crypto/ec_extra/hash_to_curve.c
index 6f8b599..9c82454 100644
--- a/crypto/ec_extra/hash_to_curve.c
+++ b/crypto/ec_extra/hash_to_curve.c
@@ -50,12 +50,10 @@
 
 // expand_message_xmd implements the operation described in section 5.3.1 of
 // draft-irtf-cfrg-hash-to-curve-07. It returns one on success and zero on
-// allocation failure or if |out_len| was too large. If |is_draft06| is one, it
-// implements the operation from draft-irtf-cfrg-hash-to-curve-06 instead.
+// allocation failure or if |out_len| was too large.
 static int expand_message_xmd(const EVP_MD *md, uint8_t *out, size_t out_len,
                               const uint8_t *msg, size_t msg_len,
-                              const uint8_t *dst, size_t dst_len,
-                              int is_draft06) {
+                              const uint8_t *dst, size_t dst_len) {
   int ret = 0;
   const size_t block_size = EVP_MD_block_size(md);
   const size_t md_size = EVP_MD_size(md);
@@ -88,9 +86,8 @@
       !EVP_DigestUpdate(&ctx, kZeros, block_size) ||
       !EVP_DigestUpdate(&ctx, msg, msg_len) ||
       !EVP_DigestUpdate(&ctx, l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
-      (is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
       !EVP_DigestUpdate(&ctx, dst, dst_len) ||
-      (!is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
+      !EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
       !EVP_DigestFinal_ex(&ctx, b_0, NULL)) {
     goto err;
   }
@@ -114,9 +111,8 @@
     if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
         !EVP_DigestUpdate(&ctx, b_i, md_size) ||
         !EVP_DigestUpdate(&ctx, &i, 1) ||
-        (is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
         !EVP_DigestUpdate(&ctx, dst, dst_len) ||
-        (!is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
+        !EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
         !EVP_DigestFinal_ex(&ctx, b_i, NULL)) {
       goto err;
     }
@@ -175,12 +171,11 @@
 static int hash_to_field2(const EC_GROUP *group, const EVP_MD *md,
                           EC_FELEM *out1, EC_FELEM *out2, const uint8_t *dst,
                           size_t dst_len, unsigned k, const uint8_t *msg,
-                          size_t msg_len, int is_draft06) {
+                          size_t msg_len) {
   size_t L;
   uint8_t buf[4 * EC_MAX_BYTES];
   if (!num_bytes_to_derive(&L, &group->field, k) ||
-      !expand_message_xmd(md, buf, 2 * L, msg, msg_len, dst, dst_len,
-                          is_draft06)) {
+      !expand_message_xmd(md, buf, 2 * L, msg, msg_len, dst, dst_len)) {
     return 0;
   }
   BN_ULONG words[2 * EC_MAX_WORDS];
@@ -196,12 +191,11 @@
 // group order rather than a field element. |k| is the security factor.
 static int hash_to_scalar(const EC_GROUP *group, const EVP_MD *md,
                           EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
-                          unsigned k, const uint8_t *msg, size_t msg_len,
-                          int is_draft06) {
+                          unsigned k, const uint8_t *msg, size_t msg_len) {
   size_t L;
   uint8_t buf[EC_MAX_BYTES * 2];
   if (!num_bytes_to_derive(&L, &group->order, k) ||
-      !expand_message_xmd(md, buf, L, msg, msg_len, dst, dst_len, is_draft06)) {
+      !expand_message_xmd(md, buf, L, msg, msg_len, dst, dst_len)) {
     return 0;
   }
 
@@ -310,10 +304,9 @@
 static int hash_to_curve(const EC_GROUP *group, const EVP_MD *md,
                          const EC_FELEM *Z, const EC_FELEM *c2, unsigned k,
                          EC_RAW_POINT *out, const uint8_t *dst, size_t dst_len,
-                         const uint8_t *msg, size_t msg_len, int is_draft06) {
+                         const uint8_t *msg, size_t msg_len) {
   EC_FELEM u0, u1;
-  if (!hash_to_field2(group, md, &u0, &u1, dst, dst_len, k, msg, msg_len,
-                      is_draft06)) {
+  if (!hash_to_field2(group, md, &u0, &u1, dst, dst_len, k, msg, msg_len)) {
     return 0;
   }
 
@@ -376,7 +369,7 @@
   ec_felem_neg(group, &Z, &Z);
 
   return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/192, out, dst,
-                       dst_len, msg, msg_len, /*is_draft06=*/0);
+                       dst_len, msg, msg_len);
 }
 
 int ec_hash_to_scalar_p384_xmd_sha512_draft07(
@@ -388,38 +381,5 @@
   }
 
   return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/192, msg,
-                        msg_len, /*is_draft06=*/0);
-}
-
-int ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
-    const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
-    size_t dst_len, const uint8_t *msg, size_t msg_len) {
-  // See section 8.3 of draft-irtf-cfrg-hash-to-curve-06.
-  if (EC_GROUP_get_curve_name(group) != NID_secp521r1) {
-    OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
-    return 0;
-  }
-
-  // Z = -4, c2 = 8.
-  EC_FELEM Z, c2;
-  if (!felem_from_u8(group, &Z, 4) ||
-      !felem_from_u8(group, &c2, 8)) {
-    return 0;
-  }
-  ec_felem_neg(group, &Z, &Z);
-
-  return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/256, out, dst,
-                       dst_len, msg, msg_len, /*is_draft06=*/1);
-}
-
-int ec_hash_to_scalar_p521_xmd_sha512_draft06(
-    const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
-    const uint8_t *msg, size_t msg_len) {
-  if (EC_GROUP_get_curve_name(group) != NID_secp521r1) {
-    OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
-    return 0;
-  }
-
-  return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/256, msg,
-                        msg_len, /*is_draft06=*/1);
+                        msg_len);
 }
diff --git a/crypto/ec_extra/internal.h b/crypto/ec_extra/internal.h
index 940a414..55314ac 100644
--- a/crypto/ec_extra/internal.h
+++ b/crypto/ec_extra/internal.h
@@ -48,28 +48,6 @@
     const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
     const uint8_t *msg, size_t msg_len);
 
-// ec_hash_to_curve_p521_xmd_sha512_sswu_draft06 hashes |msg| to a point on
-// |group| and writes the result to |out|, implementing the
-// P521_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-06. It
-// returns one on success and zero on error.
-//
-// This function implements an older version of the draft and should not be used
-// in new code.
-OPENSSL_EXPORT int ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
-    const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
-    size_t dst_len, const uint8_t *msg, size_t msg_len);
-
-// ec_hash_to_scalar_p521_xmd_sha512_draft06 hashes |msg| to a scalar on |group|
-// and writes the result to |out|, using the hash_to_field operation from the
-// P521_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-06, but
-// generating a value modulo the group order rather than a field element.
-//
-// This function implements an older version of the draft and should not be used
-// in new code.
-OPENSSL_EXPORT int ec_hash_to_scalar_p521_xmd_sha512_draft06(
-    const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
-    const uint8_t *msg, size_t msg_len);
-
 
 #if defined(__cplusplus)
 }  // extern C
diff --git a/crypto/fipsmodule/ec/ec_test.cc b/crypto/fipsmodule/ec/ec_test.cc
index 59d55b5..edcfeaa 100644
--- a/crypto/fipsmodule/ec/ec_test.cc
+++ b/crypto/fipsmodule/ec/ec_test.cc
@@ -1170,74 +1170,6 @@
        "37f2913224287b9dfb64742851f760eb14ca115ff9",
        "1510e764f1be968d661b7aaecb26a6d38c98e5205ca150f0ae426d"
        "2c3983c68e3a9ffb283c6ae4891d891b5705500475"},
-
-      // Note these tests do not match the tests vectors
-      // draft-irtf-cfrg-hash-to-curve-06 due to a
-      // spec issue. See
-      // https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/pull/238 for
-      // corrected test vectors.
-      {&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
-       "P521_XMD:SHA-512_SSWU_RO_TESTGEN", "",
-       "00758617b5e40aa8b30fcfd3c7453ad1abeff158de5697d6f1ccb8"
-       "4690aaa8bb6692986200d16206e85e4f39f1d2829fee1a5904a089"
-       "b4fab3b76873429877c58f99",
-       "016edf324d95fcbe4a30f06751f16cdd5d0b49921dd653cefb3ea2"
-       "dc2b5b903e36d9924a65407283588cc6c224ab6d6324c73cdc166c"
-       "e1530b46984b459e966349b3"},
-      {&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
-       "P521_XMD:SHA-512_SSWU_RO_TESTGEN", "abc",
-       "00dcec1a83b676247293e96b1672f67aa5d041a4ded49f542a971a"
-       "60603dd39194f4d8e587f640563a9ab57dcc69af638129b220683f"
-       "f03ed9ad8cfdff3833a01452",
-       "01edc4b497be85361a0afc508058792dc7fc6499a4c51fa3475093"
-       "fd9951ea46fe055e1b007a12caf9be1ce3028bd0b4ca4ffa5200f9"
-       "d11e7fc96e068276ad1319c2"},
-      {&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
-       "P521_XMD:SHA-512_SSWU_RO_TESTGEN", "abcdef0123456789",
-       "01f58bfb34825d028c392976a09cebee829734f7714c84b8a13580"
-       "afcc2eb4726e18e307476c1fccdc857a3d6767fd2882875ab132b7"
-       "fa7f3f6bae8954384001b1a1",
-       "00ee0d2d0bfb0bdc6215814fe7096a3dfbf020dce4f0645e8e21a9"
-       "0d6a6113a5ca61ae7d8f3b485b04f2eb2b85e34fc7f9f1bf367386"
-       "2e03932b0acc3655e84d480f"},
-      {&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
-       "P521_XMD:SHA-512_SSWU_RO_TESTGEN",
-       "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-       "016d9a90619bb20c49a2a73cc8c6218cd9b3fb13c720fff2e1f8db"
-       "ac92862c7da4faf404faeff6b64f0d9b1c5824cec99b0d0ed02b3f"
-       "acb6275ce553404ea361503e",
-       "007e301e3357fb1d53961c56e53ce2763e44b297062a3eb14b9f8d"
-       "6aadc92162a74f7e254a606275e76ea0ac343b3bc746f99804bacd"
-       "7351a76fce44347c72a6fe9a"},
-
-      // Custom test vector which triggers long DST path.
-      {&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
-       "P521_XMD:SHA-512_SSWU_RO_TESTGEN_aaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-       "abcdef0123456789",
-       "0036b0c8bbec60335ff8b0397c2cb80283b97051cc949c5c190c28"
-       "92b279fafd6c372dcec3e71eab85c48ed440c14498332548ee46d0"
-       "c85442cbdc5b4032e86c3884",
-       "0081e32ca4378ae89b03142361d9c7fbe66acf0351aca3a71eca50"
-       "7a37fb8673b69cb108d079a248aedd74f06949d6623e7f7605ea10"
-       "f6f751ab574c005db7377d7f"},
   };
 
   for (const auto &test : kTests) {
@@ -1269,8 +1201,6 @@
   EC_RAW_POINT p;
   static const uint8_t kDST[] = {0, 1, 2, 3};
   static const uint8_t kMessage[] = {4, 5, 6, 7};
-  EXPECT_FALSE(ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
-      p224.get(), &p, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
   EXPECT_FALSE(ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
       p224.get(), &p, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
 }
@@ -1308,31 +1238,6 @@
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "750f2fae7d2b2f41ac737d180c1d4363d85a1504798b4976d40921"
        "1ddb3651c13a5b4daba9975cdfce18336791131915"},
-      {&ec_hash_to_scalar_p521_xmd_sha512_draft06, NID_secp521r1,
-       "P521_XMD:SHA-512_SCALAR_TEST", "",
-       "01a6206c2fc677c11d51807bf46d64a17f92396673074c5cee9299"
-       "4d28eec5445d5ed89799b30b39c964ecf62f39d59e7d43de15d910"
-       "c2c1d69f3ebc01eab241e5dc"},
-      {&ec_hash_to_scalar_p521_xmd_sha512_draft06, NID_secp521r1,
-       "P521_XMD:SHA-512_SCALAR_TEST", "abcdef0123456789",
-       "00af484a5d9389a9912f555234c578d4b1b7c4a6f5009018d133a4"
-       "069172c9f5ce2d853b8643fe7bb50a83427ed3520a7a793c41a455"
-       "a02aa99431434fb6b5b0b26e"},
-      {&ec_hash_to_scalar_p521_xmd_sha512_draft06, NID_secp521r1,
-       "P521_XMD:SHA-512_SCALAR_TEST",
-       "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-       "00b2db2ceb64ad055cafc5a0fc92560525d6dcc4975b86bbb79013"
-       "a1c3ab5d412320cb55df8088a658039a70c5657d5aefaaaa81cc5d"
-       "eecdd40c03eb0517fe2e158c"},
   };
 
   for (const auto &test : kTests) {
@@ -1358,8 +1263,6 @@
   EC_SCALAR scalar;
   static const uint8_t kDST[] = {0, 1, 2, 3};
   static const uint8_t kMessage[] = {4, 5, 6, 7};
-  EXPECT_FALSE(ec_hash_to_scalar_p521_xmd_sha512_draft06(
-      p224.get(), &scalar, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
   EXPECT_FALSE(ec_hash_to_scalar_p384_xmd_sha512_draft07(
       p224.get(), &scalar, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
 }
diff --git a/crypto/trust_token/internal.h b/crypto/trust_token/internal.h
index d65057f..a44de76 100644
--- a/crypto/trust_token/internal.h
+++ b/crypto/trust_token/internal.h
@@ -78,27 +78,6 @@
 DEFINE_STACK_OF(PMBTOKEN_PRETOKEN)
 
 // The following functions implement the corresponding |TRUST_TOKENS_METHOD|
-// functions for |TRUST_TOKENS_experiment_v0|'s PMBTokens construction which
-// uses P-521.
-int pmbtoken_exp0_generate_key(CBB *out_private, CBB *out_public);
-int pmbtoken_exp0_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
-                                        const uint8_t *in, size_t len);
-int pmbtoken_exp0_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
-                                        const uint8_t *in, size_t len);
-STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp0_blind(CBB *cbb, size_t count);
-int pmbtoken_exp0_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_exp0_unblind(const PMBTOKEN_CLIENT_KEY *key,
-                          const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
-                          CBS *cbs, size_t count, uint32_t key_id);
-int pmbtoken_exp0_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);
-
-// The following functions implement the corresponding |TRUST_TOKENS_METHOD|
 // functions for |TRUST_TOKENS_experiment_v1|'s PMBTokens construction which
 // uses P-384.
 //
@@ -193,14 +172,6 @@
               uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
               uint8_t *out_private_metadata, const uint8_t *token,
               size_t token_len);
-
-  // use_token_hash determines whether to include the token hash in the SRR and
-  // private metadata encryption.
-  int use_token_hash : 1;
-
-  // batched_proof determines whether PMBToken uses a batched DLEQOR proof when
-  // signing tokens.
-  int batched_proof : 1;
 };
 
 // Structure representing a single Trust Token public key with the specified ID.
diff --git a/crypto/trust_token/pmbtoken.c b/crypto/trust_token/pmbtoken.c
index 291cb86..5ea60c3 100644
--- a/crypto/trust_token/pmbtoken.c
+++ b/crypto/trust_token/pmbtoken.c
@@ -52,9 +52,6 @@
   // hash_c implements the H_c operation in PMBTokens. It returns one on success
   // and zero on error.
   hash_c_func_t hash_c;
-  // batched_proof determines whether PMBToken uses a batched DLEQOR proof when
-  // signing tokens.
-  int batched_proof : 1;
 } PMBTOKEN_METHOD;
 
 static const uint8_t kDefaultAdditionalData[32] = {0};
@@ -62,7 +59,7 @@
 static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid,
                                 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, int batched_proof) {
+                                hash_c_func_t hash_c) {
   method->group = EC_GROUP_new_by_curve_name(curve_nid);
   if (method->group == NULL) {
     return 0;
@@ -71,7 +68,6 @@
   method->hash_t = hash_t;
   method->hash_s = hash_s;
   method->hash_c = hash_c;
-  method->batched_proof = batched_proof;
 
   EC_AFFINE h;
   if (!ec_point_from_uncompressed(method->group, &h, h_bytes, h_len)) {
@@ -724,37 +720,31 @@
     return 0;
   }
 
+  if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
+      num_to_issue > ((size_t)-1) / sizeof(EC_SCALAR)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
+    return 0;
+  }
+
   int ret = 0;
-  EC_RAW_POINT *Tps = NULL;
-  EC_RAW_POINT *Sps = NULL;
-  EC_RAW_POINT *Wps = NULL;
-  EC_RAW_POINT *Wsps = NULL;
-  EC_SCALAR *es = NULL;
+  EC_RAW_POINT *Tps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
+  EC_RAW_POINT *Sps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
+  EC_RAW_POINT *Wps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
+  EC_RAW_POINT *Wsps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
+  EC_SCALAR *es = OPENSSL_malloc(num_to_issue * sizeof(EC_SCALAR));
   CBB batch_cbb;
   CBB_zero(&batch_cbb);
-  if (method->batched_proof) {
-    if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
-        num_to_issue > ((size_t)-1) / sizeof(EC_SCALAR)) {
-      OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
-      goto err;
-    }
-    Tps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
-    Sps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
-    Wps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
-    Wsps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
-    es = OPENSSL_malloc(num_to_issue * sizeof(EC_SCALAR));
-    if (!Tps ||
-        !Sps ||
-        !Wps ||
-        !Wsps ||
-        !es ||
-        !CBB_init(&batch_cbb, 0) ||
-        !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
-        !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
-        !point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
-      OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
+  if (!Tps ||
+      !Sps ||
+      !Wps ||
+      !Wsps ||
+      !es ||
+      !CBB_init(&batch_cbb, 0) ||
+      !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
+      !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
+      !point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
+    goto err;
   }
 
   for (size_t i = 0; i < num_to_issue; i++) {
@@ -793,25 +783,17 @@
       goto err;
     }
 
-    if (!method->batched_proof) {
-      if (!CBB_add_u16_length_prefixed(cbb, &child) ||
-          !dleq_generate(method, &child, key, &Tp, &jacobians[0], &jacobians[1],
-                         &jacobians[2], private_metadata)) {
-        goto err;
-      }
-    } else {
-      if (!point_to_cbb(&batch_cbb, group, &Tp_affine) ||
-          !point_to_cbb(&batch_cbb, group, &affines[0]) ||
-          !point_to_cbb(&batch_cbb, group, &affines[1]) ||
-          !point_to_cbb(&batch_cbb, group, &affines[2])) {
-        OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
-        goto err;
-      }
-      Tps[i] = Tp;
-      Sps[i] = jacobians[0];
-      Wps[i] = jacobians[1];
-      Wsps[i] = jacobians[2];
+    if (!point_to_cbb(&batch_cbb, group, &Tp_affine) ||
+        !point_to_cbb(&batch_cbb, group, &affines[0]) ||
+        !point_to_cbb(&batch_cbb, group, &affines[1]) ||
+        !point_to_cbb(&batch_cbb, group, &affines[2])) {
+      OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
+      goto err;
     }
+    Tps[i] = Tp;
+    Sps[i] = jacobians[0];
+    Wps[i] = jacobians[1];
+    Wsps[i] = jacobians[2];
 
     if (!CBB_flush(cbb)) {
       goto err;
@@ -821,36 +803,34 @@
   // The DLEQ batching construction is described in appendix B of
   // https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
   // computations all act on public inputs.
-  if (method->batched_proof) {
-    for (size_t i = 0; i < num_to_issue; i++) {
-      if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
-        goto err;
-      }
-    }
-
-    EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
-    if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
-                                          /*g_scalar=*/NULL, Tps, es,
-                                          num_to_issue) ||
-        !ec_point_mul_scalar_public_batch(group, &Sp_batch,
-                                          /*g_scalar=*/NULL, Sps, es,
-                                          num_to_issue) ||
-        !ec_point_mul_scalar_public_batch(group, &Wp_batch,
-                                          /*g_scalar=*/NULL, Wps, es,
-                                          num_to_issue) ||
-        !ec_point_mul_scalar_public_batch(group, &Wsp_batch,
-                                          /*g_scalar=*/NULL, Wsps, es,
-                                          num_to_issue)) {
+  for (size_t i = 0; i < num_to_issue; i++) {
+    if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
       goto err;
     }
+  }
 
-    CBB proof;
-    if (!CBB_add_u16_length_prefixed(cbb, &proof) ||
-        !dleq_generate(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
-                       &Wsp_batch, private_metadata) ||
-        !CBB_flush(cbb)) {
-      goto err;
-    }
+  EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
+  if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
+                                        /*g_scalar=*/NULL, Tps, es,
+                                        num_to_issue) ||
+      !ec_point_mul_scalar_public_batch(group, &Sp_batch,
+                                        /*g_scalar=*/NULL, Sps, es,
+                                        num_to_issue) ||
+      !ec_point_mul_scalar_public_batch(group, &Wp_batch,
+                                        /*g_scalar=*/NULL, Wps, es,
+                                        num_to_issue) ||
+      !ec_point_mul_scalar_public_batch(group, &Wsp_batch,
+                                        /*g_scalar=*/NULL, Wsps, es,
+                                        num_to_issue)) {
+    goto err;
+  }
+
+  CBB proof;
+  if (!CBB_add_u16_length_prefixed(cbb, &proof) ||
+      !dleq_generate(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
+                     &Wsp_batch, private_metadata) ||
+      !CBB_flush(cbb)) {
+    goto err;
   }
 
   // Skip over any unused requests.
@@ -890,36 +870,29 @@
     return NULL;
   }
 
-  EC_RAW_POINT *Tps = NULL;
-  EC_RAW_POINT *Sps = NULL;
-  EC_RAW_POINT *Wps = NULL;
-  EC_RAW_POINT *Wsps = NULL;
-  EC_SCALAR *es = NULL;
+  if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
+      count > ((size_t)-1) / sizeof(EC_SCALAR)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
+    return 0;
+  }
+  EC_RAW_POINT *Tps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
+  EC_RAW_POINT *Sps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
+  EC_RAW_POINT *Wps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
+  EC_RAW_POINT *Wsps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
+  EC_SCALAR *es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
   CBB batch_cbb;
   CBB_zero(&batch_cbb);
-  if (method->batched_proof) {
-    if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
-        count > ((size_t)-1) / sizeof(EC_SCALAR)) {
-      OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
-      goto err;
-    }
-    Tps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
-    Sps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
-    Wps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
-    Wsps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
-    es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
-    if (!Tps ||
-        !Sps ||
-        !Wps ||
-        !Wsps ||
-        !es ||
-        !CBB_init(&batch_cbb, 0) ||
-        !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
-        !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
-        !point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
-      OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
+  if (!Tps ||
+      !Sps ||
+      !Wps ||
+      !Wsps ||
+      !es ||
+      !CBB_init(&batch_cbb, 0) ||
+      !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
+      !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
+      !point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
+    goto err;
   }
 
   for (size_t i = 0; i < count; i++) {
@@ -928,7 +901,6 @@
 
     uint8_t s[PMBTOKEN_NONCE_SIZE];
     EC_AFFINE Wp_affine, Wsp_affine;
-    CBS proof;
     if (!CBS_copy_bytes(cbs, s, PMBTOKEN_NONCE_SIZE) ||
         !cbs_get_prefixed_point(cbs, group, &Wp_affine) ||
         !cbs_get_prefixed_point(cbs, group, &Wsp_affine)) {
@@ -936,50 +908,29 @@
       goto err;
     }
 
-    EC_RAW_POINT Tp, Wp, Wsp, Sp;
-    ec_affine_to_jacobian(group, &Tp, &pretoken->Tp);
-    ec_affine_to_jacobian(group, &Wp, &Wp_affine);
-    ec_affine_to_jacobian(group, &Wsp, &Wsp_affine);
-    if (!method->hash_s(group, &Sp, &pretoken->Tp, s)) {
+    ec_affine_to_jacobian(group, &Tps[i], &pretoken->Tp);
+    ec_affine_to_jacobian(group, &Wps[i], &Wp_affine);
+    ec_affine_to_jacobian(group, &Wsps[i], &Wsp_affine);
+    if (!method->hash_s(group, &Sps[i], &pretoken->Tp, s)) {
       goto err;
     }
 
-    if (!method->batched_proof) {
-      if(!CBS_get_u16_length_prefixed(cbs, &proof)) {
-        OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
-        goto err;
-      }
-
-      if (!dleq_verify(method, &proof, key, &Tp, &Sp, &Wp, &Wsp)) {
-        goto err;
-      }
-
-      if (CBS_len(&proof) != 0) {
-        OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
-        goto err;
-      }
-    } else {
-      EC_AFFINE Sp_affine;
-      if (!point_to_cbb(&batch_cbb, group, &pretoken->Tp) ||
-          !ec_jacobian_to_affine(group, &Sp_affine, &Sp) ||
-          !point_to_cbb(&batch_cbb, group, &Sp_affine) ||
-          !point_to_cbb(&batch_cbb, group, &Wp_affine) ||
-          !point_to_cbb(&batch_cbb, group, &Wsp_affine)) {
-        OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
-        goto err;
-      }
-      Tps[i] = Tp;
-      Sps[i] = Sp;
-      Wps[i] = Wp;
-      Wsps[i] = Wsp;
+    EC_AFFINE Sp_affine;
+    if (!point_to_cbb(&batch_cbb, group, &pretoken->Tp) ||
+        !ec_jacobian_to_affine(group, &Sp_affine, &Sps[i]) ||
+        !point_to_cbb(&batch_cbb, group, &Sp_affine) ||
+        !point_to_cbb(&batch_cbb, group, &Wp_affine) ||
+        !point_to_cbb(&batch_cbb, group, &Wsp_affine)) {
+      OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
+      goto err;
     }
 
     // Unblind the token.
     EC_RAW_POINT jacobians[3];
     EC_AFFINE affines[3];
-    if (!ec_point_mul_scalar(group, &jacobians[0], &Sp, &pretoken->r) ||
-        !ec_point_mul_scalar(group, &jacobians[1], &Wp, &pretoken->r) ||
-        !ec_point_mul_scalar(group, &jacobians[2], &Wsp, &pretoken->r) ||
+    if (!ec_point_mul_scalar(group, &jacobians[0], &Sps[i], &pretoken->r) ||
+        !ec_point_mul_scalar(group, &jacobians[1], &Wps[i], &pretoken->r) ||
+        !ec_point_mul_scalar(group, &jacobians[2], &Wsps[i], &pretoken->r) ||
         !ec_jacobian_to_affine_batch(group, affines, jacobians, 3)) {
       goto err;
     }
@@ -1018,32 +969,30 @@
   // The DLEQ batching construction is described in appendix B of
   // https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
   // computations all act on public inputs.
-  if (method->batched_proof) {
-    for (size_t i = 0; i < count; i++) {
-      if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
-        goto err;
-      }
-    }
-
-    EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
-    if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
-                                          /*g_scalar=*/NULL, Tps, es, count) ||
-        !ec_point_mul_scalar_public_batch(group, &Sp_batch,
-                                          /*g_scalar=*/NULL, Sps, es, count) ||
-        !ec_point_mul_scalar_public_batch(group, &Wp_batch,
-                                          /*g_scalar=*/NULL, Wps, es, count) ||
-        !ec_point_mul_scalar_public_batch(group, &Wsp_batch,
-                                          /*g_scalar=*/NULL, Wsps, es, count)) {
+  for (size_t i = 0; i < count; i++) {
+    if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
       goto err;
     }
+  }
 
-    CBS proof;
-    if (!CBS_get_u16_length_prefixed(cbs, &proof) ||
-        !dleq_verify(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
-                     &Wsp_batch) ||
-        CBS_len(&proof) != 0) {
-      goto err;
-    }
+  EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
+  if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
+                                        /*g_scalar=*/NULL, Tps, es, count) ||
+      !ec_point_mul_scalar_public_batch(group, &Sp_batch,
+                                        /*g_scalar=*/NULL, Sps, es, count) ||
+      !ec_point_mul_scalar_public_batch(group, &Wp_batch,
+                                        /*g_scalar=*/NULL, Wps, es, count) ||
+      !ec_point_mul_scalar_public_batch(group, &Wsp_batch,
+                                        /*g_scalar=*/NULL, Wsps, es, count)) {
+    goto err;
+  }
+
+  CBS proof;
+  if (!CBS_get_u16_length_prefixed(cbs, &proof) ||
+      !dleq_verify(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
+                   &Wsp_batch) ||
+      CBS_len(&proof) != 0) {
+    goto err;
   }
 
   ok = 1;
@@ -1127,202 +1076,6 @@
 }
 
 
-// PMBTokens experiment v0.
-
-static int pmbtoken_exp0_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
-                                const uint8_t t[PMBTOKEN_NONCE_SIZE]) {
-  const uint8_t kHashTLabel[] = "PMBTokensV0 HashT";
-  return ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
-      group, out, kHashTLabel, sizeof(kHashTLabel), t, PMBTOKEN_NONCE_SIZE);
-}
-
-static int pmbtoken_exp0_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[] = "PMBTokensV0 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_p521_xmd_sha512_sswu_draft06(
-          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_exp0_hash_c(const EC_GROUP *group, EC_SCALAR *out,
-                                uint8_t *buf, size_t len) {
-  const uint8_t kHashCLabel[] = "PMBTokensV0 HashC";
-  return ec_hash_to_scalar_p521_xmd_sha512_draft06(
-      group, out, kHashCLabel, sizeof(kHashCLabel), buf, len);
-}
-
-// H for PMBTokens v0 was generated with the following Python code.
-/*
-import hashlib
-
-SEED_H = 'PrivacyPass H'
-
-A = -3
-B = 0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00
-P = 2**521 - 1
-
-def get_y(x):
-  y2 = (x**3 + A*x + B) % P
-  y = pow(y2, (P+1)/4, P)
-  if (y*y) % P != y2:
-    raise ValueError("point not on curve")
-  return y
-
-def bit(h,i):
-  return (ord(h[i/8]) >> (i%8)) & 1
-
-b = 521
-def decode_point(so):
-  s = hashlib.sha256(so + '0').digest() + hashlib.sha256(so + '1').digest() + \
-      hashlib.sha256(so + '2').digest()
-
-  x = 0
-  for i in range(0,b):
-    x = x + (long(bit(s,i))<<i)
-  if x >= P:
-    raise ValueError("x out of range")
-  y = get_y(x)
-  if y & 1 != bit(s,b-1): y = P-y
-  return (x, y)
-
-
-def gen_point(seed):
-  v = hashlib.sha256(seed).digest()
-  it = 1
-  while True:
-    try:
-      x,y = decode_point(v)
-    except Exception, e:
-      print e
-      it += 1
-      v = hashlib.sha256(v).digest()
-      continue
-    print "Found in %d iterations:" % it
-    print "  x = %d" % x
-    print "  y = %d" % y
-    print " Encoded (hex): (%x, %x)" % (x, y)
-    return (x, y)
-
-if __name__ == "__main__":
-  gen_point(SEED_H)
-*/
-static int pmbtoken_exp0_ok = 0;
-static PMBTOKEN_METHOD pmbtoken_exp0_method;
-static CRYPTO_once_t pmbtoken_exp0_method_once = CRYPTO_ONCE_INIT;
-
-static void pmbtoken_exp0_init_method_impl(void) {
-  static const uint8_t kH[] = {
-      0x04, 0x01, 0xf0, 0xa9, 0xf7, 0x9e, 0xbc, 0x12, 0x6c, 0xef, 0xd1, 0xab,
-      0x29, 0x10, 0x03, 0x6f, 0x4e, 0xf5, 0xbd, 0xeb, 0x0f, 0x6b, 0xc0, 0x5c,
-      0x0e, 0xce, 0xfe, 0x59, 0x45, 0xd1, 0x3e, 0x25, 0x33, 0x7e, 0x4c, 0xda,
-      0x64, 0x53, 0x54, 0x4e, 0xf9, 0x76, 0x0d, 0x6d, 0xc5, 0x39, 0x2a, 0xd4,
-      0xce, 0x84, 0x6e, 0x31, 0xc2, 0x86, 0x21, 0xf9, 0x5c, 0x98, 0xb9, 0x3d,
-      0x01, 0x74, 0x9f, 0xc5, 0x1e, 0x47, 0x24, 0x00, 0x5c, 0x17, 0x62, 0x51,
-      0x7d, 0x32, 0x5e, 0x29, 0xac, 0x52, 0x14, 0x75, 0x6f, 0x36, 0xd9, 0xc7,
-      0xfa, 0xbb, 0xa9, 0x3b, 0x9d, 0x70, 0x49, 0x1e, 0xb4, 0x53, 0xbc, 0x55,
-      0xea, 0xad, 0x8f, 0x26, 0x1d, 0xe0, 0xbc, 0xf3, 0x50, 0x5c, 0x7e, 0x66,
-      0x41, 0xb5, 0x61, 0x70, 0x12, 0x72, 0xac, 0x6a, 0xb0, 0x6e, 0x78, 0x3d,
-      0x17, 0x08, 0xe3, 0xdf, 0x3c, 0xff, 0xa6, 0xa0, 0xea, 0x96, 0x67, 0x92,
-      0xcd,
-  };
-
-  pmbtoken_exp0_ok =
-      pmbtoken_init_method(&pmbtoken_exp0_method, NID_secp521r1, kH, sizeof(kH),
-                           pmbtoken_exp0_hash_t, pmbtoken_exp0_hash_s,
-                           pmbtoken_exp0_hash_c, /*batched_proof=*/0);
-}
-
-static int pmbtoken_exp0_init_method(void) {
-  CRYPTO_once(&pmbtoken_exp0_method_once, pmbtoken_exp0_init_method_impl);
-  if (!pmbtoken_exp0_ok) {
-    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
-  return 1;
-}
-
-int pmbtoken_exp0_generate_key(CBB *out_private, CBB *out_public) {
-  if (!pmbtoken_exp0_init_method()) {
-    return 0;
-  }
-
-  return pmbtoken_generate_key(&pmbtoken_exp0_method, out_private, out_public);
-}
-
-int pmbtoken_exp0_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
-                                        const uint8_t *in, size_t len) {
-  if (!pmbtoken_exp0_init_method()) {
-    return 0;
-  }
-  return pmbtoken_client_key_from_bytes(&pmbtoken_exp0_method, key, in, len);
-}
-
-int pmbtoken_exp0_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
-                                        const uint8_t *in, size_t len) {
-  if (!pmbtoken_exp0_init_method()) {
-    return 0;
-  }
-  return pmbtoken_issuer_key_from_bytes(&pmbtoken_exp0_method, key, in, len);
-}
-
-STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp0_blind(CBB *cbb, size_t count) {
-  if (!pmbtoken_exp0_init_method()) {
-    return NULL;
-  }
-  return pmbtoken_blind(&pmbtoken_exp0_method, cbb, count);
-}
-
-int pmbtoken_exp0_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_exp0_init_method()) {
-    return 0;
-  }
-  return pmbtoken_sign(&pmbtoken_exp0_method, key, cbb, cbs, num_requested,
-                       num_to_issue, private_metadata);
-}
-
-STACK_OF(TRUST_TOKEN) *
-    pmbtoken_exp0_unblind(const PMBTOKEN_CLIENT_KEY *key,
-                          const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
-                          CBS *cbs, size_t count, uint32_t key_id) {
-  if (!pmbtoken_exp0_init_method()) {
-    return NULL;
-  }
-  return pmbtoken_unblind(&pmbtoken_exp0_method, key, pretokens, cbs, count,
-                          key_id);
-}
-
-int pmbtoken_exp0_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_exp0_init_method()) {
-    return 0;
-  }
-  return pmbtoken_read(&pmbtoken_exp0_method, key, out_nonce,
-                       out_private_metadata, token, token_len);
-}
-
-
 // PMBTokens experiment v1.
 
 static int pmbtoken_exp1_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
@@ -1387,7 +1140,7 @@
   pmbtoken_exp1_ok =
       pmbtoken_init_method(&pmbtoken_exp1_method, NID_secp384r1, kH, sizeof(kH),
                            pmbtoken_exp1_hash_t, pmbtoken_exp1_hash_s,
-                           pmbtoken_exp1_hash_c, /*batched_proof=*/1);
+                           pmbtoken_exp1_hash_c);
 }
 
 static int pmbtoken_exp1_init_method(void) {
diff --git a/crypto/trust_token/trust_token.c b/crypto/trust_token/trust_token.c
index 1ade23e..87b8277 100644
--- a/crypto/trust_token/trust_token.c
+++ b/crypto/trust_token/trust_token.c
@@ -27,21 +27,6 @@
 // protocol for issuing and redeeming tokens built on top of the PMBTokens
 // construction.
 
-const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v0(void) {
-  static const TRUST_TOKEN_METHOD kMethod = {
-      pmbtoken_exp0_generate_key,
-      pmbtoken_exp0_client_key_from_bytes,
-      pmbtoken_exp0_issuer_key_from_bytes,
-      pmbtoken_exp0_blind,
-      pmbtoken_exp0_sign,
-      pmbtoken_exp0_unblind,
-      pmbtoken_exp0_read,
-      0 /* don't use token hash */,
-      0 /* don't use batched proof */,
-  };
-  return &kMethod;
-}
-
 const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void) {
   static const TRUST_TOKEN_METHOD kMethod = {
       pmbtoken_exp1_generate_key,
@@ -51,8 +36,6 @@
       pmbtoken_exp1_sign,
       pmbtoken_exp1_unblind,
       pmbtoken_exp1_read,
-      1 /* use token hash */,
-      1 /* use batched proof */,
   };
   return &kMethod;
 }
@@ -597,16 +580,8 @@
   SHA256_Update(&sha_ctx, CBS_data(&token_copy), CBS_len(&token_copy));
   SHA256_Final(token_hash, &sha_ctx);
 
-  uint8_t metadata_obfuscator;
-  if (ctx->method->use_token_hash) {
-    metadata_obfuscator =
-        get_metadata_obfuscator(ctx->metadata_key, ctx->metadata_key_len,
-                                token_hash, sizeof(token_hash));
-  } else {
-    metadata_obfuscator =
-        get_metadata_obfuscator(ctx->metadata_key, ctx->metadata_key_len,
-                                CBS_data(&client_data), CBS_len(&client_data));
-  }
+  uint8_t metadata_obfuscator = get_metadata_obfuscator(
+      ctx->metadata_key, ctx->metadata_key_len, token_hash, sizeof(token_hash));
 
   // The SRR is constructed as per the format described in
   // https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#heading=h.7mkzvhpqb8l5
@@ -625,10 +600,7 @@
   assert(strlen(kClientDataLabel) < strlen(kExpiryTimestampLabel));
   assert(strlen(kPublicLabel) < strlen(kPrivateLabel));
 
-  size_t map_entries = 3;
-  if (ctx->method->use_token_hash) {
-    map_entries = 4;
-  }
+  size_t map_entries = 4;
 
   if (!CBB_init(&srr, 0) ||
       !add_cbor_map(&srr, map_entries) ||  // SRR map
@@ -637,20 +609,10 @@
       !add_cbor_text(&srr, kPublicLabel, strlen(kPublicLabel)) ||
       !add_cbor_int(&srr, public_metadata) ||
       !add_cbor_text(&srr, kPrivateLabel, strlen(kPrivateLabel)) ||
-      !add_cbor_int(&srr, private_metadata ^ metadata_obfuscator)) {
-    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (ctx->method->use_token_hash) {
-    if (!add_cbor_text(&srr, kTokenHashLabel, strlen(kTokenHashLabel)) ||
-        !add_cbor_bytes(&srr, token_hash, sizeof(token_hash))) {
-      OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-  }
-
-  if (!add_cbor_text(&srr, kClientDataLabel, strlen(kClientDataLabel)) ||
+      !add_cbor_int(&srr, private_metadata ^ metadata_obfuscator) ||
+      !add_cbor_text(&srr, kTokenHashLabel, strlen(kTokenHashLabel)) ||
+      !add_cbor_bytes(&srr, token_hash, sizeof(token_hash)) ||
+      !add_cbor_text(&srr, kClientDataLabel, strlen(kClientDataLabel)) ||
       !CBB_add_bytes(&srr, CBS_data(&client_data), CBS_len(&client_data)) ||
       !add_cbor_text(&srr, kExpiryTimestampLabel,
                      strlen(kExpiryTimestampLabel)) ||
diff --git a/crypto/trust_token/trust_token_test.cc b/crypto/trust_token/trust_token_test.cc
index 41bf55d..f6ff86c 100644
--- a/crypto/trust_token/trust_token_test.cc
+++ b/crypto/trust_token/trust_token_test.cc
@@ -44,18 +44,6 @@
 
 namespace {
 
-TEST(TrustTokenTest, KeyGenExp0) {
-  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_v0(), 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(400u, priv_key_len);
-  ASSERT_EQ(409u, pub_key_len);
-}
-
 TEST(TrustTokenTest, KeyGenExp1) {
   uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
   uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
@@ -91,7 +79,7 @@
 }
 
 static std::vector<const TRUST_TOKEN_METHOD *> AllMethods() {
-  return {TRUST_TOKEN_experiment_v0(), TRUST_TOKEN_experiment_v1()};
+  return {TRUST_TOKEN_experiment_v1()};
 }
 
 class TrustTokenProtocolTestBase : public ::testing::Test {
@@ -454,14 +442,7 @@
     const uint8_t kClientData[] = "\x70TEST CLIENT DATA";
     uint64_t kRedemptionTime = 13374242;
 
-    const uint8_t kExpectedSRRNoTokenHash[] =
-        "\xa3\x68\x6d\x65\x74\x61\x64\x61\x74\x61\xa2\x66\x70\x75\x62\x6c\x69"
-        "\x63\x00\x67\x70\x72\x69\x76\x61\x74\x65\x00\x6b\x63\x6c\x69\x65\x6e"
-        "\x74\x2d\x64\x61\x74\x61\x70\x54\x45\x53\x54\x20\x43\x4c\x49\x45\x4e"
-        "\x54\x20\x44\x41\x54\x41\x70\x65\x78\x70\x69\x72\x79\x2d\x74\x69\x6d"
-        "\x65\x73\x74\x61\x6d\x70\x1a\x00\xcc\x15\x7a";
-
-    const uint8_t kExpectedSRRTokenHash[] =
+    const uint8_t kExpectedSRR[] =
         "\xa4\x68\x6d\x65\x74\x61\x64\x61\x74\x61\xa2\x66\x70\x75\x62\x6c\x69"
         "\x63\x00\x67\x70\x72\x69\x76\x61\x74\x65\x00\x6a\x74\x6f\x6b\x65\x6e"
         "\x2d\x68\x61\x73\x68\x58\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
@@ -498,50 +479,33 @@
     bssl::UniquePtr<uint8_t> free_srr(srr);
     bssl::UniquePtr<uint8_t> free_sig(sig);
 
-    if (method()->use_token_hash) {
-      const uint8_t kTokenHashDSTLabel[] = "TrustTokenV0 TokenHash";
-      uint8_t token_hash[SHA256_DIGEST_LENGTH];
-      SHA256_CTX sha_ctx;
-      SHA256_Init(&sha_ctx);
-      SHA256_Update(&sha_ctx, kTokenHashDSTLabel, sizeof(kTokenHashDSTLabel));
-      SHA256_Update(&sha_ctx, token->data, token->len);
-      SHA256_Final(token_hash, &sha_ctx);
+    const uint8_t kTokenHashDSTLabel[] = "TrustTokenV0 TokenHash";
+    uint8_t token_hash[SHA256_DIGEST_LENGTH];
+    SHA256_CTX sha_ctx;
+    SHA256_Init(&sha_ctx);
+    SHA256_Update(&sha_ctx, kTokenHashDSTLabel, sizeof(kTokenHashDSTLabel));
+    SHA256_Update(&sha_ctx, token->data, token->len);
+    SHA256_Final(token_hash, &sha_ctx);
 
-      // Check the token hash is in the SRR.
-      ASSERT_EQ(Bytes(token_hash), Bytes(srr + 41, sizeof(token_hash)));
+    // Check the token hash is in the SRR.
+    ASSERT_EQ(Bytes(token_hash), Bytes(srr + 41, sizeof(token_hash)));
 
-      uint8_t decode_private_metadata;
-      ASSERT_TRUE(TRUST_TOKEN_decode_private_metadata(
-          method(), &decode_private_metadata, metadata_key,
-          sizeof(metadata_key), token_hash, sizeof(token_hash), srr[27]));
-      ASSERT_EQ(srr[18], public_metadata());
-      ASSERT_EQ(decode_private_metadata, private_metadata());
+    uint8_t decode_private_metadata;
+    ASSERT_TRUE(TRUST_TOKEN_decode_private_metadata(
+        method(), &decode_private_metadata, metadata_key, sizeof(metadata_key),
+        token_hash, sizeof(token_hash), srr[27]));
+    ASSERT_EQ(srr[18], public_metadata());
+    ASSERT_EQ(decode_private_metadata, private_metadata());
 
-      // Clear out the metadata bits.
-      srr[18] = 0;
-      srr[27] = 0;
+    // Clear out the metadata bits.
+    srr[18] = 0;
+    srr[27] = 0;
 
-      // Clear out the token hash.
-      OPENSSL_memset(srr + 41, 0, sizeof(token_hash));
+    // Clear out the token hash.
+    OPENSSL_memset(srr + 41, 0, sizeof(token_hash));
 
-      ASSERT_EQ(Bytes(kExpectedSRRTokenHash, sizeof(kExpectedSRRTokenHash) - 1),
-                Bytes(srr, srr_len));
-    } else {
-      uint8_t decode_private_metadata;
-      ASSERT_TRUE(TRUST_TOKEN_decode_private_metadata(
-          method(), &decode_private_metadata, metadata_key,
-          sizeof(metadata_key), kClientData, sizeof(kClientData) - 1, srr[27]));
-      ASSERT_EQ(srr[18], public_metadata());
-      ASSERT_EQ(decode_private_metadata, private_metadata());
-
-      // Clear out the metadata bits.
-      srr[18] = 0;
-      srr[27] = 0;
-
-      ASSERT_EQ(
-          Bytes(kExpectedSRRNoTokenHash, sizeof(kExpectedSRRNoTokenHash) - 1),
-          Bytes(srr, srr_len));
-    }
+    ASSERT_EQ(Bytes(kExpectedSRR, sizeof(kExpectedSRR) - 1),
+              Bytes(srr, srr_len));
   }
 }
 
@@ -607,23 +571,14 @@
     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)));
-    if (!method()->batched_proof) {
-      ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
-      CBB dleq;
-      ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
-      ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp) - 2));
-      ASSERT_TRUE(CBB_flush(bad_response.get()));
-    }
   }
 
-  if (method()->batched_proof) {
-    CBS tmp;
-    ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
-    CBB dleq;
-    ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
-    ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp) - 2));
-    ASSERT_TRUE(CBB_flush(bad_response.get()));
-  }
+  CBS tmp;
+  ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
+  CBB dleq;
+  ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
+  ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp) - 2));
+  ASSERT_TRUE(CBB_flush(bad_response.get()));
 
   uint8_t *bad_buf;
   size_t bad_len;
@@ -675,25 +630,15 @@
     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)));
-    if (!method()->batched_proof) {
-      ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
-      CBB dleq;
-      ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
-      ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp)));
-      ASSERT_TRUE(CBB_add_u16(&dleq, 42));
-      ASSERT_TRUE(CBB_flush(bad_response.get()));
-    }
   }
 
-  if (method()->batched_proof) {
-    CBS tmp;
-    ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
-    CBB dleq;
-    ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
-    ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp)));
-    ASSERT_TRUE(CBB_add_u16(&dleq, 42));
-    ASSERT_TRUE(CBB_flush(bad_response.get()));
-  }
+  CBS tmp;
+  ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
+  CBB dleq;
+  ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
+  ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp)));
+  ASSERT_TRUE(CBB_add_u16(&dleq, 42));
+  ASSERT_TRUE(CBB_flush(bad_response.get()));
 
   uint8_t *bad_buf;
   size_t bad_len;
diff --git a/include/openssl/trust_token.h b/include/openssl/trust_token.h
index a73a868..9ecf75f 100644
--- a/include/openssl/trust_token.h
+++ b/include/openssl/trust_token.h
@@ -36,13 +36,8 @@
 //
 // WARNING: This API is unstable and subject to change.
 
-// TRUST_TOKEN_experiment_v0 is an experimental Trust Tokens protocol using
-// PMBTokens and P-521.
-OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v0(void);
-
 // TRUST_TOKEN_experiment_v1 is an experimental Trust Tokens protocol using
-// PMBTokens and P-384. This version is still under developement and should not
-// be used yet.
+// PMBTokens and P-384.
 OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void);
 
 // trust_token_st represents a single-use token for the Trust Token protocol.
@@ -234,9 +229,6 @@
 // returning the SRR to the client. If the value has been reused, the caller
 // must discard the SRR and report an error to the caller. Returning an SRR with
 // replayed values allows an attacker to double-spend tokens.
-//
-// The private metadata construction in |TRUST_TOKEN_experiment_v0| does not
-// keep the value secret and should not be used when secrecy is required.
 OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_redeem(
     const TRUST_TOKEN_ISSUER *ctx, uint8_t **out, size_t *out_len,
     TRUST_TOKEN **out_token, uint8_t **out_client_data,
@@ -246,7 +238,6 @@
 // TRUST_TOKEN_decode_private_metadata decodes |encrypted_bit| using the
 // private metadata key specified by a |key| buffer of length |key_len| and the
 // nonce by a |nonce| buffer of length |nonce_len|. The nonce in
-// |TRUST_TOKEN_experiment_v0| is the client-data field of the SRR. The nonce in
 // |TRUST_TOKEN_experiment_v1| is the token-hash field of the SRR. |*out_value|
 // is set to the decrypted value, either zero or one. It returns one on success
 // and zero on error.
diff --git a/tool/speed.cc b/tool/speed.cc
index 2c36c80..af81a60 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -956,32 +956,6 @@
 
   TimeResults results;
   {
-    EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp521r1);
-    if (group == NULL) {
-      return false;
-    }
-    if (!TimeFunction(&results, [&]() -> bool {
-          EC_RAW_POINT out;
-          return ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
-              group, &out, kLabel, sizeof(kLabel), input, sizeof(input));
-        })) {
-      fprintf(stderr, "hash-to-curve failed.\n");
-      return false;
-    }
-    results.Print("hash-to-curve P521_XMD:SHA-512_SSWU_RO_");
-
-    if (!TimeFunction(&results, [&]() -> bool {
-          EC_SCALAR out;
-          return ec_hash_to_scalar_p521_xmd_sha512_draft06(
-              group, &out, kLabel, sizeof(kLabel), input, sizeof(input));
-        })) {
-      fprintf(stderr, "hash-to-scalar failed.\n");
-      return false;
-    }
-    results.Print("hash-to-scalar P521_XMD:SHA-512");
-  }
-
-  {
     EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
     if (group == NULL) {
       return false;
@@ -1375,10 +1349,6 @@
       !SpeedRSAKeyGen(selected) ||
       !SpeedHRSS(selected) ||
       !SpeedHashToCurve(selected) ||
-      !SpeedTrustToken("TrustToken-Exp0-Batch1", TRUST_TOKEN_experiment_v0(), 1,
-                       selected) ||
-      !SpeedTrustToken("TrustToken-Exp0-Batch10", TRUST_TOKEN_experiment_v0(),
-                       10, selected) ||
       !SpeedTrustToken("TrustToken-Exp1-Batch1", TRUST_TOKEN_experiment_v1(), 1,
                        selected) ||
       !SpeedTrustToken("TrustToken-Exp1-Batch10", TRUST_TOKEN_experiment_v1(),