1 /* 2 * Copyright 2023-2024 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 #ifndef OSSL_JSON_ENC_H 11 # define OSSL_JSON_ENC_H 12 13 # include <openssl/bio.h> 14 15 /* 16 * JSON Encoder 17 * ============ 18 * 19 * This JSON encoder is used for qlog. It supports ordinary JSON (RFC 7159), 20 * JSON-SEQ (RFC 7464) and I-JSON (RFC 7493). It supports only basic ASCII. 21 */ 22 23 struct json_write_buf { 24 BIO *bio; 25 char *buf; 26 size_t alloc, cur; 27 }; 28 29 typedef struct ossl_json_enc_st { 30 uint32_t flags; 31 /* error: 1 if an error has occurred. */ 32 /* state: current state. */ 33 /* stack stores a bitmap. 0=object, 1=array. */ 34 /* stack cur size: stack_end_byte bytes, stack_end_bit bits. */ 35 /* stack alloc size: stack_bytes bytes. */ 36 unsigned char error, stack_end_bit, state, *stack, defer_indent; 37 unsigned char stack_small[16]; 38 struct json_write_buf wbuf; 39 size_t stack_end_byte, stack_bytes; 40 } OSSL_JSON_ENC; 41 42 /* 43 * ossl_json_init 44 * -------------- 45 * 46 * Initialises a JSON encoder. 47 * 48 * If the flag OSSL_JSON_FLAG_SEQ is passed, the output is in JSON-SEQ. The 49 * caller should use the encoder as though it is encoding members of a JSON 50 * array (but without calling ossl_json_array_begin() or ossl_json_array_end()). 51 * Each top-level JSON item (e.g. JSON object) encoded will be separated 52 * correctly as per the JSON-SEQ format. 53 * 54 * If the flag OSSL_JSON_FLAG_SEQ is not passed, the output is in JSON format. 55 * Generally the caller should encode only a single output item (e.g. a JSON 56 * object). 57 * 58 * By default, JSON output is maximally compact. If OSSL_JSON_FLAG_PRETTY is 59 * set, JSON/JSON-SEQ output is spaced for optimal human readability. 60 * 61 * If OSSL_JSON_FLAG_IJSON is set, integers outside the range `[-2**53 + 1, 62 * 2**53 - 1]` are automatically converted to decimal strings before 63 * serialization. 64 */ 65 #define OSSL_JSON_FLAG_NONE 0 66 #define OSSL_JSON_FLAG_SEQ (1U << 0) 67 #define OSSL_JSON_FLAG_PRETTY (1U << 1) 68 #define OSSL_JSON_FLAG_IJSON (1U << 2) 69 70 int ossl_json_init(OSSL_JSON_ENC *json, BIO *bio, uint32_t flags); 71 72 /* 73 * ossl_json_cleanup 74 * ----------------- 75 * 76 * Destroys a JSON encoder. 77 */ 78 void ossl_json_cleanup(OSSL_JSON_ENC *json); 79 80 /* 81 * ossl_json_reset 82 * --------------- 83 * 84 * Resets a JSON encoder, as though it has just been initialised, allowing it 85 * to be used again for new output syntactically unrelated to any previous 86 * output. This is similar to calling ossl_json_cleanup followed by 87 * ossl_json_init but may allow internal buffers to be reused. 88 * 89 * If the JSON encoder has entered an error state, this function MAY allow 90 * recovery from this error state, in which case it will return 1. If this 91 * function returns 0, the JSON encoder is unrecoverable and 92 * ossl_json_cleanup() must be called. 93 * 94 * Automatically calls ossl_json_flush(). 95 */ 96 int ossl_json_reset(OSSL_JSON_ENC *json); 97 98 /* 99 * ossl_json_flush 100 * --------------- 101 * 102 * Flushes the JSON encoder, ensuring that any residual bytes in internal 103 * buffers are written to the provided sink BIO. Flushing may also happen 104 * autonomously as buffers are filled, but the caller must use this function 105 * to guarantee all data has been flushed. 106 */ 107 int ossl_json_flush(OSSL_JSON_ENC *json); 108 109 /* 110 * ossl_json_flush_cleanup 111 * ----------------------- 112 * 113 * Tries to flush as in a call to ossl_json_flush, and then calls 114 * ossl_json_cleanup regardless of the result. The result of the flush call is 115 * returned. 116 */ 117 int ossl_json_flush_cleanup(OSSL_JSON_ENC *json); 118 119 /* 120 * ossl_json_set0_sink 121 * ------------------- 122 * 123 * Changes the sink used by the JSON encoder. 124 */ 125 int ossl_json_set0_sink(OSSL_JSON_ENC *json, BIO *bio); 126 127 /* 128 * ossl_json_in_error 129 * ------------------ 130 * 131 * To enhance the ergonomics of the JSON API, the JSON object uses an implicit 132 * error tracking model. When a JSON API call fails (for example due to caller 133 * error, such as trying to close an array which was not opened), the JSON 134 * object enters an error state and all further calls are silently ignored. 135 * 136 * The caller can detect this condition after it is finished making builder 137 * calls to the JSON object by calling this function. This function returns 1 138 * if an error occurred. At this point the caller's only recourse is to call 139 * ossl_json_reset() or ossl_json_cleanup(). 140 * 141 * Note that partial (i.e., invalid) output may still have been sent to the BIO 142 * in this case. Since the amount of output which can potentially be produced 143 * by a JSON object is unbounded, it is impractical to buffer it all before 144 * flushing. It is expected that errors will ordinarily be either caller errors 145 * (programming errors) or BIO errors. 146 */ 147 int ossl_json_in_error(OSSL_JSON_ENC *json); 148 149 /* 150 * JSON Builder Calls 151 * ================== 152 * 153 * These functions are used to build JSON output. The functions which have 154 * begin and end function pairs must be called in correctly nested sequence. 155 * When writing an object, ossl_json_key() must be called exactly once before 156 * each call to write a JSON item. 157 * 158 * The JSON library takes responsibility for enforcing correct usage patterns. 159 * If a call is made that does not correspond to the JSON syntax, the JSON 160 * object enters the error state and all subsequent calls are ignored. 161 * 162 * In JSON-SEQ mode, the caller should act as though the library implicitly 163 * places all calls between an ossl_json_array_begin() and 164 * ossl_json_array_end() pair; for example, the normal usage pattern would be 165 * to call ossl_json_object_begin() followed by ossl_json_object_end(), in 166 * repeated sequence. 167 * 168 * The library does not enforce non-generation of duplicate keys. Avoiding this 169 * is the caller's responsibility. It is also the caller's responsibility to 170 * pass valid UTF-8 strings. All other forms of invalid output will cause an 171 * error. Note that due to the immediate nature of the API, partial output may 172 * have already been generated in such a case. 173 */ 174 175 /* Begin a new JSON object. */ 176 void ossl_json_object_begin(OSSL_JSON_ENC *json); 177 178 /* End a JSON object. Must be matched with a call to ossl_json_object_begin(). */ 179 void ossl_json_object_end(OSSL_JSON_ENC *json); 180 181 /* Begin a new JSON array. */ 182 void ossl_json_array_begin(OSSL_JSON_ENC *json); 183 184 /* End a JSON array. Must be matched with a call to ossl_json_array_end(). */ 185 void ossl_json_array_end(OSSL_JSON_ENC *json); 186 187 /* 188 * Encode a JSON key within an object. Pass a zero-terminated string, which can 189 * be freed immediately following the call to this function. 190 */ 191 void ossl_json_key(OSSL_JSON_ENC *json, const char *key); 192 193 /* Encode a JSON 'null' value. */ 194 void ossl_json_null(OSSL_JSON_ENC *json); 195 196 /* Encode a JSON boolean value. */ 197 void ossl_json_bool(OSSL_JSON_ENC *json, int value); 198 199 /* Encode a JSON integer from a uint64_t. */ 200 void ossl_json_u64(OSSL_JSON_ENC *json, uint64_t value); 201 202 /* Encode a JSON integer from an int64_t. */ 203 void ossl_json_i64(OSSL_JSON_ENC *json, int64_t value); 204 205 /* Encode a JSON number from a 64-bit floating point value. */ 206 void ossl_json_f64(OSSL_JSON_ENC *json, double value); 207 208 /* 209 * Encode a JSON UTF-8 string from a zero-terminated string. The string passed 210 * can be freed immediately following the call to this function. 211 */ 212 void ossl_json_str(OSSL_JSON_ENC *json, const char *str); 213 214 /* 215 * Encode a JSON UTF-8 string from a string with the given length. The string 216 * passed can be freed immediately following the call to this function. 217 */ 218 void ossl_json_str_len(OSSL_JSON_ENC *json, const char *str, size_t str_len); 219 220 /* 221 * Encode binary data as a lowercase hex string. data_len is the data length in 222 * bytes. 223 */ 224 void ossl_json_str_hex(OSSL_JSON_ENC *json, const void *data, size_t data_len); 225 226 #endif 227