Switch a bit more of libcrypto to scopers

There was no real organization to which files I looked at here. Mostly
just bounced around. At some point we'll probably need to set up some
more infrastructure though:

- For functions to return UniquePtr, they need to stop being C linkage,
  which is something we want to do anyway.

- For types to use UniquePtr, we need to get them out of malloc/free and
  into the realm of constructors and destructors. That probably means
  moving some of the helpers from ssl/internal.h to crypto/internal.h.

- UniquePtr is not very good at buffers. We should probably move Array
  Vector, and InPlaceVector to crypto/internal.h.

Change-Id: I90ebc917051d354c0e447598f382db6b22eb8813
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/78687
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/cipher/derive_key.cc b/crypto/cipher/derive_key.cc
index d8aecdd..ac0f284 100644
--- a/crypto/cipher/derive_key.cc
+++ b/crypto/cipher/derive_key.cc
@@ -25,7 +25,6 @@
 int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
                    const uint8_t *salt, const uint8_t *data, size_t data_len,
                    unsigned count, uint8_t *key, uint8_t *iv) {
-  EVP_MD_CTX c;
   uint8_t md_buf[EVP_MAX_MD_SIZE];
   unsigned addmd = 0;
   unsigned mds = 0, i;
@@ -37,36 +36,36 @@
   assert(nkey <= EVP_MAX_KEY_LENGTH);
   assert(niv <= EVP_MAX_IV_LENGTH);
 
-  if (data == NULL) {
+  if (data == nullptr) {
     return nkey;
   }
 
-  EVP_MD_CTX_init(&c);
+  bssl::ScopedEVP_MD_CTX c;
   for (;;) {
-    if (!EVP_DigestInit_ex(&c, md, NULL)) {
+    if (!EVP_DigestInit_ex(c.get(), md, nullptr)) {
       goto err;
     }
     if (addmd++) {
-      if (!EVP_DigestUpdate(&c, md_buf, mds)) {
+      if (!EVP_DigestUpdate(c.get(), md_buf, mds)) {
         goto err;
       }
     }
-    if (!EVP_DigestUpdate(&c, data, data_len)) {
+    if (!EVP_DigestUpdate(c.get(), data, data_len)) {
       goto err;
     }
-    if (salt != NULL) {
-      if (!EVP_DigestUpdate(&c, salt, PKCS5_SALT_LEN)) {
+    if (salt != nullptr) {
+      if (!EVP_DigestUpdate(c.get(), salt, PKCS5_SALT_LEN)) {
         goto err;
       }
     }
-    if (!EVP_DigestFinal_ex(&c, md_buf, &mds)) {
+    if (!EVP_DigestFinal_ex(c.get(), md_buf, &mds)) {
       goto err;
     }
 
     for (i = 1; i < count; i++) {
-      if (!EVP_DigestInit_ex(&c, md, NULL) ||
-          !EVP_DigestUpdate(&c, md_buf, mds) ||
-          !EVP_DigestFinal_ex(&c, md_buf, &mds)) {
+      if (!EVP_DigestInit_ex(c.get(), md, nullptr) ||
+          !EVP_DigestUpdate(c.get(), md_buf, mds) ||
+          !EVP_DigestFinal_ex(c.get(), md_buf, &mds)) {
         goto err;
       }
     }
@@ -77,7 +76,7 @@
         if (nkey == 0 || i == mds) {
           break;
         }
-        if (key != NULL) {
+        if (key != nullptr) {
           *(key++) = md_buf[i];
         }
         nkey--;
@@ -90,7 +89,7 @@
         if (niv == 0 || i == mds) {
           break;
         }
-        if (iv != NULL) {
+        if (iv != nullptr) {
           *(iv++) = md_buf[i];
         }
         niv--;
@@ -104,7 +103,6 @@
   rv = EVP_CIPHER_key_length(type);
 
 err:
-  EVP_MD_CTX_cleanup(&c);
   OPENSSL_cleanse(md_buf, EVP_MAX_MD_SIZE);
   return rv;
 }
diff --git a/crypto/dh/dh_asn1.cc b/crypto/dh/dh_asn1.cc
index 13bd4fd..9295e14 100644
--- a/crypto/dh/dh_asn1.cc
+++ b/crypto/dh/dh_asn1.cc
@@ -44,41 +44,40 @@
 }
 
 DH *DH_parse_parameters(CBS *cbs) {
-  DH *ret = DH_new();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<DH> ret(DH_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
       !parse_integer(&child, &ret->p) ||
       !parse_integer(&child, &ret->g)) {
-    goto err;
+    OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+    return nullptr;
   }
 
   uint64_t priv_length;
   if (CBS_len(&child) != 0) {
     if (!CBS_get_asn1_uint64(&child, &priv_length) ||
         priv_length > UINT_MAX) {
-      goto err;
+      OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+      return nullptr;
     }
     ret->priv_length = (unsigned)priv_length;
   }
 
   if (CBS_len(&child) != 0) {
-    goto err;
+    OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+    return nullptr;
   }
 
-  if (!dh_check_params_fast(ret)) {
-    goto err;
+  if (!dh_check_params_fast(ret.get())) {
+    OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
-  DH_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int DH_marshal_parameters(CBB *cbb, const DH *dh) {
diff --git a/crypto/dsa/dsa.cc b/crypto/dsa/dsa.cc
index d372c7c..e2125d5 100644
--- a/crypto/dsa/dsa.cc
+++ b/crypto/dsa/dsa.cc
@@ -425,17 +425,17 @@
     return 0;
   }
 
-  int ok = 0;
-  BIGNUM *pub_key = NULL, *priv_key = NULL;
-  BN_CTX *ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
+    return 0;
   }
 
-  priv_key = dsa->priv_key;
-  if (priv_key == NULL) {
+  int ok = 0;
+  BIGNUM *pub_key = nullptr;
+  BIGNUM *priv_key = dsa->priv_key;
+  if (priv_key == nullptr) {
     priv_key = BN_new();
-    if (priv_key == NULL) {
+    if (priv_key == nullptr) {
       goto err;
     }
   }
@@ -445,16 +445,16 @@
   }
 
   pub_key = dsa->pub_key;
-  if (pub_key == NULL) {
+  if (pub_key == nullptr) {
     pub_key = BN_new();
-    if (pub_key == NULL) {
+    if (pub_key == nullptr) {
       goto err;
     }
   }
 
   if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, &dsa->method_mont_lock,
-                              dsa->p, ctx) ||
-      !BN_mod_exp_mont_consttime(pub_key, dsa->g, priv_key, dsa->p, ctx,
+                              dsa->p, ctx.get()) ||
+      !BN_mod_exp_mont_consttime(pub_key, dsa->g, priv_key, dsa->p, ctx.get(),
                                  dsa->method_mont_p)) {
     goto err;
   }
@@ -467,13 +467,12 @@
   ok = 1;
 
 err:
-  if (dsa->pub_key == NULL) {
+  if (dsa->pub_key == nullptr) {
     BN_free(pub_key);
   }
-  if (dsa->priv_key == NULL) {
+  if (dsa->priv_key == nullptr) {
     BN_free(priv_key);
   }
-  BN_CTX_free(ctx);
 
   return ok;
 }
@@ -915,31 +914,28 @@
 }
 
 DH *DSA_dup_DH(const DSA *dsa) {
-  if (dsa == NULL) {
-    return NULL;
+  if (dsa == nullptr) {
+    return nullptr;
   }
 
-  DH *ret = DH_new();
-  if (ret == NULL) {
-    goto err;
+  bssl::UniquePtr<DH> ret(DH_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
-  if (dsa->q != NULL) {
+  if (dsa->q != nullptr) {
     ret->priv_length = BN_num_bits(dsa->q);
-    if ((ret->q = BN_dup(dsa->q)) == NULL) {
-      goto err;
+    if ((ret->q = BN_dup(dsa->q)) == nullptr) {
+      return nullptr;
     }
   }
-  if ((dsa->p != NULL && (ret->p = BN_dup(dsa->p)) == NULL) ||
-      (dsa->g != NULL && (ret->g = BN_dup(dsa->g)) == NULL) ||
-      (dsa->pub_key != NULL && (ret->pub_key = BN_dup(dsa->pub_key)) == NULL) ||
-      (dsa->priv_key != NULL &&
-       (ret->priv_key = BN_dup(dsa->priv_key)) == NULL)) {
-    goto err;
+  if ((dsa->p != nullptr && (ret->p = BN_dup(dsa->p)) == nullptr) ||
+      (dsa->g != nullptr && (ret->g = BN_dup(dsa->g)) == nullptr) ||
+      (dsa->pub_key != nullptr &&
+       (ret->pub_key = BN_dup(dsa->pub_key)) == nullptr) ||
+      (dsa->priv_key != nullptr &&
+       (ret->priv_key = BN_dup(dsa->priv_key)) == nullptr)) {
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  DH_free(ret);
-  return NULL;
+  return ret.release();
 }
diff --git a/crypto/dsa/dsa_asn1.cc b/crypto/dsa/dsa_asn1.cc
index a267473..af5ccad 100644
--- a/crypto/dsa/dsa_asn1.cc
+++ b/crypto/dsa/dsa_asn1.cc
@@ -136,9 +136,9 @@
 }
 
 DSA *DSA_parse_public_key(CBS *cbs) {
-  DSA *ret = DSA_new();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<DSA> ret(DSA_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
@@ -148,16 +148,12 @@
       !parse_integer(&child, &ret->g) ||
       CBS_len(&child) != 0) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
-  if (!dsa_check_key(ret)) {
-    goto err;
+  if (!dsa_check_key(ret.get())) {
+    return nullptr;
   }
-  return ret;
-
-err:
-  DSA_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) {
@@ -175,9 +171,9 @@
 }
 
 DSA *DSA_parse_parameters(CBS *cbs) {
-  DSA *ret = DSA_new();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<DSA> ret(DSA_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
@@ -186,16 +182,12 @@
       !parse_integer(&child, &ret->g) ||
       CBS_len(&child) != 0) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
-  if (!dsa_check_key(ret)) {
-    goto err;
+  if (!dsa_check_key(ret.get())) {
+    return nullptr;
   }
-  return ret;
-
-err:
-  DSA_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) {
@@ -212,9 +204,9 @@
 }
 
 DSA *DSA_parse_private_key(CBS *cbs) {
-  DSA *ret = DSA_new();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<DSA> ret(DSA_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
   CBS child;
@@ -222,12 +214,12 @@
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
       !CBS_get_asn1_uint64(&child, &version)) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
 
   if (version != 0) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION);
-    goto err;
+    return nullptr;
   }
 
   if (!parse_integer(&child, &ret->p) ||
@@ -237,17 +229,13 @@
       !parse_integer(&child, &ret->priv_key) ||
       CBS_len(&child) != 0) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
-  if (!dsa_check_key(ret)) {
-    goto err;
+  if (!dsa_check_key(ret.get())) {
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  DSA_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) {
diff --git a/crypto/ec/ec_asn1.cc b/crypto/ec/ec_asn1.cc
index 19d6072..c5ced25 100644
--- a/crypto/ec/ec_asn1.cc
+++ b/crypto/ec/ec_asn1.cc
@@ -51,12 +51,10 @@
       version != 1 ||
       !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) {
     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-    return NULL;
+    return nullptr;
   }
 
   // Parse the optional parameters field.
-  EC_KEY *ret = NULL;
-  BIGNUM *priv_key = NULL;
   if (CBS_peek_asn1_tag(&ec_private_key, kParametersTag)) {
     // Per SEC 1, as an alternative to omitting it, one is allowed to specify
     // this field and put in a NULL to mean inheriting this value. This was
@@ -65,43 +63,44 @@
     CBS child;
     if (!CBS_get_asn1(&ec_private_key, &child, kParametersTag)) {
       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-      goto err;
+      return nullptr;
     }
     const EC_GROUP *inner_group = EC_KEY_parse_parameters(&child);
-    if (inner_group == NULL) {
-      goto err;
+    if (inner_group == nullptr) {
+      return nullptr;
     }
-    if (group == NULL) {
+    if (group == nullptr) {
       group = inner_group;
-    } else if (EC_GROUP_cmp(group, inner_group, NULL) != 0) {
+    } else if (EC_GROUP_cmp(group, inner_group, nullptr) != 0) {
       // If a group was supplied externally, it must match.
       OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
-      goto err;
+      return nullptr;
     }
     if (CBS_len(&child) != 0) {
       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-      goto err;
+      return nullptr;
     }
   }
 
-  if (group == NULL) {
+  if (group == nullptr) {
     OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
-    goto err;
+    return nullptr;
   }
 
-  ret = EC_KEY_new();
-  if (ret == NULL || !EC_KEY_set_group(ret, group)) {
-    goto err;
+  bssl::UniquePtr<EC_KEY> ret(EC_KEY_new());
+  if (ret == nullptr || !EC_KEY_set_group(ret.get(), group)) {
+    return nullptr;
   }
 
   // Although RFC 5915 specifies the length of the key, OpenSSL historically
   // got this wrong, so accept any length. See upstream's
   // 30cd4ff294252c4b6a4b69cbef6a5b4117705d22.
-  priv_key = BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL);
+  bssl::UniquePtr<BIGNUM> priv_key(
+      BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), nullptr));
   ret->pub_key = EC_POINT_new(group);
-  if (priv_key == NULL || ret->pub_key == NULL ||
-      !EC_KEY_set_private_key(ret, priv_key)) {
-    goto err;
+  if (priv_key == nullptr || ret->pub_key == nullptr ||
+      !EC_KEY_set_private_key(ret.get(), priv_key.get())) {
+    return nullptr;
   }
 
   if (CBS_peek_asn1_tag(&ec_private_key, kPublicKeyTag)) {
@@ -117,10 +116,10 @@
         // form later.
         CBS_len(&public_key) == 0 ||
         !EC_POINT_oct2point(group, ret->pub_key, CBS_data(&public_key),
-                            CBS_len(&public_key), NULL) ||
+                            CBS_len(&public_key), nullptr) ||
         CBS_len(&child) != 0) {
       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-      goto err;
+      return nullptr;
     }
 
     // Save the point conversion form.
@@ -131,7 +130,7 @@
     // Compute the public key instead.
     if (!ec_point_mul_scalar_base(group, &ret->pub_key->raw,
                                   &ret->priv_key->scalar)) {
-      goto err;
+      return nullptr;
     }
     // Remember the original private-key-only encoding.
     // TODO(davidben): Consider removing this.
@@ -140,21 +139,15 @@
 
   if (CBS_len(&ec_private_key) != 0) {
     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
 
   // Ensure the resulting key is valid.
-  if (!EC_KEY_check_key(ret)) {
-    goto err;
+  if (!EC_KEY_check_key(ret.get())) {
+    return nullptr;
   }
 
-  BN_free(priv_key);
-  return ret;
-
-err:
-  EC_KEY_free(ret);
-  BN_free(priv_key);
-  return NULL;
+  return ret.release();
 }
 
 int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
@@ -344,14 +337,17 @@
   // TODO(davidben): Remove support for this.
   struct explicit_prime_curve curve;
   if (!parse_explicit_prime_curve(cbs, &curve)) {
-    return NULL;
+    return nullptr;
   }
 
-  const EC_GROUP *ret = NULL;
-  BIGNUM *p = BN_new(), *a = BN_new(), *b = BN_new(), *x = BN_new(),
-         *y = BN_new();
-  if (p == NULL || a == NULL || b == NULL || x == NULL || y == NULL) {
-    goto err;
+  bssl::UniquePtr<BIGNUM> p(BN_new());
+  bssl::UniquePtr<BIGNUM> a(BN_new());
+  bssl::UniquePtr<BIGNUM> b(BN_new());
+  bssl::UniquePtr<BIGNUM> x(BN_new());
+  bssl::UniquePtr<BIGNUM> y(BN_new());
+  if (p == nullptr || a == nullptr || b == nullptr || x == nullptr ||
+      y == nullptr) {
+    return nullptr;
   }
 
   for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kAllGroups); i++) {
@@ -362,36 +358,27 @@
 
     // The order alone uniquely identifies the group, but we check the other
     // parameters to avoid misinterpreting the group.
-    if (!EC_GROUP_get_curve_GFp(group, p, a, b, NULL)) {
-      goto err;
+    if (!EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr)) {
+      return nullptr;
     }
-    if (!integers_equal(&curve.prime, p) || !integers_equal(&curve.a, a) ||
-        !integers_equal(&curve.b, b)) {
+    if (!integers_equal(&curve.prime, p.get()) ||
+        !integers_equal(&curve.a, a.get()) ||
+        !integers_equal(&curve.b, b.get())) {
       break;
     }
     if (!EC_POINT_get_affine_coordinates_GFp(
-            group, EC_GROUP_get0_generator(group), x, y, NULL)) {
-      goto err;
+            group, EC_GROUP_get0_generator(group), x.get(), y.get(), nullptr)) {
+      return nullptr;
     }
-    if (!integers_equal(&curve.base_x, x) ||
-        !integers_equal(&curve.base_y, y)) {
+    if (!integers_equal(&curve.base_x, x.get()) ||
+        !integers_equal(&curve.base_y, y.get())) {
       break;
     }
-    ret = group;
-    break;
+    return const_cast<EC_GROUP *>(group);
   }
 
-  if (ret == NULL) {
-    OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
-  }
-
-err:
-  BN_free(p);
-  BN_free(a);
-  BN_free(b);
-  BN_free(x);
-  BN_free(y);
-  return (EC_GROUP *)ret;
+  OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+  return nullptr;
 }
 
 int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point,
diff --git a/crypto/ec/hash_to_curve.cc b/crypto/ec/hash_to_curve.cc
index 86c2fc6..b9601fc 100644
--- a/crypto/ec/hash_to_curve.cc
+++ b/crypto/ec/hash_to_curve.cc
@@ -57,84 +57,76 @@
     return 0;
   }
 
-  int ret = 0;
   const size_t block_size = EVP_MD_block_size(md);
   const size_t md_size = EVP_MD_size(md);
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
+  bssl::ScopedEVP_MD_CTX ctx;
 
-  {
-    // Long DSTs are hashed down to size. See section 5.3.3.
-    static_assert(EVP_MAX_MD_SIZE < 256, "hashed DST still too large");
-    uint8_t dst_buf[EVP_MAX_MD_SIZE];
-    if (dst_len >= 256) {
-      static const char kPrefix[] = "H2C-OVERSIZE-DST-";
-      if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
-          !EVP_DigestUpdate(&ctx, kPrefix, sizeof(kPrefix) - 1) ||
-          !EVP_DigestUpdate(&ctx, dst, dst_len) ||
-          !EVP_DigestFinal_ex(&ctx, dst_buf, NULL)) {
-        goto err;
-      }
-      dst = dst_buf;
-      dst_len = md_size;
+  // Long DSTs are hashed down to size. See section 5.3.3.
+  static_assert(EVP_MAX_MD_SIZE < 256, "hashed DST still too large");
+  uint8_t dst_buf[EVP_MAX_MD_SIZE];
+  if (dst_len >= 256) {
+    static const char kPrefix[] = "H2C-OVERSIZE-DST-";
+    if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) ||
+        !EVP_DigestUpdate(ctx.get(), kPrefix, sizeof(kPrefix) - 1) ||
+        !EVP_DigestUpdate(ctx.get(), dst, dst_len) ||
+        !EVP_DigestFinal_ex(ctx.get(), dst_buf, nullptr)) {
+      return 0;
     }
-    uint8_t dst_len_u8 = (uint8_t)dst_len;
+    dst = dst_buf;
+    dst_len = md_size;
+  }
+  uint8_t dst_len_u8 = (uint8_t)dst_len;
 
-    // Compute b_0.
-    static const uint8_t kZeros[EVP_MAX_MD_BLOCK_SIZE] = {0};
-    // If |out_len| exceeds 16 bits then |i| will wrap below causing an error to
-    // be returned. This depends on the static assert above.
-    uint8_t l_i_b_str_zero[3] = {static_cast<uint8_t>(out_len >> 8),
-                                 static_cast<uint8_t>(out_len), 0};
-    uint8_t b_0[EVP_MAX_MD_SIZE];
-    if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
-        !EVP_DigestUpdate(&ctx, kZeros, block_size) ||
-        !EVP_DigestUpdate(&ctx, msg, msg_len) ||
-        !EVP_DigestUpdate(&ctx, l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
-        !EVP_DigestUpdate(&ctx, dst, dst_len) ||
-        !EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
-        !EVP_DigestFinal_ex(&ctx, b_0, NULL)) {
-      goto err;
-    }
-
-    uint8_t b_i[EVP_MAX_MD_SIZE];
-    uint8_t i = 1;
-    while (out_len > 0) {
-      if (i == 0) {
-        // Input was too large.
-        OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
-        goto err;
-      }
-      if (i > 1) {
-        for (size_t j = 0; j < md_size; j++) {
-          b_i[j] ^= b_0[j];
-        }
-      } else {
-        OPENSSL_memcpy(b_i, b_0, md_size);
-      }
-
-      if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
-          !EVP_DigestUpdate(&ctx, b_i, md_size) ||
-          !EVP_DigestUpdate(&ctx, &i, 1) ||
-          !EVP_DigestUpdate(&ctx, dst, dst_len) ||
-          !EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
-          !EVP_DigestFinal_ex(&ctx, b_i, NULL)) {
-        goto err;
-      }
-
-      size_t todo = out_len >= md_size ? md_size : out_len;
-      OPENSSL_memcpy(out, b_i, todo);
-      out += todo;
-      out_len -= todo;
-      i++;
-    }
-
-    ret = 1;
+  // Compute b_0.
+  static const uint8_t kZeros[EVP_MAX_MD_BLOCK_SIZE] = {0};
+  // If |out_len| exceeds 16 bits then |i| will wrap below causing an error to
+  // be returned. This depends on the static assert above.
+  uint8_t l_i_b_str_zero[3] = {static_cast<uint8_t>(out_len >> 8),
+                               static_cast<uint8_t>(out_len), 0};
+  uint8_t b_0[EVP_MAX_MD_SIZE];
+  if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) ||
+      !EVP_DigestUpdate(ctx.get(), kZeros, block_size) ||
+      !EVP_DigestUpdate(ctx.get(), msg, msg_len) ||
+      !EVP_DigestUpdate(ctx.get(), l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
+      !EVP_DigestUpdate(ctx.get(), dst, dst_len) ||
+      !EVP_DigestUpdate(ctx.get(), &dst_len_u8, 1) ||
+      !EVP_DigestFinal_ex(ctx.get(), b_0, nullptr)) {
+    return 0;
   }
 
-err:
-  EVP_MD_CTX_cleanup(&ctx);
-  return ret;
+  uint8_t b_i[EVP_MAX_MD_SIZE];
+  uint8_t i = 1;
+  while (out_len > 0) {
+    if (i == 0) {
+      // Input was too large.
+      OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
+      return 0;
+    }
+    if (i > 1) {
+      for (size_t j = 0; j < md_size; j++) {
+        b_i[j] ^= b_0[j];
+      }
+    } else {
+      OPENSSL_memcpy(b_i, b_0, md_size);
+    }
+
+    if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) ||
+        !EVP_DigestUpdate(ctx.get(), b_i, md_size) ||
+        !EVP_DigestUpdate(ctx.get(), &i, 1) ||
+        !EVP_DigestUpdate(ctx.get(), dst, dst_len) ||
+        !EVP_DigestUpdate(ctx.get(), &dst_len_u8, 1) ||
+        !EVP_DigestFinal_ex(ctx.get(), b_i, nullptr)) {
+      return 0;
+    }
+
+    size_t todo = out_len >= md_size ? md_size : out_len;
+    OPENSSL_memcpy(out, b_i, todo);
+    out += todo;
+    out_len -= todo;
+    i++;
+  }
+
+  return 1;
 }
 
 // num_bytes_to_derive determines the number of bytes to derive when hashing to
diff --git a/crypto/ecdsa/ecdsa_asn1.cc b/crypto/ecdsa/ecdsa_asn1.cc
index 1d86a44..28d5036 100644
--- a/crypto/ecdsa/ecdsa_asn1.cc
+++ b/crypto/ecdsa/ecdsa_asn1.cc
@@ -88,25 +88,20 @@
 
   // TODO(davidben): We can actually do better and go straight from the DER
   // format to the fixed-width format without a malloc.
-  ECDSA_SIG *s = ecdsa_sig_from_fixed(eckey, fixed, fixed_len);
-  if (s == NULL) {
+  bssl::UniquePtr<ECDSA_SIG> s(ecdsa_sig_from_fixed(eckey, fixed, fixed_len));
+  if (s == nullptr) {
     return 0;
   }
 
-  int ret = 0;
   CBB cbb;
   CBB_init_fixed(&cbb, sig, ECDSA_size(eckey));
   size_t len;
-  if (!ECDSA_SIG_marshal(&cbb, s) || !CBB_finish(&cbb, NULL, &len)) {
+  if (!ECDSA_SIG_marshal(&cbb, s.get()) || !CBB_finish(&cbb, nullptr, &len)) {
     OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
-    goto err;
+    return 0;
   }
-  *out_sig_len = (unsigned)len;
-  ret = 1;
-
-err:
-  ECDSA_SIG_free(s);
-  return ret;
+  *out_sig_len = static_cast<unsigned>(len);
+  return 1;
 }
 
 int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
@@ -116,15 +111,15 @@
   // TODO(davidben): We can actually do better and go straight from the DER
   // format to the fixed-width format without a malloc.
   int ret = 0;
-  uint8_t *der = NULL;
-  ECDSA_SIG *s = ECDSA_SIG_from_bytes(sig, sig_len);
-  if (s == NULL) {
+  uint8_t *der = nullptr;
+  bssl::UniquePtr<ECDSA_SIG> s(ECDSA_SIG_from_bytes(sig, sig_len));
+  if (s == nullptr) {
     goto err;
   }
 
   // Defend against potential laxness in the DER parser.
   size_t der_len;
-  if (!ECDSA_SIG_to_bytes(&der, &der_len, s) || der_len != sig_len ||
+  if (!ECDSA_SIG_to_bytes(&der, &der_len, s.get()) || der_len != sig_len ||
       OPENSSL_memcmp(sig, der, sig_len) != 0) {
     // This should never happen. crypto/bytestring is strictly DER.
     OPENSSL_PUT_ERROR(ECDSA, ERR_R_INTERNAL_ERROR);
@@ -133,12 +128,11 @@
 
   uint8_t fixed[ECDSA_MAX_FIXED_LEN];
   size_t fixed_len;
-  ret = ecdsa_sig_to_fixed(eckey, fixed, &fixed_len, sizeof(fixed), s) &&
+  ret = ecdsa_sig_to_fixed(eckey, fixed, &fixed_len, sizeof(fixed), s.get()) &&
         ecdsa_verify_fixed(digest, digest_len, fixed, fixed_len, eckey);
 
 err:
   OPENSSL_free(der);
-  ECDSA_SIG_free(s);
   return ret;
 }
 
diff --git a/crypto/evp/evp_asn1.cc b/crypto/evp/evp_asn1.cc
index eeea963..d77a3d2 100644
--- a/crypto/evp/evp_asn1.cc
+++ b/crypto/evp/evp_asn1.cc
@@ -435,25 +435,24 @@
 
 EC_KEY *d2i_EC_PUBKEY(EC_KEY **out, const uint8_t **inp, long len) {
   if (len < 0) {
-    return NULL;
+    return nullptr;
   }
   CBS cbs;
   CBS_init(&cbs, *inp, (size_t)len);
-  EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
-  if (pkey == NULL) {
-    return NULL;
+  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
+  if (pkey == nullptr) {
+    return nullptr;
   }
-  EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(pkey);
-  EVP_PKEY_free(pkey);
-  if (ec_key == NULL) {
-    return NULL;
+  bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
+  if (ec_key == nullptr) {
+    return nullptr;
   }
-  if (out != NULL) {
+  if (out != nullptr) {
     EC_KEY_free(*out);
-    *out = ec_key;
+    *out = ec_key.get();
   }
   *inp = CBS_data(&cbs);
-  return ec_key;
+  return ec_key.release();
 }
 
 int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp) {
diff --git a/crypto/evp/evp_ctx.cc b/crypto/evp/evp_ctx.cc
index e34dfa0..9a5f97e 100644
--- a/crypto/evp/evp_ctx.cc
+++ b/crypto/evp/evp_ctx.cc
@@ -108,37 +108,36 @@
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx) {
   if (!ctx->pmeth || !ctx->pmeth->copy) {
-    return NULL;
+    return nullptr;
   }
 
-  EVP_PKEY_CTX *ret =
-      reinterpret_cast<EVP_PKEY_CTX *>(OPENSSL_zalloc(sizeof(EVP_PKEY_CTX)));
+  bssl::UniquePtr<EVP_PKEY_CTX> ret(
+      reinterpret_cast<EVP_PKEY_CTX *>(OPENSSL_zalloc(sizeof(EVP_PKEY_CTX))));
   if (!ret) {
-    return NULL;
+    return nullptr;
   }
 
   ret->pmeth = ctx->pmeth;
   ret->engine = ctx->engine;
   ret->operation = ctx->operation;
 
-  if (ctx->pkey != NULL) {
+  if (ctx->pkey != nullptr) {
     EVP_PKEY_up_ref(ctx->pkey);
     ret->pkey = ctx->pkey;
   }
 
-  if (ctx->peerkey != NULL) {
+  if (ctx->peerkey != nullptr) {
     EVP_PKEY_up_ref(ctx->peerkey);
     ret->peerkey = ctx->peerkey;
   }
 
-  if (ctx->pmeth->copy(ret, ctx) <= 0) {
-    ret->pmeth = NULL;
-    EVP_PKEY_CTX_free(ret);
+  if (ctx->pmeth->copy(ret.get(), ctx) <= 0) {
+    ret->pmeth = nullptr;
     OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
-    return NULL;
+    return nullptr;
   }
 
-  return ret;
+  return ret.release();
 }
 
 EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; }
diff --git a/crypto/evp/sign.cc b/crypto/evp/sign.cc
index 2a7836f..e14acc4 100644
--- a/crypto/evp/sign.cc
+++ b/crypto/evp/sign.cc
@@ -36,39 +36,30 @@
 
 int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig, unsigned *out_sig_len,
                   EVP_PKEY *pkey) {
-  uint8_t m[EVP_MAX_MD_SIZE];
-  unsigned m_len;
-  int ret = 0;
-  EVP_MD_CTX tmp_ctx;
-  EVP_PKEY_CTX *pkctx = NULL;
-  size_t sig_len = EVP_PKEY_size(pkey);
-
   // Ensure the final result will fit in |unsigned|.
+  size_t sig_len = EVP_PKEY_size(pkey);
   if (sig_len > UINT_MAX) {
     sig_len = UINT_MAX;
   }
 
   *out_sig_len = 0;
-  EVP_MD_CTX_init(&tmp_ctx);
-  if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
-      !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
-    goto out;
+  uint8_t m[EVP_MAX_MD_SIZE];
+  unsigned m_len;
+  bssl::ScopedEVP_MD_CTX tmp_ctx;
+  if (!EVP_MD_CTX_copy_ex(tmp_ctx.get(), ctx) ||
+      !EVP_DigestFinal_ex(tmp_ctx.get(), m, &m_len)) {
+    return 0;
   }
-  EVP_MD_CTX_cleanup(&tmp_ctx);
 
-  pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+  bssl::UniquePtr<EVP_PKEY_CTX> pkctx(EVP_PKEY_CTX_new(pkey, nullptr));
   if (!pkctx ||  //
-      !EVP_PKEY_sign_init(pkctx) ||
-      !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) ||
-      !EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len)) {
-    goto out;
+      !EVP_PKEY_sign_init(pkctx.get()) ||
+      !EVP_PKEY_CTX_set_signature_md(pkctx.get(), ctx->digest) ||
+      !EVP_PKEY_sign(pkctx.get(), sig, &sig_len, m, m_len)) {
+    return 0;
   }
-  *out_sig_len = (unsigned)sig_len;
-  ret = 1;
-
-out:
-  EVP_PKEY_CTX_free(pkctx);
-  return ret;
+  *out_sig_len = static_cast<unsigned>(sig_len);
+  return 1;
 }
 
 int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) {
@@ -87,28 +78,18 @@
                     EVP_PKEY *pkey) {
   uint8_t m[EVP_MAX_MD_SIZE];
   unsigned m_len;
-  int ret = 0;
-  EVP_MD_CTX tmp_ctx;
-  EVP_PKEY_CTX *pkctx = NULL;
-
-  EVP_MD_CTX_init(&tmp_ctx);
-  if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
-      !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
-    EVP_MD_CTX_cleanup(&tmp_ctx);
-    goto out;
+  bssl::ScopedEVP_MD_CTX tmp_ctx;
+  if (!EVP_MD_CTX_copy_ex(tmp_ctx.get(), ctx) ||
+      !EVP_DigestFinal_ex(tmp_ctx.get(), m, &m_len)) {
+    return 0;
   }
-  EVP_MD_CTX_cleanup(&tmp_ctx);
 
-  pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+  bssl::UniquePtr<EVP_PKEY_CTX> pkctx(EVP_PKEY_CTX_new(pkey, nullptr));
   if (!pkctx ||
-      !EVP_PKEY_verify_init(pkctx) ||
-      !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest)) {
-    goto out;
+      !EVP_PKEY_verify_init(pkctx.get()) ||
+      !EVP_PKEY_CTX_set_signature_md(pkctx.get(), ctx->digest)) {
+    return 0;
   }
-  ret = EVP_PKEY_verify(pkctx, sig, sig_len, m, m_len);
-
-out:
-  EVP_PKEY_CTX_free(pkctx);
-  return ret;
+  return EVP_PKEY_verify(pkctx.get(), sig, sig_len, m, m_len);
 }
 
diff --git a/crypto/fipsmodule/digest/digest.cc.inc b/crypto/fipsmodule/digest/digest.cc.inc
index dc22ad4..2edef42 100644
--- a/crypto/fipsmodule/digest/digest.cc.inc
+++ b/crypto/fipsmodule/digest/digest.cc.inc
@@ -212,16 +212,10 @@
 
 int EVP_Digest(const void *data, size_t count, uint8_t *out_md,
                unsigned int *out_size, const EVP_MD *type, ENGINE *impl) {
-  EVP_MD_CTX ctx;
-  int ret;
-
-  EVP_MD_CTX_init(&ctx);
-  ret = EVP_DigestInit_ex(&ctx, type, impl) &&
-        EVP_DigestUpdate(&ctx, data, count) &&
-        EVP_DigestFinal_ex(&ctx, out_md, out_size);
-  EVP_MD_CTX_cleanup(&ctx);
-
-  return ret;
+  bssl::ScopedEVP_MD_CTX ctx;
+  return EVP_DigestInit_ex(ctx.get(), type, impl) &&
+         EVP_DigestUpdate(ctx.get(), data, count) &&
+         EVP_DigestFinal_ex(ctx.get(), out_md, out_size);
 }
 
 const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx) {
diff --git a/crypto/fipsmodule/rsa/padding.cc.inc b/crypto/fipsmodule/rsa/padding.cc.inc
index b671382..d86627f 100644
--- a/crypto/fipsmodule/rsa/padding.cc.inc
+++ b/crypto/fipsmodule/rsa/padding.cc.inc
@@ -121,8 +121,7 @@
 int PKCS1_MGF1(uint8_t *out, size_t len, const uint8_t *seed, size_t seed_len,
                const EVP_MD *md) {
   int ret = 0;
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
+  bssl::ScopedEVP_MD_CTX ctx;
   FIPS_service_indicator_lock_state();
 
   size_t md_len = EVP_MD_size(md);
@@ -133,21 +132,21 @@
     counter[1] = (uint8_t)(i >> 16);
     counter[2] = (uint8_t)(i >> 8);
     counter[3] = (uint8_t)i;
-    if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
-        !EVP_DigestUpdate(&ctx, seed, seed_len) ||
-        !EVP_DigestUpdate(&ctx, counter, sizeof(counter))) {
+    if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) ||
+        !EVP_DigestUpdate(ctx.get(), seed, seed_len) ||
+        !EVP_DigestUpdate(ctx.get(), counter, sizeof(counter))) {
       goto err;
     }
 
     if (md_len <= len) {
-      if (!EVP_DigestFinal_ex(&ctx, out, NULL)) {
+      if (!EVP_DigestFinal_ex(ctx.get(), out, nullptr)) {
         goto err;
       }
       out += md_len;
       len -= md_len;
     } else {
       uint8_t digest[EVP_MAX_MD_SIZE];
-      if (!EVP_DigestFinal_ex(&ctx, digest, NULL)) {
+      if (!EVP_DigestFinal_ex(ctx.get(), digest, nullptr)) {
         goto err;
       }
       OPENSSL_memcpy(out, digest, len);
@@ -158,7 +157,6 @@
   ret = 1;
 
 err:
-  EVP_MD_CTX_cleanup(&ctx);
   FIPS_service_indicator_unlock_state();
   return ret;
 }
@@ -175,8 +173,7 @@
   int ret = 0;
   uint8_t *DB = NULL;
   const uint8_t *H;
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
+  bssl::ScopedEVP_MD_CTX ctx;
   unsigned MSBits;
   size_t emLen, maskedDBLen, salt_start;
   FIPS_service_indicator_lock_state();
@@ -247,11 +244,11 @@
     goto err;
   }
   uint8_t H_[EVP_MAX_MD_SIZE];
-  if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
-      !EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) ||
-      !EVP_DigestUpdate(&ctx, mHash, hLen) ||
-      !EVP_DigestUpdate(&ctx, DB + salt_start, maskedDBLen - salt_start) ||
-      !EVP_DigestFinal_ex(&ctx, H_, NULL)) {
+  if (!EVP_DigestInit_ex(ctx.get(), Hash, NULL) ||
+      !EVP_DigestUpdate(ctx.get(), kPSSZeroes, sizeof(kPSSZeroes)) ||
+      !EVP_DigestUpdate(ctx.get(), mHash, hLen) ||
+      !EVP_DigestUpdate(ctx.get(), DB + salt_start, maskedDBLen - salt_start) ||
+      !EVP_DigestFinal_ex(ctx.get(), H_, NULL)) {
     goto err;
   }
   if (OPENSSL_memcmp(H_, H, hLen) != 0) {
@@ -263,7 +260,6 @@
 
 err:
   OPENSSL_free(DB);
-  EVP_MD_CTX_cleanup(&ctx);
   FIPS_service_indicator_unlock_state();
   return ret;
 }
@@ -272,7 +268,8 @@
                                    const unsigned char *mHash,
                                    const EVP_MD *Hash, const EVP_MD *mgf1Hash,
                                    int sLenRequested) {
-  int ret = 0, digest_ok;
+  int ret = 0;
+  bssl::ScopedEVP_MD_CTX ctx;
   size_t maskedDBLen, MSBits, emLen;
   size_t hLen;
   unsigned char *H, *salt = NULL, *p;
@@ -333,15 +330,11 @@
   maskedDBLen = emLen - hLen - 1;
   H = EM + maskedDBLen;
 
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-  digest_ok = EVP_DigestInit_ex(&ctx, Hash, NULL) &&
-              EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) &&
-              EVP_DigestUpdate(&ctx, mHash, hLen) &&
-              EVP_DigestUpdate(&ctx, salt, sLen) &&
-              EVP_DigestFinal_ex(&ctx, H, NULL);
-  EVP_MD_CTX_cleanup(&ctx);
-  if (!digest_ok) {
+  if (!EVP_DigestInit_ex(ctx.get(), Hash, NULL) ||
+      !EVP_DigestUpdate(ctx.get(), kPSSZeroes, sizeof(kPSSZeroes)) ||
+      !EVP_DigestUpdate(ctx.get(), mHash, hLen) ||
+      !EVP_DigestUpdate(ctx.get(), salt, sLen) ||
+      !EVP_DigestFinal_ex(ctx.get(), H, NULL)) {
     goto err;
   }
 
diff --git a/crypto/fipsmodule/self_check/self_check.cc.inc b/crypto/fipsmodule/self_check/self_check.cc.inc
index 4fd3963..b64c64b 100644
--- a/crypto/fipsmodule/self_check/self_check.cc.inc
+++ b/crypto/fipsmodule/self_check/self_check.cc.inc
@@ -708,10 +708,6 @@
   };
   static const uint8_t kAESIV[16] = {0};
 
-  EVP_AEAD_CTX aead_ctx;
-  EVP_AEAD_CTX_zero(&aead_ctx);
-  int ret = 0;
-
   AES_KEY aes_key;
   uint8_t aes_iv[16];
   uint8_t output[256];
@@ -731,14 +727,14 @@
   if (!bcm_success(
           BCM_aes_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key))) {
     fprintf(CRYPTO_get_stderr(), "BCM_aes_set_encrypt_key failed.\n");
-    goto err;
+    return 0;
   }
   AES_cbc_encrypt(kAESCBCEncPlaintext, output, sizeof(kAESCBCEncPlaintext),
                   &aes_key, aes_iv, AES_ENCRYPT);
   if (!BORINGSSL_check_test(kAESCBCEncCiphertext, output,
                             sizeof(kAESCBCEncCiphertext),
                             "AES-CBC-encrypt KAT")) {
-    goto err;
+    return 0;
   }
 
   // AES-CBC Decryption KAT
@@ -756,23 +752,24 @@
   if (!bcm_success(
           BCM_aes_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key))) {
     fprintf(CRYPTO_get_stderr(), "BCM_aes_set_decrypt_key failed.\n");
-    goto err;
+    return 0;
   }
   AES_cbc_encrypt(kAESCBCDecCiphertext, output, sizeof(kAESCBCDecCiphertext),
                   &aes_key, aes_iv, AES_DECRYPT);
   if (!BORINGSSL_check_test(kAESCBCDecPlaintext, output,
                             sizeof(kAESCBCDecPlaintext),
                             "AES-CBC-decrypt KAT")) {
-    goto err;
+    return 0;
   }
 
   size_t out_len;
   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
   OPENSSL_memset(nonce, 0, sizeof(nonce));
-  if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
+  bssl::ScopedEVP_AEAD_CTX aead_ctx;
+  if (!EVP_AEAD_CTX_init(aead_ctx.get(), EVP_aead_aes_128_gcm(), kAESKey,
                          sizeof(kAESKey), 0, NULL)) {
     fprintf(CRYPTO_get_stderr(), "EVP_AEAD_CTX_init for AES-128-GCM failed.\n");
-    goto err;
+    return 0;
   }
 
   // AES-GCM Encryption KAT
@@ -787,14 +784,14 @@
       0x1c, 0x63, 0x2e, 0x97, 0x93, 0x0f, 0xfb, 0xed, 0xb5, 0x9e, 0x1c, 0x20,
       0xb2, 0xb0, 0x58, 0xda, 0x48, 0x07, 0x2d, 0xbd, 0x96, 0x0d, 0x34, 0xc6,
   };
-  if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce,
-                         EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
+  if (!EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, sizeof(output),
+                         nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
                          kAESGCMEncPlaintext, sizeof(kAESGCMEncPlaintext), NULL,
                          0) ||
       !BORINGSSL_check_test(kAESGCMCiphertext, output,
                             sizeof(kAESGCMCiphertext), "AES-GCM-encrypt KAT")) {
     fprintf(CRYPTO_get_stderr(), "EVP_AEAD_CTX_seal for AES-128-GCM failed.\n");
-    goto err;
+    return 0;
   }
 
   // AES-GCM Decryption KAT
@@ -810,8 +807,8 @@
           0xa9, 0x99, 0x17, 0x6a, 0x45, 0x05, 0x5e, 0x99, 0x83, 0x56, 0x01,
           0xc0, 0x82, 0x40, 0x81, 0xd2, 0x48, 0x45, 0xf2, 0xcc, 0xc3,
       };
-  if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce,
-                         EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
+  if (!EVP_AEAD_CTX_open(aead_ctx.get(), output, &out_len, sizeof(output),
+                         nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
                          kAESGCMDecCiphertext, sizeof(kAESGCMDecCiphertext),
                          NULL, 0) ||
       !BORINGSSL_check_test(kAESGCMDecPlaintext, output,
@@ -819,7 +816,7 @@
                             "AES-GCM-decrypt KAT")) {
     fprintf(CRYPTO_get_stderr(),
             "AES-GCM-decrypt KAT failed because EVP_AEAD_CTX_open failed.\n");
-    goto err;
+    return 0;
   }
 
   // SHA-1 KAT
@@ -834,12 +831,12 @@
   SHA1(kSHA1Input, sizeof(kSHA1Input), output);
   if (!BORINGSSL_check_test(kSHA1Digest, output, sizeof(kSHA1Digest),
                             "SHA-1 KAT")) {
-    goto err;
+    return 0;
   }
 
   if (!boringssl_self_test_sha256() || !boringssl_self_test_sha512() ||
       !boringssl_self_test_hmac_sha256()) {
-    goto err;
+    return 0;
   }
 
   // DBRG KAT
@@ -889,7 +886,7 @@
       !BORINGSSL_check_test(kDRBGReseedOutput, output,
                             sizeof(kDRBGReseedOutput), "DRBG-reseed KAT")) {
     fprintf(CRYPTO_get_stderr(), "CTR-DRBG failed.\n");
-    goto err;
+    return 0;
   }
   CTR_DRBG_clear(&drbg);
 
@@ -897,7 +894,7 @@
   memset(&kZeroDRBG, 0, sizeof(kZeroDRBG));
   if (!BORINGSSL_check_test(&kZeroDRBG, &drbg, sizeof(drbg),
                             "DRBG Clear KAT")) {
-    goto err;
+    return 0;
   }
 
   // TLS KDF KAT
@@ -929,7 +926,7 @@
       !BORINGSSL_check_test(kTLS10Output, tls10_output, sizeof(kTLS10Output),
                             "TLS10-KDF KAT")) {
     fprintf(CRYPTO_get_stderr(), "TLS KDF failed.\n");
-    goto err;
+    return 0;
   }
 
   static const uint8_t kTLS12Secret[32] = {
@@ -950,7 +947,7 @@
       !BORINGSSL_check_test(kTLS12Output, tls12_output, sizeof(kTLS12Output),
                             "TLS12-KDF KAT")) {
     fprintf(CRYPTO_get_stderr(), "TLS KDF failed.\n");
-    goto err;
+    return 0;
   }
 
   // TLS v1.3: derives a dummy client-early-traffic secret.
@@ -990,7 +987,7 @@
                             sizeof(kTLS13ExpandLabelOutput),
                             "CRYPTO_tls13_hkdf_expand_label")) {
     fprintf(CRYPTO_get_stderr(), "TLS13-KDF failed.\n");
-    goto err;
+    return 0;
   }
 
   // HKDF
@@ -1021,15 +1018,10 @@
       !BORINGSSL_check_test(kHKDFOutput, hkdf_output, sizeof(kHKDFOutput),
                             "HKDF")) {
     fprintf(CRYPTO_get_stderr(), "HKDF failed.\n");
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  EVP_AEAD_CTX_cleanup(&aead_ctx);
-
-  return ret;
+  return 1;
 }
 
 int BORINGSSL_self_test(void) {
diff --git a/crypto/pem/pem_lib.cc b/crypto/pem/pem_lib.cc
index 854af77..7679aa0 100644
--- a/crypto/pem/pem_lib.cc
+++ b/crypto/pem/pem_lib.cc
@@ -239,7 +239,7 @@
 int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
                        const EVP_CIPHER *enc, const unsigned char *pass,
                        int pass_len, pem_password_cb *callback, void *u) {
-  EVP_CIPHER_CTX ctx;
+  bssl::ScopedEVP_CIPHER_CTX ctx;
   int dsize = 0, i, j, ret = 0;
   unsigned char *p, *data = NULL;
   const char *objstr = NULL;
@@ -305,16 +305,14 @@
     PEM_dek_info(buf, objstr, iv_len, (char *)iv);
     // k=strlen(buf);
 
-    EVP_CIPHER_CTX_init(&ctx);
     ret = 1;
-    if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) ||
-        !EVP_EncryptUpdate(&ctx, data, &j, data, i) ||
-        !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i)) {
+    if (!EVP_EncryptInit_ex(ctx.get(), enc, NULL, key, iv) ||
+        !EVP_EncryptUpdate(ctx.get(), data, &j, data, i) ||
+        !EVP_EncryptFinal_ex(ctx.get(), &(data[j]), &i)) {
       ret = 0;
     } else {
       i += j;
     }
-    EVP_CIPHER_CTX_cleanup(&ctx);
     if (ret == 0) {
       goto err;
     }
@@ -329,7 +327,6 @@
 err:
   OPENSSL_cleanse(key, sizeof(key));
   OPENSSL_cleanse(iv, sizeof(iv));
-  OPENSSL_cleanse((char *)&ctx, sizeof(ctx));
   OPENSSL_cleanse(buf, PEM_BUFSIZE);
   OPENSSL_free(data);
   return ret;
@@ -339,7 +336,7 @@
                   long *plen, pem_password_cb *callback, void *u) {
   int i = 0, j, o, pass_len;
   long len;
-  EVP_CIPHER_CTX ctx;
+  bssl::ScopedEVP_CIPHER_CTX ctx;
   unsigned char key[EVP_MAX_KEY_LENGTH];
   char buf[PEM_BUFSIZE];
 
@@ -365,15 +362,13 @@
   }
 
   j = (int)len;
-  EVP_CIPHER_CTX_init(&ctx);
-  o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, cipher->iv);
+  o = EVP_DecryptInit_ex(ctx.get(), cipher->cipher, NULL, key, cipher->iv);
   if (o) {
-    o = EVP_DecryptUpdate(&ctx, data, &i, data, j);
+    o = EVP_DecryptUpdate(ctx.get(), data, &i, data, j);
   }
   if (o) {
-    o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j);
+    o = EVP_DecryptFinal_ex(ctx.get(), &(data[i]), &j);
   }
-  EVP_CIPHER_CTX_cleanup(&ctx);
   OPENSSL_cleanse((char *)buf, sizeof(buf));
   OPENSSL_cleanse((char *)key, sizeof(key));
   if (!o) {
diff --git a/crypto/pkcs8/pkcs8.cc b/crypto/pkcs8/pkcs8.cc
index d2dddc1..a6937c1 100644
--- a/crypto/pkcs8/pkcs8.cc
+++ b/crypto/pkcs8/pkcs8.cc
@@ -33,8 +33,8 @@
 
 static int pkcs12_encode_password(const char *in, size_t in_len, uint8_t **out,
                                   size_t *out_len) {
-  CBB cbb;
-  if (!CBB_init(&cbb, in_len * 2)) {
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), in_len * 2)) {
     return 0;
   }
 
@@ -44,22 +44,18 @@
   CBS_init(&cbs, (const uint8_t *)in, in_len);
   while (CBS_len(&cbs) != 0) {
     uint32_t c;
-    if (!CBS_get_utf8(&cbs, &c) || !CBB_add_ucs2_be(&cbb, c)) {
+    if (!CBS_get_utf8(&cbs, &c) || !CBB_add_ucs2_be(cbb.get(), c)) {
       OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_INVALID_CHARACTERS);
-      goto err;
+      return 0;
     }
   }
 
   // Terminate the result with a UCS-2 NUL.
-  if (!CBB_add_ucs2_be(&cbb, 0) || !CBB_finish(&cbb, out, out_len)) {
-    goto err;
+  if (!CBB_add_ucs2_be(cbb.get(), 0) || !CBB_finish(cbb.get(), out, out_len)) {
+    return 0;
   }
 
   return 1;
-
-err:
-  CBB_cleanup(&cbb);
-  return 0;
 }
 
 int pkcs12_key_gen(const char *pass, size_t pass_len, const uint8_t *salt,
@@ -326,9 +322,7 @@
                       size_t in_len) {
   int ret = 0;
   uint8_t *buf = NULL;
-  ;
-  EVP_CIPHER_CTX ctx;
-  EVP_CIPHER_CTX_init(&ctx);
+  bssl::ScopedEVP_CIPHER_CTX ctx;
 
   CBS obj;
   const struct pbe_suite *suite = NULL;
@@ -348,7 +342,7 @@
     goto err;
   }
 
-  if (!suite->decrypt_init(suite, &ctx, pass, pass_len, algorithm)) {
+  if (!suite->decrypt_init(suite, ctx.get(), pass, pass_len, algorithm)) {
     OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEYGEN_FAILURE);
     goto err;
   }
@@ -364,8 +358,8 @@
   }
 
   int n1, n2;
-  if (!EVP_DecryptUpdate(&ctx, buf, &n1, in, (int)in_len) ||
-      !EVP_DecryptFinal_ex(&ctx, buf + n1, &n2)) {
+  if (!EVP_DecryptUpdate(ctx.get(), buf, &n1, in, (int)in_len) ||
+      !EVP_DecryptFinal_ex(ctx.get(), buf + n1, &n2)) {
     goto err;
   }
 
@@ -376,7 +370,6 @@
 
 err:
   OPENSSL_free(buf);
-  EVP_CIPHER_CTX_cleanup(&ctx);
   return ret;
 }
 
@@ -414,8 +407,7 @@
   int ret = 0;
   uint8_t *plaintext = NULL, *salt_buf = NULL;
   size_t plaintext_len = 0;
-  EVP_CIPHER_CTX ctx;
-  EVP_CIPHER_CTX_init(&ctx);
+  bssl::ScopedEVP_CIPHER_CTX ctx;
 
   {
     // Generate a random salt if necessary.
@@ -447,13 +439,13 @@
 
     CBB epki;
     if (!CBB_add_asn1(out, &epki, CBS_ASN1_SEQUENCE) ||
-        !pkcs12_pbe_encrypt_init(&epki, &ctx, pbe_nid, cipher,
+        !pkcs12_pbe_encrypt_init(&epki, ctx.get(), pbe_nid, cipher,
                                  (uint32_t)iterations, pass, pass_len, salt,
                                  salt_len)) {
       goto err;
     }
 
-    size_t max_out = plaintext_len + EVP_CIPHER_CTX_block_size(&ctx);
+    size_t max_out = plaintext_len + EVP_CIPHER_CTX_block_size(ctx.get());
     if (max_out < plaintext_len) {
       OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_TOO_LONG);
       goto err;
@@ -464,8 +456,8 @@
     int n1, n2;
     if (!CBB_add_asn1(&epki, &ciphertext, CBS_ASN1_OCTETSTRING) ||
         !CBB_reserve(&ciphertext, &ptr, max_out) ||
-        !EVP_CipherUpdate(&ctx, ptr, &n1, plaintext, plaintext_len) ||
-        !EVP_CipherFinal_ex(&ctx, ptr + n1, &n2) ||
+        !EVP_CipherUpdate(ctx.get(), ptr, &n1, plaintext, plaintext_len) ||
+        !EVP_CipherFinal_ex(ctx.get(), ptr + n1, &n2) ||
         !CBB_did_write(&ciphertext, n1 + n2) || !CBB_flush(out)) {
       goto err;
     }
@@ -476,6 +468,5 @@
 err:
   OPENSSL_free(plaintext);
   OPENSSL_free(salt_buf);
-  EVP_CIPHER_CTX_cleanup(&ctx);
   return ret;
 }
diff --git a/crypto/x509/a_sign.cc b/crypto/x509/a_sign.cc
index a790cbf..018a31b 100644
--- a/crypto/x509/a_sign.cc
+++ b/crypto/x509/a_sign.cc
@@ -31,13 +31,11 @@
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
     return 0;
   }
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-  if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) {
-    EVP_MD_CTX_cleanup(&ctx);
+  bssl::ScopedEVP_MD_CTX ctx;
+  if (!EVP_DigestSignInit(ctx.get(), nullptr, type, nullptr, pkey)) {
     return 0;
   }
-  return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
+  return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx.get());
 }
 
 int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
diff --git a/crypto/x509/asn1_gen.cc b/crypto/x509/asn1_gen.cc
index 6b9769f..9b6bf17 100644
--- a/crypto/x509/asn1_gen.cc
+++ b/crypto/x509/asn1_gen.cc
@@ -58,27 +58,23 @@
 static int bitstr_cb(const char *elem, size_t len, void *bitstr);
 
 ASN1_TYPE *ASN1_generate_v3(const char *str, const X509V3_CTX *cnf) {
-  CBB cbb;
-  if (!CBB_init(&cbb, 0) ||  //
-      !generate_v3(&cbb, str, cnf, /*tag=*/0, ASN1_GEN_FORMAT_ASCII,
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||  //
+      !generate_v3(cbb.get(), str, cnf, /*tag=*/0, ASN1_GEN_FORMAT_ASCII,
                    /*depth=*/0)) {
-    CBB_cleanup(&cbb);
-    return NULL;
+    return nullptr;
   }
 
   // While not strictly necessary to avoid a DoS (we rely on any super-linear
   // checks being performed internally), cap the overall output to
   // |ASN1_GEN_MAX_OUTPUT| so the externally-visible behavior is consistent.
-  if (CBB_len(&cbb) > ASN1_GEN_MAX_OUTPUT) {
+  if (CBB_len(cbb.get()) > ASN1_GEN_MAX_OUTPUT) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
-    CBB_cleanup(&cbb);
-    return NULL;
+    return nullptr;
   }
 
-  const uint8_t *der = CBB_data(&cbb);
-  ASN1_TYPE *ret = d2i_ASN1_TYPE(NULL, &der, CBB_len(&cbb));
-  CBB_cleanup(&cbb);
-  return ret;
+  const uint8_t *der = CBB_data(cbb.get());
+  return d2i_ASN1_TYPE(nullptr, &der, CBB_len(cbb.get()));
 }
 
 static int cbs_str_equal(const CBS *cbs, const char *str) {
diff --git a/crypto/x509/v3_conf.cc b/crypto/x509/v3_conf.cc
index 8b755d3..f48c128 100644
--- a/crypto/x509/v3_conf.cc
+++ b/crypto/x509/v3_conf.cc
@@ -226,49 +226,41 @@
 static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
                                             int crit, int gen_type,
                                             const X509V3_CTX *ctx) {
-  unsigned char *ext_der = NULL;
-  size_t ext_len = 0;
-  ASN1_OBJECT *obj = NULL;
-  ASN1_OCTET_STRING *oct = NULL;
-  X509_EXTENSION *extension = NULL;
-  if (!(obj = OBJ_txt2obj(ext, 0))) {
+  bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(ext, 0));
+  if (obj == nullptr) {
     OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
     ERR_add_error_data(2, "name=", ext);
-    goto err;
+    return nullptr;
   }
 
+  bssl::UniquePtr<unsigned char> ext_der;
+  size_t ext_len = 0;
   if (gen_type == 1) {
-    ext_der = x509v3_hex_to_bytes(value, &ext_len);
+    ext_der.reset(x509v3_hex_to_bytes(value, &ext_len));
   } else if (gen_type == 2) {
-    ext_der = generic_asn1(value, ctx, &ext_len);
+    ext_der.reset(generic_asn1(value, ctx, &ext_len));
   }
 
-  if (ext_der == NULL) {
+  if (ext_der == nullptr) {
     OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
     ERR_add_error_data(2, "value=", value);
-    goto err;
+    return nullptr;
   }
 
   if (ext_len > INT_MAX) {
     OPENSSL_PUT_ERROR(X509V3, ERR_R_OVERFLOW);
-    goto err;
+    return nullptr;
   }
 
-  oct = ASN1_OCTET_STRING_new();
-  if (oct == NULL) {
-    goto err;
+  bssl::UniquePtr<ASN1_OCTET_STRING> oct(ASN1_OCTET_STRING_new());
+  if (oct == nullptr) {
+    return nullptr;
   }
 
-  ASN1_STRING_set0(oct, ext_der, (int)ext_len);
-  ext_der = NULL;
+  ASN1_STRING_set0(oct.get(), ext_der.get(), (int)ext_len);
+  ext_der.release();  // ASN1_STRING_set0 took ownership.
 
-  extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
-
-err:
-  ASN1_OBJECT_free(obj);
-  ASN1_OCTET_STRING_free(oct);
-  OPENSSL_free(ext_der);
-  return extension;
+  return X509_EXTENSION_create_by_OBJ(nullptr, obj.get(), crit, oct.get());
 }
 
 static unsigned char *generic_asn1(const char *value, const X509V3_CTX *ctx,
diff --git a/crypto/x509/v3_info.cc b/crypto/x509/v3_info.cc
index 5e149aa..842e34b 100644
--- a/crypto/x509/v3_info.cc
+++ b/crypto/x509/v3_info.cc
@@ -122,43 +122,37 @@
 static void *v2i_AUTHORITY_INFO_ACCESS(const X509V3_EXT_METHOD *method,
                                        const X509V3_CTX *ctx,
                                        const STACK_OF(CONF_VALUE) *nval) {
-  AUTHORITY_INFO_ACCESS *ainfo = NULL;
-  ACCESS_DESCRIPTION *acc;
-  if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
-    return NULL;
+  bssl::UniquePtr<AUTHORITY_INFO_ACCESS> ainfo(sk_ACCESS_DESCRIPTION_new_null());
+  if (ainfo == nullptr) {
+    return nullptr;
   }
   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
     const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
-    if (!(acc = ACCESS_DESCRIPTION_new()) ||
-        !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
-      goto err;
+    bssl::UniquePtr<ACCESS_DESCRIPTION> acc(ACCESS_DESCRIPTION_new());
+    if (acc == nullptr || !bssl::PushToStack(ainfo.get(), std::move(acc))) {
+      return nullptr;
     }
     char *ptmp = strchr(cnf->name, ';');
     if (!ptmp) {
       OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
-      goto err;
+      return nullptr;
     }
     CONF_VALUE ctmp;
     ctmp.name = ptmp + 1;
     ctmp.value = cnf->value;
     if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) {
-      goto err;
+      return nullptr;
     }
-    char *objtmp = OPENSSL_strndup(cnf->name, ptmp - cnf->name);
-    if (objtmp == NULL) {
-      goto err;
+    bssl::UniquePtr<char> objtmp(OPENSSL_strndup(cnf->name, ptmp - cnf->name));
+    if (objtmp == nullptr) {
+      return nullptr;
     }
-    acc->method = OBJ_txt2obj(objtmp, 0);
+    acc->method = OBJ_txt2obj(objtmp.get(), 0);
     if (!acc->method) {
       OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
-      ERR_add_error_data(2, "value=", objtmp);
-      OPENSSL_free(objtmp);
-      goto err;
+      ERR_add_error_data(2, "value=", objtmp.get());
+      return nullptr;
     }
-    OPENSSL_free(objtmp);
   }
-  return ainfo;
-err:
-  sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
-  return NULL;
+  return ainfo.release();
 }
diff --git a/crypto/x509/x_x509.cc b/crypto/x509/x_x509.cc
index 098c757..feef072 100644
--- a/crypto/x509/x_x509.cc
+++ b/crypto/x509/x_x509.cc
@@ -109,7 +109,7 @@
       !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE) ||
       !CBS_get_asn1_element(&cert, &sigalg, CBS_ASN1_SEQUENCE)) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
-    return NULL;
+    return nullptr;
   }
 
   // For just the signature field, we accept non-minimal BER lengths, though not
@@ -121,76 +121,70 @@
   size_t header_len;
   int indefinite;
   if (!CBS_get_any_ber_asn1_element(&cert, &sig, &tag, &header_len,
-                                    /*out_ber_found=*/NULL,
+                                    /*out_ber_found=*/nullptr,
                                     &indefinite) ||
       tag != CBS_ASN1_BITSTRING || indefinite ||  //
       !CBS_skip(&sig, header_len) ||              //
       CBS_len(&cert) != 0) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
-    return NULL;
+    return nullptr;
   }
 
-  X509 *ret = x509_new_null();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<X509> ret(x509_new_null());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
-  {
-    // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled
-    // from the tasn_*.c implementation, replace this with |CBS|-based
-    // functions.
-    const uint8_t *inp = CBS_data(&tbs);
-    if (ASN1_item_ex_d2i((ASN1_VALUE **)&ret->cert_info, &inp, CBS_len(&tbs),
-                         ASN1_ITEM_rptr(X509_CINF), /*tag=*/-1,
-                         /*aclass=*/0, /*opt=*/0, buf) <= 0 ||
-        inp != CBS_data(&tbs) + CBS_len(&tbs)) {
-      goto err;
-    }
-
-    inp = CBS_data(&sigalg);
-    ret->sig_alg = d2i_X509_ALGOR(NULL, &inp, CBS_len(&sigalg));
-    if (ret->sig_alg == NULL || inp != CBS_data(&sigalg) + CBS_len(&sigalg)) {
-      goto err;
-    }
-
-    inp = CBS_data(&sig);
-    ret->signature = c2i_ASN1_BIT_STRING(NULL, &inp, CBS_len(&sig));
-    if (ret->signature == NULL || inp != CBS_data(&sig) + CBS_len(&sig)) {
-      goto err;
-    }
-
-    // The version must be one of v1(0), v2(1), or v3(2).
-    long version = X509_VERSION_1;
-    if (ret->cert_info->version != NULL) {
-      version = ASN1_INTEGER_get(ret->cert_info->version);
-      // TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should
-      // also be rejected here. This means an explicitly-encoded X.509v1
-      // version. v1 is DEFAULT, so DER requires it be omitted.
-      if (version < X509_VERSION_1 || version > X509_VERSION_3) {
-        OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
-        goto err;
-      }
-    }
-
-    // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3.
-    if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != NULL ||
-                                      ret->cert_info->subjectUID != NULL)) {
-      OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
-      goto err;
-    }
-
-    // Per RFC 5280, section 4.1.2.9, extensions require v3.
-    if (version != X509_VERSION_3 && ret->cert_info->extensions != NULL) {
-      OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
-      goto err;
-    }
-
-    return ret;
+  // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled
+  // from the tasn_*.c implementation, replace this with |CBS|-based
+  // functions.
+  const uint8_t *inp = CBS_data(&tbs);
+  if (ASN1_item_ex_d2i((ASN1_VALUE **)&ret->cert_info, &inp, CBS_len(&tbs),
+                       ASN1_ITEM_rptr(X509_CINF), /*tag=*/-1,
+                       /*aclass=*/0, /*opt=*/0, buf) <= 0 ||
+      inp != CBS_data(&tbs) + CBS_len(&tbs)) {
+    return nullptr;
   }
 
-err:
-  X509_free(ret);
-  return NULL;
+  inp = CBS_data(&sigalg);
+  ret->sig_alg = d2i_X509_ALGOR(nullptr, &inp, CBS_len(&sigalg));
+  if (ret->sig_alg == nullptr || inp != CBS_data(&sigalg) + CBS_len(&sigalg)) {
+    return nullptr;
+  }
+
+  inp = CBS_data(&sig);
+  ret->signature = c2i_ASN1_BIT_STRING(nullptr, &inp, CBS_len(&sig));
+  if (ret->signature == nullptr || inp != CBS_data(&sig) + CBS_len(&sig)) {
+    return nullptr;
+  }
+
+  // The version must be one of v1(0), v2(1), or v3(2).
+  long version = X509_VERSION_1;
+  if (ret->cert_info->version != nullptr) {
+    version = ASN1_INTEGER_get(ret->cert_info->version);
+    // TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should
+    // also be rejected here. This means an explicitly-encoded X.509v1
+    // version. v1 is DEFAULT, so DER requires it be omitted.
+    if (version < X509_VERSION_1 || version > X509_VERSION_3) {
+      OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
+      return nullptr;
+    }
+  }
+
+  // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3.
+  if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != nullptr ||
+                                    ret->cert_info->subjectUID != nullptr)) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
+    return nullptr;
+  }
+
+  // Per RFC 5280, section 4.1.2.9, extensions require v3.
+  if (version != X509_VERSION_3 && ret->cert_info->extensions != nullptr) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
+    return nullptr;
+  }
+
+  return ret.release();
 }
 
 X509 *d2i_X509(X509 **out, const uint8_t **inp, long len) {
diff --git a/crypto/x509/x_x509a.cc b/crypto/x509/x_x509a.cc
index f36fcaf..9318d43 100644
--- a/crypto/x509/x_x509a.cc
+++ b/crypto/x509/x_x509a.cc
@@ -109,49 +109,33 @@
 }
 
 int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj) {
-  X509_CERT_AUX *aux;
-  ASN1_OBJECT *objtmp = OBJ_dup(obj);
-  if (objtmp == NULL) {
-    goto err;
+  bssl::UniquePtr<ASN1_OBJECT> objtmp(OBJ_dup(obj));
+  if (objtmp == nullptr) {
+    return 0;
   }
-  aux = aux_get(x);
-  if (aux->trust == NULL) {
+  X509_CERT_AUX *aux = aux_get(x);
+  if (aux->trust == nullptr) {
     aux->trust = sk_ASN1_OBJECT_new_null();
-    if (aux->trust == NULL) {
-      goto err;
+    if (aux->trust == nullptr) {
+      return 0;
     }
   }
-  if (!sk_ASN1_OBJECT_push(aux->trust, objtmp)) {
-    goto err;
-  }
-  return 1;
-
-err:
-  ASN1_OBJECT_free(objtmp);
-  return 0;
+  return bssl::PushToStack(aux->trust, std::move(objtmp));
 }
 
 int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj) {
-  X509_CERT_AUX *aux;
-  ASN1_OBJECT *objtmp = OBJ_dup(obj);
-  if (objtmp == NULL) {
-    goto err;
+  bssl::UniquePtr<ASN1_OBJECT> objtmp(OBJ_dup(obj));
+  if (objtmp == nullptr) {
+    return 0;
   }
-  aux = aux_get(x);
-  if (aux->reject == NULL) {
+  X509_CERT_AUX *aux = aux_get(x);
+  if (aux->reject == nullptr) {
     aux->reject = sk_ASN1_OBJECT_new_null();
-    if (aux->reject == NULL) {
-      goto err;
+    if (aux->reject == nullptr) {
+      return 0;
     }
   }
-  if (!sk_ASN1_OBJECT_push(aux->reject, objtmp)) {
-    goto err;
-  }
-  return 1;
-
-err:
-  ASN1_OBJECT_free(objtmp);
-  return 0;
+  return bssl::PushToStack(aux->reject, std::move(objtmp));
 }
 
 void X509_trust_clear(X509 *x) {
diff --git a/decrepit/dh/dh_decrepit.cc b/decrepit/dh/dh_decrepit.cc
index d8d1d2d..7f7b4b6 100644
--- a/decrepit/dh/dh_decrepit.cc
+++ b/decrepit/dh/dh_decrepit.cc
@@ -32,20 +32,18 @@
 DH *DH_generate_parameters(int prime_len, int generator,
                            void (*callback)(int, int, void *), void *cb_arg) {
   if (prime_len < 0 || generator < 0) {
-      return NULL;
+    return nullptr;
   }
 
-  DH *ret = DH_new();
-  if (ret == NULL) {
-      return NULL;
+  bssl::UniquePtr<DH> ret(DH_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
   BN_GENCB gencb_storage;
-  BN_GENCB *cb = NULL;
-
+  BN_GENCB *cb = nullptr;
   struct wrapped_callback wrapped;
-
-  if (callback != NULL) {
+  if (callback != nullptr) {
     wrapped.callback = callback;
     wrapped.arg = cb_arg;
 
@@ -53,13 +51,9 @@
     BN_GENCB_set(cb, callback_wrapper, &wrapped);
   }
 
-  if (!DH_generate_parameters_ex(ret, prime_len, generator, cb)) {
-    goto err;
+  if (!DH_generate_parameters_ex(ret.get(), prime_len, generator, cb)) {
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  DH_free(ret);
-  return NULL;
+  return ret.release();
 }
diff --git a/decrepit/dsa/dsa_decrepit.cc b/decrepit/dsa/dsa_decrepit.cc
index c77c7ff..86586ca 100644
--- a/decrepit/dsa/dsa_decrepit.cc
+++ b/decrepit/dsa/dsa_decrepit.cc
@@ -33,20 +33,18 @@
                              int *counter_ret, unsigned long *h_ret,
                              void (*callback)(int, int, void *), void *cb_arg) {
   if (bits < 0 || seed_len < 0) {
-      return NULL;
+      return nullptr;
   }
 
-  DSA *ret = DSA_new();
-  if (ret == NULL) {
-      return NULL;
+  bssl::UniquePtr<DSA> ret(DSA_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
   BN_GENCB gencb_storage;
-  BN_GENCB *cb = NULL;
-
+  BN_GENCB *cb = nullptr;
   struct wrapped_callback wrapped;
-
-  if (callback != NULL) {
+  if (callback != nullptr) {
     wrapped.callback = callback;
     wrapped.arg = cb_arg;
 
@@ -54,14 +52,10 @@
     BN_GENCB_set(cb, callback_wrapper, &wrapped);
   }
 
-  if (!DSA_generate_parameters_ex(ret, bits, seed_in, seed_len, counter_ret,
-                                  h_ret, cb)) {
-    goto err;
+  if (!DSA_generate_parameters_ex(ret.get(), bits, seed_in, seed_len,
+                                  counter_ret, h_ret, cb)) {
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  DSA_free(ret);
-  return NULL;
+  return ret.release();
 }
diff --git a/decrepit/rsa/rsa_decrepit.cc b/decrepit/rsa/rsa_decrepit.cc
index 22c9f01..a1b943f 100644
--- a/decrepit/rsa/rsa_decrepit.cc
+++ b/decrepit/rsa/rsa_decrepit.cc
@@ -21,26 +21,19 @@
 
 RSA *RSA_generate_key(int bits, uint64_t e_value, void *callback,
                       void *cb_arg) {
-  assert(callback == NULL);
-  assert(cb_arg == NULL);
+  assert(callback == nullptr);
+  assert(cb_arg == nullptr);
 
-  RSA *rsa = RSA_new();
-  BIGNUM *e = BN_new();
-
-  if (rsa == NULL ||
-      e == NULL ||
-      !BN_set_u64(e, e_value) ||
-      !RSA_generate_key_ex(rsa, bits, e, NULL)) {
-    goto err;
+  bssl::UniquePtr<RSA> rsa(RSA_new());
+  bssl::UniquePtr<BIGNUM> e(BN_new());
+  if (rsa == nullptr ||  //
+      e == nullptr ||    //
+      !BN_set_u64(e.get(), e_value) ||
+      !RSA_generate_key_ex(rsa.get(), bits, e.get(), nullptr)) {
+    return nullptr;
   }
 
-  BN_free(e);
-  return rsa;
-
-err:
-  BN_free(e);
-  RSA_free(rsa);
-  return NULL;
+  return rsa.release();
 }
 
 int RSA_padding_add_PKCS1_PSS(const RSA *rsa, uint8_t *EM, const uint8_t *mHash,
diff --git a/util/fipstools/test_fips.cc b/util/fipstools/test_fips.cc
index 0d53904..998f5c6 100644
--- a/util/fipstools/test_fips.cc
+++ b/util/fipstools/test_fips.cc
@@ -136,8 +136,8 @@
   size_t out_len;
   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
   OPENSSL_memset(nonce, 0, sizeof(nonce));
-  EVP_AEAD_CTX aead_ctx;
-  if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
+  bssl::ScopedEVP_AEAD_CTX aead_ctx;
+  if (!EVP_AEAD_CTX_init(aead_ctx.get(), EVP_aead_aes_128_gcm(), kAESKey,
                          sizeof(kAESKey), 0, NULL)) {
     printf("EVP_AEAD_CTX_init failed\n");
     return 0;
@@ -146,8 +146,8 @@
   /* AES-GCM Encryption */
   printf("About to AES-GCM seal ");
   hexdump(output, sizeof(kPlaintext));
-  if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce,
-                         EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
+  if (!EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, sizeof(output),
+                         nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
                          kPlaintext, sizeof(kPlaintext), NULL, 0)) {
     printf("AES-GCM encrypt failed\n");
     return 0;
@@ -158,17 +158,15 @@
   /* AES-GCM Decryption */
   printf("About to AES-GCM open ");
   hexdump(output, out_len);
-  if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce,
-                         EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), output,
-                         out_len, NULL, 0)) {
+  if (!EVP_AEAD_CTX_open(aead_ctx.get(), output, &out_len, sizeof(output),
+                         nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
+                         output, out_len, NULL, 0)) {
     printf("AES-GCM decrypt failed\n");
     return 0;
   }
   printf("  got ");
   hexdump(output, out_len);
 
-  EVP_AEAD_CTX_cleanup(&aead_ctx);
-
   DES_key_schedule des1, des2, des3;
   DES_cblock des_iv;
   DES_set_key(&kDESKey1, &des1);