Convert a few more things to scopers

Also simplify DH_generate_parameters_ex a bit. Any function that does
BN_CTX_new + BN_CTX_get isn't getting anything out of the BN_CTX-owned
BIGNUMs. BN_CTX is only useful when your function gets called multiple
times.

Change-Id: I8c3988a9c3d0939b9f3ac9fc36fcd0fe3d92a33c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/77547
Reviewed-by: Bob Beck <bbe@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/bn/exponentiation.cc b/crypto/bn/exponentiation.cc
index 9942986..a6d7d9c 100644
--- a/crypto/bn/exponentiation.cc
+++ b/crypto/bn/exponentiation.cc
@@ -22,55 +22,49 @@
 
 
 int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
-  int i, bits, ret = 0;
-  BIGNUM *v, *rr;
-
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *rr;
   if (r == a || r == p) {
     rr = BN_CTX_get(ctx);
   } else {
     rr = r;
   }
 
-  v = BN_CTX_get(ctx);
+  BIGNUM *v = BN_CTX_get(ctx);
   if (rr == NULL || v == NULL) {
-    goto err;
+    return 0;
   }
 
   if (BN_copy(v, a) == NULL) {
-    goto err;
+    return 0;
   }
-  bits = BN_num_bits(p);
+  int bits = BN_num_bits(p);
 
   if (BN_is_odd(p)) {
     if (BN_copy(rr, a) == NULL) {
-      goto err;
+      return 0;
     }
   } else {
     if (!BN_one(rr)) {
-      goto err;
+      return 0;
     }
   }
 
-  for (i = 1; i < bits; i++) {
+  for (int i = 1; i < bits; i++) {
     if (!BN_sqr(v, v, ctx)) {
-      goto err;
+      return 0;
     }
     if (BN_is_bit_set(p, i)) {
       if (!BN_mul(rr, rr, v, ctx)) {
-        goto err;
+        return 0;
       }
     }
   }
 
   if (r != rr && !BN_copy(r, rr)) {
-    goto err;
+    return 0;
   }
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 static int mod_exp_even(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
diff --git a/crypto/dh/params.cc b/crypto/dh/params.cc
index 18c585e..115505f 100644
--- a/crypto/dh/params.cc
+++ b/crypto/dh/params.cc
@@ -22,7 +22,8 @@
 #include "../fipsmodule/dh/internal.h"
 
 
-static BIGNUM *get_params(BIGNUM *ret, const BN_ULONG *words, size_t num_words) {
+static BIGNUM *get_params(BIGNUM *ret, const BN_ULONG *words,
+                          size_t num_words) {
   BIGNUM *alloc = NULL;
   if (ret == NULL) {
     alloc = BN_new();
@@ -304,92 +305,57 @@
     return 0;
   }
 
-  BIGNUM *t1, *t2;
-  int g, ok = 0;
-  BN_CTX *ctx = NULL;
-
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
-  }
-  BN_CTX_start(ctx);
-  t1 = BN_CTX_get(ctx);
-  t2 = BN_CTX_get(ctx);
-  if (t1 == NULL || t2 == NULL) {
-    goto err;
-  }
-
   // Make sure |dh| has the necessary elements
   if (dh->p == NULL) {
     dh->p = BN_new();
     if (dh->p == NULL) {
-      goto err;
+      OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
+      return 0;
     }
   }
   if (dh->g == NULL) {
     dh->g = BN_new();
     if (dh->g == NULL) {
-      goto err;
+      OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
+      return 0;
     }
   }
 
+  BN_ULONG t1, t2, g;
   if (generator <= 1) {
     OPENSSL_PUT_ERROR(DH, DH_R_BAD_GENERATOR);
-    goto err;
+    return 0;
   }
   if (generator == DH_GENERATOR_2) {
-    if (!BN_set_word(t1, 24)) {
-      goto err;
-    }
-    if (!BN_set_word(t2, 11)) {
-      goto err;
-    }
+    t1 = 24;
+    t2 = 11;
     g = 2;
   } else if (generator == DH_GENERATOR_5) {
-    if (!BN_set_word(t1, 10)) {
-      goto err;
-    }
-    if (!BN_set_word(t2, 3)) {
-      goto err;
-    }
-    // BN_set_word(t3,7); just have to miss
-    // out on these ones :-(
+    t1 = 10;
+    t2 = 3;
     g = 5;
   } else {
-    // in the general case, don't worry if 'generator' is a
-    // generator or not: since we are using safe primes,
-    // it will generate either an order-q or an order-2q group,
-    // which both is OK
-    if (!BN_set_word(t1, 2)) {
-      goto err;
-    }
-    if (!BN_set_word(t2, 1)) {
-      goto err;
-    }
+    // In the general case, don't worry if 'generator' is a generator or not:
+    // since we are using safe primes, it will generate either an order-q or an
+    // order-2q group, which both is OK.
+    t1 = 2;
+    t2 = 1;
     g = generator;
   }
 
-  if (!BN_generate_prime_ex(dh->p, prime_bits, 1, t1, t2, cb)) {
-    goto err;
-  }
-  if (!BN_GENCB_call(cb, 3, 0)) {
-    goto err;
-  }
-  if (!BN_set_word(dh->g, g)) {
-    goto err;
-  }
-  ok = 1;
-
-err:
-  if (!ok) {
+  bssl::UniquePtr<BIGNUM> t1_bn(BN_new()), t2_bn(BN_new());
+  if (t1_bn == nullptr || t2_bn == nullptr ||
+      !BN_set_word(t1_bn.get(), t1) ||  //
+      !BN_set_word(t2_bn.get(), t2) ||  //
+      !BN_generate_prime_ex(dh->p, prime_bits, 1, t1_bn.get(), t2_bn.get(),
+                            cb) ||
+      !BN_GENCB_call(cb, 3, 0) ||  //
+      !BN_set_word(dh->g, g)) {
     OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
+    return 0;
   }
 
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-  return ok;
+  return 1;
 }
 
 static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) {
diff --git a/crypto/dsa/dsa.cc b/crypto/dsa/dsa.cc
index d1bfdf0..958be93 100644
--- a/crypto/dsa/dsa.cc
+++ b/crypto/dsa/dsa.cc
@@ -167,17 +167,14 @@
     return 0;
   }
 
-  int ok = 0;
   unsigned char seed[SHA256_DIGEST_LENGTH];
   unsigned char md[SHA256_DIGEST_LENGTH];
   unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
   BIGNUM *r0, *W, *X, *c, *test;
   BIGNUM *g = NULL, *q = NULL, *p = NULL;
-  BN_MONT_CTX *mont = NULL;
   int k, n = 0, m = 0;
   int counter = 0;
   int r = 0;
-  BN_CTX *ctx = NULL;
   unsigned int h = 2;
   const EVP_MD *evpmd;
 
@@ -201,23 +198,23 @@
     OPENSSL_memcpy(seed, seed_in, seed_len);
   }
 
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
+    return 0;
   }
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx.get());
 
-  r0 = BN_CTX_get(ctx);
-  g = BN_CTX_get(ctx);
-  W = BN_CTX_get(ctx);
-  q = BN_CTX_get(ctx);
-  X = BN_CTX_get(ctx);
-  c = BN_CTX_get(ctx);
-  p = BN_CTX_get(ctx);
-  test = BN_CTX_get(ctx);
+  r0 = BN_CTX_get(ctx.get());
+  g = BN_CTX_get(ctx.get());
+  W = BN_CTX_get(ctx.get());
+  q = BN_CTX_get(ctx.get());
+  X = BN_CTX_get(ctx.get());
+  c = BN_CTX_get(ctx.get());
+  p = BN_CTX_get(ctx.get());
+  test = BN_CTX_get(ctx.get());
 
   if (test == NULL || !BN_lshift(test, BN_value_one(), bits - 1)) {
-    goto err;
+    return 0;
   }
 
   for (;;) {
@@ -225,13 +222,13 @@
     for (;;) {
       // step 1
       if (!BN_GENCB_call(cb, BN_GENCB_GENERATED, m++)) {
-        goto err;
+        return 0;
       }
 
       int use_random_seed = (seed_in == NULL);
       if (use_random_seed) {
         if (!RAND_bytes(seed, qsize)) {
-          goto err;
+          return 0;
         }
         // DSA parameters are public.
         CONSTTIME_DECLASSIFY(seed, qsize);
@@ -252,7 +249,7 @@
       // step 2
       if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) ||
           !EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) {
-        goto err;
+        return 0;
       }
       for (size_t i = 0; i < qsize; i++) {
         md[i] ^= buf2[i];
@@ -262,17 +259,17 @@
       md[0] |= 0x80;
       md[qsize - 1] |= 0x01;
       if (!BN_bin2bn(md, qsize, q)) {
-        goto err;
+        return 0;
       }
 
       // step 4
-      r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, use_random_seed,
-                                  cb);
+      r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx.get(),
+                                  use_random_seed, cb);
       if (r > 0) {
         break;
       }
       if (r != 0) {
-        goto err;
+        return 0;
       }
 
       // do a callback call
@@ -280,7 +277,7 @@
     }
 
     if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) {
-      goto err;
+      return 0;
     }
 
     // step 6
@@ -291,7 +288,7 @@
 
     for (;;) {
       if ((counter != 0) && !BN_GENCB_call(cb, BN_GENCB_GENERATED, counter)) {
-        goto err;
+        return 0;
       }
 
       // step 7
@@ -307,36 +304,36 @@
         }
 
         if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) {
-          goto err;
+          return 0;
         }
 
         // step 8
         if (!BN_bin2bn(md, qsize, r0) || !BN_lshift(r0, r0, (qsize << 3) * k) ||
             !BN_add(W, W, r0)) {
-          goto err;
+          return 0;
         }
       }
 
       // more of step 8
       if (!BN_mask_bits(W, bits - 1) || !BN_copy(X, W) || !BN_add(X, X, test)) {
-        goto err;
+        return 0;
       }
 
       // step 9
-      if (!BN_lshift1(r0, q) || !BN_mod(c, X, r0, ctx) ||
+      if (!BN_lshift1(r0, q) || !BN_mod(c, X, r0, ctx.get()) ||
           !BN_sub(r0, c, BN_value_one()) || !BN_sub(p, X, r0)) {
-        goto err;
+        return 0;
       }
 
       // step 10
       if (BN_cmp(p, test) >= 0) {
         // step 11
-        r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
+        r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx.get(), 1, cb);
         if (r > 0) {
           goto end;  // found it
         }
         if (r != 0) {
-          goto err;
+          return 0;
         }
       }
 
@@ -352,68 +349,56 @@
   }
 end:
   if (!BN_GENCB_call(cb, 2, 1)) {
-    goto err;
+    return 0;
   }
 
   // We now need to generate g
   // Set r0=(p-1)/q
-  if (!BN_sub(test, p, BN_value_one()) || !BN_div(r0, NULL, test, q, ctx)) {
-    goto err;
+  if (!BN_sub(test, p, BN_value_one()) ||
+      !BN_div(r0, NULL, test, q, ctx.get())) {
+    return 0;
   }
 
-  mont = BN_MONT_CTX_new_for_modulus(p, ctx);
-  if (mont == NULL || !BN_set_word(test, h)) {
-    goto err;
+  bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new_for_modulus(p, ctx.get()));
+  if (mont == nullptr || !BN_set_word(test, h)) {
+    return 0;
   }
 
   for (;;) {
     // g=test^r0%p
-    if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) {
-      goto err;
+    if (!BN_mod_exp_mont(g, test, r0, p, ctx.get(), mont.get())) {
+      return 0;
     }
     if (!BN_is_one(g)) {
       break;
     }
     if (!BN_add(test, test, BN_value_one())) {
-      goto err;
+      return 0;
     }
     h++;
   }
 
   if (!BN_GENCB_call(cb, 3, 1)) {
-    goto err;
+    return 0;
   }
 
-  ok = 1;
-
-err:
-  if (ok) {
-    BN_free(dsa->p);
-    BN_free(dsa->q);
-    BN_free(dsa->g);
-    dsa->p = BN_dup(p);
-    dsa->q = BN_dup(q);
-    dsa->g = BN_dup(g);
-    if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
-      ok = 0;
-      goto err;
-    }
-    if (out_counter != NULL) {
-      *out_counter = counter;
-    }
-    if (out_h != NULL) {
-      *out_h = h;
-    }
+  BN_free(dsa->p);
+  BN_free(dsa->q);
+  BN_free(dsa->g);
+  dsa->p = BN_dup(p);
+  dsa->q = BN_dup(q);
+  dsa->g = BN_dup(g);
+  if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
+    return 0;
+  }
+  if (out_counter != NULL) {
+    *out_counter = counter;
+  }
+  if (out_h != NULL) {
+    *out_h = h;
   }
 
-  if (ctx) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-
-  BN_MONT_CTX_free(mont);
-
-  return ok;
+  return 1;
 }
 
 DSA *DSAparams_dup(const DSA *dsa) {
@@ -529,14 +514,13 @@
 // neither inputs nor outputs are in Montgomery form.
 static int mod_mul_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                              const BN_MONT_CTX *mont, BN_CTX *ctx) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   // |BN_mod_mul_montgomery| removes a factor of R, so we cancel it with a
   // single |BN_to_montgomery| which adds one factor of R.
-  int ok = tmp != NULL && BN_to_montgomery(tmp, a, mont, ctx) &&
-           BN_mod_mul_montgomery(r, tmp, b, mont, ctx);
-  BN_CTX_end(ctx);
-  return ok;
+  return tmp != nullptr &&  //
+         BN_to_montgomery(tmp, a, mont, ctx) &&
+         BN_mod_mul_montgomery(r, tmp, b, mont, ctx);
 }
 
 DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, const DSA *dsa) {
diff --git a/crypto/fipsmodule/bn/div.cc.inc b/crypto/fipsmodule/bn/div.cc.inc
index b09f9fe..72ac926 100644
--- a/crypto/fipsmodule/bn/div.cc.inc
+++ b/crypto/fipsmodule/bn/div.cc.inc
@@ -147,7 +147,7 @@
     return 0;
   }
 
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   BIGNUM *snum = BN_CTX_get(ctx);
   BIGNUM *sdiv = BN_CTX_get(ctx);
@@ -155,7 +155,7 @@
   int norm_shift, num_n, loop, div_n;
   BN_ULONG d0, d1;
   if (tmp == NULL || snum == NULL || sdiv == NULL || res == NULL) {
-    goto err;
+    return 0;
   }
 
   // Knuth step D1: Normalise the numbers such that the divisor's MSB is set.
@@ -164,7 +164,7 @@
   norm_shift = BN_BITS2 - (BN_num_bits(divisor) % BN_BITS2);
   if (!BN_lshift(sdiv, divisor, norm_shift) ||
       !BN_lshift(snum, numerator, norm_shift)) {
-    goto err;
+    return 0;
   }
 
   // This algorithm relies on |sdiv| being minimal width. We do not use this
@@ -184,7 +184,7 @@
   //   digit in Knuth step D1.)
   num_n = snum->width <= div_n ? div_n + 1 : snum->width + 1;
   if (!bn_resize_words(snum, num_n)) {
-    goto err;
+    return 0;
   }
 
   // Knuth step D2: The quotient's width is the difference between numerator and
@@ -193,7 +193,7 @@
   res->neg = snum->neg ^ sdiv->neg;
   if (!bn_wexpand(res, loop) ||  //
       !bn_wexpand(tmp, div_n + 1)) {
-    goto err;
+    return 0;
   }
   res->width = loop;
 
@@ -312,15 +312,10 @@
 
   // Knuth step D8: Unnormalize. snum now contains the remainder.
   if (rem != NULL && !BN_rshift(rem, snum, norm_shift)) {
-    goto err;
+    return 0;
   }
 
-  BN_CTX_end(ctx);
   return 1;
-
-err:
-  BN_CTX_end(ctx);
-  return 0;
 }
 
 int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) {
@@ -396,8 +391,7 @@
   // but it is simple, easy to make constant-time, and performant enough for RSA
   // key generation.
 
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *q = quotient, *r = remainder;
   if (quotient == NULL || quotient == numerator || quotient == divisor) {
     q = BN_CTX_get(ctx);
@@ -410,7 +404,7 @@
   if (q == NULL || r == NULL || tmp == NULL ||
       !bn_wexpand(q, numerator->width) || !bn_wexpand(r, divisor->width) ||
       !bn_wexpand(tmp, divisor->width)) {
-    goto err;
+    return 0;
   }
 
   OPENSSL_memset(q->d, 0, numerator->width * sizeof(BN_ULONG));
@@ -461,14 +455,10 @@
 
   if ((quotient != NULL && !BN_copy(quotient, q)) ||
       (remainder != NULL && !BN_copy(remainder, r))) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 static BIGNUM *bn_scratch_space_from_ctx(size_t width, BN_CTX *ctx) {
@@ -510,26 +500,24 @@
 
 int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                      const BIGNUM *m) {
-  BN_CTX *ctx = BN_CTX_new();
-  int ok = ctx != NULL && bn_mod_add_consttime(r, a, b, m, ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  return ctx != nullptr && bn_mod_add_consttime(r, a, b, m, ctx.get());
 }
 
 int bn_mod_add_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                          const BIGNUM *m, BN_CTX *ctx) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   a = bn_resized_from_ctx(a, m->width, ctx);
   b = bn_resized_from_ctx(b, m->width, ctx);
   BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx);
-  int ok = a != NULL && b != NULL && tmp != NULL && bn_wexpand(r, m->width);
-  if (ok) {
-    bn_mod_add_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
-    r->width = m->width;
-    r->neg = 0;
+  if (a == nullptr || b == nullptr || tmp == nullptr ||
+      !bn_wexpand(r, m->width)) {
+    return 0;
   }
-  BN_CTX_end(ctx);
-  return ok;
+  bn_mod_add_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
+  r->width = m->width;
+  r->neg = 0;
+  return 1;
 }
 
 int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
@@ -542,58 +530,49 @@
 
 int bn_mod_sub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                          const BIGNUM *m, BN_CTX *ctx) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   a = bn_resized_from_ctx(a, m->width, ctx);
   b = bn_resized_from_ctx(b, m->width, ctx);
   BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx);
-  int ok = a != NULL && b != NULL && tmp != NULL && bn_wexpand(r, m->width);
-  if (ok) {
-    bn_mod_sub_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
-    r->width = m->width;
-    r->neg = 0;
+  if (a == nullptr || b == nullptr || tmp == nullptr ||
+      !bn_wexpand(r, m->width)) {
+    return 0;
   }
-  BN_CTX_end(ctx);
-  return ok;
+  bn_mod_sub_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
+  r->width = m->width;
+  r->neg = 0;
+  return 1;
 }
 
 int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                      const BIGNUM *m) {
-  BN_CTX *ctx = BN_CTX_new();
-  int ok = ctx != NULL && bn_mod_sub_consttime(r, a, b, m, ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  return ctx != nullptr && bn_mod_sub_consttime(r, a, b, m, ctx.get());
 }
 
 int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
                BN_CTX *ctx) {
-  BIGNUM *t;
-  int ret = 0;
-
-  BN_CTX_start(ctx);
-  t = BN_CTX_get(ctx);
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *t = BN_CTX_get(ctx);
   if (t == NULL) {
-    goto err;
+    return 0;
   }
 
   if (a == b) {
     if (!BN_sqr(t, a, ctx)) {
-      goto err;
+      return 0;
     }
   } else {
     if (!BN_mul(t, a, b, ctx)) {
-      goto err;
+      return 0;
     }
   }
 
   if (!BN_nnmod(r, t, m, ctx)) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) {
@@ -607,25 +586,20 @@
 
 int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
                   BN_CTX *ctx) {
-  BIGNUM *abs_m = NULL;
-  int ret;
-
   if (!BN_nnmod(r, a, m, ctx)) {
     return 0;
   }
 
+  bssl::UniquePtr<BIGNUM> abs_m;
   if (m->neg) {
-    abs_m = BN_dup(m);
-    if (abs_m == NULL) {
+    abs_m.reset(BN_dup(m));
+    if (abs_m == nullptr) {
       return 0;
     }
     abs_m->neg = 0;
   }
 
-  ret = bn_mod_lshift_consttime(r, r, n, (abs_m ? abs_m : m), ctx);
-
-  BN_free(abs_m);
-  return ret;
+  return bn_mod_lshift_consttime(r, r, n, (abs_m ? abs_m.get() : m), ctx);
 }
 
 int bn_mod_lshift_consttime(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
@@ -634,24 +608,21 @@
     return 0;
   }
 
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx);
-  int ok = tmp != NULL;
-  if (ok) {
-    for (int i = 0; i < n; i++) {
-      bn_mod_add_words(r->d, r->d, r->d, m->d, tmp->d, m->width);
-    }
-    r->neg = 0;
+  if (tmp == nullptr) {
+    return 0;
   }
-  BN_CTX_end(ctx);
-  return ok;
+  for (int i = 0; i < n; i++) {
+    bn_mod_add_words(r->d, r->d, r->d, m->d, tmp->d, m->width);
+  }
+  r->neg = 0;
+  return 1;
 }
 
 int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) {
-  BN_CTX *ctx = BN_CTX_new();
-  int ok = ctx != NULL && bn_mod_lshift_consttime(r, a, n, m, ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  return ctx != nullptr && bn_mod_lshift_consttime(r, a, n, m, ctx.get());
 }
 
 int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) {
@@ -668,10 +639,8 @@
 }
 
 int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) {
-  BN_CTX *ctx = BN_CTX_new();
-  int ok = ctx != NULL && bn_mod_lshift1_consttime(r, a, m, ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  return ctx != nullptr && bn_mod_lshift1_consttime(r, a, m, ctx.get());
 }
 
 BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
diff --git a/crypto/fipsmodule/bn/exponentiation.cc.inc b/crypto/fipsmodule/bn/exponentiation.cc.inc
index bcf88e5..b719bea 100644
--- a/crypto/fipsmodule/bn/exponentiation.cc.inc
+++ b/crypto/fipsmodule/bn/exponentiation.cc.inc
@@ -149,57 +149,55 @@
     return BN_one(rr);
   }
 
-  int ret = 0;
   BIGNUM *val[TABLE_SIZE];
-  BN_MONT_CTX *new_mont = NULL;
 
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *r = BN_CTX_get(ctx);
   val[0] = BN_CTX_get(ctx);
-  int window, r_is_one, wstart;
   if (r == NULL || val[0] == NULL) {
-    goto err;
+    return 0;
   }
 
   // Allocate a montgomery context if it was not supplied by the caller.
-  if (mont == NULL) {
-    new_mont = BN_MONT_CTX_new_consttime(m, ctx);
-    if (new_mont == NULL) {
-      goto err;
+  bssl::UniquePtr<BN_MONT_CTX> new_mont;
+  if (mont == nullptr) {
+    new_mont.reset(BN_MONT_CTX_new_consttime(m, ctx));
+    if (new_mont == nullptr) {
+      return 0;
     }
-    mont = new_mont;
+    mont = new_mont.get();
   }
 
   // We exponentiate by looking at sliding windows of the exponent and
   // precomputing powers of |a|. Windows may be shifted so they always end on a
   // set bit, so only precompute odd powers. We compute val[i] = a^(2*i + 1)
   // for i = 0 to 2^(window-1), all in Montgomery form.
-  window = BN_window_bits_for_exponent_size(bits);
+  int window = BN_window_bits_for_exponent_size(bits);
   if (!BN_to_montgomery(val[0], a, mont, ctx)) {
-    goto err;
+    return 0;
   }
   if (window > 1) {
     BIGNUM *d = BN_CTX_get(ctx);
     if (d == NULL || !BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx)) {
-      goto err;
+      return 0;
     }
     for (int i = 1; i < 1 << (window - 1); i++) {
       val[i] = BN_CTX_get(ctx);
       if (val[i] == NULL ||
           !BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx)) {
-        goto err;
+        return 0;
       }
     }
   }
 
   // |p| is non-zero, so at least one window is non-zero. To save some
   // multiplications, defer initializing |r| until then.
-  r_is_one = 1;
-  wstart = bits - 1;  // The top bit of the window.
+  int r_is_one = 1;
+  int wstart = bits - 1;  // The top bit of the window.
   for (;;) {
     if (!BN_is_bit_set(p, wstart)) {
       if (!r_is_one && !BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
-        goto err;
+        return 0;
       }
       if (wstart == 0) {
         break;
@@ -223,7 +221,7 @@
     if (!r_is_one) {
       for (int i = 0; i < wsize + 1; i++) {
         if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
-          goto err;
+          return 0;
         }
       }
     }
@@ -232,10 +230,10 @@
     assert(wvalue < (1 << window));
     if (r_is_one) {
       if (!BN_copy(r, val[wvalue >> 1])) {
-        goto err;
+        return 0;
       }
     } else if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx)) {
-      goto err;
+      return 0;
     }
 
     r_is_one = 0;
@@ -248,15 +246,7 @@
   // |p| is non-zero, so |r_is_one| must be cleared at some point.
   assert(!r_is_one);
 
-  if (!BN_from_montgomery(rr, r, mont, ctx)) {
-    goto err;
-  }
-  ret = 1;
-
-err:
-  BN_MONT_CTX_free(new_mont);
-  BN_CTX_end(ctx);
-  return ret;
+  return BN_from_montgomery(rr, r, mont, ctx);
 }
 
 void bn_mod_exp_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,