Enable tracing of packets that have been sent
[openssl.git] / ssl / quic / quic_trace.c
1 /*
2  * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <openssl/bio.h>
11 #include "../ssl_local.h"
12 #include "internal/quic_wire_pkt.h"
13
14 static const char *packet_type(int type)
15 {
16     switch (type) {
17     case QUIC_PKT_TYPE_INITIAL:
18         return "Initial";
19
20     case QUIC_PKT_TYPE_0RTT:
21         return "0RTT";
22
23     case QUIC_PKT_TYPE_HANDSHAKE:
24         return "Handshake";
25
26     case QUIC_PKT_TYPE_RETRY:
27         return "Retry";
28
29     case QUIC_PKT_TYPE_1RTT:
30         return "1RTT";
31
32     case QUIC_PKT_TYPE_VERSION_NEG:
33         return "VersionNeg";
34
35     default:
36         return "Unknown";
37     }
38 }
39
40 static const char *conn_id(QUIC_CONN_ID *id, char *buf, size_t buflen)
41 {
42     size_t i;
43     char *obuf = buf;
44
45     if (id->id_len == 0)
46         return "<zero length id>";
47
48     if ((((size_t)id->id_len * 2) + 2) > buflen - 1)
49         return "<id too long>"; /* Should never happen */
50
51     buf[0] = '0';
52     buf[1]= 'x';
53     buf += 2;
54     buflen -= 2;
55
56     for (i = 0; i < id->id_len; i++, buflen -= 2, buf += 2)
57         BIO_snprintf(buf, buflen, "%02x", id->id[i]);
58
59     return obuf;
60 }
61
62 static int frame_ack(BIO *bio, PACKET *pkt)
63 {
64     OSSL_QUIC_FRAME_ACK ack;
65     OSSL_QUIC_ACK_RANGE *ack_ranges = NULL;
66     uint64_t total_ranges = 0;
67
68     if (!ossl_quic_wire_peek_frame_ack_num_ranges(pkt, &total_ranges)
69         /* In case sizeof(uint64_t) > sizeof(size_t) */
70         || total_ranges > SIZE_MAX / sizeof(ack_ranges[0])
71         || (ack_ranges = OPENSSL_zalloc(sizeof(ack_ranges[0])
72                                         * (size_t)total_ranges)) == NULL)
73         return 0;
74
75     ack.ack_ranges = ack_ranges;
76     ack.num_ack_ranges = (size_t)total_ranges;
77
78     if (!ossl_quic_wire_decode_frame_ack(pkt, 0, &ack, NULL))
79         return 0;
80
81     /* TODO(QUIC): Display the ack data here */
82
83     OPENSSL_free(ack_ranges);
84     return 1;
85 }
86
87 static int frame_reset_stream(BIO *bio, PACKET *pkt)
88 {
89     OSSL_QUIC_FRAME_RESET_STREAM frame_data;
90
91     if (!ossl_quic_wire_decode_frame_reset_stream(pkt, &frame_data))
92         return 0;
93
94     /* TODO(QUIC): Display reset stream data here */
95
96     return 1;
97 }
98
99 static int frame_stop_sending(BIO *bio, PACKET *pkt)
100 {
101     OSSL_QUIC_FRAME_STOP_SENDING frame_data;
102
103     if (!ossl_quic_wire_decode_frame_stop_sending(pkt, &frame_data))
104         return 0;
105
106     return 1;
107 }
108
109 static int frame_crypto(BIO *bio, PACKET *pkt)
110 {
111     OSSL_QUIC_FRAME_CRYPTO frame_data;
112
113     if (!ossl_quic_wire_decode_frame_crypto(pkt, &frame_data))
114         return 0;
115
116     BIO_printf(bio, "    Offset: %lu\n", frame_data.offset);
117     BIO_printf(bio, "    Len: %lu\n", frame_data.len);
118
119     return 1;
120 }
121
122 static int frame_new_token(BIO *bio, PACKET *pkt)
123 {
124     const uint8_t *token;
125     size_t token_len;
126
127     if (!ossl_quic_wire_decode_frame_new_token(pkt, &token, &token_len))
128         return 0;
129
130     return 1;
131 }
132
133 static int frame_stream(BIO *bio, PACKET *pkt, uint64_t frame_type)
134 {
135
136     OSSL_QUIC_FRAME_STREAM frame_data;
137
138     BIO_puts(bio, "Stream");
139     switch(frame_type) {
140     case OSSL_QUIC_FRAME_TYPE_STREAM:
141         BIO_puts(bio, "\n");
142         break;
143
144     case OSSL_QUIC_FRAME_TYPE_STREAM_FIN:
145         BIO_puts(bio, " (Fin)\n");
146         break;
147
148     case OSSL_QUIC_FRAME_TYPE_STREAM_LEN:
149         BIO_puts(bio, " (Len)\n");
150         break;
151
152     case OSSL_QUIC_FRAME_TYPE_STREAM_LEN_FIN:
153         BIO_puts(bio, " (Len, Fin)\n");
154         break;
155
156     case OSSL_QUIC_FRAME_TYPE_STREAM_OFF:
157         BIO_puts(bio, " (Off)\n");
158         break;
159
160     case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_FIN:
161         BIO_puts(bio, " (Off, Fin)\n");
162         break;
163
164     case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN:
165         BIO_puts(bio, " (Off, Len)\n");
166         break;
167
168     case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN_FIN:
169         BIO_puts(bio, " (Off, Len, Fin)\n");
170         break;
171
172     default:
173         return 0;
174     }
175
176     if (!ossl_quic_wire_decode_frame_stream(pkt, &frame_data))
177         return 0;
178
179     BIO_printf(bio, "    Stream id: %lu\n", frame_data.stream_id);
180     BIO_printf(bio, "    Offset: %lu\n", frame_data.offset);
181     BIO_printf(bio, "    Len: %lu\n", frame_data.len);
182
183     return 1;
184 }
185
186 static int frame_max_data(BIO *bio, PACKET *pkt)
187 {
188     uint64_t max_data = 0;
189
190     if (!ossl_quic_wire_decode_frame_max_data(pkt, &max_data))
191         return 0;
192
193     return 1;
194 }
195
196 static int frame_max_stream_data(BIO *bio, PACKET *pkt)
197 {
198     uint64_t stream_id = 0;
199     uint64_t max_stream_data = 0;
200
201     if (!ossl_quic_wire_decode_frame_max_stream_data(pkt, &stream_id,
202                                                      &max_stream_data))
203         return 0;
204
205     return 1;
206 }
207
208 static int frame_max_streams(BIO *bio, PACKET *pkt)
209 {
210     uint64_t max_streams = 0;
211
212     if (!ossl_quic_wire_decode_frame_max_streams(pkt, &max_streams))
213         return 0;
214
215     return 1;
216 }
217
218 static int frame_data_blocked(BIO *bio, PACKET *pkt)
219 {
220     uint64_t max_data = 0;
221
222     if (!ossl_quic_wire_decode_frame_data_blocked(pkt, &max_data))
223         return 0;
224
225     return 1;
226 }
227
228 static int frame_stream_data_blocked(BIO *bio, PACKET *pkt)
229 {
230     uint64_t stream_id = 0;
231     uint64_t max_data = 0;
232
233     if (!ossl_quic_wire_decode_frame_stream_data_blocked(pkt, &stream_id,
234                                                          &max_data))
235         return 0;
236
237     return 1;
238 }
239
240 static int frame_streams_blocked(BIO *bio, PACKET *pkt)
241 {
242     uint64_t max_data = 0;
243
244     if (!ossl_quic_wire_decode_frame_streams_blocked(pkt, &max_data))
245         return 0;
246
247     return 1;
248 }
249
250 static int frame_new_conn_id(BIO *bio, PACKET *pkt)
251 {
252     OSSL_QUIC_FRAME_NEW_CONN_ID frame_data;
253
254     if (!ossl_quic_wire_decode_frame_new_conn_id(pkt, &frame_data))
255         return 0;
256
257     return 1;
258 }
259
260 static int frame_retire_conn_id(BIO *bio, PACKET *pkt)
261 {
262     uint64_t seq_num;
263
264     if (!ossl_quic_wire_decode_frame_retire_conn_id(pkt, &seq_num))
265         return 0;
266
267     return 1;
268 }
269
270 static int frame_path_challenge(BIO *bio, PACKET *pkt)
271 {
272     uint64_t frame_data = 0;
273
274     if (!ossl_quic_wire_decode_frame_path_challenge(pkt, &frame_data))
275         return 0;
276
277     return 1;
278 }
279
280 static int frame_path_response(BIO *bio, PACKET *pkt)
281 {
282     uint64_t frame_data = 0;
283
284     if (!ossl_quic_wire_decode_frame_path_response(pkt, &frame_data))
285         return 0;
286
287     return 1;
288 }
289
290 static int frame_conn_closed(BIO *bio, PACKET *pkt)
291 {
292     OSSL_QUIC_FRAME_CONN_CLOSE frame_data;
293
294     if (!ossl_quic_wire_decode_frame_conn_close(pkt, &frame_data))
295         return 0;
296
297     return 1;
298 }
299
300 static int trace_frame_data(BIO *bio, PACKET *pkt)
301 {
302     uint64_t frame_type;
303
304     if (!ossl_quic_wire_peek_frame_header(pkt, &frame_type))
305         return 0;
306
307     switch (frame_type) {
308     case OSSL_QUIC_FRAME_TYPE_PING:
309         BIO_puts(bio, "Ping\n");
310         if (!ossl_quic_wire_decode_frame_ping(pkt))
311             return 0;
312         break;
313
314     case OSSL_QUIC_FRAME_TYPE_PADDING:
315         BIO_puts(bio, "Padding\n");
316         ossl_quic_wire_decode_padding(pkt);
317         break;
318
319     case OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN:
320     case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN:
321         BIO_puts(bio, "Ack ");
322         if (frame_type == OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN)
323             BIO_puts(bio, " (with ECN)\n");
324         else
325             BIO_puts(bio, " (without ECN)\n");
326         if (!frame_ack(bio, pkt))
327             return 0;
328         break;
329
330     case OSSL_QUIC_FRAME_TYPE_RESET_STREAM:
331         BIO_puts(bio, "Reset stream\n");
332         if (!frame_reset_stream(bio, pkt))
333             return 0;
334         break;
335
336     case OSSL_QUIC_FRAME_TYPE_STOP_SENDING:
337         BIO_puts(bio, "Stop sending\n");
338         if (!frame_stop_sending(bio, pkt))
339             return 0;
340         break;
341
342     case OSSL_QUIC_FRAME_TYPE_CRYPTO:
343         BIO_puts(bio, "Crypto\n");
344         if (!frame_crypto(bio, pkt))
345             return 0;
346         break;
347
348     case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
349         BIO_puts(bio, "New token\n");
350         if (!frame_new_token(bio, pkt))
351             return 0;
352         break;
353
354     case OSSL_QUIC_FRAME_TYPE_STREAM:
355     case OSSL_QUIC_FRAME_TYPE_STREAM_FIN:
356     case OSSL_QUIC_FRAME_TYPE_STREAM_LEN:
357     case OSSL_QUIC_FRAME_TYPE_STREAM_LEN_FIN:
358     case OSSL_QUIC_FRAME_TYPE_STREAM_OFF:
359     case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_FIN:
360     case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN:
361     case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN_FIN:
362         /* frame_stream() prints the frame type string */
363         if (!frame_stream(bio, pkt, frame_type))
364             return 0;
365         break;
366
367     case OSSL_QUIC_FRAME_TYPE_MAX_DATA:
368         BIO_puts(bio, "Max data\n");
369         if (!frame_max_data(bio, pkt))
370             return 0;
371         break;
372
373     case OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA:
374         BIO_puts(bio, "Max stream data\n");
375         if (!frame_max_stream_data(bio, pkt))
376             return 0;
377         break;
378
379     case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI:
380     case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI:
381         BIO_puts(bio, "Max streams ");
382         if (frame_type == OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI)
383             BIO_puts(bio, " (Bidi)\n");
384         else
385             BIO_puts(bio, " (Uni)\n");
386         if (!frame_max_streams(bio, pkt))
387             return 0;
388         break;
389
390     case OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED:
391         BIO_puts(bio, "Data blocked\n");
392         if (!frame_data_blocked(bio, pkt))
393             return 0;
394         break;
395
396     case OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED:
397         BIO_puts(bio, "Stream data blocked\n");
398         if (!frame_stream_data_blocked(bio, pkt))
399             return 0;
400         break;
401
402     case OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI:
403     case OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_UNI:
404         BIO_puts(bio, "Streams blocked");
405         if (frame_type == OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI)
406             BIO_puts(bio, " (Bidi)\n");
407         else
408             BIO_puts(bio, " (Uni)\n");
409         if (!frame_streams_blocked(bio, pkt))
410             return 0;
411         break;
412
413     case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
414         BIO_puts(bio, "New conn id\n");
415         if (!frame_new_conn_id(bio, pkt))
416             return 0;
417         break;
418
419     case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
420         BIO_puts(bio, "Retire conn id\n");
421         if (!frame_retire_conn_id(bio, pkt))
422             return 0;
423         break;
424
425     case OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE:
426         BIO_puts(bio, "Path challenge\n");
427         if (!frame_path_challenge(bio, pkt))
428             return 0;
429         break;
430
431     case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
432         BIO_puts(bio, "Path response\n");
433         if (!frame_path_response(bio, pkt))
434             return 0;
435         break;
436
437     case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP:
438     case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT:
439         BIO_puts(bio, "Connection close");
440         if (frame_type == OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP)
441             BIO_puts(bio, " (app)\n");
442         else
443             BIO_puts(bio, " (transport)\n");
444         if (!frame_conn_closed(bio, pkt))
445             return 0;
446         break;
447
448     case OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE:
449         BIO_puts(bio, "Handshake done\n");
450         if (!ossl_quic_wire_decode_frame_handshake_done(pkt))
451             return 0;
452         break;
453
454     default:
455         return 0;
456     }
457
458     if (PACKET_remaining(pkt) != 0)
459         BIO_puts(bio, "    <unexpected trailing frame data skipped>\n");
460
461     return 1;
462 }
463
464 int ossl_quic_trace(int write_p, int version, int content_type,
465                     const void *buf, size_t msglen, SSL *ssl, void *arg)
466 {
467     BIO *bio = arg;
468     PACKET pkt;
469
470     switch (content_type) {
471     case SSL3_RT_QUIC_DATAGRAM:
472         BIO_puts(bio, write_p ? "Sent" : "Received");
473         /*
474          * Unfortunately there is no way of receiving auxilliary information
475          * about the datagram through the msg_callback API such as the peer
476          * address
477          */
478         BIO_printf(bio, " Datagram\n  Length: %zu\n", msglen);
479         break;
480
481     case SSL3_RT_QUIC_PACKET:
482         {
483             QUIC_PKT_HDR hdr;
484             /*
485              * Max Conn id is 20 bytes (40 hex digits) plus "0x" bytes plus NUL
486              * terminator
487              */
488             char tmpbuf[43];
489             size_t i;
490
491             if (!PACKET_buf_init(&pkt, buf, msglen))
492                 return 0;
493             /* Decode the packet header */
494             /*
495              * TODO(QUIC): We need to query the short connection id len here,
496              *             e.g. via some API SSL_get_short_conn_id_len()
497              */
498             if (ossl_quic_wire_decode_pkt_hdr(&pkt, 0, 0, 1, &hdr, NULL) != 1)
499                 return 0;
500
501             BIO_puts(bio, write_p ? "Sent" : "Received");
502             BIO_puts(bio, " Packet\n");
503             BIO_printf(bio, "  Packet Type: %s\n", packet_type(hdr.type));
504             if (hdr.type != QUIC_PKT_TYPE_1RTT)
505                 BIO_printf(bio, "  Version: 0x%08x\n", hdr.version);
506             BIO_printf(bio, "  Destination Conn Id: %s\n",
507                        conn_id(&hdr.dst_conn_id, tmpbuf, sizeof(tmpbuf)));
508             if (hdr.type != QUIC_PKT_TYPE_1RTT)
509                 BIO_printf(bio, "  Source Conn Id: %s\n",
510                            conn_id(&hdr.src_conn_id, tmpbuf, sizeof(tmpbuf)));
511             BIO_printf(bio, "  Payload length: %zu\n", hdr.len);
512             if (hdr.type == QUIC_PKT_TYPE_INITIAL) {
513                 BIO_puts(bio, "  Token: ");
514                 if (hdr.token_len == 0) {
515                     BIO_puts(bio, "<zerlo length token>");
516                 } else {
517                     for (i = 0; i < hdr.token_len; i++)
518                         BIO_printf(bio, "%02x", hdr.token[i]);
519                 }
520                 BIO_puts(bio, "\n");
521             }
522             if (hdr.type != QUIC_PKT_TYPE_VERSION_NEG
523                     && hdr.type != QUIC_PKT_TYPE_RETRY) {
524                 BIO_puts(bio, "  Packet Number: 0x");
525                 /* Will always be at least 1 byte */
526                 for (i = 0; i < hdr.pn_len; i++)
527                     BIO_printf(bio, "%02x", hdr.pn[i]);
528                 BIO_puts(bio, "\n");
529             }
530             break;
531         }
532
533     case SSL3_RT_QUIC_FRAME_PADDING:
534     case SSL3_RT_QUIC_FRAME_FULL:
535         {
536             BIO_puts(bio, write_p ? "Sent" : "Received");
537             BIO_puts(bio, " Frame: ");
538
539             if (!PACKET_buf_init(&pkt, buf, msglen))
540                 return 0;
541             if (!trace_frame_data(bio, &pkt)) {
542                 BIO_puts(bio, "  <error processing frame data>\n");
543                 return 0;
544             }
545         }
546         break;
547
548     case SSL3_RT_QUIC_FRAME_HEADER:
549         {
550             BIO_puts(bio, write_p ? "Sent" : "Received");
551             BIO_puts(bio, " Frame Data\n");
552
553             /* TODO(QUIC): Implement me */
554             BIO_puts(bio, "  <content skipped>\n");
555         }
556         break;
557
558     default:
559         /* Unrecognised content_type. We defer to SSL_trace */
560         return 0;
561     }
562
563     return 1;
564 }