Various -Wshorten-64-to-32 fixes.

This is far from all of it, but finishes a good chunk of bcm.c.

Bug: 516
Change-Id: If764e5af1c6b62e8342554502ecc4d563e44bc50
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/54207
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/fipsmodule/aes/aes_nohw.c b/crypto/fipsmodule/aes/aes_nohw.c
index b5990b8..c5dec0e 100644
--- a/crypto/fipsmodule/aes/aes_nohw.c
+++ b/crypto/fipsmodule/aes/aes_nohw.c
@@ -1192,7 +1192,7 @@
   for (;;) {
     // Update counters.
     for (size_t i = 0; i < AES_NOHW_BATCH_SIZE; i++) {
-      CRYPTO_store_u32_be(ivs + 16 * i + 12, ctr + i);
+      CRYPTO_store_u32_be(ivs + 16 * i + 12, ctr + (uint32_t)i);
     }
 
     size_t todo = blocks >= AES_NOHW_BATCH_SIZE ? AES_NOHW_BATCH_SIZE : blocks;
diff --git a/crypto/fipsmodule/bn/bn.c b/crypto/fipsmodule/bn/bn.c
index f2e3b7b..f3fbb7a 100644
--- a/crypto/fipsmodule/bn/bn.c
+++ b/crypto/fipsmodule/bn/bn.c
@@ -67,6 +67,11 @@
 #include "../delocate.h"
 
 
+// BN_MAX_WORDS is the maximum number of words allowed in a |BIGNUM|. It is
+// sized so byte and bit counts of a |BIGNUM| always fit in |int|, with room to
+// spare.
+#define BN_MAX_WORDS (INT_MAX / (4 * BN_BITS2))
+
 BIGNUM *BN_new(void) {
   BIGNUM *bn = OPENSSL_malloc(sizeof(BIGNUM));
 
@@ -292,8 +297,9 @@
   }
   bn->d = (BN_ULONG *)words;
 
-  bn->width = num;
-  bn->dmax = num;
+  assert(num <= BN_MAX_WORDS);
+  bn->width = (int)num;
+  bn->dmax = (int)num;
   bn->neg = 0;
   bn->flags |= BN_FLG_STATIC_DATA;
 }
@@ -346,7 +352,7 @@
     return 1;
   }
 
-  if (words > (INT_MAX / (4 * BN_BITS2))) {
+  if (words > BN_MAX_WORDS) {
     OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
     return 0;
   }
@@ -403,7 +409,7 @@
     }
     OPENSSL_memset(bn->d + bn->width, 0,
                    (words - bn->width) * sizeof(BN_ULONG));
-    bn->width = words;
+    bn->width = (int)words;
     return 1;
   }
 
@@ -412,7 +418,7 @@
     OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
     return 0;
   }
-  bn->width = words;
+  bn->width = (int)words;
   return 1;
 }
 
diff --git a/crypto/fipsmodule/bn/bytes.c b/crypto/fipsmodule/bn/bytes.c
index 38d71a3..da27426 100644
--- a/crypto/fipsmodule/bn/bytes.c
+++ b/crypto/fipsmodule/bn/bytes.c
@@ -138,7 +138,7 @@
     BN_free(bn);
     return NULL;
   }
-  ret->width = num_words;
+  ret->width = (int)num_words;
 
   // Make sure the top bytes will be zeroed.
   ret->d[num_words - 1] = 0;
diff --git a/crypto/fipsmodule/bn/div.c b/crypto/fipsmodule/bn/div.c
index 02b9931..6de5a43 100644
--- a/crypto/fipsmodule/bn/div.c
+++ b/crypto/fipsmodule/bn/div.c
@@ -552,7 +552,7 @@
     return NULL;
   }
   ret->neg = 0;
-  ret->width = width;
+  ret->width = (int)width;
   return ret;
 }
 
diff --git a/crypto/fipsmodule/bn/div_extra.c b/crypto/fipsmodule/bn/div_extra.c
index 7f03f28..141f7da 100644
--- a/crypto/fipsmodule/bn/div_extra.c
+++ b/crypto/fipsmodule/bn/div_extra.c
@@ -70,7 +70,7 @@
   // This operation is not constant-time, but |p| and |d| are public values.
   // Note that |p| is at most 16, so the computation fits in |uint64_t|.
   assert(p <= 16);
-  uint32_t m = ((UINT64_C(1) << (32 + p)) + d - 1) / d;
+  uint32_t m = (uint32_t)(((UINT64_C(1) << (32 + p)) + d - 1) / d);
 
   uint16_t ret = 0;
   for (int i = bn->width - 1; i >= 0; i--) {
diff --git a/crypto/fipsmodule/bn/gcd_extra.c b/crypto/fipsmodule/bn/gcd_extra.c
index 53ab170..b4fe00e 100644
--- a/crypto/fipsmodule/bn/gcd_extra.c
+++ b/crypto/fipsmodule/bn/gcd_extra.c
@@ -240,8 +240,10 @@
 
   // Each loop iteration halves at least one of |u| and |v|. Thus we need at
   // most the combined bit width of inputs for at least one value to be zero.
-  unsigned a_bits = a_width * BN_BITS2, n_bits = n_width * BN_BITS2;
-  unsigned num_iters = a_bits + n_bits;
+  // |a_bits| and |n_bits| cannot overflow because |bn_wexpand| ensures bit
+  // counts fit in even |int|.
+  size_t a_bits = a_width * BN_BITS2, n_bits = n_width * BN_BITS2;
+  size_t num_iters = a_bits + n_bits;
   if (num_iters < a_bits) {
     OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
     goto err;
@@ -260,7 +262,7 @@
   //
   // After each loop iteration, u and v only get smaller, and at least one of
   // them shrinks by at least a factor of two.
-  for (unsigned i = 0; i < num_iters; i++) {
+  for (size_t i = 0; i < num_iters; i++) {
     BN_ULONG both_odd = word_is_odd_mask(u->d[0]) & word_is_odd_mask(v->d[0]);
 
     // If both |u| and |v| are odd, subtract the smaller from the larger.
diff --git a/crypto/fipsmodule/bn/internal.h b/crypto/fipsmodule/bn/internal.h
index 50fd362..f7c181e 100644
--- a/crypto/fipsmodule/bn/internal.h
+++ b/crypto/fipsmodule/bn/internal.h
@@ -439,7 +439,7 @@
 
 // bn_is_bit_set_words returns one if bit |bit| is set in |a| and zero
 // otherwise.
-int bn_is_bit_set_words(const BN_ULONG *a, size_t num, unsigned bit);
+int bn_is_bit_set_words(const BN_ULONG *a, size_t num, size_t bit);
 
 // bn_one_to_montgomery sets |r| to one in Montgomery form. It returns one on
 // success and zero on error. This function treats the bit width of the modulus
diff --git a/crypto/fipsmodule/bn/random.c b/crypto/fipsmodule/bn/random.c
index 4966778..2500cc1 100644
--- a/crypto/fipsmodule/bn/random.c
+++ b/crypto/fipsmodule/bn/random.c
@@ -336,7 +336,7 @@
   assert(bn_in_range_words(r->d, min_inclusive, max_exclusive->d, words));
 
   r->neg = 0;
-  r->width = words;
+  r->width = (int)words;
   return 1;
 }
 
diff --git a/crypto/fipsmodule/bn/shift.c b/crypto/fipsmodule/bn/shift.c
index 55f864e..6960e57 100644
--- a/crypto/fipsmodule/bn/shift.c
+++ b/crypto/fipsmodule/bn/shift.c
@@ -258,9 +258,9 @@
   return 1;
 }
 
-int bn_is_bit_set_words(const BN_ULONG *a, size_t num, unsigned bit) {
-  unsigned i = bit / BN_BITS2;
-  unsigned j = bit % BN_BITS2;
+int bn_is_bit_set_words(const BN_ULONG *a, size_t num, size_t bit) {
+  size_t i = bit / BN_BITS2;
+  size_t j = bit % BN_BITS2;
   if (i >= num) {
     return 0;
   }
diff --git a/crypto/fipsmodule/cipher/e_aes.c b/crypto/fipsmodule/cipher/e_aes.c
index 8d5ed4c..5f23793 100644
--- a/crypto/fipsmodule/cipher/e_aes.c
+++ b/crypto/fipsmodule/cipher/e_aes.c
@@ -47,6 +47,7 @@
  * ==================================================================== */
 
 #include <assert.h>
+#include <limits.h>
 #include <string.h>
 
 #include <openssl/aead.h>
@@ -289,8 +290,10 @@
 ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key,
                          block128_f *out_block, const uint8_t *key,
                          size_t key_bytes) {
+  // This function assumes the key length was previously validated.
+  assert(key_bytes == 128 / 8 || key_bytes == 192 / 8 || key_bytes == 256 / 8);
   if (hwaes_capable()) {
-    aes_hw_set_encrypt_key(key, key_bytes * 8, aes_key);
+    aes_hw_set_encrypt_key(key, (int)key_bytes * 8, aes_key);
     if (gcm_key != NULL) {
       CRYPTO_gcm128_init_key(gcm_key, aes_key, aes_hw_encrypt, 1);
     }
@@ -301,7 +304,7 @@
   }
 
   if (vpaes_capable()) {
-    vpaes_set_encrypt_key(key, key_bytes * 8, aes_key);
+    vpaes_set_encrypt_key(key, (int)key_bytes * 8, aes_key);
     if (out_block) {
       *out_block = vpaes_encrypt;
     }
@@ -318,7 +321,7 @@
 #endif
   }
 
-  aes_nohw_set_encrypt_key(key, key_bytes * 8, aes_key);
+  aes_nohw_set_encrypt_key(key, (int)key_bytes * 8, aes_key);
   if (gcm_key != NULL) {
     CRYPTO_gcm128_init_key(gcm_key, aes_key, aes_nohw_encrypt, 0);
   }
@@ -552,6 +555,14 @@
     return -1;
   }
 
+  if (len > INT_MAX) {
+    // This function signature can only express up to |INT_MAX| bytes encrypted.
+    //
+    // TODO(https://crbug.com/boringssl/494): Make the internal |EVP_CIPHER|
+    // calling convention |size_t|-clean.
+    return -1;
+  }
+
   if (in) {
     if (out == NULL) {
       if (!CRYPTO_gcm128_aad(&gctx->gcm, in, len)) {
@@ -580,7 +591,7 @@
         }
       }
     }
-    return len;
+    return (int)len;
   } else {
     if (!ctx->encrypt) {
       if (gctx->taglen < 0 ||
diff --git a/crypto/fipsmodule/cmac/cmac.c b/crypto/fipsmodule/cmac/cmac.c
index f5c805d..efffe5f 100644
--- a/crypto/fipsmodule/cmac/cmac.c
+++ b/crypto/fipsmodule/cmac/cmac.c
@@ -49,6 +49,7 @@
 #include <openssl/cmac.h>
 
 #include <assert.h>
+#include <limits.h>
 #include <string.h>
 
 #include <openssl/aes.h>
@@ -269,7 +270,10 @@
   }
 
   OPENSSL_memcpy(ctx->block, in, in_len);
-  ctx->block_used = in_len;
+  // |in_len| is bounded by |block_size|, which fits in |unsigned|.
+  static_assert(EVP_MAX_BLOCK_LENGTH < UINT_MAX,
+                "EVP_MAX_BLOCK_LENGTH is too large");
+  ctx->block_used = (unsigned)in_len;
   ret = 1;
 
 out:
diff --git a/crypto/fipsmodule/dh/dh.c b/crypto/fipsmodule/dh/dh.c
index 31eaff4..1a3c974 100644
--- a/crypto/fipsmodule/dh/dh.c
+++ b/crypto/fipsmodule/dh/dh.c
@@ -368,7 +368,8 @@
   int ret = -1;
   BIGNUM *shared_key = BN_CTX_get(ctx);
   if (shared_key && dh_compute_key(dh, shared_key, peers_key, ctx)) {
-    ret = BN_bn2bin(shared_key, out);
+    // A |BIGNUM|'s byte count fits in |int|.
+    ret = (int)BN_bn2bin(shared_key, out);
   }
 
   BN_CTX_end(ctx);
diff --git a/crypto/fipsmodule/rand/ctrdrbg.c b/crypto/fipsmodule/rand/ctrdrbg.c
index 0e8995f..805372f 100644
--- a/crypto/fipsmodule/rand/ctrdrbg.c
+++ b/crypto/fipsmodule/rand/ctrdrbg.c
@@ -184,7 +184,7 @@
       OPENSSL_memset(out, 0, todo);
       ctr32_add(drbg, 1);
       drbg->ctr(out, out, num_blocks, &drbg->ks, drbg->counter);
-      ctr32_add(drbg, num_blocks - 1);
+      ctr32_add(drbg, (uint32_t)(num_blocks - 1));
     } else {
       for (size_t i = 0; i < todo; i += AES_BLOCK_SIZE) {
         ctr32_add(drbg, 1);
diff --git a/crypto/fipsmodule/rsa/rsa.c b/crypto/fipsmodule/rsa/rsa.c
index 733e7fa..14cdae5 100644
--- a/crypto/fipsmodule/rsa/rsa.c
+++ b/crypto/fipsmodule/rsa/rsa.c
@@ -300,7 +300,7 @@
     OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
     return -1;
   }
-  return out_len;
+  return (int)out_len;
 }
 
 static int rsa_sign_raw_no_self_test(RSA *rsa, size_t *out_len, uint8_t *out,
@@ -332,7 +332,7 @@
     OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
     return -1;
   }
-  return out_len;
+  return (int)out_len;
 }
 
 int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
@@ -347,7 +347,6 @@
 int RSA_private_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
                         int padding) {
   size_t out_len;
-
   if (!RSA_decrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
     return -1;
   }
@@ -356,13 +355,12 @@
     OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
     return -1;
   }
-  return out_len;
+  return (int)out_len;
 }
 
 int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
                        int padding) {
   size_t out_len;
-
   if (!RSA_verify_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
     return -1;
   }
@@ -371,15 +369,16 @@
     OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
     return -1;
   }
-  return out_len;
+  return (int)out_len;
 }
 
 unsigned RSA_size(const RSA *rsa) {
-  if (rsa->meth->size) {
-    return rsa->meth->size(rsa);
-  }
-
-  return rsa_default_size(rsa);
+  size_t ret = rsa->meth->size ? rsa->meth->size(rsa) : rsa_default_size(rsa);
+  // RSA modulus sizes are bounded by |BIGNUM|, which must fit in |unsigned|.
+  //
+  // TODO(https://crbug.com/boringssl/516): Should we make this return |size_t|?
+  assert(ret < UINT_MAX);
+  return (unsigned)ret;
 }
 
 int RSA_is_opaque(const RSA *rsa) {
@@ -474,8 +473,6 @@
 int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len,
                          int *is_alloced, int hash_nid, const uint8_t *digest,
                          size_t digest_len) {
-  unsigned i;
-
   if (hash_nid == NID_md5_sha1) {
     // Special case: SSL signature, just check the length.
     if (digest_len != SSL_SIG_LENGTH) {
@@ -489,7 +486,7 @@
     return 1;
   }
 
-  for (i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) {
+  for (size_t i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) {
     const struct pkcs1_sig_prefix *sig_prefix = &kPKCS1SigPrefixes[i];
     if (sig_prefix->nid != hash_nid) {
       continue;
@@ -501,17 +498,14 @@
     }
 
     const uint8_t* prefix = sig_prefix->bytes;
-    unsigned prefix_len = sig_prefix->len;
-    unsigned signed_msg_len;
-    uint8_t *signed_msg;
-
-    signed_msg_len = prefix_len + digest_len;
+    size_t prefix_len = sig_prefix->len;
+    size_t signed_msg_len = prefix_len + digest_len;
     if (signed_msg_len < prefix_len) {
       OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_LONG);
       return 0;
     }
 
-    signed_msg = OPENSSL_malloc(signed_msg_len);
+    uint8_t *signed_msg = OPENSSL_malloc(signed_msg_len);
     if (!signed_msg) {
       OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
       return 0;
@@ -554,7 +548,12 @@
     goto err;
   }
 
-  *out_len = size_t_out_len;
+  if (size_t_out_len > UINT_MAX) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
+    goto err;
+  }
+
+  *out_len = (unsigned)size_t_out_len;
   ret = 1;
 
 err:
diff --git a/crypto/fipsmodule/tls/kdf.c b/crypto/fipsmodule/tls/kdf.c
index 6f2b68b..046cb52 100644
--- a/crypto/fipsmodule/tls/kdf.c
+++ b/crypto/fipsmodule/tls/kdf.c
@@ -91,7 +91,7 @@
   }
 
   for (;;) {
-    unsigned len;
+    unsigned len_u;
     uint8_t hmac[EVP_MAX_MD_SIZE];
     if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
         !HMAC_Update(&ctx, A1, A1_len) ||
@@ -100,16 +100,17 @@
         !HMAC_Update(&ctx, (const uint8_t *) label, label_len) ||
         !HMAC_Update(&ctx, seed1, seed1_len) ||
         !HMAC_Update(&ctx, seed2, seed2_len) ||
-        !HMAC_Final(&ctx, hmac, &len)) {
+        !HMAC_Final(&ctx, hmac, &len_u)) {
       goto err;
     }
+    size_t len = len_u;
     assert(len == chunk);
 
     // XOR the result into |out|.
     if (len > out_len) {
       len = out_len;
     }
-    for (unsigned i = 0; i < len; i++) {
+    for (size_t i = 0; i < len; i++) {
       out[i] ^= hmac[i];
     }
     out += len;
diff --git a/crypto/test/file_test.cc b/crypto/test/file_test.cc
index 47a6f4c..e1ab2aa 100644
--- a/crypto/test/file_test.cc
+++ b/crypto/test/file_test.cc
@@ -20,6 +20,7 @@
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -377,7 +378,8 @@
       return FileTest::kReadError;
     }
 
-    if (fgets(out, len, file_) == nullptr) {
+    len = std::min(len, size_t{INT_MAX});
+    if (fgets(out, static_cast<int>(len), file_) == nullptr) {
       return feof(file_) ? FileTest::kReadEOF : FileTest::kReadError;
     }
 
diff --git a/crypto/test/wycheproof_util.cc b/crypto/test/wycheproof_util.cc
index cd870dd..9d31706 100644
--- a/crypto/test/wycheproof_util.cc
+++ b/crypto/test/wycheproof_util.cc
@@ -14,6 +14,7 @@
 
 #include "./wycheproof_util.h"
 
+#include <limits.h>
 #include <stdlib.h>
 
 #include <algorithm>
@@ -138,7 +139,8 @@
     return nullptr;
   }
   BIGNUM *bn = nullptr;
-  if (BN_hex2bn(&bn, value.c_str()) != static_cast<int>(value.size())) {
+  if (value.size() > INT_MAX ||
+      BN_hex2bn(&bn, value.c_str()) != static_cast<int>(value.size())) {
     BN_free(bn);
     t->PrintLine("Could not decode value '%s'", value.c_str());
     return nullptr;
@@ -151,8 +153,9 @@
     // https://github.com/google/wycheproof/blob/0329f5b751ef102bd6b7b7181b6e049522a887f5/java/com/google/security/wycheproof/JsonUtil.java#L62.
     if ('0' > value[0] || value[0] > '7') {
       bssl::UniquePtr<BIGNUM> tmp(BN_new());
-      if (!tmp ||
-          !BN_set_bit(tmp.get(), value.size() * 4) ||
+      if (!tmp ||  //
+          value.size() > INT_MAX / 4 ||
+          !BN_set_bit(tmp.get(), static_cast<int>(value.size() * 4)) ||
           !BN_sub(ret.get(), ret.get(), tmp.get())) {
         return nullptr;
       }
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index 3a721fe..0f381af 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -205,6 +205,10 @@
 
 // BN_num_bytes returns the minimum number of bytes needed to represent the
 // absolute value of |bn|.
+//
+// While |size_t| is the preferred type for byte counts, callers can assume that
+// |BIGNUM|s are bounded such that this value, and its corresponding bit count,
+// will always fit in |int|.
 OPENSSL_EXPORT unsigned BN_num_bytes(const BIGNUM *bn);
 
 // BN_zero sets |bn| to zero.