QLOG: JSON Encoder: Rename JSON_ENC
[openssl.git] / ssl / quic / json_enc.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 "internal/json_enc.h"
11 #include "internal/nelem.h"
12 #include <string.h>
13 #include <math.h>
14
15 /*
16  * wbuf
17  * ====
18  */
19 static int wbuf_flush(struct json_write_buf *wbuf);
20
21 static int wbuf_init(struct json_write_buf *wbuf, BIO *bio, size_t alloc)
22 {
23     wbuf->buf = OPENSSL_malloc(alloc);
24     if (wbuf->buf == NULL)
25         return 0;
26
27     wbuf->cur   = 0;
28     wbuf->alloc = alloc;
29     wbuf->bio   = bio;
30     return 1;
31 }
32
33 static void wbuf_cleanup(struct json_write_buf *wbuf)
34 {
35     OPENSSL_free(wbuf->buf);
36     wbuf->buf   = NULL;
37     wbuf->alloc = 0;
38 }
39
40 static void wbuf_set_bio(struct json_write_buf *wbuf, BIO *bio)
41 {
42     wbuf->bio = bio;
43 }
44
45 /* Empty write buffer. */
46 static ossl_inline void wbuf_clean(struct json_write_buf *wbuf)
47 {
48     wbuf->cur = 0;
49 }
50
51 /* Available data remaining in buffer. */
52 static ossl_inline size_t wbuf_avail(struct json_write_buf *wbuf)
53 {
54     return wbuf->alloc - wbuf->cur;
55 }
56
57 /* Add character to write buffer, returning 0 on flush failure. */
58 static ossl_inline int wbuf_write_char(struct json_write_buf *wbuf, char c)
59 {
60     if (wbuf_avail(wbuf) == 0) {
61         if (!wbuf_flush(wbuf))
62             return 0;
63     }
64
65     wbuf->buf[wbuf->cur++] = c;
66     return 1;
67 }
68
69 /*
70  * Write zero-terminated string to write buffer, returning 0 on flush failure.
71  */
72 static int wbuf_write_str(struct json_write_buf *wbuf, const char *s)
73 {
74     char c;
75
76     while ((c = *s++) != 0)
77         if (!wbuf_write_char(wbuf, c))
78             return 0;
79
80     return 1;
81 }
82
83 /* Flush write buffer, returning 0 on I/O failure. */
84 static int wbuf_flush(struct json_write_buf *wbuf)
85 {
86     size_t written = 0, total_written = 0;
87
88     while (total_written < wbuf->cur) {
89         if (!BIO_write_ex(wbuf->bio,
90                           wbuf->buf + total_written,
91                           wbuf->cur - total_written,
92                           &written)) {
93             memmove(wbuf->buf,
94                     wbuf->buf + total_written,
95                     wbuf->cur - total_written);
96             wbuf->cur = 0;
97             return 0;
98         }
99
100         total_written += written;
101     }
102
103     wbuf->cur = 0;
104     return 1;
105 }
106
107 /*
108  * OSSL_JSON_ENC: Stack Management
109  * ===============================
110  */
111
112 static int json_ensure_stack_size(OSSL_JSON_ENC *json, size_t num_bytes)
113 {
114     unsigned char *stack;
115
116     if (json->stack_bytes >= num_bytes)
117         return 1;
118
119     if (num_bytes <= OSSL_NELEM(json->stack_small)) {
120         stack = json->stack_small;
121     } else {
122         if (json->stack == json->stack_small)
123             json->stack = NULL;
124
125         stack = OPENSSL_realloc(json->stack, num_bytes);
126         if (stack == NULL)
127             return 0;
128     }
129
130     json->stack         = stack;
131     json->stack_bytes   = num_bytes;
132     return 1;
133 }
134
135 /* Push one bit onto the stack. Returns 0 on allocation failure. */
136 static int json_push(OSSL_JSON_ENC *json, unsigned int v)
137 {
138     if (v > 1)
139         return 0;
140
141     if (json->stack_end_byte >= json->stack_bytes) {
142         size_t new_size
143             = (json->stack_bytes == 0)
144             ? OSSL_NELEM(json->stack_small)
145             : (json->stack_bytes * 2);
146
147         if (!json_ensure_stack_size(json, new_size))
148             return 0;
149
150         json->stack_bytes = new_size;
151     }
152
153     if (v > 0)
154         json->stack[json->stack_end_byte] |= (v << json->stack_end_bit);
155     else
156         json->stack[json->stack_end_byte] &= ~(1U << json->stack_end_bit);
157
158     json->stack_end_bit = (json->stack_end_bit + 1) % CHAR_BIT;
159     if (json->stack_end_bit == 0)
160         ++json->stack_end_byte;
161
162     return 1;
163 }
164
165 /*
166  * Pop a bit from the stack. Returns 0 if stack is empty. Use json_peek() to get
167  * the value before calling this.
168  */
169 static int json_pop(OSSL_JSON_ENC *json)
170 {
171     if (json->stack_end_byte == 0 && json->stack_end_bit == 0)
172         return 0;
173
174     if (json->stack_end_bit == 0) {
175         --json->stack_end_byte;
176         json->stack_end_bit = CHAR_BIT - 1;
177     } else {
178         --json->stack_end_bit;
179     }
180
181     return 1;
182 }
183
184 /*
185  * Returns the bit on the top of the stack, or -1 if the stack is empty.
186  */
187 static int json_peek(OSSL_JSON_ENC *json)
188 {
189     size_t obyte, obit;
190
191     obyte = json->stack_end_byte;
192     obit  = json->stack_end_bit;
193     if (obit == 0) {
194        if (obyte == 0)
195            return -1;
196
197         --obyte;
198         obit = CHAR_BIT - 1;
199     } else {
200         --obit;
201     }
202
203     return (json->stack[obyte] & (1U << obit)) != 0;
204 }
205
206 /*
207  * OSSL_JSON_ENC: Initialisation
208  * =============================
209  */
210
211 enum {
212     STATE_PRE_KEY,
213     STATE_PRE_ITEM,
214     STATE_PRE_COMMA
215 };
216
217 static ossl_inline int in_ijson(const OSSL_JSON_ENC *json)
218 {
219     return (json->flags & OSSL_JSON_FLAG_IJSON) != 0;
220 }
221
222 static ossl_inline int in_seq(const OSSL_JSON_ENC *json)
223 {
224     return (json->flags & OSSL_JSON_FLAG_SEQ) != 0;
225 }
226
227 static ossl_inline int in_pretty(const OSSL_JSON_ENC *json)
228 {
229     return (json->flags & OSSL_JSON_FLAG_PRETTY) != 0;
230 }
231
232 int ossl_json_init(OSSL_JSON_ENC *json, BIO *bio, uint32_t flags)
233 {
234     memset(json, 0, sizeof(*json));
235     json->flags     = flags;
236     json->error     = 1;
237     if (!wbuf_init(&json->wbuf, bio, 4096))
238         return 0;
239
240     json->state = STATE_PRE_COMMA;
241     return ossl_json_reset(json);
242 }
243
244 void ossl_json_cleanup(OSSL_JSON_ENC *json)
245 {
246     wbuf_cleanup(&json->wbuf);
247
248     if (json->stack != json->stack_small)
249         OPENSSL_free(json->stack);
250
251     json->stack = NULL;
252 }
253
254 int ossl_json_flush_cleanup(OSSL_JSON_ENC *json)
255 {
256     int ok = ossl_json_flush(json);
257
258     ossl_json_cleanup(json);
259     return ok;
260 }
261
262 int ossl_json_reset(OSSL_JSON_ENC *json)
263 {
264     wbuf_clean(&json->wbuf);
265     json->stack_end_byte    = 0;
266     json->stack_end_bit     = 0;
267     json->error             = 0;
268     return 1;
269 }
270
271 int ossl_json_flush(OSSL_JSON_ENC *json)
272 {
273     return wbuf_flush(&json->wbuf);
274 }
275
276 int ossl_json_set_sink(OSSL_JSON_ENC *json, BIO *bio)
277 {
278     wbuf_set_bio(&json->wbuf, bio);
279     return 1;
280 }
281
282 int ossl_json_in_error(OSSL_JSON_ENC *json)
283 {
284     return json->error;
285 }
286
287 /*
288  * JSON Builder Calls
289  * ==================
290  */
291
292 static void json_write_qstring(OSSL_JSON_ENC *json, const char *str);
293 static void json_indent(OSSL_JSON_ENC *json);
294
295 static ossl_inline int json_in_error(const OSSL_JSON_ENC *json)
296 {
297     return json->error;
298 }
299
300 static void json_raise_error(OSSL_JSON_ENC *json)
301 {
302     json->error = 1;
303 }
304
305 static void json_undefer(OSSL_JSON_ENC *json)
306 {
307     if (!json->defer_indent)
308         return;
309
310     json_indent(json);
311 }
312
313 static void json_write_char(OSSL_JSON_ENC *json, char ch)
314 {
315     if (json_in_error(json))
316         return;
317
318     json_undefer(json);
319     if (!wbuf_write_char(&json->wbuf, ch))
320         json_raise_error(json);
321 }
322
323 static void json_write_str(OSSL_JSON_ENC *json, const char *s)
324 {
325     if (json_in_error(json))
326         return;
327
328     json_undefer(json);
329     if (!wbuf_write_str(&json->wbuf, s))
330         json_raise_error(json);
331 }
332
333 static void json_indent(OSSL_JSON_ENC *json)
334 {
335     size_t i, depth;
336
337     json->defer_indent = 0;
338
339     if (!in_pretty(json))
340         return;
341
342     json_write_char(json, '\n');
343
344     depth = json->stack_end_byte * 8 + json->stack_end_bit;
345     for (i = 0; i < depth * 4; ++i)
346         json_write_str(json, "    ");
347 }
348
349 static int json_pre_item(OSSL_JSON_ENC *json)
350 {
351     int s;
352
353     if (json_in_error(json))
354         return 0;
355
356     switch (json->state) {
357     case STATE_PRE_COMMA:
358         s = json_peek(json);
359
360         if (s == 0) {
361             json_raise_error(json);
362             return 0;
363         }
364
365         if (s == 1) {
366             json_write_char(json, ',');
367             if (json_in_error(json))
368                 return 0;
369
370             json_indent(json);
371         }
372
373         if (s < 0 && in_seq(json))
374             json_write_char(json, '\x1E');
375
376         json->state = STATE_PRE_ITEM;
377         break;
378
379     case STATE_PRE_ITEM:
380         break;
381
382     case STATE_PRE_KEY:
383     default:
384         json_raise_error(json);
385         return 0;
386     }
387
388     return 1;
389 }
390
391 static void json_post_item(OSSL_JSON_ENC *json)
392 {
393     int s = json_peek(json);
394
395     json->state = STATE_PRE_COMMA;
396
397     if (s < 0 && in_seq(json))
398         json_write_char(json, '\n');
399 }
400
401 /*
402  * Begin a composite structure (object or array).
403  *
404  * type: 0=object, 1=array.
405  */
406 static void composite_begin(OSSL_JSON_ENC *json, int type, char ch)
407 {
408     if (!json_pre_item(json)
409         || !json_push(json, type))
410         json_raise_error(json);
411
412     json_write_char(json, ch);
413     json->defer_indent = 1;
414 }
415
416 /*
417  * End a composite structure (object or array).
418  *
419  * type: 0=object, 1=array. Errors on mismatch.
420  */
421 static void composite_end(OSSL_JSON_ENC *json, int type, char ch)
422 {
423     int was_defer = json->defer_indent;
424
425     if (json_in_error(json))
426         return;
427
428     json->defer_indent = 0;
429
430     if (json_peek(json) != type)
431         return;
432
433     if (type == 0 && json->state == STATE_PRE_ITEM) {
434         json_raise_error(json);
435         return;
436     }
437
438     if (!json_pop(json))
439         return;
440
441     if (!was_defer)
442         json_indent(json);
443
444     json_write_char(json, ch);
445     json_post_item(json);
446 }
447
448 /* Begin a new JSON object. */
449 void ossl_json_object_begin(OSSL_JSON_ENC *json)
450 {
451     composite_begin(json, 0, '{');
452     json->state = STATE_PRE_KEY;
453 }
454
455 /* End a JSON obejct. Must be matched with a call to ossl_json_object_begin(). */
456 void ossl_json_object_end(OSSL_JSON_ENC *json)
457 {
458     composite_end(json, 0, '}');
459 }
460
461 /* Begin a new JSON array. */
462 void ossl_json_array_begin(OSSL_JSON_ENC *json)
463 {
464     composite_begin(json, 1, '[');
465     json->state = STATE_PRE_ITEM;
466 }
467
468 /* End a JSON array. Must be matched with a call to ossl_json_array_end(). */
469 void ossl_json_array_end(OSSL_JSON_ENC *json)
470 {
471     composite_end(json, 1, ']');
472 }
473
474 /*
475  * Encode a JSON key within an object. Pass a zero-terminated string, which can
476  * be freed immediately following the call to this function.
477  */
478 void ossl_json_key(OSSL_JSON_ENC *json, const char *key)
479 {
480     if (json_in_error(json))
481         return;
482
483     if (json_peek(json) != 0) {
484         /* Not in object */
485         json_raise_error(json);
486         return;
487     }
488
489     if (json->state == STATE_PRE_COMMA) {
490         json_write_char(json, ',');
491         json->state = STATE_PRE_KEY;
492     }
493
494     json_indent(json);
495     if (json->state != STATE_PRE_KEY) {
496         json_raise_error(json);
497         return;
498     }
499
500     json_write_qstring(json, key);
501     if (json_in_error(json))
502         return;
503
504     json_write_char(json, ':');
505     if (in_pretty(json))
506         json_write_char(json, ' ');
507
508     json->state = STATE_PRE_ITEM;
509 }
510
511 /* Encode a JSON 'null' value. */
512 void ossl_json_null(OSSL_JSON_ENC *json)
513 {
514     if (!json_pre_item(json))
515         return;
516
517     json_write_str(json, "null");
518     json_post_item(json);
519 }
520
521 void ossl_json_bool(OSSL_JSON_ENC *json, int v)
522 {
523     if (!json_pre_item(json))
524         return;
525
526     json_write_str(json, v > 0 ? "true" : "false");
527     json_post_item(json);
528 }
529
530 #define POW_53 (((int64_t)1) << 53)
531
532 /* Encode a JSON integer from a uint64_t. */
533 static void json_u64(OSSL_JSON_ENC *json, uint64_t v, int noquote)
534 {
535     char buf[22], *p = buf + sizeof(buf) - 1;
536     int quote = !noquote && in_ijson(json) && v > (uint64_t)(POW_53 - 1);
537
538     if (!json_pre_item(json))
539         return;
540
541     if (quote)
542         json_write_char(json, '"');
543
544     if (v == 0)
545         p = "0";
546     else
547         for (*p = '\0'; v > 0; v /= 10)
548             *--p = '0' + v % 10;
549
550     json_write_str(json, p);
551
552     if (quote)
553         json_write_char(json, '"');
554
555     json_post_item(json);
556 }
557
558 void ossl_json_u64(OSSL_JSON_ENC *json, uint64_t v)
559 {
560     json_u64(json, v, 0);
561 }
562
563 /* Encode a JSON integer from an int64_t. */
564 void ossl_json_i64(OSSL_JSON_ENC *json, int64_t value)
565 {
566     uint64_t uv;
567     int quote;
568
569     if (value >= 0) {
570         ossl_json_u64(json, (uint64_t)value);
571         return;
572     }
573
574     if (!json_pre_item(json))
575         return;
576
577     quote = in_ijson(json)
578         && (value > POW_53 - 1 || value < -POW_53 + 1);
579
580     if (quote)
581         json_write_char(json, '"');
582
583     json_write_char(json, '-');
584
585     uv = (value == INT64_MIN)
586         ? ((uint64_t)-(INT64_MIN + 1)) + 1
587         : (uint64_t)-value;
588     json_u64(json, uv, /*noquote=*/1);
589
590     if (quote && !json_in_error(json))
591         json_write_char(json, '"');
592 }
593
594 /* Encode a JSON number from a 64-bit floating point value. */
595 void ossl_json_f64(OSSL_JSON_ENC *json, double value)
596 {
597     char buf[32];
598
599     if (!json_pre_item(json))
600         return;
601
602     if (isnan(value) || isinf(value)) {
603         json_raise_error(json);
604         return;
605     }
606
607     snprintf(buf, sizeof(buf), "%1.17g", value);
608     json_write_str(json, buf);
609     json_post_item(json);
610 }
611
612 /*
613  * Encode a JSON UTF-8 string from a zero-terminated string. The string passed
614  * can be freed immediately following the call to this function.
615  */
616 static ossl_inline int hex_digit(int v)
617 {
618     return v >= 10 ? 'a' + (v - 10) : '0' + v;
619 }
620
621 static ossl_inline void
622 json_write_qstring_inner(OSSL_JSON_ENC *json, const char *str, size_t str_len,
623                          int nul_term)
624 {
625     char c, *o, obuf[7];
626     int i;
627     size_t j;
628
629     if (json_in_error(json))
630         return;
631
632     json_write_char(json, '"');
633
634     for (j = 0; (nul_term && *str != '\0')
635                 || (!nul_term && j < str_len); ++str, ++j) {
636         c = *str;
637         switch (c) {
638         case '\n': o = "\\n"; break;
639         case '\r': o = "\\r"; break;
640         case '\t': o = "\\t"; break;
641         case '\b': o = "\\b"; break;
642         case '\f': o = "\\f"; break;
643         case '"': o = "\\\""; break;
644         case '\\': o = "\\\\"; break;
645         default:
646             if ((unsigned char)c >= 0x80) {
647                 json_raise_error(json);
648                 return;
649             }
650             if ((unsigned char)c < 0x20 || (unsigned char)c >= 0x7f) {
651                 obuf[0] = '\\';
652                 obuf[1] = 'u';
653                 for (i = 0; i < 4; ++i)
654                     obuf[2 + i] = hex_digit((c >> ((3 - i) * 4)) & 0xF);
655                 obuf[6] = '\0';
656                 o = obuf;
657             } else {
658                 json_write_char(json, c);
659                 continue;
660             }
661             break;
662         }
663
664         json_write_str(json, o);
665     }
666
667     json_write_char(json, '"');
668 }
669
670 static void
671 json_write_qstring(OSSL_JSON_ENC *json, const char *str)
672 {
673     json_write_qstring_inner(json, str, 0, 1);
674 }
675
676 static void
677 json_write_qstring_len(OSSL_JSON_ENC *json, const char *str, size_t str_len)
678 {
679     json_write_qstring_inner(json, str, str_len, 0);
680 }
681
682 void ossl_json_str(OSSL_JSON_ENC *json, const char *str)
683 {
684     if (!json_pre_item(json))
685         return;
686
687     json_write_qstring(json, str);
688     json_post_item(json);
689 }
690
691 void ossl_json_str_len(OSSL_JSON_ENC *json, const char *str, size_t str_len)
692 {
693     if (!json_pre_item(json))
694         return;
695
696     json_write_qstring_len(json, str, str_len);
697     json_post_item(json);
698 }
699
700 /*
701  * Encode binary data as a lowercase hex string. data_len is the data length in
702  * bytes.
703  */
704 void ossl_json_str_hex(OSSL_JSON_ENC *json, const void *data, size_t data_len)
705 {
706     const unsigned char *b = data, *end = b + data_len;
707     unsigned char c;
708
709     if (!json_pre_item(json))
710         return;
711
712     json_write_char(json, '"');
713
714     for (; b < end; ++b) {
715         c = *b;
716         json_write_char(json, hex_digit(c >> 4));
717         json_write_char(json, hex_digit(c & 0x0F));
718     }
719
720     json_write_char(json, '"');
721     json_post_item(json);
722 }