Replace OPENSSL_ARRAY_SIZE with std::size

In the STL, <iterator> has a std::size for arrays. Some of these could
also just be ranged for loops. One static_assert could not use
std::size(out->whatever) because out was not a compile-time value, but
std::extent_v<decltype(out->whatever)> works instead.

Change-Id: I28007c79f5583e09167b81a34a447e205ee6dd9b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/81658
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/asn1/a_strnid.cc b/crypto/asn1/a_strnid.cc
index c2a0c27..bbd5673 100644
--- a/crypto/asn1/a_strnid.cc
+++ b/crypto/asn1/a_strnid.cc
@@ -18,6 +18,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/err.h>
 #include <openssl/mem.h>
 #include <openssl/obj.h>
@@ -129,7 +131,7 @@
   ASN1_STRING_TABLE key;
   key.nid = nid;
   const ASN1_STRING_TABLE *tbl = reinterpret_cast<ASN1_STRING_TABLE *>(
-      bsearch(&key, tbl_standard, OPENSSL_ARRAY_SIZE(tbl_standard),
+      bsearch(&key, tbl_standard, std::size(tbl_standard),
               sizeof(ASN1_STRING_TABLE), table_cmp_void));
   if (tbl != NULL) {
     return tbl;
@@ -202,5 +204,5 @@
 void asn1_get_string_table_for_testing(const ASN1_STRING_TABLE **out_ptr,
                                        size_t *out_len) {
   *out_ptr = tbl_standard;
-  *out_len = OPENSSL_ARRAY_SIZE(tbl_standard);
+  *out_len = std::size(tbl_standard);
 }
diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc
index 36ef5d6..e2cf0d3 100644
--- a/crypto/asn1/asn1_test.cc
+++ b/crypto/asn1/asn1_test.cc
@@ -15,6 +15,7 @@
 #include <limits.h>
 #include <stdio.h>
 
+#include <iterator>
 #include <map>
 #include <string>
 #include <string_view>
@@ -460,13 +461,13 @@
     }
   }
 
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTests); i++) {
+  for (size_t i = 0; i < std::size(kTests); i++) {
     SCOPED_TRACE(Bytes(kTests[i].der));
     const uint8_t *ptr = kTests[i].der.data();
     bssl::UniquePtr<ASN1_INTEGER> a(
         d2i_ASN1_INTEGER(nullptr, &ptr, kTests[i].der.size()));
     ASSERT_TRUE(a);
-    for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(kTests); j++) {
+    for (size_t j = 0; j < std::size(kTests); j++) {
       SCOPED_TRACE(Bytes(kTests[j].der));
       ptr = kTests[j].der.data();
       bssl::UniquePtr<ASN1_INTEGER> b(
@@ -2185,7 +2186,7 @@
       {V_ASN1_UTF8STRING, {0xff, 0x00}, 0, false},
   };
   std::vector<bssl::UniquePtr<ASN1_STRING>> strs;
-  strs.reserve(OPENSSL_ARRAY_SIZE(kInputs));
+  strs.reserve(std::size(kInputs));
   for (const auto &input : kInputs) {
     strs.emplace_back(ASN1_STRING_type_new(input.type));
     ASSERT_TRUE(strs.back());
diff --git a/crypto/blake2/blake2.cc b/crypto/blake2/blake2.cc
index 3f69a6e..8173015 100644
--- a/crypto/blake2/blake2.cc
+++ b/crypto/blake2/blake2.cc
@@ -16,6 +16,8 @@
 
 #include <assert.h>
 
+#include <iterator>
+
 #include "../internal.h"
 
 // https://tools.ietf.org/html/rfc7693#section-2.6
@@ -99,7 +101,7 @@
                 blake2b_load(block, s[15]));
   }
 
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(b2b->h); i++) {
+  for (size_t i = 0; i < std::size(b2b->h); i++) {
     b2b->h[i] ^= v[i];
     b2b->h[i] ^= v[i + 8];
   }
diff --git a/crypto/cipher/get_cipher.cc b/crypto/cipher/get_cipher.cc
index 2622dc7..6513df0 100644
--- a/crypto/cipher/get_cipher.cc
+++ b/crypto/cipher/get_cipher.cc
@@ -55,17 +55,17 @@
 };
 
 const EVP_CIPHER *EVP_get_cipherbynid(int nid) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCiphers); i++) {
-    if (kCiphers[i].nid == nid) {
-      return kCiphers[i].func();
+  for (const auto &cipher : kCiphers) {
+    if (cipher.nid == nid) {
+      return cipher.func();
     }
   }
-  return NULL;
+  return nullptr;
 }
 
 const EVP_CIPHER *EVP_get_cipherbyname(const char *name) {
-  if (name == NULL) {
-    return NULL;
+  if (name == nullptr) {
+    return nullptr;
   }
 
   // This is not a name used by OpenSSL, but tcpdump registers it with
@@ -75,11 +75,11 @@
     name = "des-ede3-cbc";
   }
 
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCiphers); i++) {
-    if (OPENSSL_strcasecmp(kCiphers[i].name, name) == 0) {
-      return kCiphers[i].func();
+  for (const auto &cipher : kCiphers) {
+    if (OPENSSL_strcasecmp(cipher.name, name) == 0) {
+      return cipher.func();
     }
   }
 
-  return NULL;
+  return nullptr;
 }
diff --git a/crypto/compiler_test.cc b/crypto/compiler_test.cc
index c65028f..04978d2 100644
--- a/crypto/compiler_test.cc
+++ b/crypto/compiler_test.cc
@@ -15,6 +15,7 @@
 #include <limits.h>
 #include <stdint.h>
 
+#include <iterator>
 #include <type_traits>
 
 #include <gtest/gtest.h>
@@ -204,7 +205,7 @@
   }
 
   int ints[256];
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(ints); i++) {
+  for (size_t i = 0; i < std::size(ints); i++) {
     EXPECT_EQ(reinterpret_cast<uintptr_t>(ints) + i * sizeof(int),
               reinterpret_cast<uintptr_t>(ints + i));
   }
diff --git a/crypto/curve25519/spake25519.cc b/crypto/curve25519/spake25519.cc
index 2a3164b..cf149bf 100644
--- a/crypto/curve25519/spake25519.cc
+++ b/crypto/curve25519/spake25519.cc
@@ -17,6 +17,8 @@
 #include <assert.h>
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/bytestring.h>
 #include <openssl/mem.h>
 #include <openssl/rand.h>
@@ -333,18 +335,17 @@
 // scalar_cmov copies |src| to |dest| if |mask| is all ones.
 static void scalar_cmov(scalar *dest, const scalar *src, crypto_word_t mask) {
   bn_select_words(dest->words, mask, src->words, dest->words,
-                  OPENSSL_ARRAY_SIZE(dest->words));
+                  std::size(dest->words));
 }
 
 // scalar_double sets |s| to |2×s|.
 static void scalar_double(scalar *s) {
-  bn_add_words(s->words, s->words, s->words, OPENSSL_ARRAY_SIZE(s->words));
+  bn_add_words(s->words, s->words, s->words, std::size(s->words));
 }
 
 // scalar_add sets |dest| to |dest| plus |src|.
 static void scalar_add(scalar *dest, const scalar *src) {
-  bn_add_words(dest->words, dest->words, src->words,
-               OPENSSL_ARRAY_SIZE(dest->words));
+  bn_add_words(dest->words, dest->words, src->words, std::size(dest->words));
 }
 
 int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len,
diff --git a/crypto/dh/params.cc b/crypto/dh/params.cc
index 115505f..9c1e857 100644
--- a/crypto/dh/params.cc
+++ b/crypto/dh/params.cc
@@ -17,13 +17,13 @@
 #include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
+#include <openssl/span.h>
 
 #include "../fipsmodule/bn/internal.h"
 #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, bssl::Span<const BN_ULONG> words) {
   BIGNUM *alloc = NULL;
   if (ret == NULL) {
     alloc = BN_new();
@@ -33,7 +33,7 @@
     ret = alloc;
   }
 
-  if (!bn_set_words(ret, words, num_words)) {
+  if (!bn_set_words(ret, words.data(), words.size())) {
     BN_free(alloc);
     return NULL;
   }
@@ -56,7 +56,7 @@
       TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1),
       TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff),
   };
-  return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords));
+  return get_params(ret, kWords);
 }
 
 BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *ret) {
@@ -78,7 +78,7 @@
       TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1),
       TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff),
   };
-  return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords));
+  return get_params(ret, kWords);
 }
 
 BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *ret) {
@@ -108,7 +108,7 @@
       TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1),
       TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff),
   };
-  return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords));
+  return get_params(ret, kWords);
 }
 
 BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *ret) {
@@ -146,7 +146,7 @@
       TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1),
       TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff),
   };
-  return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords));
+  return get_params(ret, kWords);
 }
 
 BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *ret) {
@@ -200,7 +200,7 @@
       TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1),
       TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff),
   };
-  return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords));
+  return get_params(ret, kWords);
 }
 
 BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *ret) {
@@ -270,7 +270,7 @@
       TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1),
       TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff),
   };
-  return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords));
+  return get_params(ret, kWords);
 }
 
 int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator,
diff --git a/crypto/digest/digest_extra.cc b/crypto/digest/digest_extra.cc
index 03df5f7..345c94f 100644
--- a/crypto/digest/digest_extra.cc
+++ b/crypto/digest/digest_extra.cc
@@ -73,9 +73,9 @@
     return NULL;
   }
 
-  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) {
-    if (nid_to_digest_mapping[i].nid == nid) {
-      return nid_to_digest_mapping[i].md_func();
+  for (const auto &mapping : nid_to_digest_mapping) {
+    if (mapping.nid == nid) {
+      return mapping.md_func();
     }
   }
 
@@ -207,16 +207,16 @@
 }
 
 const EVP_MD *EVP_get_digestbyname(const char *name) {
-  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) {
-    const char *short_name = nid_to_digest_mapping[i].short_name;
-    const char *long_name = nid_to_digest_mapping[i].long_name;
+  for (const auto &mapping : nid_to_digest_mapping) {
+    const char *short_name = mapping.short_name;
+    const char *long_name = mapping.long_name;
     if ((short_name && strcmp(short_name, name) == 0) ||
         (long_name && strcmp(long_name, name) == 0)) {
-      return nid_to_digest_mapping[i].md_func();
+      return mapping.md_func();
     }
   }
 
-  return NULL;
+  return nullptr;
 }
 
 static void blake2b256_init(EVP_MD_CTX *ctx) {
diff --git a/crypto/digest/digest_test.cc b/crypto/digest/digest_test.cc
index 8cdc48d..e3047e7 100644
--- a/crypto/digest/digest_test.cc
+++ b/crypto/digest/digest_test.cc
@@ -16,6 +16,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <iterator>
 #include <memory>
 #include <vector>
 
@@ -253,7 +254,7 @@
 }
 
 TEST(DigestTest, TestVectors) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTestVectors); i++) {
+  for (size_t i = 0; i < std::size(kTestVectors); i++) {
     SCOPED_TRACE(i);
     TestDigest(&kTestVectors[i]);
   }
diff --git a/crypto/fipsmodule/bn/bn_test.cc b/crypto/fipsmodule/bn/bn_test.cc
index 78ee00f..969f402 100644
--- a/crypto/fipsmodule/bn/bn_test.cc
+++ b/crypto/fipsmodule/bn/bn_test.cc
@@ -2017,7 +2017,7 @@
   int is_probably_prime_1 = 0, is_probably_prime_2 = 0;
   enum bn_primality_result_t result_3;
 
-  const int max_prime = kPrimes[OPENSSL_ARRAY_SIZE(kPrimes) - 1];
+  const int max_prime = kPrimes[std::size(kPrimes) - 1];
   size_t next_prime_index = 0;
 
   for (int i = 0; i <= max_prime; i++) {
@@ -2483,32 +2483,27 @@
 
   // Determine where the single-word values stop.
   size_t one_word;
-  for (one_word = 0; one_word < OPENSSL_ARRAY_SIZE(kTestVectors); one_word++) {
-    int is_word = 1;
-    for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(kTestVectors[one_word]); i++) {
-      if (kTestVectors[one_word][i] != 0) {
-        is_word = 0;
-        break;
-      }
-    }
-    if (!is_word) {
+  for (one_word = 0; one_word < std::size(kTestVectors); one_word++) {
+    if (std::any_of(std::begin(kTestVectors[one_word]) + 1,
+                    std::end(kTestVectors[one_word]),
+                    [](BN_ULONG w) { return w != 0; })) {
       break;
     }
   }
 
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTestVectors); i++) {
+  for (size_t i = 0; i < std::size(kTestVectors); i++) {
     SCOPED_TRACE(i);
-    for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(kTestVectors); j++) {
+    for (size_t j = 0; j < std::size(kTestVectors); j++) {
       SCOPED_TRACE(j);
       EXPECT_EQ(i < j ? 1 : 0,
                 bn_less_than_words(kTestVectors[i], kTestVectors[j],
-                                   OPENSSL_ARRAY_SIZE(kTestVectors[i])));
+                                   std::size(kTestVectors[i])));
       for (size_t k = 0; k < one_word; k++) {
         SCOPED_TRACE(k);
         EXPECT_EQ(k <= i && i < j ? 1 : 0,
                   bn_in_range_words(kTestVectors[i], kTestVectors[k][0],
                                     kTestVectors[j],
-                                    OPENSSL_ARRAY_SIZE(kTestVectors[i])));
+                                    std::size(kTestVectors[i])));
       }
     }
   }
diff --git a/crypto/fipsmodule/bn/prime.cc.inc b/crypto/fipsmodule/bn/prime.cc.inc
index fabb545..cf9c203 100644
--- a/crypto/fipsmodule/bn/prime.cc.inc
+++ b/crypto/fipsmodule/bn/prime.cc.inc
@@ -14,6 +14,8 @@
 
 #include <openssl/bn.h>
 
+#include <iterator>
+
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
@@ -193,9 +195,9 @@
 // of excluding a candidate with trial division is larger.
 static size_t num_trial_division_primes(const BIGNUM *n) {
   if (n->width * BN_BITS2 > 1024) {
-    return OPENSSL_ARRAY_SIZE(kPrimes);
+    return std::size(kPrimes);
   }
-  return OPENSSL_ARRAY_SIZE(kPrimes) / 2;
+  return std::size(kPrimes) / 2;
 }
 
 // BN_PRIME_CHECKS_BLINDED is the iteration count for blinding the constant-time
diff --git a/crypto/fipsmodule/dh/dh.cc.inc b/crypto/fipsmodule/dh/dh.cc.inc
index c106940..097e4c6 100644
--- a/crypto/fipsmodule/dh/dh.cc.inc
+++ b/crypto/fipsmodule/dh/dh.cc.inc
@@ -16,6 +16,8 @@
 
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/bn.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
@@ -406,7 +408,7 @@
   }
 
   bn_set_static_words(ffdhe2048_p.get(), kFFDHE2048Data,
-                      OPENSSL_ARRAY_SIZE(kFFDHE2048Data));
+                      std::size(kFFDHE2048Data));
 
   if (!BN_rshift1(ffdhe2048_q.get(), ffdhe2048_p.get()) ||
       !BN_set_word(ffdhe2048_g.get(), 2) ||
diff --git a/crypto/fipsmodule/ec/ec.cc.inc b/crypto/fipsmodule/ec/ec.cc.inc
index 14916ee..4d76d0e 100644
--- a/crypto/fipsmodule/ec/ec.cc.inc
+++ b/crypto/fipsmodule/ec/ec.cc.inc
@@ -18,6 +18,8 @@
 #include <assert.h>
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
@@ -64,10 +66,10 @@
   OPENSSL_memcpy(out->oid, kOIDP224, sizeof(kOIDP224));
   out->oid_len = sizeof(kOIDP224);
 
-  ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP224Field),
-                            kP224Field, kP224FieldRR, kP224FieldN0);
-  ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP224Order),
-                            kP224Order, kP224OrderRR, kP224OrderN0);
+  ec_group_init_static_mont(&out->field, std::size(kP224Field), kP224Field,
+                            kP224FieldRR, kP224FieldN0);
+  ec_group_init_static_mont(&out->order, std::size(kP224Order), kP224Order,
+                            kP224OrderRR, kP224OrderN0);
 
 #if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL)
   out->meth = EC_GFp_nistp224_method();
@@ -98,10 +100,10 @@
   OPENSSL_memcpy(out->oid, kOIDP256, sizeof(kOIDP256));
   out->oid_len = sizeof(kOIDP256);
 
-  ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP256Field),
-                            kP256Field, kP256FieldRR, kP256FieldN0);
-  ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP256Order),
-                            kP256Order, kP256OrderRR, kP256OrderN0);
+  ec_group_init_static_mont(&out->field, std::size(kP256Field), kP256Field,
+                            kP256FieldRR, kP256FieldN0);
+  ec_group_init_static_mont(&out->order, std::size(kP256Order), kP256Order,
+                            kP256OrderRR, kP256OrderN0);
 
 #if !defined(OPENSSL_NO_ASM) &&                              \
     (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \
@@ -129,10 +131,10 @@
   OPENSSL_memcpy(out->oid, kOIDP384, sizeof(kOIDP384));
   out->oid_len = sizeof(kOIDP384);
 
-  ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP384Field),
-                            kP384Field, kP384FieldRR, kP384FieldN0);
-  ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP384Order),
-                            kP384Order, kP384OrderRR, kP384OrderN0);
+  ec_group_init_static_mont(&out->field, std::size(kP384Field), kP384Field,
+                            kP384FieldRR, kP384FieldN0);
+  ec_group_init_static_mont(&out->order, std::size(kP384Order), kP384Order,
+                            kP384OrderRR, kP384OrderN0);
 
   out->meth = EC_GFp_mont_method();
   out->generator.group = out;
@@ -154,10 +156,10 @@
   OPENSSL_memcpy(out->oid, kOIDP521, sizeof(kOIDP521));
   out->oid_len = sizeof(kOIDP521);
 
-  ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP521Field),
-                            kP521Field, kP521FieldRR, kP521FieldN0);
-  ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP521Order),
-                            kP521Order, kP521OrderRR, kP521OrderN0);
+  ec_group_init_static_mont(&out->field, std::size(kP521Field), kP521Field,
+                            kP521FieldRR, kP521FieldN0);
+  ec_group_init_static_mont(&out->order, std::size(kP521Order), kP521Order,
+                            kP521OrderRR, kP521OrderN0);
 
   out->meth = EC_GFp_mont_method();
   out->generator.group = out;
@@ -870,7 +872,7 @@
                        const EC_PRECOMP *a, const EC_PRECOMP *b) {
   static_assert(sizeof(out->comb) == sizeof(*out),
                 "out->comb does not span the entire structure");
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(out->comb); i++) {
+  for (size_t i = 0; i < std::size(out->comb); i++) {
     ec_affine_select(group, &out->comb[i], mask, &a->comb[i], &b->comb[i]);
   }
 }
diff --git a/crypto/fipsmodule/ec/p256-nistz.cc.inc b/crypto/fipsmodule/ec/p256-nistz.cc.inc
index e640712..fd01452 100644
--- a/crypto/fipsmodule/ec/p256-nistz.cc.inc
+++ b/crypto/fipsmodule/ec/p256-nistz.cc.inc
@@ -651,9 +651,9 @@
                   {4, i_111},     {5, i_111},    {5, i_101},    {3, i_11},
                   {10, i_101111}, {2, i_11},     {5, i_11},     {5, i_11},
                   {3, i_1},       {7, i_10101},  {6, i_1111}};
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kChain); i++) {
-    ecp_nistz256_ord_sqr_mont(out->words, out->words, kChain[i].p);
-    ecp_nistz256_ord_mul_mont(out->words, out->words, table[kChain[i].i]);
+  for (const auto &step : kChain) {
+    ecp_nistz256_ord_sqr_mont(out->words, out->words, step.p);
+    ecp_nistz256_ord_mul_mont(out->words, out->words, table[step.i]);
   }
 }
 
diff --git a/crypto/fipsmodule/ec/p256.cc.inc b/crypto/fipsmodule/ec/p256.cc.inc
index 6a8abcd..cdf28f2 100644
--- a/crypto/fipsmodule/ec/p256.cc.inc
+++ b/crypto/fipsmodule/ec/p256.cc.inc
@@ -26,6 +26,8 @@
 #include <assert.h>
 #include <string.h>
 
+#include <iterator>
+
 #include "../../internal.h"
 #include "../delocate.h"
 #include "./internal.h"
@@ -434,7 +436,7 @@
   fiat_p256_felem p2[3];
   fiat_p256_point_double(p2[0], p2[1], p2[2], p_pre_comp[0][0],
                          p_pre_comp[0][1], p_pre_comp[0][2]);
-  for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(p_pre_comp); i++) {
+  for (size_t i = 1; i < std::size(p_pre_comp); i++) {
     fiat_p256_point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2],
                         p_pre_comp[i - 1][0], p_pre_comp[i - 1][1],
                         p_pre_comp[i - 1][2], p2[0], p2[1], p2[2]);
diff --git a/crypto/fipsmodule/ec/simple_mul.cc.inc b/crypto/fipsmodule/ec/simple_mul.cc.inc
index 36288a7..b317ccd 100644
--- a/crypto/fipsmodule/ec/simple_mul.cc.inc
+++ b/crypto/fipsmodule/ec/simple_mul.cc.inc
@@ -16,6 +16,9 @@
 
 #include <assert.h>
 
+#include <iterator>
+#include <type_traits>
+
 #include "internal.h"
 #include "../bn/internal.h"
 #include "../../internal.h"
@@ -31,7 +34,7 @@
   EC_JACOBIAN precomp[32];
   ec_GFp_simple_point_set_to_infinity(group, &precomp[0]);
   ec_GFp_simple_point_copy(&precomp[1], p);
-  for (size_t j = 2; j < OPENSSL_ARRAY_SIZE(precomp); j++) {
+  for (size_t j = 2; j < std::size(precomp); j++) {
     if (j & 1) {
       ec_GFp_mont_add(group, &precomp[j], &precomp[1], &precomp[j - 1]);
     } else {
@@ -58,7 +61,7 @@
       // Select the entry in constant-time.
       EC_JACOBIAN tmp;
       OPENSSL_memset(&tmp, 0, sizeof(EC_JACOBIAN));
-      for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(precomp); j++) {
+      for (size_t j = 0; j < std::size(precomp); j++) {
         BN_ULONG mask = constant_time_eq_w(j, window);
         ec_point_select(group, &tmp, mask, &precomp[j], &tmp);
       }
@@ -202,10 +205,10 @@
 
   // Store the comb in affine coordinates to shrink the table. (This reduces
   // cache pressure and makes the constant-time selects faster.)
-  static_assert(OPENSSL_ARRAY_SIZE(comb) == OPENSSL_ARRAY_SIZE(out->comb),
-                "comb sizes did not match");
-  return ec_jacobian_to_affine_batch(group, out->comb, comb,
-                                     OPENSSL_ARRAY_SIZE(comb));
+  static_assert(
+      std::extent_v<decltype(comb)> == std::extent_v<decltype(out->comb)>,
+      "comb sizes did not match");
+  return ec_jacobian_to_affine_batch(group, out->comb, comb, std::size(comb));
 }
 
 static void ec_GFp_mont_get_comb_window(const EC_GROUP *group,
@@ -224,7 +227,7 @@
   // Select precomp->comb[window - 1]. If |window| is zero, |match| will always
   // be zero, which will leave |out| at infinity.
   OPENSSL_memset(out, 0, sizeof(EC_JACOBIAN));
-  for (unsigned j = 0; j < OPENSSL_ARRAY_SIZE(precomp->comb); j++) {
+  for (unsigned j = 0; j < std::size(precomp->comb); j++) {
     BN_ULONG match = constant_time_eq_w(window, j + 1);
     ec_felem_select(group, &out->X, match, &precomp->comb[j].X, &out->X);
     ec_felem_select(group, &out->Y, match, &precomp->comb[j].Y, &out->Y);
diff --git a/crypto/fipsmodule/ec/wnaf.cc.inc b/crypto/fipsmodule/ec/wnaf.cc.inc
index 6a9b29a..c733895 100644
--- a/crypto/fipsmodule/ec/wnaf.cc.inc
+++ b/crypto/fipsmodule/ec/wnaf.cc.inc
@@ -18,6 +18,8 @@
 #include <assert.h>
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
@@ -167,7 +169,7 @@
 
   int8_t g_wNAF[EC_MAX_BYTES * 8 + 1];
   EC_JACOBIAN g_precomp[EC_WNAF_TABLE_SIZE];
-  assert(wNAF_len <= OPENSSL_ARRAY_SIZE(g_wNAF));
+  assert(wNAF_len <= std::size(g_wNAF));
   const EC_JACOBIAN *g = &group->generator.raw;
   if (g_scalar != NULL) {
     ec_compute_wNAF(group, g_wNAF, g_scalar, bits, EC_WNAF_WINDOW_BITS);
@@ -175,7 +177,7 @@
   }
 
   for (size_t i = 0; i < num; i++) {
-    assert(wNAF_len <= OPENSSL_ARRAY_SIZE(wNAF[i]));
+    assert(wNAF_len <= std::size(wNAF[i]));
     ec_compute_wNAF(group, wNAF[i], &scalars[i], bits, EC_WNAF_WINDOW_BITS);
     compute_precomp(group, precomp[i], &points[i], EC_WNAF_TABLE_SIZE);
   }
diff --git a/crypto/fipsmodule/hkdf/hkdf_test.cc b/crypto/fipsmodule/hkdf/hkdf_test.cc
index fc8af6b..5d2db62 100644
--- a/crypto/fipsmodule/hkdf/hkdf_test.cc
+++ b/crypto/fipsmodule/hkdf/hkdf_test.cc
@@ -18,6 +18,8 @@
 #include <openssl/hkdf.h>
 #include <openssl/kdf.h>
 
+#include <iterator>
+
 #include <gtest/gtest.h>
 
 #include "../../test/file_test.h"
@@ -253,7 +255,7 @@
 };
 
 TEST(HKDFTest, TestVectors) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTests); i++) {
+  for (size_t i = 0; i < std::size(kTests); i++) {
     SCOPED_TRACE(i);
     const HKDFTestVector *test = &kTests[i];
 
diff --git a/crypto/fipsmodule/rsa/rsa.cc.inc b/crypto/fipsmodule/rsa/rsa.cc.inc
index 4c7c6ee..2341f51 100644
--- a/crypto/fipsmodule/rsa/rsa.cc.inc
+++ b/crypto/fipsmodule/rsa/rsa.cc.inc
@@ -18,6 +18,8 @@
 #include <limits.h>
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/bn.h>
 #include <openssl/digest.h>
 #include <openssl/engine.h>
@@ -869,8 +871,8 @@
                                               0x000017b1};
 
 DEFINE_LOCAL_DATA(BIGNUM, g_small_factors) {
-  out->d = (BN_ULONG *)kSmallFactorsLimbs;
-  out->width = OPENSSL_ARRAY_SIZE(kSmallFactorsLimbs);
+  out->d = const_cast<BN_ULONG *>(kSmallFactorsLimbs);
+  out->width = std::size(kSmallFactorsLimbs);
   out->dmax = out->width;
   out->neg = 0;
   out->flags = BN_FLG_STATIC_DATA;
diff --git a/crypto/fipsmodule/rsa/rsa_impl.cc.inc b/crypto/fipsmodule/rsa/rsa_impl.cc.inc
index 3fad8e0..5305f89 100644
--- a/crypto/fipsmodule/rsa/rsa_impl.cc.inc
+++ b/crypto/fipsmodule/rsa/rsa_impl.cc.inc
@@ -18,6 +18,8 @@
 #include <limits.h>
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
@@ -840,7 +842,7 @@
     TOBN(0xed17ac85, 0x83339915), TOBN(0x1d6f60ba, 0x893ba84c),
     TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484),
 };
-const size_t kBoringSSLRSASqrtTwoLen = OPENSSL_ARRAY_SIZE(kBoringSSLRSASqrtTwo);
+const size_t kBoringSSLRSASqrtTwoLen = std::size(kBoringSSLRSASqrtTwo);
 
 // generate_prime sets |out| to a prime with length |bits| such that |out|-1 is
 // relatively prime to |e|. If |p| is non-NULL, |out| will also not be close to
diff --git a/crypto/fipsmodule/self_check/fips.cc.inc b/crypto/fipsmodule/self_check/fips.cc.inc
index d51983c..65b0301 100644
--- a/crypto/fipsmodule/self_check/fips.cc.inc
+++ b/crypto/fipsmodule/self_check/fips.cc.inc
@@ -67,8 +67,8 @@
     "SHA2-512",
     "SHA2-512/256",
   };
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kApprovedAlgorithms); i++) {
-    if (strcmp(algorithm, kApprovedAlgorithms[i]) == 0) {
+  for (const char *approved : kApprovedAlgorithms) {
+    if (strcmp(algorithm, approved) == 0) {
       return 1;
     }
   }
diff --git a/crypto/fipsmodule/self_check/self_check.cc.inc b/crypto/fipsmodule/self_check/self_check.cc.inc
index a7999bb..fc92f32 100644
--- a/crypto/fipsmodule/self_check/self_check.cc.inc
+++ b/crypto/fipsmodule/self_check/self_check.cc.inc
@@ -17,6 +17,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <iterator>
+
 #include <openssl/aead.h>
 #include <openssl/aes.h>
 #include <openssl/bn.h>
@@ -269,7 +271,7 @@
   };
 
   bn_set_static_words(priv, kFFDHE2048PrivateKeyData,
-                      OPENSSL_ARRAY_SIZE(kFFDHE2048PrivateKeyData));
+                      std::size(kFFDHE2048PrivateKeyData));
 
   if (!DH_set0_key(dh, NULL, priv)) {
     goto err;
@@ -569,7 +571,7 @@
   ffdhe2048_value = BN_new();
   if (ffdhe2048_value) {
     bn_set_static_words(ffdhe2048_value, kFFDHE2048PublicValueData,
-                        OPENSSL_ARRAY_SIZE(kFFDHE2048PublicValueData));
+                        std::size(kFFDHE2048PublicValueData));
   }
 
   dh = self_test_dh();
diff --git a/crypto/hrss/hrss.cc b/crypto/hrss/hrss.cc
index 35311ef..c9cfcc5 100644
--- a/crypto/hrss/hrss.cc
+++ b/crypto/hrss/hrss.cc
@@ -17,6 +17,8 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+
+#include <iterator>
 #include <type_traits>
 
 #include <openssl/bn.h>
@@ -309,7 +311,7 @@
   };
 #endif
 
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMasks); i++) {
+  for (size_t i = 0; i < std::size(kMasks); i++) {
     in = ((in >> (1 << i)) & kMasks[i]) | ((in & kMasks[i]) << (1 << i));
   }
 
diff --git a/crypto/internal.h b/crypto/internal.h
index e1dcf223..95d60e1 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -104,8 +104,6 @@
 #endif
 #endif
 
-#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
-
 // GCC-like compilers indicate SSE2 with |__SSE2__|. MSVC leaves the caller to
 // know that x86_64 has SSE2, and uses _M_IX86_FP to indicate SSE2 on x86.
 // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170
diff --git a/crypto/obj/obj.cc b/crypto/obj/obj.cc
index 3f2d85e..a0723d9 100644
--- a/crypto/obj/obj.cc
+++ b/crypto/obj/obj.cc
@@ -18,6 +18,8 @@
 #include <limits.h>
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/asn1.h>
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
@@ -173,7 +175,7 @@
   CRYPTO_MUTEX_unlock_read(&global_added_lock);
 
   const uint16_t *nid_ptr = reinterpret_cast<const uint16_t *>(
-      bsearch(obj, kNIDsInOIDOrder, OPENSSL_ARRAY_SIZE(kNIDsInOIDOrder),
+      bsearch(obj, kNIDsInOIDOrder, std::size(kNIDsInOIDOrder),
               sizeof(kNIDsInOIDOrder[0]), obj_cmp));
   if (nid_ptr == NULL) {
     return NID_undef;
@@ -219,10 +221,9 @@
   }
   CRYPTO_MUTEX_unlock_read(&global_added_lock);
 
-  const uint16_t *nid_ptr = reinterpret_cast<const uint16_t *>(
-      bsearch(short_name, kNIDsInShortNameOrder,
-              OPENSSL_ARRAY_SIZE(kNIDsInShortNameOrder),
-              sizeof(kNIDsInShortNameOrder[0]), short_name_cmp));
+  const uint16_t *nid_ptr = reinterpret_cast<const uint16_t *>(bsearch(
+      short_name, kNIDsInShortNameOrder, std::size(kNIDsInShortNameOrder),
+      sizeof(kNIDsInShortNameOrder[0]), short_name_cmp));
   if (nid_ptr == NULL) {
     return NID_undef;
   }
@@ -254,9 +255,9 @@
   }
   CRYPTO_MUTEX_unlock_read(&global_added_lock);
 
-  const uint16_t *nid_ptr = reinterpret_cast<const uint16_t *>(bsearch(
-      long_name, kNIDsInLongNameOrder, OPENSSL_ARRAY_SIZE(kNIDsInLongNameOrder),
-      sizeof(kNIDsInLongNameOrder[0]), long_name_cmp));
+  const uint16_t *nid_ptr = reinterpret_cast<const uint16_t *>(
+      bsearch(long_name, kNIDsInLongNameOrder, std::size(kNIDsInLongNameOrder),
+              sizeof(kNIDsInLongNameOrder[0]), long_name_cmp));
   if (nid_ptr == NULL) {
     return NID_undef;
   }
diff --git a/crypto/obj/obj_xref.cc b/crypto/obj/obj_xref.cc
index 0095dea..8df2b4e 100644
--- a/crypto/obj/obj_xref.cc
+++ b/crypto/obj/obj_xref.cc
@@ -50,13 +50,13 @@
 };
 
 int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, int *out_pkey_nid) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTriples); i++) {
-    if (kTriples[i].sign_nid == sign_nid) {
+  for (const auto &triple : kTriples) {
+    if (triple.sign_nid == sign_nid) {
       if (out_digest_nid != NULL) {
-        *out_digest_nid = kTriples[i].digest_nid;
+        *out_digest_nid = triple.digest_nid;
       }
       if (out_pkey_nid != NULL) {
-        *out_pkey_nid = kTriples[i].pkey_nid;
+        *out_pkey_nid = triple.pkey_nid;
       }
       return 1;
     }
@@ -66,11 +66,11 @@
 }
 
 int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid, int pkey_nid) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTriples); i++) {
-    if (kTriples[i].digest_nid == digest_nid &&
-        kTriples[i].pkey_nid == pkey_nid) {
+  for (const auto &triple : kTriples) {
+    if (triple.digest_nid == digest_nid &&
+        triple.pkey_nid == pkey_nid) {
       if (out_sign_nid != NULL) {
-        *out_sign_nid = kTriples[i].sign_nid;
+        *out_sign_nid = triple.sign_nid;
       }
       return 1;
     }
diff --git a/crypto/pkcs8/pkcs8.cc b/crypto/pkcs8/pkcs8.cc
index 91a81fa..ba29550 100644
--- a/crypto/pkcs8/pkcs8.cc
+++ b/crypto/pkcs8/pkcs8.cc
@@ -271,15 +271,15 @@
 };
 
 static const struct pbe_suite *get_pkcs12_pbe_suite(int pbe_nid) {
-  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kBuiltinPBE); i++) {
-    if (kBuiltinPBE[i].pbe_nid == pbe_nid &&
+  for (const auto &pbe : kBuiltinPBE) {
+    if (pbe.pbe_nid == pbe_nid &&
         // If |cipher_func| or |md_func| are missing, this is a PBES2 scheme.
-        kBuiltinPBE[i].cipher_func != NULL && kBuiltinPBE[i].md_func != NULL) {
-      return &kBuiltinPBE[i];
+        pbe.cipher_func != nullptr && pbe.md_func != nullptr) {
+      return &pbe;
     }
   }
 
-  return NULL;
+  return nullptr;
 }
 
 int pkcs12_pbe_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, int alg_nid,
@@ -333,9 +333,9 @@
     goto err;
   }
 
-  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kBuiltinPBE); i++) {
-    if (CBS_mem_equal(&obj, kBuiltinPBE[i].oid, kBuiltinPBE[i].oid_len)) {
-      suite = &kBuiltinPBE[i];
+  for (const auto &pbe : kBuiltinPBE) {
+    if (CBS_mem_equal(&obj, pbe.oid, pbe.oid_len)) {
+      suite = &pbe;
       break;
     }
   }
diff --git a/crypto/rand/rand_test.cc b/crypto/rand/rand_test.cc
index 901ab49..3a20b3c 100644
--- a/crypto/rand/rand_test.cc
+++ b/crypto/rand/rand_test.cc
@@ -16,6 +16,8 @@
 
 #include <stdio.h>
 
+#include <iterator>
+
 #include <gtest/gtest.h>
 
 #include <openssl/span.h>
@@ -155,7 +157,7 @@
   for (const auto &buf : bufs) {
     EXPECT_NE(Bytes(buf), Bytes(kZeros));
   }
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(bufs); i++) {
+  for (size_t i = 0; i < std::size(bufs); i++) {
     for (size_t j = 0; j < i; j++) {
       EXPECT_NE(Bytes(bufs[i]), Bytes(bufs[j]))
           << "buffers " << i << " and " << j << " matched";
diff --git a/crypto/trust_token/pmbtoken.cc b/crypto/trust_token/pmbtoken.cc
index 58ba28f..1cab2d4 100644
--- a/crypto/trust_token/pmbtoken.cc
+++ b/crypto/trust_token/pmbtoken.cc
@@ -196,13 +196,13 @@
 
   const EC_SCALAR *scalars[] = {x0, y0, x1, y1, xs, ys};
   size_t scalar_len = BN_num_bytes(EC_GROUP_get0_order(group));
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) {
+  for (const EC_SCALAR *scalar : scalars) {
     uint8_t *buf;
     if (!CBB_add_space(out_private, &buf, scalar_len)) {
       OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL);
       return 0;
     }
-    ec_scalar_to_bytes(group, buf, &scalar_len, scalars[i]);
+    ec_scalar_to_bytes(group, buf, &scalar_len, scalar);
   }
 
   EC_AFFINE pub_affine[3];
@@ -287,10 +287,9 @@
   size_t scalar_len = BN_num_bytes(EC_GROUP_get0_order(group));
   EC_SCALAR *scalars[] = {&key->x0, &key->y0, &key->x1,
                           &key->y1, &key->xs, &key->ys};
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) {
+  for (EC_SCALAR *scalar : scalars) {
     if (!CBS_get_bytes(&cbs, &tmp, scalar_len) ||
-        !ec_scalar_from_bytes(group, scalars[i], CBS_data(&tmp),
-                              CBS_len(&tmp))) {
+        !ec_scalar_from_bytes(group, scalar, CBS_data(&tmp), CBS_len(&tmp))) {
       OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
       return 0;
     }
diff --git a/crypto/trust_token/trust_token.cc b/crypto/trust_token/trust_token.cc
index a5c2b87..ee1f3ec 100644
--- a/crypto/trust_token/trust_token.cc
+++ b/crypto/trust_token/trust_token.cc
@@ -12,12 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <openssl/trust_token.h>
+
+#include <iterator>
+
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/sha2.h>
-#include <openssl/trust_token.h>
 
 #include "internal.h"
 
@@ -226,7 +229,7 @@
 
 int TRUST_TOKEN_CLIENT_add_key(TRUST_TOKEN_CLIENT *ctx, size_t *out_key_index,
                                const uint8_t *key, size_t key_len) {
-  if (ctx->num_keys == OPENSSL_ARRAY_SIZE(ctx->keys) ||
+  if (ctx->num_keys == std::size(ctx->keys) ||
       ctx->num_keys >= ctx->method->max_keys) {
     OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_TOO_MANY_KEYS);
     return 0;
@@ -462,7 +465,7 @@
 
 int TRUST_TOKEN_ISSUER_add_key(TRUST_TOKEN_ISSUER *ctx, const uint8_t *key,
                                size_t key_len) {
-  if (ctx->num_keys == OPENSSL_ARRAY_SIZE(ctx->keys) ||
+  if (ctx->num_keys == std::size(ctx->keys) ||
       ctx->num_keys >= ctx->method->max_keys) {
     OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_TOO_MANY_KEYS);
     return 0;
diff --git a/crypto/x509/asn1_gen.cc b/crypto/x509/asn1_gen.cc
index 9b6bf17..6e56456 100644
--- a/crypto/x509/asn1_gen.cc
+++ b/crypto/x509/asn1_gen.cc
@@ -299,9 +299,9 @@
       {"SET", CBS_ASN1_SET},
   };
   CBS_ASN1_TAG type = 0;
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTypes); i++) {
-    if (cbs_str_equal(&name, kTypes[i].name)) {
-      type = kTypes[i].type;
+  for (const auto &t : kTypes) {
+    if (cbs_str_equal(&name, t.name)) {
+      type = t.type;
       break;
     }
   }
diff --git a/crypto/x509/v3_purp.cc b/crypto/x509/v3_purp.cc
index 096fa53..5e5b57c 100644
--- a/crypto/x509/v3_purp.cc
+++ b/crypto/x509/v3_purp.cc
@@ -105,18 +105,18 @@
 }
 
 const X509_PURPOSE *X509_PURPOSE_get0(int id) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(xstandard); i++) {
-    if (xstandard[i].purpose == id) {
-      return &xstandard[i];
+  for (const auto &p : xstandard) {
+    if (p.purpose == id) {
+      return &p;
     }
   }
   return NULL;
 }
 
 int X509_PURPOSE_get_by_sname(const char *sname) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(xstandard); i++) {
-    if (strcmp(xstandard[i].sname, sname) == 0) {
-      return xstandard[i].purpose;
+  for (const auto &p : xstandard) {
+    if (strcmp(p.sname, sname) == 0) {
+      return p.purpose;
     }
   }
   return -1;
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index f8e2b4c..5d905e2 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -15,6 +15,7 @@
 #include <limits.h>
 
 #include <algorithm>
+#include <iterator>
 #include <functional>
 #include <string>
 #include <string_view>
@@ -3092,8 +3093,8 @@
   bssl::UniquePtr<STACK_OF(X509_INFO)> infos(
       PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr));
   ASSERT_TRUE(infos);
-  ASSERT_EQ(OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) {
+  ASSERT_EQ(std::size(kExpected), sk_X509_INFO_num(infos.get()));
+  for (size_t i = 0; i < std::size(kExpected); i++) {
     SCOPED_TRACE(i);
     check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i));
   }
@@ -3103,13 +3104,12 @@
   ASSERT_TRUE(bio);
   ASSERT_EQ(infos.get(),
             PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr));
-  ASSERT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) {
+  ASSERT_EQ(2 * std::size(kExpected), sk_X509_INFO_num(infos.get()));
+  for (size_t i = 0; i < std::size(kExpected); i++) {
     SCOPED_TRACE(i);
     check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i));
-    check_info(
-        &kExpected[i],
-        sk_X509_INFO_value(infos.get(), i + OPENSSL_ARRAY_SIZE(kExpected)));
+    check_info(&kExpected[i],
+               sk_X509_INFO_value(infos.get(), i + std::size(kExpected)));
   }
 
   // Gracefully handle errors in both the append and fresh cases.
@@ -3125,7 +3125,7 @@
   ASSERT_TRUE(bio);
   EXPECT_FALSE(
       PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr));
-  EXPECT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
+  EXPECT_EQ(2 * std::size(kExpected), sk_X509_INFO_num(infos.get()));
 }
 
 TEST(X509Test, ReadBIOEmpty) {
@@ -4037,7 +4037,7 @@
   };
 
   // Every name should be equal to itself and not equal to any others.
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kNames); i++) {
+  for (size_t i = 0; i < std::size(kNames); i++) {
     SCOPED_TRACE(Bytes(kNames[i]));
 
     const uint8_t *ptr = kNames[i].data();
@@ -4052,7 +4052,7 @@
     bssl::UniquePtr<uint8_t> free_enc(enc);
     EXPECT_EQ(Bytes(enc, enc_len), Bytes(kNames[i]));
 
-    for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(kNames); j++) {
+    for (size_t j = 0; j < std::size(kNames); j++) {
       SCOPED_TRACE(Bytes(kNames[j]));
 
       ptr = kNames[j].data();
diff --git a/crypto/x509/x509_trs.cc b/crypto/x509/x509_trs.cc
index d5540bf..eb11804 100644
--- a/crypto/x509/x509_trs.cc
+++ b/crypto/x509/x509_trs.cc
@@ -43,9 +43,9 @@
     {X509_TRUST_TSA, trust_1oidany, NID_time_stamp}};
 
 static const X509_TRUST *X509_TRUST_get0(int id) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(trstandard); i++) {
-    if (trstandard[i].trust == id) {
-      return &trstandard[i];
+  for (const auto &t : trstandard) {
+    if (t.trust == id) {
+      return &t;
     }
   }
   return NULL;
diff --git a/fuzz/ssl_ctx_api.cc b/fuzz/ssl_ctx_api.cc
index ca74b05..9d5eee6 100644
--- a/fuzz/ssl_ctx_api.cc
+++ b/fuzz/ssl_ctx_api.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include <functional>
+#include <iterator>
 #include <string>
 #include <type_traits>
 #include <vector>
@@ -529,7 +530,7 @@
 
   // If the number of functions exceeds this limit then the code needs to do
   // more than sample a single uint8_t to pick the function.
-  static_assert(OPENSSL_ARRAY_SIZE(kAPIs) < 256, "kAPIs too large");
+  static_assert(std::size(kAPIs) < 256, "kAPIs too large");
 
   CBS cbs;
   CBS_init(&cbs, buf, len);
@@ -540,7 +541,7 @@
       break;
     }
 
-    kAPIs[index % OPENSSL_ARRAY_SIZE(kAPIs)](ctx.get(), &cbs);
+    kAPIs[index % std::size(kAPIs)](ctx.get(), &cbs);
   }
 
   bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
diff --git a/ssl/ssl_cipher.cc b/ssl/ssl_cipher.cc
index 724a0f2..8a21904 100644
--- a/ssl/ssl_cipher.cc
+++ b/ssl/ssl_cipher.cc
@@ -19,6 +19,8 @@
 #include <assert.h>
 #include <string.h>
 
+#include <iterator>
+
 #include <openssl/err.h>
 #include <openssl/md5.h>
 #include <openssl/mem.h>
@@ -445,7 +447,7 @@
     {"SHA384", 0, 0, 0, 0, 0},
 };
 
-static const size_t kCipherAliasesLen = OPENSSL_ARRAY_SIZE(kCipherAliases);
+static const size_t kCipherAliasesLen = std::size(kCipherAliases);
 
 bool ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
                              size_t *out_mac_secret_len,
@@ -916,11 +918,10 @@
       // Look for a matching exact cipher. These aren't allowed in multipart
       // rules.
       if (!multi && ch != '+') {
-        for (j = 0; j < OPENSSL_ARRAY_SIZE(kCiphers); j++) {
-          const SSL_CIPHER *cipher = &kCiphers[j];
-          if (rule_equals(cipher->name, buf, buf_len) ||
-              rule_equals(cipher->standard_name, buf, buf_len)) {
-            cipher_id = cipher->id;
+        for (const SSL_CIPHER &cipher : kCiphers) {
+          if (rule_equals(cipher.name, buf, buf_len) ||
+              rule_equals(cipher.standard_name, buf, buf_len)) {
+            cipher_id = cipher.id;
             break;
           }
         }
@@ -1037,18 +1038,16 @@
   };
 
   // Set up a linked list of ciphers.
-  CIPHER_ORDER co_list[OPENSSL_ARRAY_SIZE(kAESCiphers) +
-                       OPENSSL_ARRAY_SIZE(kChaChaCiphers) +
-                       OPENSSL_ARRAY_SIZE(kLegacyCiphers)];
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(co_list); i++) {
-    co_list[i].next =
-        i + 1 < OPENSSL_ARRAY_SIZE(co_list) ? &co_list[i + 1] : nullptr;
+  CIPHER_ORDER co_list[std::size(kAESCiphers) + std::size(kChaChaCiphers) +
+                       std::size(kLegacyCiphers)];
+  for (size_t i = 0; i < std::size(co_list); i++) {
+    co_list[i].next = i + 1 < std::size(co_list) ? &co_list[i + 1] : nullptr;
     co_list[i].prev = i == 0 ? nullptr : &co_list[i - 1];
     co_list[i].active = false;
     co_list[i].in_group = false;
   }
   CIPHER_ORDER *head = &co_list[0];
-  CIPHER_ORDER *tail = &co_list[OPENSSL_ARRAY_SIZE(co_list) - 1];
+  CIPHER_ORDER *tail = &co_list[std::size(co_list) - 1];
 
   // Order AES ciphers vs ChaCha ciphers based on whether we have AES hardware.
   //
@@ -1075,9 +1074,8 @@
     co_list[num++].cipher = SSL_get_cipher_by_value(id);
     assert(co_list[num - 1].cipher != nullptr);
   }
-  assert(num == OPENSSL_ARRAY_SIZE(co_list));
-  static_assert(OPENSSL_ARRAY_SIZE(co_list) + NumTLS13Ciphers() ==
-                    OPENSSL_ARRAY_SIZE(kCiphers),
+  assert(num == std::size(co_list));
+  static_assert(std::size(co_list) + NumTLS13Ciphers() == std::size(kCiphers),
                 "Not all ciphers are included in the cipher order");
 
   // If the rule_string begins with DEFAULT, apply the default rule before
@@ -1104,7 +1102,7 @@
   UniquePtr<STACK_OF(SSL_CIPHER)> cipherstack(sk_SSL_CIPHER_new_null());
   Array<bool> in_group_flags;
   if (cipherstack == nullptr ||
-      !in_group_flags.InitForOverwrite(OPENSSL_ARRAY_SIZE(kCiphers))) {
+      !in_group_flags.InitForOverwrite(std::size(kCiphers))) {
     return false;
   }
 
@@ -1221,7 +1219,7 @@
 
   c.id = 0x03000000L | value;
   return reinterpret_cast<const SSL_CIPHER *>(
-      bsearch(&c, kCiphers, OPENSSL_ARRAY_SIZE(kCiphers), sizeof(SSL_CIPHER),
+      bsearch(&c, kCiphers, std::size(kCiphers), sizeof(SSL_CIPHER),
               ssl_cipher_id_cmp_void));
 }
 
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index aa8ef8a..24c0d49 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -17,6 +17,7 @@
 #include <openssl/ssl.h>
 
 #include <algorithm>
+#include <iterator>
 
 #include <assert.h>
 #include <limits.h>
@@ -3273,11 +3274,9 @@
       // Encrypt-then-MAC extension is required for all CBC cipher suites and so
       // it's easier to drop them.
       SSL_CTX_set_strict_cipher_list(ctx, kTLS12Ciphers) &&
-      SSL_CTX_set1_group_ids(ctx, kGroups, OPENSSL_ARRAY_SIZE(kGroups)) &&
-      SSL_CTX_set_signing_algorithm_prefs(ctx, kSigAlgs,
-                                          OPENSSL_ARRAY_SIZE(kSigAlgs)) &&
-      SSL_CTX_set_verify_algorithm_prefs(ctx, kSigAlgs,
-                                         OPENSSL_ARRAY_SIZE(kSigAlgs));
+      SSL_CTX_set1_group_ids(ctx, kGroups, std::size(kGroups)) &&
+      SSL_CTX_set_signing_algorithm_prefs(ctx, kSigAlgs, std::size(kSigAlgs)) &&
+      SSL_CTX_set_verify_algorithm_prefs(ctx, kSigAlgs, std::size(kSigAlgs));
 }
 
 static int Configure(SSL *ssl) {
@@ -3287,11 +3286,9 @@
   return SSL_set_min_proto_version(ssl, TLS1_2_VERSION) &&
          SSL_set_max_proto_version(ssl, TLS1_3_VERSION) &&
          SSL_set_strict_cipher_list(ssl, kTLS12Ciphers) &&
-         SSL_set1_group_ids(ssl, kGroups, OPENSSL_ARRAY_SIZE(kGroups)) &&
-         SSL_set_signing_algorithm_prefs(ssl, kSigAlgs,
-                                         OPENSSL_ARRAY_SIZE(kSigAlgs)) &&
-         SSL_set_verify_algorithm_prefs(ssl, kSigAlgs,
-                                        OPENSSL_ARRAY_SIZE(kSigAlgs));
+         SSL_set1_group_ids(ssl, kGroups, std::size(kGroups)) &&
+         SSL_set_signing_algorithm_prefs(ssl, kSigAlgs, std::size(kSigAlgs)) &&
+         SSL_set_verify_algorithm_prefs(ssl, kSigAlgs, std::size(kSigAlgs));
 }
 
 }  // namespace fips202205
@@ -3320,11 +3317,10 @@
   return SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION) &&
          SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION) &&
          SSL_CTX_set_strict_cipher_list(ctx, kTLS12Ciphers) &&
-         SSL_CTX_set1_group_ids(ctx, kGroups, OPENSSL_ARRAY_SIZE(kGroups)) &&
+         SSL_CTX_set1_group_ids(ctx, kGroups, std::size(kGroups)) &&
          SSL_CTX_set_signing_algorithm_prefs(ctx, kSigAlgs,
-                                             OPENSSL_ARRAY_SIZE(kSigAlgs)) &&
-         SSL_CTX_set_verify_algorithm_prefs(ctx, kSigAlgs,
-                                            OPENSSL_ARRAY_SIZE(kSigAlgs));
+                                             std::size(kSigAlgs)) &&
+         SSL_CTX_set_verify_algorithm_prefs(ctx, kSigAlgs, std::size(kSigAlgs));
 }
 
 static int Configure(SSL *ssl) {
@@ -3333,11 +3329,9 @@
   return SSL_set_min_proto_version(ssl, TLS1_2_VERSION) &&
          SSL_set_max_proto_version(ssl, TLS1_3_VERSION) &&
          SSL_set_strict_cipher_list(ssl, kTLS12Ciphers) &&
-         SSL_set1_group_ids(ssl, kGroups, OPENSSL_ARRAY_SIZE(kGroups)) &&
-         SSL_set_signing_algorithm_prefs(ssl, kSigAlgs,
-                                         OPENSSL_ARRAY_SIZE(kSigAlgs)) &&
-         SSL_set_verify_algorithm_prefs(ssl, kSigAlgs,
-                                        OPENSSL_ARRAY_SIZE(kSigAlgs));
+         SSL_set1_group_ids(ssl, kGroups, std::size(kGroups)) &&
+         SSL_set_signing_algorithm_prefs(ssl, kSigAlgs, std::size(kSigAlgs)) &&
+         SSL_set_verify_algorithm_prefs(ssl, kSigAlgs, std::size(kSigAlgs));
 }
 
 }  // namespace wpa202304
diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc
index 5db3dc6..74a330a 100644
--- a/ssl/ssl_privkey.cc
+++ b/ssl/ssl_privkey.cc
@@ -101,12 +101,12 @@
 };
 
 static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kSignatureAlgorithms); i++) {
-    if (kSignatureAlgorithms[i].sigalg == sigalg) {
-      return &kSignatureAlgorithms[i];
+  for (const auto &alg : kSignatureAlgorithms) {
+    if (alg.sigalg == sigalg) {
+      return &alg;
     }
   }
-  return NULL;
+  return nullptr;
 }
 
 bssl::UniquePtr<EVP_PKEY> ssl_parse_peer_subject_public_key_info(
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index 4c1bd55..35711a7 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -18,6 +18,7 @@
 #include <time.h>
 
 #include <algorithm>
+#include <iterator>
 #include <limits>
 #include <string>
 #include <utility>
@@ -6444,8 +6445,7 @@
   };
 
   EXPECT_LT(1u, sk_SSL_CIPHER_num(SSL_get_ciphers(server.get())));
-  ASSERT_TRUE(
-      SSL_apply_handoff(server.get(), {handoff, OPENSSL_ARRAY_SIZE(handoff)}));
+  ASSERT_TRUE(SSL_apply_handoff(server.get(), handoff));
   EXPECT_EQ(1u, sk_SSL_CIPHER_num(SSL_get_ciphers(server.get())));
 }
 
@@ -6483,8 +6483,7 @@
 
   // The zero length means that the default list of groups is used.
   EXPECT_EQ(0u, server->config->supported_group_list.size());
-  ASSERT_TRUE(
-      SSL_apply_handoff(server.get(), {handoff, OPENSSL_ARRAY_SIZE(handoff)}));
+  ASSERT_TRUE(SSL_apply_handoff(server.get(), handoff));
   EXPECT_EQ(1u, server->config->supported_group_list.size());
 }
 
@@ -7397,10 +7396,10 @@
   // preferences will trigger HelloRetryRequest.
   static const int kClientPrefs[] = {NID_X25519, NID_X9_62_prime256v1};
   ASSERT_TRUE(SSL_CTX_set1_groups(client_ctx_.get(), kClientPrefs,
-                                  OPENSSL_ARRAY_SIZE(kClientPrefs)));
+                                  std::size(kClientPrefs)));
   static const int kServerPrefs[] = {NID_X9_62_prime256v1, NID_X25519};
   ASSERT_TRUE(SSL_CTX_set1_groups(server_ctx_.get(), kServerPrefs,
-                                  OPENSSL_ARRAY_SIZE(kServerPrefs)));
+                                  std::size(kServerPrefs)));
 
   ASSERT_TRUE(CreateClientAndServer());
   ASSERT_TRUE(CompleteHandshakesForQUIC());
@@ -9474,7 +9473,7 @@
       // Preserve existing duplicates.
       {{kName1, kName2, kName2}, kCert1 + kCert2, {kName1, kName2, kName2}},
   };
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTests); i++) {
+  for (size_t i = 0; i < std::size(kTests); i++) {
     SCOPED_TRACE(i);
     const auto &t = kTests[i];
 
@@ -9962,17 +9961,17 @@
   ASSERT_TRUE(ctx);
 
   static const uint16_t kInvalidPrefs[] = {1234};
-  EXPECT_FALSE(SSL_CTX_set_signing_algorithm_prefs(
-      ctx.get(), kInvalidPrefs, OPENSSL_ARRAY_SIZE(kInvalidPrefs)));
-  EXPECT_FALSE(SSL_CTX_set_verify_algorithm_prefs(
-      ctx.get(), kInvalidPrefs, OPENSSL_ARRAY_SIZE(kInvalidPrefs)));
+  EXPECT_FALSE(SSL_CTX_set_signing_algorithm_prefs(ctx.get(), kInvalidPrefs,
+                                                   std::size(kInvalidPrefs)));
+  EXPECT_FALSE(SSL_CTX_set_verify_algorithm_prefs(ctx.get(), kInvalidPrefs,
+                                                  std::size(kInvalidPrefs)));
 
   static const uint16_t kDuplicatePrefs[] = {SSL_SIGN_RSA_PKCS1_SHA256,
                                              SSL_SIGN_RSA_PKCS1_SHA256};
-  EXPECT_FALSE(SSL_CTX_set_signing_algorithm_prefs(
-      ctx.get(), kDuplicatePrefs, OPENSSL_ARRAY_SIZE(kDuplicatePrefs)));
-  EXPECT_FALSE(SSL_CTX_set_verify_algorithm_prefs(
-      ctx.get(), kDuplicatePrefs, OPENSSL_ARRAY_SIZE(kDuplicatePrefs)));
+  EXPECT_FALSE(SSL_CTX_set_signing_algorithm_prefs(ctx.get(), kDuplicatePrefs,
+                                                   std::size(kDuplicatePrefs)));
+  EXPECT_FALSE(SSL_CTX_set_verify_algorithm_prefs(ctx.get(), kDuplicatePrefs,
+                                                  std::size(kDuplicatePrefs)));
 }
 
 TEST(SSLTest, InvalidGroups) {
@@ -9980,13 +9979,13 @@
   ASSERT_TRUE(ctx);
 
   static const uint16_t kInvalidIDs[] = {1234};
-  EXPECT_FALSE(SSL_CTX_set1_group_ids(ctx.get(), kInvalidIDs,
-                                      OPENSSL_ARRAY_SIZE(kInvalidIDs)));
+  EXPECT_FALSE(
+      SSL_CTX_set1_group_ids(ctx.get(), kInvalidIDs, std::size(kInvalidIDs)));
 
   // This is a valid NID, but it is not a valid group.
   static const int kInvalidNIDs[] = {NID_rsaEncryption};
-  EXPECT_FALSE(SSL_CTX_set1_groups(ctx.get(), kInvalidNIDs,
-                                   OPENSSL_ARRAY_SIZE(kInvalidNIDs)));
+  EXPECT_FALSE(
+      SSL_CTX_set1_groups(ctx.get(), kInvalidNIDs, std::size(kInvalidNIDs)));
 }
 
 TEST(SSLTest, NameLists) {
diff --git a/ssl/ssl_versions.cc b/ssl/ssl_versions.cc
index 81b5fbf..0bbeed8 100644
--- a/ssl/ssl_versions.cc
+++ b/ssl/ssl_versions.cc
@@ -16,7 +16,7 @@
 
 #include <assert.h>
 
-#include <algorithm>
+#include <iterator>
 
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
@@ -213,7 +213,7 @@
   // enabled protocols. Note that this means it is impossible to set a maximum
   // version of the higest supported TLS version in a future-proof way.
   bool any_enabled = false;
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kProtocolVersions); i++) {
+  for (size_t i = 0; i < std::size(kProtocolVersions); i++) {
     // Only look at the versions already enabled.
     if (min_version > kProtocolVersions[i].version) {
       continue;
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index ff93490..4f65f16 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -1141,8 +1141,7 @@
     OPENSSL_memset(buf.get(), 0x42, kBufLen);
     static const size_t kRecordSizes[] = {
         0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
-    for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kRecordSizes); i++) {
-      const size_t len = kRecordSizes[i];
+    for (size_t len : kRecordSizes) {
       if (len > kBufLen) {
         fprintf(stderr, "Bad kRecordSizes value.\n");
         return false;
diff --git a/ssl/test/fuzzer.h b/ssl/test/fuzzer.h
index 7b5960d..32521a5 100644
--- a/ssl/test/fuzzer.h
+++ b/ssl/test/fuzzer.h
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #include <algorithm>
+#include <iterator>
 #include <vector>
 
 #include <openssl/bio.h>
@@ -454,8 +455,7 @@
         SSL_GROUP_MLKEM1024,       SSL_GROUP_X25519,
         SSL_GROUP_SECP256R1,       SSL_GROUP_SECP384R1,
         SSL_GROUP_SECP521R1};
-    if (!SSL_CTX_set1_group_ids(ctx_.get(), kGroups,
-                                OPENSSL_ARRAY_SIZE(kGroups))) {
+    if (!SSL_CTX_set1_group_ids(ctx_.get(), kGroups, std::size(kGroups))) {
       return false;
     }
 
diff --git a/tool/speed.cc b/tool/speed.cc
index a6e75e0..0f1d0a8 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -310,11 +310,11 @@
       {"RSA 4096", kDERRSAPrivate4096, kDERRSAPrivate4096Len},
   };
 
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kRSAKeys); i++) {
-    const std::string name = kRSAKeys[i].name;
+  for (const auto &key_info : kRSAKeys) {
+    const std::string name = key_info.name;
 
     bssl::UniquePtr<RSA> key(
-        RSA_private_key_from_bytes(kRSAKeys[i].key, kRSAKeys[i].key_len));
+        RSA_private_key_from_bytes(key_info.key, key_info.key_len));
     if (key == nullptr) {
       fprintf(stderr, "Failed to parse %s key.\n", name.c_str());
       ERR_print_errors_fp(stderr);
@@ -385,7 +385,7 @@
 
     if (!TimeFunctionParallel(&results, [&]() -> bool {
           return bssl::UniquePtr<RSA>(RSA_private_key_from_bytes(
-                     kRSAKeys[i].key, kRSAKeys[i].key_len)) != nullptr;
+                     key_info.key, key_info.key_len)) != nullptr;
         })) {
       fprintf(stderr, "Failed to parse %s key.\n", name.c_str());
       ERR_print_errors_fp(stderr);