int ssl_add_cert_chain(SSL *ssl, CBB *cbb) { if (!ssl_has_certificate(ssl)) { return CBB_add_u24(cbb, 0); } CBB certs; if (!CBB_add_u24_length_prefixed(cbb, &certs)) { goto err; } STACK_OF(CRYPTO_BUFFER) *chain = ssl->cert->chain; for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(chain); i++) { CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(chain, i); CBB child; if (!CBB_add_u24_length_prefixed(&certs, &child) || !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer)) || !CBB_flush(&certs)) { goto err; } } return CBB_flush(cbb); err: OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; }
static int test_cbb_prefixed(void) { static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3, 4, 5, 6, 5, 4, 1, 0, 1, 2}; uint8_t *buf; size_t buf_len; CBB cbb, contents, inner_contents, inner_inner_contents; int ok; if (!CBB_init(&cbb, 0) || !CBB_add_u8_length_prefixed(&cbb, &contents) || !CBB_add_u8_length_prefixed(&cbb, &contents) || !CBB_add_u8(&contents, 1) || !CBB_add_u16_length_prefixed(&cbb, &contents) || !CBB_add_u16(&contents, 0x203) || !CBB_add_u24_length_prefixed(&cbb, &contents) || !CBB_add_u24(&contents, 0x40506) || !CBB_add_u8_length_prefixed(&cbb, &contents) || !CBB_add_u8_length_prefixed(&contents, &inner_contents) || !CBB_add_u8(&inner_contents, 1) || !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) || !CBB_add_u8(&inner_inner_contents, 2) || !CBB_finish(&cbb, &buf, &buf_len)) { return 0; } ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; free(buf); return ok; }
static int test_cbb_misuse(void) { CBB cbb, child, contents; uint8_t *buf; size_t buf_len; if (!CBB_init(&cbb, 0) || !CBB_add_u8_length_prefixed(&cbb, &child) || !CBB_add_u8(&child, 1) || !CBB_add_u8(&cbb, 2)) { return 0; } /* Since we wrote to |cbb|, |child| is now invalid and attempts to write to * it should fail. */ if (CBB_add_u8(&child, 1) || CBB_add_u16(&child, 1) || CBB_add_u24(&child, 1) || CBB_add_u8_length_prefixed(&child, &contents) || CBB_add_u16_length_prefixed(&child, &contents) || CBB_add_asn1(&child, &contents, 1) || CBB_add_bytes(&child, (const uint8_t*) "a", 1)) { fprintf(stderr, "CBB operation on invalid CBB did not fail.\n"); return 0; } if (!CBB_finish(&cbb, &buf, &buf_len) || buf_len != 3 || memcmp(buf, "\x01\x01\x02", 3) != 0) { return 0; } free(buf); return 1; }
static int test_cbb_basic(void) { static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8}; uint8_t *buf; size_t buf_len; int ok; CBB cbb; if (!CBB_init(&cbb, 100)) { return 0; } CBB_cleanup(&cbb); if (!CBB_init(&cbb, 0) || !CBB_add_u8(&cbb, 1) || !CBB_add_u16(&cbb, 0x203) || !CBB_add_u24(&cbb, 0x40506) || !CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) || !CBB_finish(&cbb, &buf, &buf_len)) { return 0; } ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; free(buf); return ok; }