forked from aws/aws-lc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrust_token.h
344 lines (294 loc) · 17 KB
/
trust_token.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/* 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#ifndef OPENSSL_HEADER_TRUST_TOKEN_H
#define OPENSSL_HEADER_TRUST_TOKEN_H
#include <openssl/base.h>
#include <openssl/stack.h>
#if defined(__cplusplus)
extern "C" {
#endif
// Trust Token implementation.
//
// Trust Token is an implementation of an experimental mechanism similar to
// Privacy Pass which allows issuance and redemption of anonymized tokens with
// limited private metadata.
//
// References:
// https://eprint.iacr.org/2020/072.pdf
// https://github.com/alxdavids/privacy-pass-ietf/tree/master/drafts
// https://github.com/WICG/trust-token-api/blob/master/README.md
//
// WARNING: This API is unstable and subject to change.
// TRUST_TOKEN_experiment_v1 is an experimental Trust Tokens protocol using
// PMBTokens and P-384.
OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void);
// TRUST_TOKEN_experiment_v2_voprf is an experimental Trust Tokens protocol
// using VOPRFs and P-384 with up to 6 keys, without RR verification.
OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_voprf(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.
OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_pmb(void);
// TRUST_TOKEN_pst_v1_voprf is an experimental Trust Tokens protocol
// using VOPRFs and P-384 with up to 6 keys, without RR verification.
OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_pst_v1_voprf(void);
// TRUST_TOKEN_pst_v1_pmb is an experimental Trust Tokens protocol using
// PMBTokens and P-384 with up to 3 keys, without RR verification.
OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_pst_v1_pmb(void);
// 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
// TRUST_TOKEN_generate_key creates a new Trust Token keypair labeled with |id|
// and serializes the private and public keys, writing the private key to
// |out_priv_key| and setting |*out_priv_key_len| to the number of bytes
// written, and writing the public key to |out_pub_key| and setting
// |*out_pub_key_len| to the number of bytes written.
//
// At most |max_priv_key_len| and |max_pub_key_len| bytes are written. In order
// to ensure success, these should be at least
// |TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE| and |TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE|.
//
// This function returns one on success or zero on error.
OPENSSL_EXPORT int TRUST_TOKEN_generate_key(
const TRUST_TOKEN_METHOD *method, uint8_t *out_priv_key,
size_t *out_priv_key_len, size_t max_priv_key_len, uint8_t *out_pub_key,
size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id);
// TRUST_TOKEN_derive_key_from_secret deterministically derives a new Trust
// Token keypair labeled with |id| from an input |secret| and serializes the
// private and public keys, writing the private key to |out_priv_key| and
// setting |*out_priv_key_len| to the number of bytes written, and writing the
// public key to |out_pub_key| and setting |*out_pub_key_len| to the number of
// bytes written.
//
// At most |max_priv_key_len| and |max_pub_key_len| bytes are written. In order
// to ensure success, these should be at least
// |TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE| and |TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE|.
//
// This function returns one on success or zero on error.
OPENSSL_EXPORT int TRUST_TOKEN_derive_key_from_secret(
const TRUST_TOKEN_METHOD *method, uint8_t *out_priv_key,
size_t *out_priv_key_len, size_t max_priv_key_len, uint8_t *out_pub_key,
size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id,
const uint8_t *secret, size_t secret_len);
// 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|. This
// function will return an error if |max_batchsize| is too large for Trust
// Tokens.
OPENSSL_EXPORT TRUST_TOKEN_CLIENT *TRUST_TOKEN_CLIENT_new(
const TRUST_TOKEN_METHOD *method, size_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_begin_issuance_over_message produces a request for a trust
// token derived from |msg| 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_over_message(
TRUST_TOKEN_CLIENT *ctx, uint8_t **out, size_t *out_len, size_t count,
const uint8_t *msg, size_t msg_len);
// 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 in TrustTokenV1 and ignored in
// other versions. 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. In
// |TRUST_TOKEN_experiment_v1|, it then verifies the SRR and if valid 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). In other versions, it sets |*out_rr| and |*out_rr_len|
// to a newly-allocated buffer containing |response| and leaves all validation
// to the caller. It returns one on success or zero on failure.
OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_finish_redemption(
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,
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|. This
// function will return an error if |max_batchsize| is too large for Trust
// Tokens.
OPENSSL_EXPORT TRUST_TOKEN_ISSUER *TRUST_TOKEN_ISSUER_new(
const TRUST_TOKEN_METHOD *method, size_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,
size_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. The public metadata is stored in |*out_public|. The
// private metadata (if any) is stored in |*out_private|. 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 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| seen globally before
// returning a response to the client. If the value has been reused, the caller
// must report an error to the client. Returning a response with replayed values
// allows an attacker to double-spend tokens.
OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_redeem(
const TRUST_TOKEN_ISSUER *ctx, uint32_t *out_public, uint8_t *out_private,
TRUST_TOKEN **out_token, uint8_t **out_client_data,
size_t *out_client_data_len, const uint8_t *request, size_t request_len);
// TRUST_TOKEN_ISSUER_redeem_raw is a legacy alias for
// |TRUST_TOKEN_ISSUER_redeem|.
#define TRUST_TOKEN_ISSUER_redeem_raw TRUST_TOKEN_ISSUER_redeem
// TRUST_TOKEN_ISSUER_redeem_over_message ingests a |request| for token
// redemption and a message and verifies the token and that it is derived from
// the provided |msg|. The public metadata is stored in
// |*out_public|. The private metadata (if any) is stored in |*out_private|. 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 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| seen globally before
// returning a response to the client. If the value has been reused, the caller
// must report an error to the client. Returning a response with replayed values
// allows an attacker to double-spend tokens.
OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_redeem_over_message(
const TRUST_TOKEN_ISSUER *ctx, uint32_t *out_public, uint8_t *out_private,
TRUST_TOKEN **out_token, uint8_t **out_client_data,
size_t *out_client_data_len, const uint8_t *request, size_t request_len,
const uint8_t *msg, size_t msg_len);
// 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_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.
OPENSSL_EXPORT int TRUST_TOKEN_decode_private_metadata(
const TRUST_TOKEN_METHOD *method, uint8_t *out_value, const uint8_t *key,
size_t key_len, const uint8_t *nonce, size_t nonce_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
#define TRUST_TOKEN_R_INVALID_PROOF 114
#endif // OPENSSL_HEADER_TRUST_TOKEN_H