1*72c33676SMaxim Ag /* $OpenBSD: bs_cbb.c,v 1.20 2019/01/23 22:20:40 beck Exp $ */ 2f5b1c8a1SJohn Marino /* 3f5b1c8a1SJohn Marino * Copyright (c) 2014, Google Inc. 4f5b1c8a1SJohn Marino * 5f5b1c8a1SJohn Marino * Permission to use, copy, modify, and/or distribute this software for any 6f5b1c8a1SJohn Marino * purpose with or without fee is hereby granted, provided that the above 7f5b1c8a1SJohn Marino * copyright notice and this permission notice appear in all copies. 8f5b1c8a1SJohn Marino * 9f5b1c8a1SJohn Marino * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10f5b1c8a1SJohn Marino * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11f5b1c8a1SJohn Marino * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 12f5b1c8a1SJohn Marino * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13f5b1c8a1SJohn Marino * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 14f5b1c8a1SJohn Marino * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15f5b1c8a1SJohn Marino * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 16f5b1c8a1SJohn Marino 17f5b1c8a1SJohn Marino #include <stdlib.h> 18f5b1c8a1SJohn Marino #include <string.h> 19f5b1c8a1SJohn Marino 20f5b1c8a1SJohn Marino #include <openssl/opensslconf.h> 21f5b1c8a1SJohn Marino 22f5b1c8a1SJohn Marino #include "bytestring.h" 23f5b1c8a1SJohn Marino 24*72c33676SMaxim Ag #define CBB_INITIAL_SIZE 64 25*72c33676SMaxim Ag 26f5b1c8a1SJohn Marino static int 27f5b1c8a1SJohn Marino cbb_init(CBB *cbb, uint8_t *buf, size_t cap) 28f5b1c8a1SJohn Marino { 29f5b1c8a1SJohn Marino struct cbb_buffer_st *base; 30f5b1c8a1SJohn Marino 31f5b1c8a1SJohn Marino base = malloc(sizeof(struct cbb_buffer_st)); 32f5b1c8a1SJohn Marino if (base == NULL) 33f5b1c8a1SJohn Marino return 0; 34f5b1c8a1SJohn Marino 35f5b1c8a1SJohn Marino base->buf = buf; 36f5b1c8a1SJohn Marino base->len = 0; 37f5b1c8a1SJohn Marino base->cap = cap; 38f5b1c8a1SJohn Marino base->can_resize = 1; 39f5b1c8a1SJohn Marino 40f5b1c8a1SJohn Marino cbb->base = base; 41f5b1c8a1SJohn Marino cbb->is_top_level = 1; 42f5b1c8a1SJohn Marino 43f5b1c8a1SJohn Marino return 1; 44f5b1c8a1SJohn Marino } 45f5b1c8a1SJohn Marino 46f5b1c8a1SJohn Marino int 47f5b1c8a1SJohn Marino CBB_init(CBB *cbb, size_t initial_capacity) 48f5b1c8a1SJohn Marino { 49f5b1c8a1SJohn Marino uint8_t *buf = NULL; 50f5b1c8a1SJohn Marino 51f5b1c8a1SJohn Marino memset(cbb, 0, sizeof(*cbb)); 52f5b1c8a1SJohn Marino 53*72c33676SMaxim Ag if (initial_capacity == 0) 54*72c33676SMaxim Ag initial_capacity = CBB_INITIAL_SIZE; 55*72c33676SMaxim Ag 56f5b1c8a1SJohn Marino if ((buf = malloc(initial_capacity)) == NULL) 57f5b1c8a1SJohn Marino return 0; 58f5b1c8a1SJohn Marino 59f5b1c8a1SJohn Marino if (!cbb_init(cbb, buf, initial_capacity)) { 60f5b1c8a1SJohn Marino free(buf); 61f5b1c8a1SJohn Marino return 0; 62f5b1c8a1SJohn Marino } 63f5b1c8a1SJohn Marino 64f5b1c8a1SJohn Marino return 1; 65f5b1c8a1SJohn Marino } 66f5b1c8a1SJohn Marino 67f5b1c8a1SJohn Marino int 68f5b1c8a1SJohn Marino CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) 69f5b1c8a1SJohn Marino { 70f5b1c8a1SJohn Marino memset(cbb, 0, sizeof(*cbb)); 71f5b1c8a1SJohn Marino 72f5b1c8a1SJohn Marino if (!cbb_init(cbb, buf, len)) 73f5b1c8a1SJohn Marino return 0; 74f5b1c8a1SJohn Marino 75f5b1c8a1SJohn Marino cbb->base->can_resize = 0; 76f5b1c8a1SJohn Marino 77f5b1c8a1SJohn Marino return 1; 78f5b1c8a1SJohn Marino } 79f5b1c8a1SJohn Marino 80f5b1c8a1SJohn Marino void 81f5b1c8a1SJohn Marino CBB_cleanup(CBB *cbb) 82f5b1c8a1SJohn Marino { 83f5b1c8a1SJohn Marino if (cbb->base) { 84f5b1c8a1SJohn Marino if (cbb->base->can_resize) 85*72c33676SMaxim Ag freezero(cbb->base->buf, cbb->base->cap); 86f5b1c8a1SJohn Marino free(cbb->base); 87f5b1c8a1SJohn Marino } 88f5b1c8a1SJohn Marino cbb->base = NULL; 89*72c33676SMaxim Ag cbb->child = NULL; 90f5b1c8a1SJohn Marino } 91f5b1c8a1SJohn Marino 92f5b1c8a1SJohn Marino static int 93f5b1c8a1SJohn Marino cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len) 94f5b1c8a1SJohn Marino { 95f5b1c8a1SJohn Marino size_t newlen; 96f5b1c8a1SJohn Marino 97f5b1c8a1SJohn Marino if (base == NULL) 98f5b1c8a1SJohn Marino return 0; 99f5b1c8a1SJohn Marino 100f5b1c8a1SJohn Marino newlen = base->len + len; 101f5b1c8a1SJohn Marino if (newlen < base->len) 102f5b1c8a1SJohn Marino /* Overflow */ 103f5b1c8a1SJohn Marino return 0; 104f5b1c8a1SJohn Marino 105f5b1c8a1SJohn Marino if (newlen > base->cap) { 106f5b1c8a1SJohn Marino size_t newcap = base->cap * 2; 107f5b1c8a1SJohn Marino uint8_t *newbuf; 108f5b1c8a1SJohn Marino 109f5b1c8a1SJohn Marino if (!base->can_resize) 110f5b1c8a1SJohn Marino return 0; 111f5b1c8a1SJohn Marino 112f5b1c8a1SJohn Marino if (newcap < base->cap || newcap < newlen) 113f5b1c8a1SJohn Marino newcap = newlen; 114f5b1c8a1SJohn Marino 115*72c33676SMaxim Ag newbuf = recallocarray(base->buf, base->cap, newcap, 1); 116f5b1c8a1SJohn Marino if (newbuf == NULL) 117f5b1c8a1SJohn Marino return 0; 118f5b1c8a1SJohn Marino 119f5b1c8a1SJohn Marino base->buf = newbuf; 120f5b1c8a1SJohn Marino base->cap = newcap; 121f5b1c8a1SJohn Marino } 122f5b1c8a1SJohn Marino 123f5b1c8a1SJohn Marino if (out) 124f5b1c8a1SJohn Marino *out = base->buf + base->len; 125f5b1c8a1SJohn Marino 126f5b1c8a1SJohn Marino base->len = newlen; 127f5b1c8a1SJohn Marino return 1; 128f5b1c8a1SJohn Marino } 129f5b1c8a1SJohn Marino 130f5b1c8a1SJohn Marino static int 131f5b1c8a1SJohn Marino cbb_add_u(CBB *cbb, uint32_t v, size_t len_len) 132f5b1c8a1SJohn Marino { 133f5b1c8a1SJohn Marino uint8_t *buf; 134f5b1c8a1SJohn Marino size_t i; 135f5b1c8a1SJohn Marino 136f5b1c8a1SJohn Marino if (len_len == 0) 137f5b1c8a1SJohn Marino return 1; 138f5b1c8a1SJohn Marino 139f5b1c8a1SJohn Marino if (len_len > 4) 140f5b1c8a1SJohn Marino return 0; 141f5b1c8a1SJohn Marino 142f5b1c8a1SJohn Marino if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len)) 143f5b1c8a1SJohn Marino return 0; 144f5b1c8a1SJohn Marino 145f5b1c8a1SJohn Marino for (i = len_len - 1; i < len_len; i--) { 146f5b1c8a1SJohn Marino buf[i] = v; 147f5b1c8a1SJohn Marino v >>= 8; 148f5b1c8a1SJohn Marino } 149f5b1c8a1SJohn Marino return 1; 150f5b1c8a1SJohn Marino } 151f5b1c8a1SJohn Marino 152f5b1c8a1SJohn Marino int 153f5b1c8a1SJohn Marino CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) 154f5b1c8a1SJohn Marino { 155f5b1c8a1SJohn Marino if (!cbb->is_top_level) 156f5b1c8a1SJohn Marino return 0; 157f5b1c8a1SJohn Marino 158f5b1c8a1SJohn Marino if (!CBB_flush(cbb)) 159f5b1c8a1SJohn Marino return 0; 160f5b1c8a1SJohn Marino 161f5b1c8a1SJohn Marino if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) 162f5b1c8a1SJohn Marino /* 163f5b1c8a1SJohn Marino * |out_data| and |out_len| can only be NULL if the CBB is 164f5b1c8a1SJohn Marino * fixed. 165f5b1c8a1SJohn Marino */ 166f5b1c8a1SJohn Marino return 0; 167f5b1c8a1SJohn Marino 168f5b1c8a1SJohn Marino if (out_data != NULL) 169f5b1c8a1SJohn Marino *out_data = cbb->base->buf; 170f5b1c8a1SJohn Marino 171f5b1c8a1SJohn Marino if (out_len != NULL) 172f5b1c8a1SJohn Marino *out_len = cbb->base->len; 173f5b1c8a1SJohn Marino 174f5b1c8a1SJohn Marino cbb->base->buf = NULL; 175f5b1c8a1SJohn Marino CBB_cleanup(cbb); 176f5b1c8a1SJohn Marino return 1; 177f5b1c8a1SJohn Marino } 178f5b1c8a1SJohn Marino 179f5b1c8a1SJohn Marino /* 180f5b1c8a1SJohn Marino * CBB_flush recurses and then writes out any pending length prefix. The current 181f5b1c8a1SJohn Marino * length of the underlying base is taken to be the length of the 182f5b1c8a1SJohn Marino * length-prefixed data. 183f5b1c8a1SJohn Marino */ 184f5b1c8a1SJohn Marino int 185f5b1c8a1SJohn Marino CBB_flush(CBB *cbb) 186f5b1c8a1SJohn Marino { 187f5b1c8a1SJohn Marino size_t child_start, i, len; 188f5b1c8a1SJohn Marino 189f5b1c8a1SJohn Marino if (cbb->base == NULL) 190f5b1c8a1SJohn Marino return 0; 191f5b1c8a1SJohn Marino 192f5b1c8a1SJohn Marino if (cbb->child == NULL || cbb->pending_len_len == 0) 193f5b1c8a1SJohn Marino return 1; 194f5b1c8a1SJohn Marino 195f5b1c8a1SJohn Marino child_start = cbb->offset + cbb->pending_len_len; 196f5b1c8a1SJohn Marino 197f5b1c8a1SJohn Marino if (!CBB_flush(cbb->child) || child_start < cbb->offset || 198f5b1c8a1SJohn Marino cbb->base->len < child_start) 199f5b1c8a1SJohn Marino return 0; 200f5b1c8a1SJohn Marino 201f5b1c8a1SJohn Marino len = cbb->base->len - child_start; 202f5b1c8a1SJohn Marino 203f5b1c8a1SJohn Marino if (cbb->pending_is_asn1) { 204f5b1c8a1SJohn Marino /* 205f5b1c8a1SJohn Marino * For ASN.1, we assumed that we were using short form which 206f5b1c8a1SJohn Marino * only requires a single byte for the length octet. 207f5b1c8a1SJohn Marino * 208f5b1c8a1SJohn Marino * If it turns out that we need long form, we have to move 209f5b1c8a1SJohn Marino * the contents along in order to make space for more length 210f5b1c8a1SJohn Marino * octets. 211f5b1c8a1SJohn Marino */ 212f5b1c8a1SJohn Marino size_t len_len = 1; /* total number of length octets */ 213f5b1c8a1SJohn Marino uint8_t initial_length_byte; 214f5b1c8a1SJohn Marino 215f5b1c8a1SJohn Marino /* We already wrote 1 byte for the length. */ 216*72c33676SMaxim Ag if (cbb->pending_len_len != 1) 217*72c33676SMaxim Ag return 0; 218f5b1c8a1SJohn Marino 219f5b1c8a1SJohn Marino /* Check for long form */ 220f5b1c8a1SJohn Marino if (len > 0xfffffffe) 221f5b1c8a1SJohn Marino return 0; /* 0xffffffff is reserved */ 222f5b1c8a1SJohn Marino else if (len > 0xffffff) 223f5b1c8a1SJohn Marino len_len = 5; 224f5b1c8a1SJohn Marino else if (len > 0xffff) 225f5b1c8a1SJohn Marino len_len = 4; 226f5b1c8a1SJohn Marino else if (len > 0xff) 227f5b1c8a1SJohn Marino len_len = 3; 228f5b1c8a1SJohn Marino else if (len > 0x7f) 229f5b1c8a1SJohn Marino len_len = 2; 230f5b1c8a1SJohn Marino 231f5b1c8a1SJohn Marino if (len_len == 1) { 232f5b1c8a1SJohn Marino /* For short form, the initial byte is the length. */ 233f5b1c8a1SJohn Marino initial_length_byte = len; 234f5b1c8a1SJohn Marino len = 0; 235f5b1c8a1SJohn Marino 236f5b1c8a1SJohn Marino } else { 237f5b1c8a1SJohn Marino /* 238f5b1c8a1SJohn Marino * For long form, the initial byte is the number of 239f5b1c8a1SJohn Marino * subsequent length octets (plus bit 8 set). 240f5b1c8a1SJohn Marino */ 241f5b1c8a1SJohn Marino initial_length_byte = 0x80 | (len_len - 1); 242f5b1c8a1SJohn Marino 243f5b1c8a1SJohn Marino /* 244f5b1c8a1SJohn Marino * We need to move the contents along in order to make 245f5b1c8a1SJohn Marino * space for the long form length octets. 246f5b1c8a1SJohn Marino */ 247f5b1c8a1SJohn Marino size_t extra_bytes = len_len - 1; 248f5b1c8a1SJohn Marino if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) 249f5b1c8a1SJohn Marino return 0; 250f5b1c8a1SJohn Marino 251f5b1c8a1SJohn Marino memmove(cbb->base->buf + child_start + extra_bytes, 252f5b1c8a1SJohn Marino cbb->base->buf + child_start, len); 253f5b1c8a1SJohn Marino } 254f5b1c8a1SJohn Marino cbb->base->buf[cbb->offset++] = initial_length_byte; 255f5b1c8a1SJohn Marino cbb->pending_len_len = len_len - 1; 256f5b1c8a1SJohn Marino } 257f5b1c8a1SJohn Marino 258f5b1c8a1SJohn Marino for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) { 259f5b1c8a1SJohn Marino cbb->base->buf[cbb->offset + i] = len; 260f5b1c8a1SJohn Marino len >>= 8; 261f5b1c8a1SJohn Marino } 262f5b1c8a1SJohn Marino if (len != 0) 263f5b1c8a1SJohn Marino return 0; 264f5b1c8a1SJohn Marino 265f5b1c8a1SJohn Marino cbb->child->base = NULL; 266f5b1c8a1SJohn Marino cbb->child = NULL; 267f5b1c8a1SJohn Marino cbb->pending_len_len = 0; 268f5b1c8a1SJohn Marino cbb->pending_is_asn1 = 0; 269f5b1c8a1SJohn Marino cbb->offset = 0; 270f5b1c8a1SJohn Marino 271f5b1c8a1SJohn Marino return 1; 272f5b1c8a1SJohn Marino } 273f5b1c8a1SJohn Marino 274*72c33676SMaxim Ag void 275*72c33676SMaxim Ag CBB_discard_child(CBB *cbb) 276*72c33676SMaxim Ag { 277*72c33676SMaxim Ag if (cbb->child == NULL) 278*72c33676SMaxim Ag return; 279*72c33676SMaxim Ag 280*72c33676SMaxim Ag cbb->base->len = cbb->offset; 281*72c33676SMaxim Ag 282*72c33676SMaxim Ag cbb->child->base = NULL; 283*72c33676SMaxim Ag cbb->child = NULL; 284*72c33676SMaxim Ag cbb->pending_len_len = 0; 285*72c33676SMaxim Ag cbb->pending_is_asn1 = 0; 286*72c33676SMaxim Ag cbb->offset = 0; 287*72c33676SMaxim Ag } 288f5b1c8a1SJohn Marino 289f5b1c8a1SJohn Marino static int 290f5b1c8a1SJohn Marino cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len) 291f5b1c8a1SJohn Marino { 292f5b1c8a1SJohn Marino uint8_t *prefix_bytes; 293f5b1c8a1SJohn Marino 294f5b1c8a1SJohn Marino if (!CBB_flush(cbb)) 295f5b1c8a1SJohn Marino return 0; 296f5b1c8a1SJohn Marino 297f5b1c8a1SJohn Marino cbb->offset = cbb->base->len; 298f5b1c8a1SJohn Marino if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) 299f5b1c8a1SJohn Marino return 0; 300f5b1c8a1SJohn Marino 301f5b1c8a1SJohn Marino memset(prefix_bytes, 0, len_len); 302f5b1c8a1SJohn Marino memset(out_contents, 0, sizeof(CBB)); 303f5b1c8a1SJohn Marino out_contents->base = cbb->base; 304f5b1c8a1SJohn Marino cbb->child = out_contents; 305f5b1c8a1SJohn Marino cbb->pending_len_len = len_len; 306f5b1c8a1SJohn Marino cbb->pending_is_asn1 = 0; 307f5b1c8a1SJohn Marino 308f5b1c8a1SJohn Marino return 1; 309f5b1c8a1SJohn Marino } 310f5b1c8a1SJohn Marino 311f5b1c8a1SJohn Marino int 312f5b1c8a1SJohn Marino CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) 313f5b1c8a1SJohn Marino { 314f5b1c8a1SJohn Marino return cbb_add_length_prefixed(cbb, out_contents, 1); 315f5b1c8a1SJohn Marino } 316f5b1c8a1SJohn Marino 317f5b1c8a1SJohn Marino int 318f5b1c8a1SJohn Marino CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) 319f5b1c8a1SJohn Marino { 320f5b1c8a1SJohn Marino return cbb_add_length_prefixed(cbb, out_contents, 2); 321f5b1c8a1SJohn Marino } 322f5b1c8a1SJohn Marino 323f5b1c8a1SJohn Marino int 324f5b1c8a1SJohn Marino CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) 325f5b1c8a1SJohn Marino { 326f5b1c8a1SJohn Marino return cbb_add_length_prefixed(cbb, out_contents, 3); 327f5b1c8a1SJohn Marino } 328f5b1c8a1SJohn Marino 329f5b1c8a1SJohn Marino int 330f5b1c8a1SJohn Marino CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag) 331f5b1c8a1SJohn Marino { 332f5b1c8a1SJohn Marino if (tag > UINT8_MAX) 333f5b1c8a1SJohn Marino return 0; 334f5b1c8a1SJohn Marino 335f5b1c8a1SJohn Marino /* Long form identifier octets are not supported. */ 336f5b1c8a1SJohn Marino if ((tag & 0x1f) == 0x1f) 337f5b1c8a1SJohn Marino return 0; 338f5b1c8a1SJohn Marino 339f5b1c8a1SJohn Marino /* Short-form identifier octet only needs a single byte */ 340f5b1c8a1SJohn Marino if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag)) 341f5b1c8a1SJohn Marino return 0; 342f5b1c8a1SJohn Marino 343f5b1c8a1SJohn Marino /* 344f5b1c8a1SJohn Marino * Add 1 byte to cover the short-form length octet case. If it turns 345f5b1c8a1SJohn Marino * out we need long-form, it will be extended later. 346f5b1c8a1SJohn Marino */ 347f5b1c8a1SJohn Marino cbb->offset = cbb->base->len; 348f5b1c8a1SJohn Marino if (!CBB_add_u8(cbb, 0)) 349f5b1c8a1SJohn Marino return 0; 350f5b1c8a1SJohn Marino 351f5b1c8a1SJohn Marino memset(out_contents, 0, sizeof(CBB)); 352f5b1c8a1SJohn Marino out_contents->base = cbb->base; 353f5b1c8a1SJohn Marino cbb->child = out_contents; 354f5b1c8a1SJohn Marino cbb->pending_len_len = 1; 355f5b1c8a1SJohn Marino cbb->pending_is_asn1 = 1; 356f5b1c8a1SJohn Marino 357f5b1c8a1SJohn Marino return 1; 358f5b1c8a1SJohn Marino } 359f5b1c8a1SJohn Marino 360f5b1c8a1SJohn Marino int 361f5b1c8a1SJohn Marino CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) 362f5b1c8a1SJohn Marino { 363f5b1c8a1SJohn Marino uint8_t *dest; 364f5b1c8a1SJohn Marino 365f5b1c8a1SJohn Marino if (!CBB_add_space(cbb, &dest, len)) 366f5b1c8a1SJohn Marino return 0; 367f5b1c8a1SJohn Marino 368f5b1c8a1SJohn Marino memcpy(dest, data, len); 369f5b1c8a1SJohn Marino return 1; 370f5b1c8a1SJohn Marino } 371f5b1c8a1SJohn Marino 372f5b1c8a1SJohn Marino int 373f5b1c8a1SJohn Marino CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) 374f5b1c8a1SJohn Marino { 375f5b1c8a1SJohn Marino if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len)) 376f5b1c8a1SJohn Marino return 0; 377f5b1c8a1SJohn Marino 378f5b1c8a1SJohn Marino return 1; 379f5b1c8a1SJohn Marino } 380f5b1c8a1SJohn Marino 381f5b1c8a1SJohn Marino int 382f5b1c8a1SJohn Marino CBB_add_u8(CBB *cbb, size_t value) 383f5b1c8a1SJohn Marino { 384f5b1c8a1SJohn Marino if (value > UINT8_MAX) 385f5b1c8a1SJohn Marino return 0; 386f5b1c8a1SJohn Marino 387f5b1c8a1SJohn Marino return cbb_add_u(cbb, (uint32_t)value, 1); 388f5b1c8a1SJohn Marino } 389f5b1c8a1SJohn Marino 390f5b1c8a1SJohn Marino int 391f5b1c8a1SJohn Marino CBB_add_u16(CBB *cbb, size_t value) 392f5b1c8a1SJohn Marino { 393f5b1c8a1SJohn Marino if (value > UINT16_MAX) 394f5b1c8a1SJohn Marino return 0; 395f5b1c8a1SJohn Marino 396f5b1c8a1SJohn Marino return cbb_add_u(cbb, (uint32_t)value, 2); 397f5b1c8a1SJohn Marino } 398f5b1c8a1SJohn Marino 399f5b1c8a1SJohn Marino int 400f5b1c8a1SJohn Marino CBB_add_u24(CBB *cbb, size_t value) 401f5b1c8a1SJohn Marino { 402f5b1c8a1SJohn Marino if (value > 0xffffffUL) 403f5b1c8a1SJohn Marino return 0; 404f5b1c8a1SJohn Marino 405f5b1c8a1SJohn Marino return cbb_add_u(cbb, (uint32_t)value, 3); 406f5b1c8a1SJohn Marino } 407f5b1c8a1SJohn Marino 408f5b1c8a1SJohn Marino int 409*72c33676SMaxim Ag CBB_add_u32(CBB *cbb, size_t value) 410*72c33676SMaxim Ag { 411*72c33676SMaxim Ag if (value > 0xffffffffUL) 412*72c33676SMaxim Ag return 0; 413*72c33676SMaxim Ag 414*72c33676SMaxim Ag return cbb_add_u(cbb, (uint32_t)value, 4); 415*72c33676SMaxim Ag } 416*72c33676SMaxim Ag 417*72c33676SMaxim Ag int 418f5b1c8a1SJohn Marino CBB_add_asn1_uint64(CBB *cbb, uint64_t value) 419f5b1c8a1SJohn Marino { 420f5b1c8a1SJohn Marino CBB child; 421f5b1c8a1SJohn Marino size_t i; 422f5b1c8a1SJohn Marino int started = 0; 423f5b1c8a1SJohn Marino 424f5b1c8a1SJohn Marino if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) 425f5b1c8a1SJohn Marino return 0; 426f5b1c8a1SJohn Marino 427f5b1c8a1SJohn Marino for (i = 0; i < 8; i++) { 428f5b1c8a1SJohn Marino uint8_t byte = (value >> 8 * (7 - i)) & 0xff; 429f5b1c8a1SJohn Marino 430f5b1c8a1SJohn Marino /* 431f5b1c8a1SJohn Marino * ASN.1 restriction: first 9 bits cannot be all zeroes or 432f5b1c8a1SJohn Marino * all ones. Since this function only encodes unsigned 433f5b1c8a1SJohn Marino * integers, the only concerns are not encoding leading 434f5b1c8a1SJohn Marino * zeros and adding a padding byte if necessary. 435f5b1c8a1SJohn Marino * 436f5b1c8a1SJohn Marino * In practice, this means: 437f5b1c8a1SJohn Marino * 1) Skip leading octets of all zero bits in the value 438f5b1c8a1SJohn Marino * 2) After skipping the leading zero octets, if the next 9 439f5b1c8a1SJohn Marino * bits are all ones, add an all zero prefix octet (and 440f5b1c8a1SJohn Marino * set the high bit of the prefix octet if negative). 441f5b1c8a1SJohn Marino * 442f5b1c8a1SJohn Marino * Additionally, for an unsigned value, add an all zero 443f5b1c8a1SJohn Marino * prefix if the high bit of the first octet would be one. 444f5b1c8a1SJohn Marino */ 445f5b1c8a1SJohn Marino if (!started) { 446f5b1c8a1SJohn Marino if (byte == 0) 447f5b1c8a1SJohn Marino /* Don't encode leading zeros. */ 448f5b1c8a1SJohn Marino continue; 449f5b1c8a1SJohn Marino 450f5b1c8a1SJohn Marino /* 451f5b1c8a1SJohn Marino * If the high bit is set, add a padding byte to make it 452f5b1c8a1SJohn Marino * unsigned. 453f5b1c8a1SJohn Marino */ 454f5b1c8a1SJohn Marino if ((byte & 0x80) && !CBB_add_u8(&child, 0)) 455f5b1c8a1SJohn Marino return 0; 456f5b1c8a1SJohn Marino 457f5b1c8a1SJohn Marino started = 1; 458f5b1c8a1SJohn Marino } 459f5b1c8a1SJohn Marino if (!CBB_add_u8(&child, byte)) 460f5b1c8a1SJohn Marino return 0; 461f5b1c8a1SJohn Marino } 462f5b1c8a1SJohn Marino 463f5b1c8a1SJohn Marino /* 0 is encoded as a single 0, not the empty string. */ 464f5b1c8a1SJohn Marino if (!started && !CBB_add_u8(&child, 0)) 465f5b1c8a1SJohn Marino return 0; 466f5b1c8a1SJohn Marino 467f5b1c8a1SJohn Marino return CBB_flush(cbb); 468f5b1c8a1SJohn Marino } 469