static int test_cbb_fixed(void) { CBB cbb; uint8_t buf[1]; uint8_t *out_buf; size_t out_size; if (!CBB_init_fixed(&cbb, NULL, 0) || CBB_add_u8(&cbb, 1) || !CBB_finish(&cbb, &out_buf, &out_size) || out_buf != NULL || out_size != 0) { return 0; } if (!CBB_init_fixed(&cbb, buf, 1) || !CBB_add_u8(&cbb, 1) || CBB_add_u8(&cbb, 2) || !CBB_finish(&cbb, &out_buf, &out_size) || out_buf != buf || out_size != 1 || buf[0] != 1) { return 0; } return 1; }
int ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) { int ret = 0; ECDSA_SIG *s = NULL; s = ECDSA_do_sign_ex(digest, digest_len, kinv, r, eckey); if (s == NULL) { *sig_len = 0; goto err; } CBB cbb; CBB_zero(&cbb); size_t len; if (!CBB_init_fixed(&cbb, sig, ECDSA_size(eckey)) || !ECDSA_SIG_marshal(&cbb, s) || !CBB_finish(&cbb, NULL, &len)) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); CBB_cleanup(&cbb); *sig_len = 0; goto err; } *sig_len = (unsigned)len; ret = 1; err: ECDSA_SIG_free(s); return ret; }
static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest, const uint8_t *secret, size_t secret_len, const uint8_t *label, size_t label_len, const uint8_t *hash, size_t hash_len, size_t len) { static const char kTLS13LabelVersion[] = "TLS 1.3, "; CBB cbb, child; uint8_t *hkdf_label; size_t hkdf_label_len; if (!CBB_init(&cbb, 2 + 1 + strlen(kTLS13LabelVersion) + label_len + 1 + hash_len) || !CBB_add_u16(&cbb, len) || !CBB_add_u8_length_prefixed(&cbb, &child) || !CBB_add_bytes(&child, (const uint8_t *)kTLS13LabelVersion, strlen(kTLS13LabelVersion)) || !CBB_add_bytes(&child, label, label_len) || !CBB_add_u8_length_prefixed(&cbb, &child) || !CBB_add_bytes(&child, hash, hash_len) || !CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) { CBB_cleanup(&cbb); return 0; } int ret = HKDF_expand(out, len, digest, secret, secret_len, hkdf_label, hkdf_label_len); OPENSSL_free(hkdf_label); return ret; }
int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) { CBB cbb; /* First, do a quick walk to find any indefinite-length elements. Most of the * time we hope that there aren't any and thus we can quickly return. */ char conversion_needed; if (!cbs_find_ber(in, &conversion_needed, 0)) { return 0; } if (!conversion_needed) { *out = NULL; *out_len = 0; return 1; } if (!CBB_init(&cbb, CBS_len(in)) || !cbs_convert_ber(in, &cbb, 0, 0, 0) || !CBB_finish(&cbb, out, out_len)) { CBB_cleanup(&cbb); return 0; } return 1; }
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_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_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; }
static int test_cbb_finish_child(void) { CBB cbb, child; uint8_t *out_buf; size_t out_size; if (!CBB_init(&cbb, 16) || !CBB_add_u8_length_prefixed(&cbb, &child) || CBB_finish(&child, &out_buf, &out_size) || !CBB_finish(&cbb, &out_buf, &out_size) || out_size != 1 || out_buf[0] != 0) { return 0; } free(out_buf); return 1; }
MONO_API MonoBtlsX509Name * mono_btls_x509_name_from_data (const void *data, int len, int use_canon_enc) { MonoBtlsX509Name *name; uint8_t *buf; const unsigned char *ptr; X509_NAME *ret; name = OPENSSL_malloc (sizeof (MonoBtlsX509Name)); if (!name) return NULL; memset (name, 0, sizeof(MonoBtlsX509Name)); name->owns = 1; name->name = X509_NAME_new (); if (!name->name) { OPENSSL_free (name); return NULL; } if (use_canon_enc) { CBB cbb, contents; size_t buf_len; // re-add ASN1 SEQUENCE header. CBB_init(&cbb, 0); if (!CBB_add_asn1(&cbb, &contents, 0x30) || !CBB_add_bytes(&contents, data, len) || !CBB_finish(&cbb, &buf, &buf_len)) { CBB_cleanup (&cbb); mono_btls_x509_name_free (name); return NULL; } ptr = buf; len = (int)buf_len; } else { ptr = data; buf = NULL; } ret = d2i_X509_NAME (&name->name, &ptr, len); if (buf) OPENSSL_free (buf); if (ret != name->name) { mono_btls_x509_name_free (name); return NULL; } return name; }
int tls13_get_cert_verify_signature_input( SSL *ssl, uint8_t **out, size_t *out_len, enum ssl_cert_verify_context_t cert_verify_context) { CBB cbb; if (!CBB_init(&cbb, 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) { goto err; } for (size_t i = 0; i < 64; i++) { if (!CBB_add_u8(&cbb, 0x20)) { goto err; } } const uint8_t *context; size_t context_len; if (cert_verify_context == ssl_cert_verify_server) { /* Include the NUL byte. */ static const char kContext[] = "TLS 1.3, server CertificateVerify"; context = (const uint8_t *)kContext; context_len = sizeof(kContext); } else if (cert_verify_context == ssl_cert_verify_client) { static const char kContext[] = "TLS 1.3, client CertificateVerify"; context = (const uint8_t *)kContext; context_len = sizeof(kContext); } else if (cert_verify_context == ssl_cert_verify_channel_id) { static const char kContext[] = "TLS 1.3, Channel ID"; context = (const uint8_t *)kContext; context_len = sizeof(kContext); } else { goto err; } if (!CBB_add_bytes(&cbb, context, context_len)) { goto err; } uint8_t context_hash[EVP_MAX_MD_SIZE]; size_t context_hash_len; if (!tls13_get_context_hash(ssl, context_hash, &context_hash_len) || !CBB_add_bytes(&cbb, context_hash, context_hash_len) || !CBB_finish(&cbb, out, out_len)) { goto err; } return 1; err: OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); CBB_cleanup(&cbb); return 0; }
int RSA_private_key_to_bytes(uint8_t **out_bytes, size_t *out_len, const RSA *rsa) { CBB cbb; CBB_zero(&cbb); if (!CBB_init(&cbb, 0) || !RSA_marshal_private_key(&cbb, rsa) || !CBB_finish(&cbb, out_bytes, out_len)) { OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); CBB_cleanup(&cbb); return 0; } return 1; }
int ECDSA_SIG_to_bytes(uint8_t **out_bytes, size_t *out_len, const ECDSA_SIG *sig) { CBB cbb; CBB_zero(&cbb); if (!CBB_init(&cbb, 0) || !ECDSA_SIG_marshal(&cbb, sig) || !CBB_finish(&cbb, out_bytes, out_len)) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); CBB_cleanup(&cbb); return 0; } return 1; }
static int test_asn1_uint64(void) { size_t i; for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]); i++) { const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i]; CBS cbs; uint64_t value; CBB cbb; uint8_t *out; size_t len; CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len); if (!CBS_get_asn1_uint64(&cbs, &value) || CBS_len(&cbs) != 0 || value != test->value) { return 0; } if (!CBB_init(&cbb, 0)) { return 0; } if (!CBB_add_asn1_uint64(&cbb, test->value) || !CBB_finish(&cbb, &out, &len)) { CBB_cleanup(&cbb); return 0; } if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) { free(out); return 0; } free(out); } for (i = 0; i < sizeof(kAsn1InvalidUint64Tests) / sizeof(kAsn1InvalidUint64Tests[0]); i++) { const ASN1_INVALID_UINT64_TEST *test = &kAsn1InvalidUint64Tests[i]; CBS cbs; uint64_t value; CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len); if (CBS_get_asn1_uint64(&cbs, &value)) { return 0; } } return 1; }
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage, unsigned outer_tag, unsigned inner_tag) { assert(!(outer_tag & CBS_ASN1_CONSTRUCTED)); assert(!(inner_tag & CBS_ASN1_CONSTRUCTED)); assert(is_string_type(inner_tag)); if (CBS_peek_asn1_tag(in, outer_tag)) { /* Normal implicitly-tagged string. */ *out_storage = NULL; return CBS_get_asn1(in, out, outer_tag); } /* Otherwise, try to parse an implicitly-tagged constructed string. * |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep * of nesting. */ CBB result; CBS child; if (!CBB_init(&result, CBS_len(in)) || !CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) { goto err; } while (CBS_len(&child) > 0) { CBS chunk; if (!CBS_get_asn1(&child, &chunk, inner_tag) || !CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) { goto err; } } uint8_t *data; size_t len; if (!CBB_finish(&result, &data, &len)) { goto err; } CBS_init(out, data, len); *out_storage = data; return 1; err: CBB_cleanup(&result); return 0; }
static int tls13_get_cert_verify_signature_input(SSL *ssl, uint8_t **out, size_t *out_len, int server) { CBB cbb; if (!CBB_init(&cbb, 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) { goto err; } for (size_t i = 0; i < 64; i++) { if (!CBB_add_u8(&cbb, 0x20)) { goto err; } } if (server) { /* Include the NUL byte. */ static const char kContext[] = "TLS 1.3, server CertificateVerify"; if (!CBB_add_bytes(&cbb, (const uint8_t *)kContext, sizeof(kContext))) { goto err; } } else { static const char kContext[] = "TLS 1.3, client CertificateVerify"; if (!CBB_add_bytes(&cbb, (const uint8_t *)kContext, sizeof(kContext))) { goto err; } } uint8_t context_hashes[2 * EVP_MAX_MD_SIZE]; size_t context_hashes_len; if (!tls13_get_context_hashes(ssl, context_hashes, &context_hashes_len) || !CBB_add_bytes(&cbb, context_hashes, context_hashes_len) || !CBB_finish(&cbb, out, out_len)) { goto err; } return 1; err: OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); CBB_cleanup(&cbb); return 0; }
static int test_crl_reparse(const uint8_t *der_bytes, size_t der_len) { CBS pkcs7; CBB cbb; STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null(); STACK_OF(X509_CRL) *crls2 = sk_X509_CRL_new_null(); uint8_t *result_data, *result2_data; size_t result_len, result2_len, i; CBS_init(&pkcs7, der_bytes, der_len); if (!PKCS7_get_CRLs(crls, &pkcs7)) { fprintf(stderr, "PKCS7_get_CRLs failed.\n"); return 0; } CBB_init(&cbb, der_len); if (!PKCS7_bundle_CRLs(&cbb, crls) || !CBB_finish(&cbb, &result_data, &result_len)) { fprintf(stderr, "PKCS7_bundle_CRLs failed.\n"); return 0; } CBS_init(&pkcs7, result_data, result_len); if (!PKCS7_get_CRLs(crls2, &pkcs7)) { fprintf(stderr, "PKCS7_get_CRLs reparse failed.\n"); return 0; } if (sk_X509_CRL_num(crls) != sk_X509_CRL_num(crls)) { fprintf(stderr, "Number of CRLs in results differ.\n"); return 0; } for (i = 0; i < sk_X509_CRL_num(crls); i++) { X509_CRL *a = sk_X509_CRL_value(crls, i); X509_CRL *b = sk_X509_CRL_value(crls2, i); if (X509_CRL_cmp(a, b) != 0) { fprintf(stderr, "CRL %u differs.\n", (unsigned) i); return 0; } } CBB_init(&cbb, der_len); if (!PKCS7_bundle_CRLs(&cbb, crls2) || !CBB_finish(&cbb, &result2_data, &result2_len)) { fprintf(stderr, "PKCS7_bundle_CRLs failed the second time.\n"); return 0; } if (result_len != result2_len || memcmp(result_data, result2_data, result_len) != 0) { fprintf(stderr, "Serialisation is not stable.\n"); return 0; } OPENSSL_free(result_data); OPENSSL_free(result2_data); sk_X509_CRL_pop_free(crls, X509_CRL_free); sk_X509_CRL_pop_free(crls2, X509_CRL_free); return 1; }
static int test_cbb_asn1(void) { static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3}; uint8_t *buf, *test_data; size_t buf_len; CBB cbb, contents, inner_contents; if (!CBB_init(&cbb, 0) || !CBB_add_asn1(&cbb, &contents, 0x30) || !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) || !CBB_finish(&cbb, &buf, &buf_len)) { return 0; } if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) { return 0; } free(buf); test_data = malloc(100000); memset(test_data, 0x42, 100000); if (!CBB_init(&cbb, 0) || !CBB_add_asn1(&cbb, &contents, 0x30) || !CBB_add_bytes(&contents, test_data, 130) || !CBB_finish(&cbb, &buf, &buf_len)) { return 0; } if (buf_len != 3 + 130 || memcmp(buf, "\x30\x81\x82", 3) != 0 || memcmp(buf + 3, test_data, 130) != 0) { return 0; } free(buf); if (!CBB_init(&cbb, 0) || !CBB_add_asn1(&cbb, &contents, 0x30) || !CBB_add_bytes(&contents, test_data, 1000) || !CBB_finish(&cbb, &buf, &buf_len)) { return 0; } if (buf_len != 4 + 1000 || memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 || memcmp(buf + 4, test_data, 1000)) { return 0; } free(buf); if (!CBB_init(&cbb, 0) || !CBB_add_asn1(&cbb, &contents, 0x30) || !CBB_add_asn1(&contents, &inner_contents, 0x30) || !CBB_add_bytes(&inner_contents, test_data, 100000) || !CBB_finish(&cbb, &buf, &buf_len)) { return 0; } if (buf_len != 5 + 5 + 100000 || memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 || memcmp(buf + 10, test_data, 100000)) { return 0; } free(buf); free(test_data); return 1; }
int i2d_SSL_SESSION(SSL_SESSION *s, unsigned char **pp) { CBB cbb, session, cipher_suite, session_id, master_key, time, timeout; CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket; CBB value; unsigned char *data = NULL, *peer_cert_bytes = NULL; size_t data_len = 0; int len, rv = -1; uint16_t cid; if (s == NULL) return (0); if (s->cipher == NULL && s->cipher_id == 0) return (0); if (!CBB_init(&cbb, 0)) goto err; if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE)) goto err; /* Session ASN1 version. */ if (!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION)) goto err; /* TLS/SSL protocol version. */ if (s->ssl_version < 0) goto err; if (!CBB_add_asn1_uint64(&session, s->ssl_version)) goto err; /* Cipher suite ID. */ /* XXX - require cipher to be non-NULL or always/only use cipher_id. */ cid = (uint16_t)(s->cipher_id & 0xffff); if (s->cipher != NULL) cid = ssl3_cipher_get_value(s->cipher); if (!CBB_add_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING)) goto err; if (!CBB_add_u16(&cipher_suite, cid)) goto err; /* Session ID. */ if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING)) goto err; if (!CBB_add_bytes(&session_id, s->session_id, s->session_id_length)) goto err; /* Master key. */ if (!CBB_add_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING)) goto err; if (!CBB_add_bytes(&master_key, s->master_key, s->master_key_length)) goto err; /* Time [1]. */ if (s->time != 0) { if (s->time < 0) goto err; if (!CBB_add_asn1(&session, &time, SSLASN1_TIME_TAG)) goto err; if (!CBB_add_asn1_uint64(&time, s->time)) goto err; } /* Timeout [2]. */ if (s->timeout != 0) { if (s->timeout < 0) goto err; if (!CBB_add_asn1(&session, &timeout, SSLASN1_TIMEOUT_TAG)) goto err; if (!CBB_add_asn1_uint64(&timeout, s->timeout)) goto err; } /* Peer certificate [3]. */ if (s->peer != NULL) { if ((len = i2d_X509(s->peer, &peer_cert_bytes)) <= 0) goto err; if (!CBB_add_asn1(&session, &peer_cert, SSLASN1_PEER_CERT_TAG)) goto err; if (!CBB_add_bytes(&peer_cert, peer_cert_bytes, len)) goto err; } /* Session ID context [4]. */ /* XXX - Actually handle this as optional? */ if (!CBB_add_asn1(&session, &sidctx, SSLASN1_SESSION_ID_CTX_TAG)) goto err; if (!CBB_add_asn1(&sidctx, &value, CBS_ASN1_OCTETSTRING)) goto err; if (!CBB_add_bytes(&value, s->sid_ctx, s->sid_ctx_length)) goto err; /* Verify result [5]. */ if (s->verify_result != X509_V_OK) { if (s->verify_result < 0) goto err; if (!CBB_add_asn1(&session, &verify_result, SSLASN1_VERIFY_RESULT_TAG)) goto err; if (!CBB_add_asn1_uint64(&verify_result, s->verify_result)) goto err; } /* Hostname [6]. */ if (s->tlsext_hostname != NULL) { if (!CBB_add_asn1(&session, &hostname, SSLASN1_HOSTNAME_TAG)) goto err; if (!CBB_add_asn1(&hostname, &value, CBS_ASN1_OCTETSTRING)) goto err; if (!CBB_add_bytes(&value, (const uint8_t *)s->tlsext_hostname, strlen(s->tlsext_hostname))) goto err; } /* PSK identity hint [7]. */ /* PSK identity [8]. */ /* Ticket lifetime hint [9]. */ if (s->tlsext_tick_lifetime_hint > 0) { if (!CBB_add_asn1(&session, &lifetime, SSLASN1_LIFETIME_TAG)) goto err; if (!CBB_add_asn1_uint64(&lifetime, s->tlsext_tick_lifetime_hint)) goto err; } /* Ticket [10]. */ if (s->tlsext_tick) { if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG)) goto err; if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING)) goto err; if (!CBB_add_bytes(&value, s->tlsext_tick, s->tlsext_ticklen)) goto err; } /* Compression method [11]. */ /* SRP username [12]. */ if (!CBB_finish(&cbb, &data, &data_len)) goto err; if (data_len > INT_MAX) goto err; if (pp != NULL) { if (*pp == NULL) { *pp = data; data = NULL; } else { memcpy(*pp, data, data_len); *pp += data_len; } } rv = (int)data_len; err: CBB_cleanup(&cbb); freezero(data, data_len); free(peer_cert_bytes); return rv; }
static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, size_t *out_len, int for_ticket) { CBB cbb, session, child, child2; if (in == NULL || in->cipher == NULL) { return 0; } CBB_zero(&cbb); if (!CBB_init(&cbb, 0) || !CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) || !CBB_add_asn1_uint64(&session, kVersion) || !CBB_add_asn1_uint64(&session, in->ssl_version) || !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || !CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) || !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || /* The session ID is irrelevant for a session ticket. */ !CBB_add_bytes(&child, in->session_id, for_ticket ? 0 : in->session_id_length) || !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child, in->master_key, in->master_key_length) || !CBB_add_asn1(&session, &child, kTimeTag) || !CBB_add_asn1_uint64(&child, in->time) || !CBB_add_asn1(&session, &child, kTimeoutTag) || !CBB_add_asn1_uint64(&child, in->timeout)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* The peer certificate is only serialized if the SHA-256 isn't * serialized instead. */ if (sk_CRYPTO_BUFFER_num(in->certs) > 0 && !in->peer_sha256_valid) { const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, 0); if (!CBB_add_asn1(&session, &child, kPeerTag) || !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } /* Although it is OPTIONAL and usually empty, OpenSSL has * historically always encoded the sid_ctx. */ if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (in->verify_result != X509_V_OK) { if (!CBB_add_asn1(&session, &child, kVerifyResultTag) || !CBB_add_asn1_uint64(&child, in->verify_result)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->tlsext_hostname) { if (!CBB_add_asn1(&session, &child, kHostNameTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname, strlen(in->tlsext_hostname))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->psk_identity) { if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity, strlen(in->psk_identity))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->tlsext_tick_lifetime_hint > 0) { if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) || !CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->tlsext_tick && !for_ticket) { if (!CBB_add_asn1(&session, &child, kTicketTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->peer_sha256_valid) { if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->original_handshake_hash_len > 0) { if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->original_handshake_hash, in->original_handshake_hash_len)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->tlsext_signed_cert_timestamp_list_length > 0) { if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list, in->tlsext_signed_cert_timestamp_list_length)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->ocsp_response_length > 0) { if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->extended_master_secret) { if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || !CBB_add_u8(&child2, 0xff)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->group_id > 0 && (!CBB_add_asn1(&session, &child, kGroupIDTag) || !CBB_add_asn1_uint64(&child, in->group_id))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* The certificate chain is only serialized if the leaf's SHA-256 isn't * serialized instead. */ if (in->certs != NULL && !in->peer_sha256_valid && sk_CRYPTO_BUFFER_num(in->certs) >= 2) { if (!CBB_add_asn1(&session, &child, kCertChainTag)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs); i++) { const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, i); if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } } if (in->ticket_age_add_valid) { if (!CBB_add_asn1(&session, &child, kTicketAgeAddTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_u32(&child2, in->ticket_age_add)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (!in->is_server) { if (!CBB_add_asn1(&session, &child, kIsServerTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || !CBB_add_u8(&child2, 0x00)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->peer_signature_algorithm != 0 && (!CBB_add_asn1(&session, &child, kPeerSignatureAlgorithmTag) || !CBB_add_asn1_uint64(&child, in->peer_signature_algorithm))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (in->ticket_max_early_data != 0 && (!CBB_add_asn1(&session, &child, kTicketMaxEarlyDataTag) || !CBB_add_asn1_uint64(&child, in->ticket_max_early_data))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (in->timeout != in->auth_timeout && (!CBB_add_asn1(&session, &child, kAuthTimeoutTag) || !CBB_add_asn1_uint64(&child, in->auth_timeout))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (in->early_alpn) { if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn, in->early_alpn_len)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (!CBB_finish(&cbb, out_data, out_len)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } return 1; err: CBB_cleanup(&cbb); return 0; }