1 module deimos.openssl.bytestring; 2 3 import std.stdint; 4 5 // Bytestrings are used for parsing and building TLS and ASN.1 messages. 6 // 7 // A "CBS" (CRYPTO ByteString) represents a string of bytes in memory and 8 // provides utility functions for safely parsing length-prefixed structures 9 // like TLS and ASN.1 from it. 10 // 11 // A "CBB" (CRYPTO ByteBuilder) is a memory buffer that grows as needed and 12 // provides utility functions for building length-prefixed messages. 13 14 15 extern (C): 16 nothrow: 17 18 // CRYPTO ByteString 19 20 struct cbs_st { 21 const uint8_t *data; 22 size_t len; 23 } 24 25 alias CBS = cbs_st; 26 27 // CBS_init sets |cbs| to point to |data|. It does not take ownership of 28 // |data|. 29 void CBS_init(CBS *cbs, const(uint8_t) *data, size_t len); 30 31 // CBS_skip advances |cbs| by |len| bytes. It returns one on success and zero 32 // otherwise. 33 int CBS_skip(CBS *cbs, size_t len); 34 35 // CBS_data returns a pointer to the contents of |cbs|. 36 const(uint8_t) *CBS_data(const(CBS) *cbs); 37 38 // CBS_len returns the number of bytes remaining in |cbs|. 39 size_t CBS_len(const(CBS) *cbs); 40 41 // CBS_stow copies the current contents of |cbs| into |*out_ptr| and 42 // |*out_len|. If |*out_ptr| is not NULL, the contents are freed with 43 // OPENSSL_free. It returns one on success and zero on allocation failure. On 44 // success, |*out_ptr| should be freed with OPENSSL_free. If |cbs| is empty, 45 // |*out_ptr| will be NULL. 46 int CBS_stow(const(CBS) *cbs, uint8_t **out_ptr, size_t *out_len); 47 48 // CBS_strdup copies the current contents of |cbs| into |*out_ptr| as a 49 // NUL-terminated C string. If |*out_ptr| is not NULL, the contents are freed 50 // with OPENSSL_free. It returns one on success and zero on allocation 51 // failure. On success, |*out_ptr| should be freed with OPENSSL_free. 52 // 53 // NOTE: If |cbs| contains NUL bytes, the string will be truncated. Call 54 // |CBS_contains_zero_byte(cbs)| to check for NUL bytes. 55 int CBS_strdup(const(CBS) *cbs, char **out_ptr); 56 57 // CBS_contains_zero_byte returns one if the current contents of |cbs| contains 58 // a NUL byte and zero otherwise. 59 int CBS_contains_zero_byte(const(CBS) *cbs); 60 61 // CBS_mem_equal compares the current contents of |cbs| with the |len| bytes 62 // starting at |data|. If they're equal, it returns one, otherwise zero. If the 63 // lengths match, it uses a constant-time comparison. 64 int CBS_mem_equal(const(CBS) *cbs, const uint8_t *data, 65 size_t len); 66 67 // CBS_get_u8 sets |*out_ptr| to the next uint8_t from |cbs| and advances |cbs|. It 68 // returns one on success and zero on error. 69 int CBS_get_u8(CBS *cbs, uint8_t *out_ptr); 70 71 // CBS_get_u16 sets |*out_ptr| to the next, big-endian uint16_t from |cbs| and 72 // advances |cbs|. It returns one on success and zero on error. 73 int CBS_get_u16(CBS *cbs, uint16_t *out_ptr); 74 75 // CBS_get_u24 sets |*out_ptr| to the next, big-endian 24-bit value from |cbs| and 76 // advances |cbs|. It returns one on success and zero on error. 77 int CBS_get_u24(CBS *cbs, uint32_t *out_ptr); 78 79 // CBS_get_u32 sets |*out_ptr| to the next, big-endian uint32_t value from |cbs| 80 // and advances |cbs|. It returns one on success and zero on error. 81 int CBS_get_u32(CBS *cbs, uint32_t *out_ptr); 82 83 // CBS_get_last_u8 sets |*out_ptr| to the last uint8_t from |cbs| and shortens 84 // |cbs|. It returns one on success and zero on error. 85 int CBS_get_last_u8(CBS *cbs, uint8_t *out_ptr); 86 87 // CBS_get_bytes sets |*out_ptr| to the next |len| bytes from |cbs| and advances 88 // |cbs|. It returns one on success and zero on error. 89 int CBS_get_bytes(CBS *cbs, CBS *out_ptr, size_t len); 90 91 // CBS_copy_bytes copies the next |len| bytes from |cbs| to |out| and advances 92 // |cbs|. It returns one on success and zero on error. 93 int CBS_copy_bytes(CBS *cbs, uint8_t *out_ptr, size_t len); 94 95 // CBS_get_u8_length_prefixed sets |*out_ptr| to the contents of an 8-bit, 96 // length-prefixed value from |cbs| and advances |cbs| over it. It returns one 97 // on success and zero on error. 98 int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out_ptr); 99 100 // CBS_get_u16_length_prefixed sets |*out_ptr| to the contents of a 16-bit, 101 // big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It 102 // returns one on success and zero on error. 103 int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out_ptr); 104 105 // CBS_get_u24_length_prefixed sets |*out_ptr| to the contents of a 24-bit, 106 // big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It 107 // returns one on success and zero on error. 108 int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out_ptr); 109 110 111 // Parsing ASN.1 112 113 // The following values are tag numbers for UNIVERSAL elements. 114 enum CBS_ASN1_BOOLEAN = 0x1; 115 enum CBS_ASN1_INTEGER = 0x2; 116 enum CBS_ASN1_BITSTRING = 0x3; 117 enum CBS_ASN1_OCTETSTRING = 0x4; 118 enum CBS_ASN1_NULL = 0x5; 119 enum CBS_ASN1_OBJECT = 0x6; 120 enum CBS_ASN1_ENUMERATED = 0xa; 121 enum CBS_ASN1_UTF8STRING = 0xc; 122 enum CBS_ASN1_SEQUENCE = (0x10 | CBS_ASN1_CONSTRUCTED); 123 enum CBS_ASN1_SET = (0x11 | CBS_ASN1_CONSTRUCTED); 124 enum CBS_ASN1_NUMERICSTRING = 0x12; 125 enum CBS_ASN1_PRINTABLESTRING = 0x13; 126 enum CBS_ASN1_T61STRING = 0x14; 127 enum CBS_ASN1_VIDEOTEXSTRING = 0x15; 128 enum CBS_ASN1_IA5STRING = 0x16; 129 enum CBS_ASN1_UTCTIME = 0x17; 130 enum CBS_ASN1_GENERALIZEDTIME = 0x18; 131 enum CBS_ASN1_GRAPHICSTRING = 0x19; 132 enum CBS_ASN1_VISIBLESTRING = 0x1a; 133 enum CBS_ASN1_GENERALSTRING = 0x1b; 134 enum CBS_ASN1_UNIVERSALSTRING = 0x1c; 135 enum CBS_ASN1_BMPSTRING = 0x1e; 136 137 // CBS_ASN1_TAG_SHIFT is how much the in-memory representation shifts the class 138 // and constructed bits from the DER serialization. This allows representing tag 139 // numbers beyond 31. 140 // 141 // Consumers must use the following constants to decompose or assemble tags. 142 enum CBS_ASN1_TAG_SHIFT = 24; 143 144 // CBS_ASN1_CONSTRUCTED may be ORed into a tag to toggle the constructed 145 // bit. |CBS| and |CBB| APIs consider the constructed bit to be part of the 146 // tag. 147 enum CBS_ASN1_CONSTRUCTED = (0x20 << CBS_ASN1_TAG_SHIFT); 148 149 // The following values specify the tag class and may be ORed into a tag number 150 // to produce the final tag. If none is used, the tag will be UNIVERSAL. 151 enum CBS_ASN1_UNIVERSAL = (0 << CBS_ASN1_TAG_SHIFT); 152 enum CBS_ASN1_APPLICATION = (0x40 << CBS_ASN1_TAG_SHIFT); 153 enum CBS_ASN1_CONTEXT_SPECIFIC = (0x80 << CBS_ASN1_TAG_SHIFT); 154 enum CBS_ASN1_PRIVATE = (0xc0 << CBS_ASN1_TAG_SHIFT); 155 156 // CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class. This will 157 // give one of the four values above. 158 enum CBS_ASN1_CLASS_MASK = (0xc0 << CBS_ASN1_TAG_SHIFT); 159 160 // CBS_ASN1_TAG_NUMBER_MASK may be ANDed with a tag to query its number. 161 enum CBS_ASN1_TAG_NUMBER_MASK = ((1 << (5 + CBS_ASN1_TAG_SHIFT)) - 1); 162 163 // CBS_get_asn1 sets |*out_ptr| to the contents of DER-encoded, ASN.1 element (not 164 // including tag and length bytes) and advances |cbs| over it. The ASN.1 165 // element must match |tag_value|. It returns one on success and zero 166 // on error. 167 int CBS_get_asn1(CBS *cbs, CBS *out_ptr, uint tag_value); 168 169 // CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the 170 // ASN.1 header bytes too. 171 int CBS_get_asn1_element(CBS *cbs, CBS *out_ptr, uint tag_value); 172 173 // CBS_peek_asn1_tag looks ahead at the next ASN.1 tag and returns one 174 // if the next ASN.1 element on |cbs| would have tag |tag_value|. If 175 // |cbs| is empty or the tag does not match, it returns zero. Note: if 176 // it returns one, CBS_get_asn1 may still fail if the rest of the 177 // element is malformed. 178 int CBS_peek_asn1_tag(const(CBS) *cbs, uint tag_value); 179 180 // CBS_get_any_asn1 sets |*out_ptr| to contain the next ASN.1 element from |*cbs| 181 // (not including tag and length bytes), sets |*out_tag| to the tag number, and 182 // advances |*cbs|. It returns one on success and zero on error. Either of |out| 183 // and |out_tag| may be NULL to ignore the value. 184 int CBS_get_any_asn1(CBS *cbs, CBS *out_ptr, uint *out_tag); 185 186 // CBS_get_any_asn1_element sets |*out_ptr| to contain the next ASN.1 element from 187 // |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to 188 // the tag number and |*out_header_len| to the length of the ASN.1 header. Each 189 // of |out|, |out_tag|, and |out_header_len| may be NULL to ignore the value. 190 int CBS_get_any_asn1_element(CBS *cbs, CBS *out_ptr, 191 uint *out_tag, 192 size_t *out_header_len); 193 194 // CBS_get_any_ber_asn1_element acts the same as |CBS_get_any_asn1_element| but 195 // also allows indefinite-length elements to be returned. In that case, 196 // |*out_header_len| and |CBS_len(out)| will both be two as only the header is 197 // returned, otherwise it behaves the same as the previous function. 198 int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out_ptr, 199 uint *out_tag, 200 size_t *out_header_len); 201 202 // CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1| 203 // and sets |*out_ptr| to its value. It returns one on success and zero on error, 204 // where error includes the integer being negative, or too large to represent 205 // in 64 bits. 206 int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out_ptr); 207 208 // CBS_get_asn1_bool gets an ASN.1 BOOLEAN from |cbs| and sets |*out_ptr| to zero 209 // or one based on its value. It returns one on success or zero on error. 210 int CBS_get_asn1_bool(CBS *cbs, int *out_ptr); 211 212 // CBS_get_optional_asn1 gets an optional explicitly-tagged element from |cbs| 213 // tagged with |tag| and sets |*out_ptr| to its contents, or ignores it if |out| is 214 // NULL. If present and if |out_present| is not NULL, it sets |*out_present| to 215 // one, otherwise zero. It returns one on success, whether or not the element 216 // was present, and zero on decode failure. 217 int CBS_get_optional_asn1(CBS *cbs, CBS *out_ptr, int *out_present, 218 uint tag); 219 220 // CBS_get_optional_asn1_octet_string gets an optional 221 // explicitly-tagged OCTET STRING from |cbs|. If present, it sets 222 // |*out_ptr| to the string and |*out_present| to one. Otherwise, it sets 223 // |*out_ptr| to empty and |*out_present| to zero. |out_present| may be 224 // NULL. It returns one on success, whether or not the element was 225 // present, and zero on decode failure. 226 int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out_ptr, 227 int *out_present, 228 uint tag); 229 230 // CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged 231 // INTEGER from |cbs|. If present, it sets |*out_ptr| to the 232 // value. Otherwise, it sets |*out_ptr| to |default_value|. It returns one 233 // on success, whether or not the element was present, and zero on 234 // decode failure. 235 int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out_ptr, 236 uint tag, 237 uint64_t default_value); 238 239 // CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from 240 // |cbs|. If present, it sets |*out_ptr| to either zero or one, based on the 241 // boolean. Otherwise, it sets |*out_ptr| to |default_value|. It returns one on 242 // success, whether or not the element was present, and zero on decode 243 // failure. 244 int CBS_get_optional_asn1_bool(CBS *cbs, int *out_ptr, uint tag, 245 int default_value); 246 247 // CBS_is_valid_asn1_bitstring returns one if |cbs| is a valid ASN.1 BIT STRING 248 // and zero otherwise. 249 int CBS_is_valid_asn1_bitstring(const(CBS) *cbs); 250 251 // CBS_asn1_bitstring_has_bit returns one if |cbs| is a valid ASN.1 BIT STRING 252 // and the specified bit is present and set. Otherwise, it returns zero. |bit| 253 // is indexed starting from zero. 254 int CBS_asn1_bitstring_has_bit(const(CBS) *cbs, uint bit); 255 256 // CBS_asn1_oid_to_text interprets |cbs| as DER-encoded ASN.1 OBJECT IDENTIFIER 257 // contents (not including the element framing) and returns the ASCII 258 // representation (e.g., "1.2.840.113554.4.1.72585") in a newly-allocated 259 // string, or NULL on failure. The caller must release the result with 260 // |OPENSSL_free|. 261 char *CBS_asn1_oid_to_text(const(CBS) *cbs); 262 263 264 // CRYPTO ByteBuilder. 265 // 266 // |CBB| objects allow one to build length-prefixed serialisations. A |CBB| 267 // object is associated with a buffer and new buffers are created with 268 // |CBB_init|. Several |CBB| objects can point at the same buffer when a 269 // length-prefix is pending, however only a single |CBB| can be 'current' at 270 // any one time. For example, if one calls |CBB_add_u8_length_prefixed| then 271 // the new |CBB| points at the same buffer as the original. But if the original 272 // |CBB| is used then the length prefix is written out and the new |CBB| must 273 // not be used again. 274 // 275 // If one needs to force a length prefix to be written out because a |CBB| is 276 // going out of scope, use |CBB_flush|. If an operation on a |CBB| fails, it is 277 // in an undefined state and must not be used except to call |CBB_cleanup|. 278 279 struct cbb_buffer_st { 280 uint8_t *buf; 281 size_t len; // The number of valid bytes. 282 size_t cap; // The size of buf. 283 char can_resize; /* One iff |buf| is owned by this object. If not then |buf| 284 cannot be resized. */ 285 char error; /* One iff there was an error writing to this CBB. All future 286 operations will fail. */ 287 } 288 289 struct cbb_st { 290 cbb_buffer_st *base; 291 // child points to a child CBB if a length-prefix is pending. 292 CBB *child; 293 // offset is the number of bytes from the start of |base->buf| to this |CBB|'s 294 // pending length prefix. 295 size_t offset; 296 // pending_len_len contains the number of bytes in this |CBB|'s pending 297 // length-prefix, or zero if no length-prefix is pending. 298 uint8_t pending_len_len; 299 char pending_is_asn1; 300 // is_top_level is true iff this is a top-level |CBB| (as opposed to a child 301 // |CBB|). Top-level objects are valid arguments for |CBB_finish|. 302 char is_top_level; 303 } 304 305 alias CBB = cbb_st; 306 307 // CBB_zero sets an uninitialised |cbb| to the zero state. It must be 308 // initialised with |CBB_init| or |CBB_init_fixed| before use, but it is safe to 309 // call |CBB_cleanup| without a successful |CBB_init|. This may be used for more 310 // uniform cleanup of a |CBB|. 311 void CBB_zero(CBB *cbb); 312 313 // CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as 314 // needed, the |initial_capacity| is just a hint. It returns one on success or 315 // zero on error. 316 int CBB_init(CBB *cbb, size_t initial_capacity); 317 318 // CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since 319 // |buf| cannot grow, trying to write more than |len| bytes will cause CBB 320 // functions to fail. It returns one on success or zero on error. 321 int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len); 322 323 // CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects 324 // writing to the same buffer. This should be used in an error case where a 325 // serialisation is abandoned. 326 // 327 // This function can only be called on a "top level" |CBB|, i.e. one initialised 328 // with |CBB_init| or |CBB_init_fixed|, or a |CBB| set to the zero state with 329 // |CBB_zero|. 330 void CBB_cleanup(CBB *cbb); 331 332 // CBB_finish completes any pending length prefix and sets |*out_data| to a 333 // malloced buffer and |*out_len| to the length of that buffer. The caller 334 // takes ownership of the buffer and, unless the buffer was fixed with 335 // |CBB_init_fixed|, must call |OPENSSL_free| when done. 336 // 337 // It can only be called on a "top level" |CBB|, i.e. one initialised with 338 // |CBB_init| or |CBB_init_fixed|. It returns one on success and zero on 339 // error. 340 int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len); 341 342 // CBB_flush causes any pending length prefixes to be written out and any child 343 // |CBB| objects of |cbb| to be invalidated. This allows |cbb| to continue to be 344 // used after the children go out of scope, e.g. when local |CBB| objects are 345 // added as children to a |CBB| that persists after a function returns. This 346 // function returns one on success or zero on error. 347 int CBB_flush(CBB *cbb); 348 349 // CBB_data returns a pointer to the bytes written to |cbb|. It does not flush 350 // |cbb|. The pointer is valid until the next operation to |cbb|. 351 // 352 // To avoid unfinalized length prefixes, it is a fatal error to call this on a 353 // CBB with any active children. 354 const(uint8_t) *CBB_data(const CBB *cbb); 355 356 // CBB_len returns the number of bytes written to |cbb|. It does not flush 357 // |cbb|. 358 // 359 // To avoid unfinalized length prefixes, it is a fatal error to call this on a 360 // CBB with any active children. 361 size_t CBB_len(const CBB *cbb); 362 363 // CBB_add_u8_length_prefixed sets |*out_contents| to a new child of |cbb|. The 364 // data written to |*out_contents| will be prefixed in |cbb| with an 8-bit 365 // length. It returns one on success or zero on error. 366 int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents); 367 368 // CBB_add_u16_length_prefixed sets |*out_contents| to a new child of |cbb|. 369 // The data written to |*out_contents| will be prefixed in |cbb| with a 16-bit, 370 // big-endian length. It returns one on success or zero on error. 371 int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents); 372 373 // CBB_add_u24_length_prefixed sets |*out_contents| to a new child of |cbb|. 374 // The data written to |*out_contents| will be prefixed in |cbb| with a 24-bit, 375 // big-endian length. It returns one on success or zero on error. 376 int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents); 377 378 // CBB_add_asn1 sets |*out_contents| to a |CBB| into which the contents of an 379 // ASN.1 object can be written. The |tag| argument will be used as the tag for 380 // the object. It returns one on success or zero on error. 381 int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint tag); 382 383 // CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on 384 // success and zero otherwise. 385 int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len); 386 387 // CBB_add_space appends |len| bytes to |cbb| and sets |*out_data| to point to 388 // the beginning of that space. The caller must then write |len| bytes of 389 // actual contents to |*out_data|. It returns one on success and zero 390 // otherwise. 391 int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len); 392 393 // CBB_reserve ensures |cbb| has room for |len| additional bytes and sets 394 // |*out_data| to point to the beginning of that space. It returns one on 395 // success and zero otherwise. The caller may write up to |len| bytes to 396 // |*out_data| and call |CBB_did_write| to complete the write. |*out_data| is 397 // valid until the next operation on |cbb| or an ancestor |CBB|. 398 int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len); 399 400 // CBB_did_write advances |cbb| by |len| bytes, assuming the space has been 401 // written to by the caller. It returns one on success and zero on error. 402 int CBB_did_write(CBB *cbb, size_t len); 403 404 // CBB_add_u8 appends an 8-bit number from |value| to |cbb|. It returns one on 405 // success and zero otherwise. 406 int CBB_add_u8(CBB *cbb, uint8_t value); 407 408 // CBB_add_u16 appends a 16-bit, big-endian number from |value| to |cbb|. It 409 // returns one on success and zero otherwise. 410 int CBB_add_u16(CBB *cbb, uint16_t value); 411 412 // CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It 413 // returns one on success and zero otherwise. 414 int CBB_add_u24(CBB *cbb, uint32_t value); 415 416 // CBB_add_u32 appends a 32-bit, big-endian number from |value| to |cbb|. It 417 // returns one on success and zero otherwise. 418 int CBB_add_u32(CBB *cbb, uint32_t value); 419 420 // CBB_discard_child discards the current unflushed child of |cbb|. Neither the 421 // child's contents nor the length prefix will be included in the output. 422 void CBB_discard_child(CBB *cbb); 423 424 // CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1| 425 // and writes |value| in its contents. It returns one on success and zero on 426 // error. 427 int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); 428 429 // CBB_add_asn1_octet_string writes an ASN.1 OCTET STRING into |cbb| with the 430 // given contents. It returns one on success and zero on error. 431 int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, 432 size_t data_len); 433 434 // CBB_add_asn1_bool writes an ASN.1 BOOLEAN into |cbb| which is true iff 435 // |value| is non-zero. It returns one on success and zero on error. 436 int CBB_add_asn1_bool(CBB *cbb, int value); 437 438 // CBB_add_asn1_oid_from_text decodes |len| bytes from |text| as an ASCII OID 439 // representation, e.g. "1.2.840.113554.4.1.72585", and writes the DER-encoded 440 // contents to |cbb|. It returns one on success and zero on malloc failure or if 441 // |text| was invalid. It does not include the OBJECT IDENTIFER framing, only 442 // the element's contents. 443 // 444 // This function considers OID strings with components which do not fit in a 445 // |uint64_t| to be invalid. 446 int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, 447 size_t len); 448 449 // CBB_flush_asn1_set_of calls |CBB_flush| on |cbb| and then reorders the 450 // contents for a DER-encoded ASN.1 SET OF type. It returns one on success and 451 // zero on failure. DER canonicalizes SET OF contents by sorting 452 // lexicographically by encoding. Call this function when encoding a SET OF 453 // type in an order that is not already known to be canonical. 454 // 455 // Note a SET type has a slightly different ordering than a SET OF. 456 int CBB_flush_asn1_set_of(CBB *cbb);