Switch various things to scopers.

Clear out some of the easy cases.

Bug: 132
Change-Id: Icd5c246cb6bec4a96c72eccd6569235c3d030ebd
Reviewed-on: https://boringssl-review.googlesource.com/18204
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/d1_both.cc b/ssl/d1_both.cc
index 6db348a..591189f 100644
--- a/ssl/d1_both.cc
+++ b/ssl/d1_both.cc
@@ -156,6 +156,7 @@
 }
 
 static hm_fragment *dtls1_hm_fragment_new(const struct hm_header_st *msg_hdr) {
+  ScopedCBB cbb;
   hm_fragment *frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
   if (frag == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
@@ -174,15 +175,13 @@
     goto err;
   }
 
-  CBB cbb;
-  if (!CBB_init_fixed(&cbb, frag->data, DTLS1_HM_HEADER_LENGTH) ||
-      !CBB_add_u8(&cbb, msg_hdr->type) ||
-      !CBB_add_u24(&cbb, msg_hdr->msg_len) ||
-      !CBB_add_u16(&cbb, msg_hdr->seq) ||
-      !CBB_add_u24(&cbb, 0 /* frag_off */) ||
-      !CBB_add_u24(&cbb, msg_hdr->msg_len) ||
-      !CBB_finish(&cbb, NULL, NULL)) {
-    CBB_cleanup(&cbb);
+  if (!CBB_init_fixed(cbb.get(), frag->data, DTLS1_HM_HEADER_LENGTH) ||
+      !CBB_add_u8(cbb.get(), msg_hdr->type) ||
+      !CBB_add_u24(cbb.get(), msg_hdr->msg_len) ||
+      !CBB_add_u16(cbb.get(), msg_hdr->seq) ||
+      !CBB_add_u24(cbb.get(), 0 /* frag_off */) ||
+      !CBB_add_u24(cbb.get(), msg_hdr->msg_len) ||
+      !CBB_finish(cbb.get(), NULL, NULL)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     goto err;
   }
@@ -681,18 +680,17 @@
   }
 
   /* Assemble a fragment, to be sealed in-place. */
-  CBB cbb;
+  ScopedCBB cbb;
   uint8_t *frag = out + prefix;
   size_t max_frag = max_out - prefix, frag_len;
-  if (!CBB_init_fixed(&cbb, frag, max_frag) ||
-      !CBB_add_u8(&cbb, hdr.type) ||
-      !CBB_add_u24(&cbb, hdr.msg_len) ||
-      !CBB_add_u16(&cbb, hdr.seq) ||
-      !CBB_add_u24(&cbb, ssl->d1->outgoing_offset) ||
-      !CBB_add_u24(&cbb, todo) ||
-      !CBB_add_bytes(&cbb, CBS_data(&body), todo) ||
-      !CBB_finish(&cbb, NULL, &frag_len)) {
-    CBB_cleanup(&cbb);
+  if (!CBB_init_fixed(cbb.get(), frag, max_frag) ||
+      !CBB_add_u8(cbb.get(), hdr.type) ||
+      !CBB_add_u24(cbb.get(), hdr.msg_len) ||
+      !CBB_add_u16(cbb.get(), hdr.seq) ||
+      !CBB_add_u24(cbb.get(), ssl->d1->outgoing_offset) ||
+      !CBB_add_u24(cbb.get(), todo) ||
+      !CBB_add_bytes(cbb.get(), CBS_data(&body), todo) ||
+      !CBB_finish(cbb.get(), NULL, &frag_len)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return seal_error;
   }
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index cd3ee9a..1bd62ce 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -1198,9 +1198,6 @@
 
 static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  EC_KEY *ecdh = NULL;
-  EC_POINT *srvr_ecpoint = NULL;
-
   int ret = ssl->method->ssl_get_message(ssl);
   if (ret <= 0) {
     return ret;
@@ -1238,7 +1235,7 @@
                                      &psk_identity_hint)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      goto err;
+      return -1;
     }
 
     /* Store PSK identity hint for later use, hint is used in
@@ -1252,7 +1249,7 @@
         CBS_contains_zero_byte(&psk_identity_hint)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-      goto err;
+      return -1;
     }
 
     /* Save non-empty identity hints as a C string. Empty identity hints we
@@ -1264,7 +1261,7 @@
         !CBS_strdup(&psk_identity_hint, &hs->peer_psk_identity_hint)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-      goto err;
+      return -1;
     }
   }
 
@@ -1279,7 +1276,7 @@
         !CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      goto err;
+      return -1;
     }
     hs->new_session->group_id = group_id;
 
@@ -1287,18 +1284,18 @@
     if (!tls1_check_group_id(ssl, group_id)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-      goto err;
+      return -1;
     }
 
     /* Initialize ECDH and save the peer public key for later. */
     if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
         !CBS_stow(&point, &hs->peer_key, &hs->peer_key_len)) {
-      goto err;
+      return -1;
     }
   } else if (!(alg_k & SSL_kPSK)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
-    goto err;
+    return -1;
   }
 
   /* At this point, |server_key_exchange| contains the signature, if any, while
@@ -1315,19 +1312,19 @@
       if (!CBS_get_u16(&server_key_exchange, &signature_algorithm)) {
         OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
         ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-        goto err;
+        return -1;
       }
       uint8_t alert = SSL_AD_DECODE_ERROR;
       if (!tls12_check_peer_sigalg(ssl, &alert, signature_algorithm)) {
         ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
-        goto err;
+        return -1;
       }
       hs->new_session->peer_signature_algorithm = signature_algorithm;
     } else if (!tls1_get_legacy_signature_algorithm(&signature_algorithm,
                                                     hs->peer_pubkey)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_CERTIFICATE);
-      goto err;
+      return -1;
     }
 
     /* The last field in |server_key_exchange| is the signature. */
@@ -1336,21 +1333,24 @@
         CBS_len(&server_key_exchange) != 0) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      goto err;
+      return -1;
     }
 
-    CBB transcript;
+    ScopedCBB transcript;
     uint8_t *transcript_data;
     size_t transcript_len;
-    if (!CBB_init(&transcript, 2*SSL3_RANDOM_SIZE + CBS_len(&parameter)) ||
-        !CBB_add_bytes(&transcript, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
-        !CBB_add_bytes(&transcript, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
-        !CBB_add_bytes(&transcript, CBS_data(&parameter), CBS_len(&parameter)) ||
-        !CBB_finish(&transcript, &transcript_data, &transcript_len)) {
-      CBB_cleanup(&transcript);
+    if (!CBB_init(transcript.get(),
+                  2 * SSL3_RANDOM_SIZE + CBS_len(&parameter)) ||
+        !CBB_add_bytes(transcript.get(), ssl->s3->client_random,
+                       SSL3_RANDOM_SIZE) ||
+        !CBB_add_bytes(transcript.get(), ssl->s3->server_random,
+                       SSL3_RANDOM_SIZE) ||
+        !CBB_add_bytes(transcript.get(), CBS_data(&parameter),
+                       CBS_len(&parameter)) ||
+        !CBB_finish(transcript.get(), &transcript_data, &transcript_len)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-      goto err;
+      return -1;
     }
 
     int sig_ok = ssl_public_key_verify(
@@ -1366,7 +1366,7 @@
       /* bad signature */
       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
-      goto err;
+      return -1;
     }
   } else {
     /* PSK ciphers are the only supported certificate-less ciphers. */
@@ -1375,15 +1375,10 @@
     if (CBS_len(&server_key_exchange) > 0) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      goto err;
+      return -1;
     }
   }
   return 1;
-
-err:
-  EC_POINT_free(srvr_ecpoint);
-  EC_KEY_free(ecdh);
-  return -1;
 }
 
 static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
@@ -1650,18 +1645,17 @@
   /* For a PSK cipher suite, other_secret is combined with the pre-shared
    * key. */
   if (alg_a & SSL_aPSK) {
-    CBB pms_cbb, child;
+    ScopedCBB pms_cbb;
+    CBB child;
     uint8_t *new_pms;
     size_t new_pms_len;
 
-    CBB_zero(&pms_cbb);
-    if (!CBB_init(&pms_cbb, 2 + psk_len + 2 + pms_len) ||
-        !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+    if (!CBB_init(pms_cbb.get(), 2 + psk_len + 2 + pms_len) ||
+        !CBB_add_u16_length_prefixed(pms_cbb.get(), &child) ||
         !CBB_add_bytes(&child, pms, pms_len) ||
-        !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+        !CBB_add_u16_length_prefixed(pms_cbb.get(), &child) ||
         !CBB_add_bytes(&child, psk, psk_len) ||
-        !CBB_finish(&pms_cbb, &new_pms, &new_pms_len)) {
-      CBB_cleanup(&pms_cbb);
+        !CBB_finish(pms_cbb.get(), &new_pms, &new_pms_len)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
     }
@@ -1744,12 +1738,10 @@
       return -1;
     }
 
-    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
-    int ok = pctx != NULL &&
-             EVP_PKEY_sign_init(pctx) &&
-             EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len);
-    EVP_PKEY_CTX_free(pctx);
-    if (!ok) {
+    UniquePtr<EVP_PKEY_CTX> pctx(EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL));
+    if (!pctx ||
+        !EVP_PKEY_sign_init(pctx.get()) ||
+        !EVP_PKEY_sign(pctx.get(), ptr, &sig_len, digest, digest_len)) {
       return -1;
     }
   } else {
@@ -1782,16 +1774,16 @@
   static const uint8_t kZero[32] = {0};
   size_t padding_len = 32 - ((ssl->s3->next_proto_negotiated_len + 2) % 32);
 
-  CBB cbb, body, child;
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_NEXT_PROTO) ||
+  ScopedCBB cbb;
+  CBB body, child;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_NEXT_PROTO) ||
       !CBB_add_u8_length_prefixed(&body, &child) ||
       !CBB_add_bytes(&child, ssl->s3->next_proto_negotiated,
                      ssl->s3->next_proto_negotiated_len) ||
       !CBB_add_u8_length_prefixed(&body, &child) ||
       !CBB_add_bytes(&child, kZero, padding_len) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
+      !ssl_add_message_cbb(ssl, cbb.get())) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    CBB_cleanup(&cbb);
     return -1;
   }
 
@@ -1809,12 +1801,12 @@
     return -1;
   }
 
-  CBB cbb, body;
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
+  ScopedCBB cbb;
+  CBB body;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CHANNEL_ID) ||
       !tls1_write_channel_id(hs, &body) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
+      !ssl_add_message_cbb(ssl, cbb.get())) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    CBB_cleanup(&cbb);
     return -1;
   }
 
@@ -1852,18 +1844,20 @@
     return 1;
   }
 
-  int session_renewed = ssl->session != NULL;
   SSL_SESSION *session = hs->new_session;
-  if (session_renewed) {
+  UniquePtr<SSL_SESSION> renewed_session;
+  if (ssl->session != NULL) {
     /* The server is sending a new ticket for an existing session. Sessions are
      * immutable once established, so duplicate all but the ticket of the
      * existing session. */
-    session = SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
-    if (session == NULL) {
+    renewed_session.reset(
+        SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH));
+    if (!renewed_session) {
       /* This should never happen. */
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
+      return -1;
     }
+    session = renewed_session.get();
   }
 
   /* |tlsext_tick_lifetime_hint| is measured from when the ticket was issued. */
@@ -1871,7 +1865,7 @@
 
   if (!CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
+    return -1;
   }
   session->tlsext_tick_lifetime_hint = tlsext_tick_lifetime_hint;
 
@@ -1881,22 +1875,16 @@
   if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket),
                   session->session_id, &session->session_id_length,
                   EVP_sha256(), NULL)) {
-    goto err;
+    return -1;
   }
 
-  if (session_renewed) {
+  if (renewed_session) {
     session->not_resumable = 0;
     SSL_SESSION_free(ssl->session);
-    ssl->session = session;
+    ssl->session = renewed_session.release();
   }
 
   return 1;
-
-err:
-  if (session_renewed) {
-    SSL_SESSION_free(session);
-  }
-  return -1;
 }
 
 }  // namespace bssl
diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc
index 85c1c82..35ea402 100644
--- a/ssl/handshake_server.cc
+++ b/ssl/handshake_server.cc
@@ -984,8 +984,9 @@
     session = ssl->session;
   }
 
-  CBB cbb, body, session_id;
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
+  ScopedCBB cbb;
+  CBB body, session_id;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
       !CBB_add_u16(&body, ssl->version) ||
       !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
       !CBB_add_u8_length_prefixed(&body, &session_id) ||
@@ -994,9 +995,8 @@
       !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
       !CBB_add_u8(&body, 0 /* no compression */) ||
       !ssl_add_serverhello_tlsext(hs, &body) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
+      !ssl_add_message_cbb(ssl, cbb.get())) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    CBB_cleanup(&cbb);
     return -1;
   }
 
@@ -1091,33 +1091,34 @@
 
 static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  CBB cbb, body, child;
-  if (!ssl->method->init_message(ssl, &cbb, &body,
+  ScopedCBB cbb;
+  CBB body, child;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_SERVER_KEY_EXCHANGE) ||
       /* |hs->server_params| contains a prefix for signing. */
       hs->server_params_len < 2 * SSL3_RANDOM_SIZE ||
       !CBB_add_bytes(&body, hs->server_params + 2 * SSL3_RANDOM_SIZE,
                      hs->server_params_len - 2 * SSL3_RANDOM_SIZE)) {
-    goto err;
+    return -1;
   }
 
   /* Add a signature. */
   if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
     if (!ssl_has_private_key(ssl)) {
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-      goto err;
+      return -1;
     }
 
     /* Determine the signature algorithm. */
     uint16_t signature_algorithm;
     if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
-      goto err;
+      return -1;
     }
     if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
       if (!CBB_add_u16(&body, signature_algorithm)) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
         ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        goto err;
+        return -1;
       }
     }
 
@@ -1126,7 +1127,7 @@
     uint8_t *ptr;
     if (!CBB_add_u16_length_prefixed(&body, &child) ||
         !CBB_reserve(&child, &ptr, max_sig_len)) {
-      goto err;
+      return -1;
     }
 
     size_t sig_len;
@@ -1135,19 +1136,19 @@
                                  hs->server_params_len)) {
       case ssl_private_key_success:
         if (!CBB_did_write(&child, sig_len)) {
-          goto err;
+          return -1;
         }
         break;
       case ssl_private_key_failure:
-        goto err;
+        return -1;
       case ssl_private_key_retry:
         ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
-        goto err;
+        return -1;
     }
   }
 
-  if (!ssl_add_message_cbb(ssl, &cbb)) {
-    goto err;
+  if (!ssl_add_message_cbb(ssl, cbb.get())) {
+    return -1;
   }
 
   OPENSSL_free(hs->server_params);
@@ -1155,19 +1156,16 @@
   hs->server_params_len = 0;
 
   return 1;
-
-err:
-  CBB_cleanup(&cbb);
-  return -1;
 }
 
 static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  CBB cbb, body;
+  ScopedCBB cbb;
+  CBB body;
 
   if (hs->cert_request) {
     CBB cert_types, sigalgs_cbb;
-    if (!ssl->method->init_message(ssl, &cbb, &body,
+    if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                    SSL3_MT_CERTIFICATE_REQUEST) ||
         !CBB_add_u8_length_prefixed(&body, &cert_types) ||
         !CBB_add_u8(&cert_types, SSL3_CT_RSA_SIGN) ||
@@ -1177,22 +1175,20 @@
          (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
           !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb))) ||
         !ssl_add_client_CA_list(ssl, &body) ||
-        !ssl_add_message_cbb(ssl, &cbb)) {
-      goto err;
+        !ssl_add_message_cbb(ssl, cbb.get())) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return -1;
     }
   }
 
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO_DONE) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
-    goto err;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body,
+                                 SSL3_MT_SERVER_HELLO_DONE) ||
+      !ssl_add_message_cbb(ssl, cbb.get())) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
   }
 
   return 1;
-
-err:
-  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-  CBB_cleanup(&cbb);
-  return -1;
 }
 
 static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
@@ -1491,18 +1487,18 @@
       OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
     }
 
-    CBB new_premaster, child;
+    ScopedCBB new_premaster;
+    CBB child;
     uint8_t *new_data;
     size_t new_len;
-    CBB_zero(&new_premaster);
-    if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
-        !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+    if (!CBB_init(new_premaster.get(),
+                  2 + psk_len + 2 + premaster_secret_len) ||
+        !CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
         !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
-        !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+        !CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
         !CBB_add_bytes(&child, psk, psk_len) ||
-        !CBB_finish(&new_premaster, &new_data, &new_len)) {
+        !CBB_finish(new_premaster.get(), &new_data, &new_len)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      CBB_cleanup(&new_premaster);
       goto err;
     }
 
@@ -1602,12 +1598,11 @@
       return -1;
     }
 
-    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(hs->peer_pubkey, NULL);
-    sig_ok = pctx != NULL &&
-             EVP_PKEY_verify_init(pctx) &&
-             EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature),
-                             digest, digest_len);
-    EVP_PKEY_CTX_free(pctx);
+    UniquePtr<EVP_PKEY_CTX> pctx(EVP_PKEY_CTX_new(hs->peer_pubkey, NULL));
+    sig_ok = pctx &&
+             EVP_PKEY_verify_init(pctx.get()) &&
+             EVP_PKEY_verify(pctx.get(), CBS_data(&signature),
+                             CBS_len(&signature), digest, digest_len);
   } else {
     sig_ok = ssl_public_key_verify(
         ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
@@ -1688,7 +1683,7 @@
 
   if (hs->ticket_expected) {
     const SSL_SESSION *session;
-    SSL_SESSION *session_copy = NULL;
+    UniquePtr<SSL_SESSION> session_copy;
     if (ssl->session == NULL) {
       /* Fix the timeout to measure from the ticket issuance time. */
       ssl_session_rebase_time(ssl, hs->new_session);
@@ -1696,25 +1691,24 @@
     } else {
       /* We are renewing an existing session. Duplicate the session to adjust
        * the timeout. */
-      session_copy = SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
-      if (session_copy == NULL) {
+      session_copy.reset(
+          SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH));
+      if (!session_copy) {
         return -1;
       }
 
-      ssl_session_rebase_time(ssl, session_copy);
-      session = session_copy;
+      ssl_session_rebase_time(ssl, session_copy.get());
+      session = session_copy.get();
     }
 
-    CBB cbb, body, ticket;
-    int ok = ssl->method->init_message(ssl, &cbb, &body,
-                                       SSL3_MT_NEW_SESSION_TICKET) &&
-             CBB_add_u32(&body, session->timeout) &&
-             CBB_add_u16_length_prefixed(&body, &ticket) &&
-             ssl_encrypt_ticket(ssl, &ticket, session) &&
-             ssl_add_message_cbb(ssl, &cbb);
-    SSL_SESSION_free(session_copy);
-    CBB_cleanup(&cbb);
-    if (!ok) {
+    ScopedCBB cbb;
+    CBB body, ticket;
+    if (!ssl->method->init_message(ssl, cbb.get(), &body,
+                                   SSL3_MT_NEW_SESSION_TICKET) ||
+        !CBB_add_u32(&body, session->timeout) ||
+        !CBB_add_u16_length_prefixed(&body, &ticket) ||
+        !ssl_encrypt_ticket(ssl, &ticket, session) ||
+        !ssl_add_message_cbb(ssl, cbb.get())) {
       return -1;
     }
   }
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index dea1b4f..79f72ea 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -415,12 +415,12 @@
     }
   }
 
-  CBB cbb, body;
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
+  ScopedCBB cbb;
+  CBB body;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_FINISHED) ||
       !CBB_add_bytes(&body, finished, finished_len) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
+      !ssl_add_message_cbb(ssl, cbb.get())) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    CBB_cleanup(&cbb);
     return -1;
   }
 
@@ -480,12 +480,12 @@
 }
 
 int ssl3_output_cert_chain(SSL *ssl) {
-  CBB cbb, body;
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) ||
+  ScopedCBB cbb;
+  CBB body;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE) ||
       !ssl_add_cert_chain(ssl, &body) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
+      !ssl_add_message_cbb(ssl, cbb.get())) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    CBB_cleanup(&cbb);
     return 0;
   }
 
@@ -640,19 +640,18 @@
                                2 /* cipher list length */ +
                                CBS_len(&cipher_specs) / 3 * 2 +
                                1 /* compression length */ + 1 /* compression */;
-  CBB client_hello, hello_body, cipher_suites;
-  CBB_zero(&client_hello);
+  ScopedCBB client_hello;
+  CBB hello_body, cipher_suites;
   if (!BUF_MEM_reserve(ssl->init_buf, max_v3_client_hello) ||
-      !CBB_init_fixed(&client_hello, (uint8_t *)ssl->init_buf->data,
+      !CBB_init_fixed(client_hello.get(), (uint8_t *)ssl->init_buf->data,
                       ssl->init_buf->max) ||
-      !CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
-      !CBB_add_u24_length_prefixed(&client_hello, &hello_body) ||
+      !CBB_add_u8(client_hello.get(), SSL3_MT_CLIENT_HELLO) ||
+      !CBB_add_u24_length_prefixed(client_hello.get(), &hello_body) ||
       !CBB_add_u16(&hello_body, version) ||
       !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) ||
       /* No session id. */
       !CBB_add_u8(&hello_body, 0) ||
       !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) {
-    CBB_cleanup(&client_hello);
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return -1;
   }
@@ -661,7 +660,6 @@
   while (CBS_len(&cipher_specs) > 0) {
     uint32_t cipher_spec;
     if (!CBS_get_u24(&cipher_specs, &cipher_spec)) {
-      CBB_cleanup(&client_hello);
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
       return -1;
     }
@@ -671,16 +669,15 @@
       continue;
     }
     if (!CBB_add_u16(&cipher_suites, cipher_spec)) {
-      CBB_cleanup(&client_hello);
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
       return -1;
     }
   }
 
   /* Add the null compression scheme and finish. */
-  if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) ||
-      !CBB_finish(&client_hello, NULL, &ssl->init_buf->length)) {
-    CBB_cleanup(&client_hello);
+  if (!CBB_add_u8(&hello_body, 1) ||
+      !CBB_add_u8(&hello_body, 0) ||
+      !CBB_finish(client_hello.get(), NULL, &ssl->init_buf->length)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return -1;
   }
diff --git a/ssl/ssl_asn1.cc b/ssl/ssl_asn1.cc
index d8b1bd6..371e8e8 100644
--- a/ssl/ssl_asn1.cc
+++ b/ssl/ssl_asn1.cc
@@ -200,15 +200,14 @@
 
 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) ||
+  ScopedCBB cbb;
+  CBB session, child, child2;
+  if (!CBB_init(cbb.get(), 0) ||
+      !CBB_add_asn1(cbb.get(), &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) ||
@@ -224,7 +223,7 @@
       !CBB_add_asn1(&session, &child, kTimeoutTag) ||
       !CBB_add_asn1_uint64(&child, in->timeout)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
+    return 0;
   }
 
   /* The peer certificate is only serialized if the SHA-256 isn't
@@ -235,7 +234,7 @@
         !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
                        CRYPTO_BUFFER_len(buffer))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return 0;
     }
   }
 
@@ -245,14 +244,14 @@
       !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;
+    return 0;
   }
 
   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;
+      return 0;
     }
   }
 
@@ -262,7 +261,7 @@
         !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname,
                        strlen(in->tlsext_hostname))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return 0;
     }
   }
 
@@ -272,7 +271,7 @@
         !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity,
                        strlen(in->psk_identity))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return 0;
     }
   }
 
@@ -280,7 +279,7 @@
     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;
+      return 0;
     }
   }
 
@@ -289,7 +288,7 @@
         !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;
+      return 0;
     }
   }
 
@@ -298,7 +297,7 @@
         !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;
+      return 0;
     }
   }
 
@@ -308,7 +307,7 @@
         !CBB_add_bytes(&child2, in->original_handshake_hash,
                        in->original_handshake_hash_len)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return 0;
     }
   }
 
@@ -318,7 +317,7 @@
         !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;
+      return 0;
     }
   }
 
@@ -327,7 +326,7 @@
         !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;
+      return 0;
     }
   }
 
@@ -336,7 +335,7 @@
         !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
         !CBB_add_u8(&child2, 0xff)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return 0;
     }
   }
 
@@ -344,7 +343,7 @@
       (!CBB_add_asn1(&session, &child, kGroupIDTag) ||
        !CBB_add_asn1_uint64(&child, in->group_id))) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
+    return 0;
   }
 
   /* The certificate chain is only serialized if the leaf's SHA-256 isn't
@@ -354,14 +353,14 @@
       sk_CRYPTO_BUFFER_num(in->certs) >= 2) {
     if (!CBB_add_asn1(&session, &child, kCertChainTag)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return 0;
     }
     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;
+        return 0;
       }
     }
   }
@@ -371,7 +370,7 @@
         !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;
+      return 0;
     }
   }
 
@@ -380,7 +379,7 @@
         !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
         !CBB_add_u8(&child2, 0x00)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return 0;
     }
   }
 
@@ -388,21 +387,21 @@
       (!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;
+    return 0;
   }
 
   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;
+    return 0;
   }
 
   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;
+    return 0;
   }
 
   if (in->early_alpn) {
@@ -411,19 +410,15 @@
         !CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn,
                        in->early_alpn_len)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
+      return 0;
     }
   }
 
-  if (!CBB_finish(&cbb, out_data, out_len)) {
+  if (!CBB_finish(cbb.get(), out_data, out_len)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
+    return 0;
   }
   return 1;
-
- err:
-  CBB_cleanup(&cbb);
-  return 0;
 }
 
 /* SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 305bcad..60ee322 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -287,19 +287,18 @@
     return 1;
   }
 
-  CBB cbb;
+  ScopedCBB cbb;
   uint8_t *out;
   size_t out_len;
-  if (!CBB_init(&cbb, strlen(label) + 1 + SSL3_RANDOM_SIZE * 2 + 1 +
+  if (!CBB_init(cbb.get(), strlen(label) + 1 + SSL3_RANDOM_SIZE * 2 + 1 +
                           secret_len * 2 + 1) ||
-      !CBB_add_bytes(&cbb, (const uint8_t *)label, strlen(label)) ||
-      !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
-      !cbb_add_hex(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
-      !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
-      !cbb_add_hex(&cbb, secret, secret_len) ||
-      !CBB_add_u8(&cbb, 0 /* NUL */) ||
-      !CBB_finish(&cbb, &out, &out_len)) {
-    CBB_cleanup(&cbb);
+      !CBB_add_bytes(cbb.get(), (const uint8_t *)label, strlen(label)) ||
+      !CBB_add_bytes(cbb.get(), (const uint8_t *)" ", 1) ||
+      !cbb_add_hex(cbb.get(), ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+      !CBB_add_bytes(cbb.get(), (const uint8_t *)" ", 1) ||
+      !cbb_add_hex(cbb.get(), secret, secret_len) ||
+      !CBB_add_u8(cbb.get(), 0 /* NUL */) ||
+      !CBB_finish(cbb.get(), &out, &out_len)) {
     return 0;
   }
 
diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc
index 73808eb..56a331d 100644
--- a/ssl/ssl_privkey.cc
+++ b/ssl/ssl_privkey.cc
@@ -240,23 +240,20 @@
   }
 
   *out_len = max_out;
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-  int ret = setup_ctx(ssl, &ctx, ssl->cert->privatekey, sigalg, 0 /* sign */) &&
-            EVP_DigestSign(&ctx, out, out_len, in, in_len);
-  EVP_MD_CTX_cleanup(&ctx);
-  return ret ? ssl_private_key_success : ssl_private_key_failure;
+  ScopedEVP_MD_CTX ctx;
+  if (!setup_ctx(ssl, ctx.get(), ssl->cert->privatekey, sigalg, 0 /* sign */) ||
+      !EVP_DigestSign(ctx.get(), out, out_len, in, in_len)) {
+    return ssl_private_key_failure;
+  }
+  return ssl_private_key_success;
 }
 
 int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
                           size_t signature_len, uint16_t sigalg, EVP_PKEY *pkey,
                           const uint8_t *in, size_t in_len) {
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-  int ret = setup_ctx(ssl, &ctx, pkey, sigalg, 1 /* verify */) &&
-            EVP_DigestVerify(&ctx, signature, signature_len, in, in_len);
-  EVP_MD_CTX_cleanup(&ctx);
-  return ret;
+  ScopedEVP_MD_CTX ctx;
+  return setup_ctx(ssl, ctx.get(), pkey, sigalg, 1 /* verify */) &&
+         EVP_DigestVerify(ctx.get(), signature, signature_len, in, in_len);
 }
 
 enum ssl_private_key_result_t ssl_private_key_decrypt(
diff --git a/ssl/t1_enc.cc b/ssl/t1_enc.cc
index 7d20fbf..c3c4bdd 100644
--- a/ssl/t1_enc.cc
+++ b/ssl/t1_enc.cc
@@ -165,36 +165,33 @@
                        const uint8_t *seed1, size_t seed1_len,
                        const uint8_t *seed2, size_t seed2_len,
                        const uint8_t *seed3, size_t seed3_len) {
-  HMAC_CTX ctx, ctx_tmp, ctx_init;
+  ScopedHMAC_CTX ctx, ctx_tmp, ctx_init;
   uint8_t A1[EVP_MAX_MD_SIZE];
   unsigned A1_len;
   int ret = 0;
 
   size_t chunk = EVP_MD_size(md);
 
-  HMAC_CTX_init(&ctx);
-  HMAC_CTX_init(&ctx_tmp);
-  HMAC_CTX_init(&ctx_init);
-  if (!HMAC_Init_ex(&ctx_init, secret, secret_len, md, NULL) ||
-      !HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
-      !HMAC_Update(&ctx, seed1, seed1_len) ||
-      !HMAC_Update(&ctx, seed2, seed2_len) ||
-      !HMAC_Update(&ctx, seed3, seed3_len) ||
-      !HMAC_Final(&ctx, A1, &A1_len)) {
+  if (!HMAC_Init_ex(ctx_init.get(), secret, secret_len, md, NULL) ||
+      !HMAC_CTX_copy_ex(ctx.get(), ctx_init.get()) ||
+      !HMAC_Update(ctx.get(), seed1, seed1_len) ||
+      !HMAC_Update(ctx.get(), seed2, seed2_len) ||
+      !HMAC_Update(ctx.get(), seed3, seed3_len) ||
+      !HMAC_Final(ctx.get(), A1, &A1_len)) {
     goto err;
   }
 
   for (;;) {
     unsigned len;
     uint8_t hmac[EVP_MAX_MD_SIZE];
-    if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
-        !HMAC_Update(&ctx, A1, A1_len) ||
+    if (!HMAC_CTX_copy_ex(ctx.get(), ctx_init.get()) ||
+        !HMAC_Update(ctx.get(), A1, A1_len) ||
         /* Save a copy of |ctx| to compute the next A1 value below. */
-        (out_len > chunk && !HMAC_CTX_copy_ex(&ctx_tmp, &ctx)) ||
-        !HMAC_Update(&ctx, seed1, seed1_len) ||
-        !HMAC_Update(&ctx, seed2, seed2_len) ||
-        !HMAC_Update(&ctx, seed3, seed3_len) ||
-        !HMAC_Final(&ctx, hmac, &len)) {
+        (out_len > chunk && !HMAC_CTX_copy_ex(ctx_tmp.get(), ctx.get())) ||
+        !HMAC_Update(ctx.get(), seed1, seed1_len) ||
+        !HMAC_Update(ctx.get(), seed2, seed2_len) ||
+        !HMAC_Update(ctx.get(), seed3, seed3_len) ||
+        !HMAC_Final(ctx.get(), hmac, &len)) {
       goto err;
     }
     assert(len == chunk);
@@ -215,7 +212,7 @@
     }
 
     /* Calculate the next A1 value. */
-    if (!HMAC_Final(&ctx_tmp, A1, &A1_len)) {
+    if (!HMAC_Final(ctx_tmp.get(), A1, &A1_len)) {
       goto err;
     }
   }
@@ -223,9 +220,6 @@
   ret = 1;
 
 err:
-  HMAC_CTX_cleanup(&ctx);
-  HMAC_CTX_cleanup(&ctx_tmp);
-  HMAC_CTX_cleanup(&ctx_init);
   OPENSSL_cleanse(A1, sizeof(A1));
   return ret;
 }
@@ -270,15 +264,13 @@
                     size_t secret_len, const char *label, size_t label_len,
                     const uint8_t *seed1, size_t seed1_len,
                     const uint8_t *seed2, size_t seed2_len) {
-  EVP_MD_CTX md5;
-  EVP_MD_CTX sha1;
+  ScopedEVP_MD_CTX md5;
+  ScopedEVP_MD_CTX sha1;
   uint8_t buf[16], smd[SHA_DIGEST_LENGTH];
   uint8_t c = 'A';
   size_t i, j, k;
 
   k = 0;
-  EVP_MD_CTX_init(&md5);
-  EVP_MD_CTX_init(&sha1);
   for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) {
     k++;
     if (k > sizeof(buf)) {
@@ -291,41 +283,38 @@
       buf[j] = c;
     }
     c++;
-    if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) {
+    if (!EVP_DigestInit_ex(sha1.get(), EVP_sha1(), NULL)) {
       OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
       return 0;
     }
-    EVP_DigestUpdate(&sha1, buf, k);
-    EVP_DigestUpdate(&sha1, secret, secret_len);
+    EVP_DigestUpdate(sha1.get(), buf, k);
+    EVP_DigestUpdate(sha1.get(), secret, secret_len);
     /* |label| is ignored for SSLv3. */
     if (seed1_len) {
-      EVP_DigestUpdate(&sha1, seed1, seed1_len);
+      EVP_DigestUpdate(sha1.get(), seed1, seed1_len);
     }
     if (seed2_len) {
-      EVP_DigestUpdate(&sha1, seed2, seed2_len);
+      EVP_DigestUpdate(sha1.get(), seed2, seed2_len);
     }
-    EVP_DigestFinal_ex(&sha1, smd, NULL);
+    EVP_DigestFinal_ex(sha1.get(), smd, NULL);
 
-    if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) {
+    if (!EVP_DigestInit_ex(md5.get(), EVP_md5(), NULL)) {
       OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
       return 0;
     }
-    EVP_DigestUpdate(&md5, secret, secret_len);
-    EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
+    EVP_DigestUpdate(md5.get(), secret, secret_len);
+    EVP_DigestUpdate(md5.get(), smd, SHA_DIGEST_LENGTH);
     if (i + MD5_DIGEST_LENGTH > out_len) {
-      EVP_DigestFinal_ex(&md5, smd, NULL);
+      EVP_DigestFinal_ex(md5.get(), smd, NULL);
       OPENSSL_memcpy(out, smd, out_len - i);
     } else {
-      EVP_DigestFinal_ex(&md5, out, NULL);
+      EVP_DigestFinal_ex(md5.get(), out, NULL);
     }
 
     out += MD5_DIGEST_LENGTH;
   }
 
   OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
-  EVP_MD_CTX_cleanup(&md5);
-  EVP_MD_CTX_cleanup(&sha1);
-
   return 1;
 }
 
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index 228c1c5..338f78e 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -2276,16 +2276,16 @@
   size_t secret_len;
   SSL_ECDH_CTX group;
   OPENSSL_memset(&group, 0, sizeof(SSL_ECDH_CTX));
-  CBB public_key;
-  if (!CBB_init(&public_key, 32) ||
+  ScopedCBB public_key;
+  if (!CBB_init(public_key.get(), 32) ||
       !SSL_ECDH_CTX_init(&group, group_id) ||
-      !SSL_ECDH_CTX_accept(&group, &public_key, &secret, &secret_len, out_alert,
-                           CBS_data(&peer_key), CBS_len(&peer_key)) ||
-      !CBB_finish(&public_key, &hs->ecdh_public_key,
+      !SSL_ECDH_CTX_accept(&group, public_key.get(), &secret, &secret_len,
+                           out_alert, CBS_data(&peer_key),
+                           CBS_len(&peer_key)) ||
+      !CBB_finish(public_key.get(), &hs->ecdh_public_key,
                   &hs->ecdh_public_key_len)) {
     OPENSSL_free(secret);
     SSL_ECDH_CTX_cleanup(&group);
-    CBB_cleanup(&public_key);
     *out_alert = SSL_AD_ILLEGAL_PARAMETER;
     return 0;
   }
diff --git a/ssl/tls13_both.cc b/ssl/tls13_both.cc
index 91b7f2b..634ab68 100644
--- a/ssl/tls13_both.cc
+++ b/ssl/tls13_both.cc
@@ -141,14 +141,16 @@
 int tls13_get_cert_verify_signature_input(
     SSL_HANDSHAKE *hs, 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;
+  ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
   }
 
   for (size_t i = 0; i < 64; i++) {
-    if (!CBB_add_u8(&cbb, 0x20)) {
-      goto err;
+    if (!CBB_add_u8(cbb.get(), 0x20)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      return 0;
     }
   }
 
@@ -168,28 +170,26 @@
     context = (const uint8_t *)kContext;
     context_len = sizeof(kContext);
   } else {
-    goto err;
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
   }
 
-  if (!CBB_add_bytes(&cbb, context, context_len)) {
-    goto err;
+  if (!CBB_add_bytes(cbb.get(), context, context_len)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
   }
 
   uint8_t context_hash[EVP_MAX_MD_SIZE];
   size_t context_hash_len;
   if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
                                &context_hash_len) ||
-      !CBB_add_bytes(&cbb, context_hash, context_hash_len) ||
-      !CBB_finish(&cbb, out, out_len)) {
-    goto err;
+      !CBB_add_bytes(cbb.get(), context_hash, context_hash_len) ||
+      !CBB_finish(cbb.get(), out, out_len)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
   }
 
   return 1;
-
-err:
-  OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-  CBB_cleanup(&cbb);
-  return 0;
 }
 
 int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
@@ -591,11 +591,11 @@
     return 0;
   }
 
-  CBB cbb, body;
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
+  ScopedCBB cbb;
+  CBB body;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_FINISHED) ||
       !CBB_add_bytes(&body, verify_data, verify_data_len) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
-    CBB_cleanup(&cbb);
+      !ssl_add_message_cbb(ssl, cbb.get())) {
     return 0;
   }
 
@@ -622,12 +622,12 @@
   /* Acknowledge the KeyUpdate */
   if (key_update_request == SSL_KEY_UPDATE_REQUESTED &&
       !ssl->s3->key_update_pending) {
-    CBB cbb, body;
-    if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_KEY_UPDATE) ||
+    ScopedCBB cbb;
+    CBB body;
+    if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_KEY_UPDATE) ||
         !CBB_add_u8(&body, SSL_KEY_UPDATE_NOT_REQUESTED) ||
-        !ssl_add_message_cbb(ssl, &cbb) ||
+        !ssl_add_message_cbb(ssl, cbb.get()) ||
         !tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
-      CBB_cleanup(&cbb);
       return 0;
     }
 
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc
index 5e2b03e..516dd3d 100644
--- a/ssl/tls13_client.cc
+++ b/ssl/tls13_client.cc
@@ -632,11 +632,11 @@
       return ssl_hs_channel_id_lookup;
     }
 
-    CBB cbb, body;
-    if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
+    ScopedCBB cbb;
+    CBB body;
+    if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CHANNEL_ID) ||
         !tls1_write_channel_id(hs, &body) ||
-        !ssl_add_message_cbb(ssl, &cbb)) {
-      CBB_cleanup(&cbb);
+        !ssl_add_message_cbb(ssl, cbb.get())) {
       return ssl_hs_error;
     }
   }
diff --git a/ssl/tls13_enc.cc b/ssl/tls13_enc.cc
index 8dd6765..bd15bcb 100644
--- a/ssl/tls13_enc.cc
+++ b/ssl/tls13_enc.cc
@@ -77,20 +77,20 @@
                              const uint8_t *hash, size_t hash_len, size_t len) {
   static const char kTLS13LabelVersion[] = "TLS 1.3, ";
 
-  CBB cbb, child;
+  ScopedCBB 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) ||
+  if (!CBB_init(cbb.get(), 2 + 1 + strlen(kTLS13LabelVersion) + label_len + 1 +
+                               hash_len) ||
+      !CBB_add_u16(cbb.get(), len) ||
+      !CBB_add_u8_length_prefixed(cbb.get(), &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_u8_length_prefixed(cbb.get(), &child) ||
       !CBB_add_bytes(&child, hash, hash_len) ||
-      !CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) {
-    CBB_cleanup(&cbb);
+      !CBB_finish(cbb.get(), &hkdf_label, &hkdf_label_len)) {
     return 0;
   }
 
@@ -385,21 +385,17 @@
     return 0;
   }
 
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
+  ScopedEVP_MD_CTX ctx;
   uint8_t context[EVP_MAX_MD_SIZE];
   unsigned context_len;
-  if (!EVP_DigestInit_ex(&ctx, digest, NULL) ||
-      !EVP_DigestUpdate(&ctx, hs->transcript.buffer->data,
+  if (!EVP_DigestInit_ex(ctx.get(), digest, NULL) ||
+      !EVP_DigestUpdate(ctx.get(), hs->transcript.buffer->data,
                         hs->transcript.buffer->length) ||
-      !EVP_DigestUpdate(&ctx, msg, len - hash_len - 3) ||
-      !EVP_DigestFinal_ex(&ctx, context, &context_len)) {
-    EVP_MD_CTX_cleanup(&ctx);
+      !EVP_DigestUpdate(ctx.get(), msg, len - hash_len - 3) ||
+      !EVP_DigestFinal_ex(ctx.get(), context, &context_len)) {
     return 0;
   }
 
-  EVP_MD_CTX_cleanup(&ctx);
-
   uint8_t verify_data[EVP_MAX_MD_SIZE] = {0};
   if (!tls13_psk_binder(verify_data, digest, ssl->session->master_key,
                         ssl->session->master_key_length, context, context_len,
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index a110b3a..89649a0 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -162,8 +162,6 @@
   static const int kNumTickets = 2;
 
   SSL_SESSION *session = hs->new_session;
-  CBB cbb;
-  CBB_zero(&cbb);
 
   /* Rebase the session timestamp so that it is measured from ticket
    * issuance. */
@@ -171,19 +169,20 @@
 
   for (int i = 0; i < kNumTickets; i++) {
     if (!RAND_bytes((uint8_t *)&session->ticket_age_add, 4)) {
-      goto err;
+      return 0;
     }
     session->ticket_age_add_valid = 1;
 
+    ScopedCBB cbb;
     CBB body, ticket, extensions;
-    if (!ssl->method->init_message(ssl, &cbb, &body,
+    if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                    SSL3_MT_NEW_SESSION_TICKET) ||
         !CBB_add_u32(&body, session->timeout) ||
         !CBB_add_u32(&body, session->ticket_age_add) ||
         !CBB_add_u16_length_prefixed(&body, &ticket) ||
         !ssl_encrypt_ticket(ssl, &ticket, session) ||
         !CBB_add_u16_length_prefixed(&body, &extensions)) {
-      goto err;
+      return 0;
     }
 
     if (ssl->cert->enable_early_data) {
@@ -194,7 +193,7 @@
           !CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
           !CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
           !CBB_flush(&extensions)) {
-        goto err;
+        return 0;
       }
     }
 
@@ -202,19 +201,15 @@
     if (!CBB_add_u16(&extensions,
                      ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
         !CBB_add_u16(&extensions, 0 /* empty */)) {
-      goto err;
+      return 0;
     }
 
-    if (!ssl_add_message_cbb(ssl, &cbb)) {
-      goto err;
+    if (!ssl_add_message_cbb(ssl, cbb.get())) {
+      return 0;
     }
   }
 
   return 1;
-
-err:
-  CBB_cleanup(&cbb);
-  return 0;
 }
 
 static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
@@ -483,9 +478,10 @@
 
 static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  CBB cbb, body, extensions;
+  ScopedCBB cbb;
+  CBB body, extensions;
   uint16_t group_id;
-  if (!ssl->method->init_message(ssl, &cbb, &body,
+  if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_HELLO_RETRY_REQUEST) ||
       !CBB_add_u16(&body, ssl->version) ||
       !tls1_get_shared_group(hs, &group_id) ||
@@ -493,8 +489,7 @@
       !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
       !CBB_add_u16(&extensions, 2 /* length */) ||
       !CBB_add_u16(&extensions, group_id) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
-    CBB_cleanup(&cbb);
+      !ssl_add_message_cbb(ssl, cbb.get())) {
     return ssl_hs_error;
   }
 
@@ -544,8 +539,9 @@
   }
 
   /* Send a ServerHello. */
-  CBB cbb, body, extensions, session_id;
-  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
+  ScopedCBB cbb;
+  CBB body, extensions, session_id;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
       !CBB_add_u16(&body, version) ||
       !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
       !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
@@ -559,28 +555,28 @@
       !ssl_ext_key_share_add_serverhello(hs, &extensions) ||
       (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
        !ssl_ext_supported_versions_add_serverhello(hs, &extensions)) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
-    goto err;
+      !ssl_add_message_cbb(ssl, cbb.get())) {
+    return ssl_hs_error;
   }
 
   if (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
       !ssl3_add_change_cipher_spec(ssl)) {
-    goto err;
+    return ssl_hs_error;
   }
 
   /* Derive and enable the handshake traffic secrets. */
   if (!tls13_derive_handshake_secrets(hs) ||
       !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret,
                              hs->hash_len)) {
-    goto err;
+    return ssl_hs_error;
   }
 
   /* Send EncryptedExtensions. */
-  if (!ssl->method->init_message(ssl, &cbb, &body,
+  if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                  SSL3_MT_ENCRYPTED_EXTENSIONS) ||
       !ssl_add_serverhello_tlsext(hs, &body) ||
-      !ssl_add_message_cbb(ssl, &cbb)) {
-    goto err;
+      !ssl_add_message_cbb(ssl, cbb.get())) {
+    return ssl_hs_error;
   }
 
   if (!ssl->s3->session_reused) {
@@ -596,15 +592,15 @@
   /* Send a CertificateRequest, if necessary. */
   if (hs->cert_request) {
     CBB sigalgs_cbb;
-    if (!ssl->method->init_message(ssl, &cbb, &body,
+    if (!ssl->method->init_message(ssl, cbb.get(), &body,
                                    SSL3_MT_CERTIFICATE_REQUEST) ||
         !CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
         !CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
         !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb) ||
         !ssl_add_client_CA_list(ssl, &body) ||
         !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
-        !ssl_add_message_cbb(ssl, &cbb)) {
-      goto err;
+        !ssl_add_message_cbb(ssl, cbb.get())) {
+      return ssl_hs_error;
     }
   }
 
@@ -612,11 +608,11 @@
   if (!ssl->s3->session_reused) {
     if (!ssl_has_certificate(ssl)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
-      goto err;
+      return ssl_hs_error;
     }
 
     if (!tls13_add_certificate(hs)) {
-      goto err;
+      return ssl_hs_error;
     }
 
     hs->tls13_state = state_send_server_certificate_verify;
@@ -625,10 +621,6 @@
 
   hs->tls13_state = state_send_server_finished;
   return ssl_hs_ok;
-
-err:
-  CBB_cleanup(&cbb);
-  return ssl_hs_error;
 }
 
 static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs) {