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': o = "\\n"; break; 625 case '\r': o = "\\r"; break; 626 case '\t': o = "\\t"; break; 627 case '\b': o = "\\b"; break; 628 case '\f': o = "\\f"; break; 629 case '"': o = "\\\""; break; 630 case '\\': o = "\\\\"; break; 631 default: 632 /* valid UTF-8 sequences according to RFC-3629 */ 633 if (u_str[0] >= 0xc2 && u_str[0] <= 0xdf && j >= 2 634 && u_str[1] >= 0x80 && u_str[1] <= 0xbf) { 635 memcpy(obuf, str, 2); 636 obuf[2] = '\0'; 637 str++, j--; 638 o = obuf; 639 break; 640 } 641 if (u_str[0] >= 0xe0 && u_str[0] <= 0xef && j >= 3 642 && u_str[1] >= 0x80 && u_str[1] <= 0xbf 643 && u_str[2] >= 0x80 && u_str[2] <= 0xbf 644 && !(u_str[0] == 0xe0 && u_str[1] <= 0x9f) 645 && !(u_str[0] == 0xed && u_str[1] >= 0xa0)) { 646 memcpy(obuf, str, 3); 647 obuf[3] = '\0'; 648 str += 2; 649 j -= 2; 650 o = obuf; 651 break; 652 } 653 if (u_str[0] >= 0xf0 && u_str[0] <= 0xf4 && j >= 4 654 && u_str[1] >= 0x80 && u_str[1] <= 0xbf 655 && u_str[2] >= 0x80 && u_str[2] <= 0xbf 656 && u_str[3] >= 0x80 && u_str[3] <= 0xbf 657 && !(u_str[0] == 0xf0 && u_str[1] <= 0x8f) 658 && !(u_str[0] == 0xf4 && u_str[1] >= 0x90)) { 659 memcpy(obuf, str, 4); 660 obuf[4] = '\0'; 661 str += 3; 662 j -= 3; 663 o = obuf; 664 break; 665 } 666 if (u_str[0] < 0x20 || u_str[0] >= 0x7f) { 667 obuf[0] = '\\'; 668 obuf[1] = 'u'; 669 for (i = 0; i < 4; ++i) 670 obuf[2 + i] = hex_digit((u_str[0] >> ((3 - i) * 4)) & 0x0F); 671 obuf[6] = '\0'; 672 o = obuf; 673 } else { 674 json_write_char(json, c); 675 continue; 676 } 677 break; 678 } 679 680 json_write_str(json, o); 681 } 682 683 json_write_char(json, '"'); 684 } 685 686 static void 687 json_write_qstring(OSSL_JSON_ENC *json, const char *str) 688 { 689 json_write_qstring_inner(json, str, 0, 1); 690 } 691 692 static void 693 json_write_qstring_len(OSSL_JSON_ENC *json, const char *str, size_t str_len) 694 { 695 json_write_qstring_inner(json, str, str_len, 0); 696 } 697 698 void ossl_json_str(OSSL_JSON_ENC *json, const char *str) 699 { 700 if (!json_pre_item(json)) 701 return; 702 703 json_write_qstring(json, str); 704 json_post_item(json); 705 } 706 707 void ossl_json_str_len(OSSL_JSON_ENC *json, const char *str, size_t str_len) 708 { 709 if (!json_pre_item(json)) 710 return; 711 712 json_write_qstring_len(json, str, str_len); 713 json_post_item(json); 714 } 715 716 /* 717 * Encode binary data as a lowercase hex string. data_len is the data length in 718 * bytes. 719 */ 720 void ossl_json_str_hex(OSSL_JSON_ENC *json, const void *data, size_t data_len) 721 { 722 const unsigned char *b = data, *end = b + data_len; 723 unsigned char c; 724 725 if (!json_pre_item(json)) 726 return; 727 728 json_write_char(json, '"'); 729 730 for (; b < end; ++b) { 731 c = *b; 732 json_write_char(json, hex_digit(c >> 4)); 733 json_write_char(json, hex_digit(c & 0x0F)); 734 } 735 736 json_write_char(json, '"'); 737 json_post_item(json); 738 } 739