Trust Token Implementation.

Trust Token implementation based on PrivacyPass using the PMBToken construction.
This implementation currently omits the DLEQ proofs.

https://github.com/alxdavids/privacy-pass-ietf/blob/master/draft-davidson-pp-protocol.md
https://eprint.iacr.org/2020/072.pdf

Change-Id: If236cc8beaf33a80bdad2991c3163f9dd0cb7571
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39244
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/include/openssl/trust_token.h b/include/openssl/trust_token.h
index bf5b5fa..473999d 100644
--- a/include/openssl/trust_token.h
+++ b/include/openssl/trust_token.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, Google Inc.
+/* Copyright (c) 2020, Google Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -36,6 +36,23 @@
 //
 // WARNING: This API is unstable and subject to change.
 
+// 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
+// issuer, this is the token itself.
+struct trust_token_st {
+  uint8_t *data;
+  size_t len;
+};
+
+DEFINE_STACK_OF(TRUST_TOKEN)
+
+// TRUST_TOKEN_new creates a newly-allocated |TRUST_TOKEN| with value |data| or
+// NULL on allocation failure.
+OPENSSL_EXPORT TRUST_TOKEN *TRUST_TOKEN_new(const uint8_t *data, size_t len);
+
+// TRUST_TOKEN_free releases memory associated with |token|.
+OPENSSL_EXPORT void TRUST_TOKEN_free(TRUST_TOKEN *token);
+
 #define TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE 512
 #define TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE 512
 
@@ -59,11 +76,202 @@
     uint32_t id);
 
 
+// Trust Token client implementation.
+//
+// These functions implements the client half of the Trust Token protocol. A
+// single |TRUST_TOKEN_CLIENT| can perform a single protocol operation.
+
+// TRUST_TOKEN_CLIENT_new returns a newly-allocated |TRUST_TOKEN_CLIENT|
+// configured to use a max batchsize of |max_batchsize| or NULL on error.
+// Issuance requests must be made in batches smaller than |max_batchsize|.
+OPENSSL_EXPORT TRUST_TOKEN_CLIENT *TRUST_TOKEN_CLIENT_new(
+    uint16_t max_batchsize);
+
+// TRUST_TOKEN_CLIENT_free releases memory associated with |ctx|.
+OPENSSL_EXPORT void TRUST_TOKEN_CLIENT_free(TRUST_TOKEN_CLIENT *ctx);
+
+// TRUST_TOKEN_CLIENT_add_key configures the |ctx| to support the public key
+// |key|. It sets |*out_key_index| to the index this key has been configured to.
+// It returns one on success or zero on error if the |key| can't be parsed or
+// too many keys have been configured.
+OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_add_key(TRUST_TOKEN_CLIENT *ctx,
+                                              size_t *out_key_index,
+                                              const uint8_t *key,
+                                              size_t key_len);
+
+// TRUST_TOKEN_CLIENT_set_srr_key sets the public key used to verify the SRR. It
+// returns one on success and zero on error.
+OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_set_srr_key(TRUST_TOKEN_CLIENT *ctx,
+                                                  EVP_PKEY *key);
+
+// TRUST_TOKEN_CLIENT_begin_issuance produces a request for |count| trust tokens
+// and serializes the request into a newly-allocated buffer, setting |*out| to
+// that buffer and |*out_len| to its length. The caller takes ownership of the
+// buffer and must call |OPENSSL_free| when done. It returns one on success and
+// zero on error.
+OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_begin_issuance(TRUST_TOKEN_CLIENT *ctx,
+                                                     uint8_t **out,
+                                                     size_t *out_len,
+                                                     size_t count);
+
+// TRUST_TOKEN_CLIENT_finish_issuance consumes |response| from the issuer and
+// extracts the tokens, returning a list of tokens and the index of the key used
+// to sign the tokens in |*out_key_index|. The caller can use this to determine
+// what key was used in an issuance and to drop tokens if a new key commitment
+// arrives without the specified key present. The caller takes ownership of the
+// list and must call |sk_TRUST_TOKEN_pop_free| when done. The list is empty if
+// issuance fails.
+OPENSSL_EXPORT STACK_OF(TRUST_TOKEN) *
+    TRUST_TOKEN_CLIENT_finish_issuance(TRUST_TOKEN_CLIENT *ctx,
+                                       size_t *out_key_index,
+                                       const uint8_t *response,
+                                       size_t response_len);
+
+
+// TRUST_TOKEN_CLIENT_begin_redemption produces a request to redeem a token
+// |token| and receive a signature over |data| and serializes the request into
+// a newly-allocated buffer, setting |*out| to that buffer and |*out_len| to
+// its length. |time| is the number of seconds since the UNIX epoch and used to
+// verify the validity of the issuer's response. The caller takes ownership of
+// the buffer and must call |OPENSSL_free| when done. It returns one on success
+// or zero on error.
+OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_begin_redemption(
+    TRUST_TOKEN_CLIENT *ctx, uint8_t **out, size_t *out_len,
+    const TRUST_TOKEN *token, const uint8_t *data, size_t data_len,
+    uint64_t time);
+
+// TRUST_TOKEN_CLIENT_finish_redemption consumes |response| from the issuer and
+// verifies the SRR. If valid, it returns one and sets |*out_srr| and
+// |*out_srr_len| (respectively, |*out_sig| and |*out_sig_len|) to a
+// newly-allocated buffer containing the SRR (respectively, the SRR signature).
+// Otherwise, it returns zero.
+OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_finish_redemption(
+    TRUST_TOKEN_CLIENT *ctx, uint8_t **out_srr, size_t *out_srr_len,
+    uint8_t **out_sig, size_t *out_sig_len, const uint8_t *response,
+    size_t response_len);
+
+
+// Trust Token issuer implementation.
+//
+// These functions implement the issuer half of the Trust Token protocol. A
+// |TRUST_TOKEN_ISSUER| can be reused across multiple protocol operations. It
+// may be used concurrently on multiple threads by non-mutating functions,
+// provided no other thread is concurrently calling a mutating function.
+// Functions which take a |const| pointer are non-mutating and functions which
+// take a non-|const| pointer are mutating.
+
+// TRUST_TOKEN_ISSUER_new returns a newly-allocated |TRUST_TOKEN_ISSUER|
+// configured to use a max batchsize of |max_batchsize| or NULL on error.
+// Issuance requests must be made in batches smaller than |max_batchsize|.
+OPENSSL_EXPORT TRUST_TOKEN_ISSUER *TRUST_TOKEN_ISSUER_new(
+    uint16_t max_batchsize);
+
+// TRUST_TOKEN_ISSUER_free releases memory associated with |ctx|.
+OPENSSL_EXPORT void TRUST_TOKEN_ISSUER_free(TRUST_TOKEN_ISSUER *ctx);
+
+// TRUST_TOKEN_ISSUER_add_key configures the |ctx| to support the private key
+// |key|. It must be a private key returned by |TRUST_TOKEN_generate_key|. It
+// returns one on success or zero on error. This function may fail if the |key|
+// can't be parsed or too many keys have been configured.
+OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_add_key(TRUST_TOKEN_ISSUER *ctx,
+                                              const uint8_t *key,
+                                              size_t key_len);
+
+// TRUST_TOKEN_ISSUER_set_srr_key sets the private key used to sign the SRR. It
+// returns one on success and zero on error.
+OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_set_srr_key(TRUST_TOKEN_ISSUER *ctx,
+                                                  EVP_PKEY *key);
+
+// TRUST_TOKEN_ISSUER_set_metadata_key sets the key used to encrypt the private
+// metadata. The key is a randomly generated bytestring of at least 32 bytes
+// used to encode the private metadata bit in the SRR. It returns one on success
+// and zero on error.
+OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_set_metadata_key(TRUST_TOKEN_ISSUER *ctx,
+                                                       const uint8_t *key,
+                                                       size_t len);
+
+// TRUST_TOKEN_ISSUER_issue ingests |request| for token issuance
+// and generates up to |max_issuance| valid tokens, producing a list of blinded
+// tokens and storing the response into a newly-allocated buffer and setting
+// |*out| to that buffer, |*out_len| to its length, and |*out_tokens_issued| to
+// the number of tokens issued. The tokens are issued with public metadata of
+// |public_metadata| and a private metadata value of |private_metadata|.
+// |public_metadata| must be one of the previously configured key IDs.
+// |private_metadata| must be 0 or 1. The caller takes ownership of the buffer
+// and must call |OPENSSL_free| when done. It returns one on success or zero on
+// error.
+OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_issue(
+    const TRUST_TOKEN_ISSUER *ctx, uint8_t **out, size_t *out_len,
+    uint8_t *out_tokens_issued, const uint8_t *request, size_t request_len,
+    uint32_t public_metadata, uint8_t private_metadata, size_t max_issuance);
+
+// TRUST_TOKEN_ISSUER_redeem ingests a |request| for token redemption and
+// verifies the token. If the token is valid, a SRR is produced with a lifetime
+// of |lifetime| (in seconds), signing over the requested data from the request
+// and the value of the token, storing the result into a newly-allocated buffer
+// and setting |*out| to that buffer and |*out_len| to its length. The extracted
+// |TRUST_TOKEN| is stored into a newly-allocated buffer and stored in
+// |*out_token|. The extracted client data is stored into a newly-allocated
+// buffer and stored in |*out_client_data|. The extracted redemption time is
+// stored in |*out_redemption_time|. The caller takes ownership of each output
+// buffer and must call |OPENSSL_free| when done. It returns one on success or
+// zero on error.
+//
+// The caller must keep track of all values of |*out_token| and
+// |*out_client_data| and seen globally before returning the SRR to the client.
+// If either value has been repeated, 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 and query private metadata bits in SRRs.
+//
+// TODO(svaldez): The private metadata bit should not be leaked on replay. This
+// means callers cannot use eventual consistency to trade off double-spending
+// and distributed system performance. See https://crbug.com/boringssl/328.
+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,
+    size_t *out_client_data_len, uint64_t *out_redemption_time,
+    const uint8_t *request, size_t request_len, uint64_t lifetime);
+
+// TRUST_TOKEN_decode_private_metadata decodes |encrypted_bit| using the
+// private metadata key specified by a |key| buffer of length |key_len| and the
+// client data specified by a |client_data| buffer of length |client_data_len|.
+// |*out_value is set to the decrypted value, either zero or one. It returns one
+// on success and zero on error.
+OPENSSL_EXPORT int TRUST_TOKEN_decode_private_metadata(
+    uint8_t *out_value, const uint8_t *key, size_t key_len,
+    const uint8_t *client_data, size_t client_data_len, uint8_t encrypted_bit);
+
+
 #if defined(__cplusplus)
 }  // extern C
+
+extern "C++" {
+
+BSSL_NAMESPACE_BEGIN
+
+BORINGSSL_MAKE_DELETER(TRUST_TOKEN, TRUST_TOKEN_free)
+BORINGSSL_MAKE_DELETER(TRUST_TOKEN_CLIENT, TRUST_TOKEN_CLIENT_free)
+BORINGSSL_MAKE_DELETER(TRUST_TOKEN_ISSUER, TRUST_TOKEN_ISSUER_free)
+
+
+BSSL_NAMESPACE_END
+
+}  // extern C++
 #endif
 
 #define TRUST_TOKEN_R_KEYGEN_FAILURE 100
 #define TRUST_TOKEN_R_BUFFER_TOO_SMALL 101
+#define TRUST_TOKEN_R_OVER_BATCHSIZE 102
+#define TRUST_TOKEN_R_DECODE_ERROR 103
+#define TRUST_TOKEN_R_SRR_SIGNATURE_ERROR 104
+#define TRUST_TOKEN_R_DECODE_FAILURE 105
+#define TRUST_TOKEN_R_INVALID_METADATA 106
+#define TRUST_TOKEN_R_TOO_MANY_KEYS 107
+#define TRUST_TOKEN_R_NO_KEYS_CONFIGURED 108
+#define TRUST_TOKEN_R_INVALID_KEY_ID 109
+#define TRUST_TOKEN_R_INVALID_TOKEN 110
+#define TRUST_TOKEN_R_BAD_VALIDITY_CHECK 111
+#define TRUST_TOKEN_R_NO_SRR_KEY_CONFIGURED 112
+#define TRUST_TOKEN_R_INVALID_METADATA_KEY 113
 
 #endif  // OPENSSL_HEADER_TRUST_TOKEN_H