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