forked from microsoft/msquic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcrypto.h
445 lines (391 loc) · 10.7 KB
/
crypto.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
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
/*++
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
Abstract:
Definitions for the Crypto interface, which manages the send and receive
queues for TLS data.
--*/
#if defined(__cplusplus)
extern "C" {
#endif
//
// Set of callbacks for TLS.
//
extern CXPLAT_TLS_CALLBACKS QuicTlsCallbacks;
//
// Stream of TLS data.
//
typedef struct QUIC_CRYPTO {
//
// Indicates the crypto object has been initialized.
//
BOOLEAN Initialized : 1;
//
// Indicates the send state is in recovery.
//
BOOLEAN InRecovery : 1;
//
// Indicates custom cert validation (by the app) is outstanding.
//
BOOLEAN CertValidationPending : 1;
//
// The TLS context for processing handshake messages.
//
CXPLAT_TLS* TLS;
//
// Send State
//
CXPLAT_TLS_PROCESS_STATE TlsState;
//
// Result flags from the last Tls process call.
//
CXPLAT_TLS_RESULT_FLAGS ResultFlags;
//
// The length of bytes that have been sent at least once.
//
uint32_t MaxSentLength;
//
// The smallest offset for unacknowledged send data. This variable is
// similar to RFC793 SND.UNA.
//
uint32_t UnAckedOffset;
//
// The next offset we will start sending at.
//
uint32_t NextSendOffset;
//
// Recovery window
//
uint32_t RecoveryNextOffset;
uint32_t RecoveryEndOffset;
#define RECOV_WINDOW_OPEN(S) ((S)->RecoveryNextOffset < (S)->RecoveryEndOffset)
//
// The ACK ranges greater than 'UnAckedOffset', with holes between them.
//
QUIC_RANGE SparseAckRanges;
//
// Recv State
//
//
// The total amount of data consumed by TLS.
//
uint32_t RecvTotalConsumed;
//
// Indicates Resumption ticket validation is under validation asynchronously
//
BOOLEAN TicketValidationPending : 1;
BOOLEAN TicketValidationRejecting : 1;
uint32_t PendingValidationBufferLength;
//
// The offset the current receive encryption level starts.
//
uint32_t RecvEncryptLevelStartOffset;
//
// The structure for tracking received buffers.
//
QUIC_RECV_BUFFER RecvBuffer;
//
// Resumption ticket to send to server.
//
uint8_t* ResumptionTicket;
uint32_t ResumptionTicketLength;
} QUIC_CRYPTO;
inline
BOOLEAN
QuicCryptoHasPendingCryptoFrame(
_In_ QUIC_CRYPTO* Crypto
)
{
return
RECOV_WINDOW_OPEN(Crypto) ||
(Crypto->NextSendOffset < Crypto->TlsState.BufferTotalLength);
}
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicCryptoInitialize(
_Inout_ QUIC_CRYPTO* Crypto
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoUninitialize(
_In_ QUIC_CRYPTO* Crypto
);
//
// Initializes the TLS state.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicCryptoInitializeTls(
_Inout_ QUIC_CRYPTO* Crypto,
_In_ CXPLAT_SEC_CONFIG* SecConfig,
_In_ const QUIC_TRANSPORT_PARAMETERS* Params
);
//
// Update the initial keys when the QUIC version changes.
//
QUIC_STATUS
QuicCryptoOnVersionChange(
_In_ QUIC_CRYPTO* Crypto
);
//
// Indicate the connection is starting over and the initial data needs to be
// resent.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoReset(
_In_ QUIC_CRYPTO* Crypto
);
//
// Indicates both peers know the handshake completed successfully.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoHandshakeConfirmed(
_In_ QUIC_CRYPTO* Crypto,
_In_ BOOLEAN SignalBinding
);
//
// Cleans up the indicated key type so that it cannot be used for encryption or
// decryption of packets any more. Returns TRUE if keys were actually discarded
// or FALSE if keys had previously been discarded already.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
BOOLEAN
QuicCryptoDiscardKeys(
_In_ QUIC_CRYPTO* Crypto,
_In_ QUIC_PACKET_KEY_TYPE KeyType
);
//
// Returns the next encryption level with data ready to be sent.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_ENCRYPT_LEVEL
QuicCryptoGetNextEncryptLevel(
_In_ QUIC_CRYPTO* Crypto
);
//
// Called to write any frames it needs to the packet buffer. Returns TRUE if
// frames were written; FALSE if it ran out of space to write anything.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
BOOLEAN
QuicCryptoWriteFrames(
_In_ QUIC_CRYPTO* Crypto,
_Inout_ QUIC_PACKET_BUILDER* Builder
);
//
// Called when a crypto frame is inferred to be lost. Returns TRUE if data is
// queued to be sent.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
BOOLEAN
QuicCryptoOnLoss(
_In_ QUIC_CRYPTO* Crypto,
_In_ QUIC_SENT_FRAME_METADATA* FrameMetadata
);
//
// Called when an ACK is received for a crypto frame.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoOnAck(
_In_ QUIC_CRYPTO* Crypto,
_In_ QUIC_SENT_FRAME_METADATA* FrameMetadata
);
//
// Processes a received crypto frame.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicCryptoProcessFrame(
_In_ QUIC_CRYPTO* Crypto,
_In_ QUIC_PACKET_KEY_TYPE KeyType,
_In_ const QUIC_CRYPTO_EX* const Frame
);
//
// Passes any data queued up to TLS for processing.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicCryptoProcessData(
_In_ QUIC_CRYPTO* Crypto,
_In_ BOOLEAN IsClientInitial
);
//
// Processes app-provided data for TLS (i.e. resumption ticket data).
//
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicCryptoProcessAppData(
_In_ QUIC_CRYPTO* Crypto,
_In_ uint32_t DataLength,
_In_reads_bytes_(DataLength)
const uint8_t* AppData
);
//
// Invoked when the app has completed its custom certificate validation.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoCustomCertValidationComplete(
_In_ QUIC_CRYPTO* Crypto,
_In_ BOOLEAN Result,
_In_ QUIC_TLS_ALERT_CODES TlsAlert
);
//
// Invoked when the app has completed its custom resumption ticket validation.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoCustomTicketValidationComplete(
_In_ QUIC_CRYPTO* Crypto,
_In_ BOOLEAN Result
);
//
// Helper function to determine how much complete TLS data is contained in the
// buffer, and should be passed to TLS.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
uint32_t
QuicCryptoTlsGetCompleteTlsMessagesLength(
_In_reads_(BufferLength)
const uint8_t* Buffer,
_In_ uint32_t BufferLength
);
//
// Reads, validates and decodes all information needed for preprocessing the
// initial CRYPTO data from a client. Return QUIC_STATUS_PENDING if not all the
// data necessary to decode is available.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicCryptoTlsReadInitial(
_In_ QUIC_CONNECTION* Connection,
_In_reads_(BufferLength)
const uint8_t* Buffer,
_In_ uint32_t BufferLength,
_Inout_ QUIC_NEW_CONNECTION_INFO* Info
);
//
// Reads only the ClientRandom out of the initial CRYPTO data.
// MUST ONLY BE CALLED AFTER QuicCryptoTlsReadInitial!!
//
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicCryptoTlsReadClientRandom(
_In_reads_(BufferLength)
const uint8_t* Buffer,
_In_ uint32_t BufferLength,
_Inout_ QUIC_TLS_SECRETS* TlsSecrets
);
//
// Generates new 1-RTT read and write keys, unless they already exist.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
QUIC_STATUS
QuicCryptoGenerateNewKeys(
_In_ QUIC_CONNECTION* Connection
);
//
// Shift 1-RTT keys, freeing the old keys and replacing them with the current
// keys, replacing the current keys with the new keys; update the start packet
// number; and invert the key phase bit.
// If the shift is locally-initiated, then set the flag to await confirmation
// of the key update from the peer.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoUpdateKeyPhase (
_In_ QUIC_CONNECTION* Connection,
_In_ BOOLEAN LocalUpdate
);
//
// Encode all state the server needs to resume the connection into a ticket
// ready to be passed to TLS.
// The buffer returned in Ticket needs to be freed with CXPLAT_FREE().
// Note: Connection is only used for logging and may be NULL for testing.
//
QUIC_STATUS
QuicCryptoEncodeServerTicket(
_In_opt_ QUIC_CONNECTION* Connection,
_In_ uint32_t QuicVersion,
_In_ uint32_t AppDataLength,
_In_reads_bytes_opt_(AppDataLength)
const uint8_t* const AppResumptionData,
_In_ const QUIC_TRANSPORT_PARAMETERS* HandshakeTP,
_In_ uint8_t AlpnLength,
_In_reads_bytes_(AlpnLength)
const uint8_t* const NegotiatedAlpn,
_Outptr_result_buffer_(*TicketLength)
uint8_t** Ticket,
_Out_ uint32_t* TicketLength
);
//
// Decode a previously-generated resumption ticket and extract all data needed
// to resume the connection.
// AppData contains a pointer to the offset within Ticket, so do not free it.
// AppData contain NULL if the server application didn't pass any resumption
// data.
// Note: Connection is only used for logging and may be NULL for testing.
//
QUIC_STATUS
QuicCryptoDecodeServerTicket(
_In_ QUIC_CONNECTION* Connection,
_In_ uint16_t TicketLength,
_In_reads_bytes_(TicketLength)
const uint8_t* Ticket,
_In_ const uint8_t* AlpnList,
_In_ uint16_t AlpnListLength,
_Inout_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
_Outptr_result_buffer_maybenull_(*AppDataLength)
const uint8_t** AppData,
_Out_ uint32_t* AppDataLength
);
//
// Encodes necessary data into the client ticket to enable connection resumption.
// The pointer held by ClientTicket needs to be freed by CXPLAT_FREE().
// Note: Connection is only used for logging and may be NULL for testing.
//
QUIC_STATUS
QuicCryptoEncodeClientTicket(
_In_opt_ QUIC_CONNECTION* Connection,
_In_ uint32_t TicketLength,
_In_reads_bytes_(TicketLength)
const uint8_t* Ticket,
_In_ const QUIC_TRANSPORT_PARAMETERS* ServerTP,
_In_ uint32_t QuicVersion,
_Outptr_result_buffer_(*ClientTicketLength)
const uint8_t** ClientTicket,
_Out_ uint32_t* ClientTicketLength
);
//
// Decodes and returns data necessary to resume a connection from a client ticket.
// The buffer held in ServerTicket must be freed with CXPLAT_FREE().
// Note: Connection is only used for logging and my be NULL for testing.
//
QUIC_STATUS
QuicCryptoDecodeClientTicket(
_In_opt_ QUIC_CONNECTION* Connection,
_In_ uint16_t ClientTicketLength,
_In_reads_bytes_(ClientTicketLength)
const uint8_t* ClientTicket,
_Inout_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
_Outptr_result_buffer_maybenull_(*ServerTicketLength)
uint8_t** ServerTicket,
_Out_ uint32_t* ServerTicketLength,
_Out_ uint32_t* QuicVersion
);
//
// Helper function to NegotiateAlpn.
//
QUIC_STATUS
QuicCryptoReNegotiateAlpn(
_In_opt_ QUIC_CONNECTION* Connection,
_In_ uint16_t AlpnListLength,
_In_reads_bytes_(AlpnListLength)
const uint8_t* AlpnList
);
#if defined(__cplusplus)
}
#endif