Pass span to CRYPT_AESSetIV()

This CL made feasible by fixed-size spans in pdfium.

Change-Id: I39a76f58e6579339ff5edf88484d9d8ce9e8b85c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/132850
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fdrm/fx_crypt_aes.cpp b/core/fdrm/fx_crypt_aes.cpp
index 57a0b3d..74d2fdf 100644
--- a/core/fdrm/fx_crypt_aes.cpp
+++ b/core/fdrm/fx_crypt_aes.cpp
@@ -448,14 +448,14 @@
                      (Sbox[(block[(i + C3) % Nb]) & 0xFF])))
 
 void aes_encrypt_nb_4(CRYPT_aes_context* ctx, uint32_t* block) {
-  int i;
   const int C1 = 1;
   const int C2 = 2;
   const int C3 = 3;
   const int Nb = 4;
   uint32_t* keysched = ctx->keysched.data();
   uint32_t newstate[4];
-  for (i = 0; i < ctx->Nr - 1; i++) {
+  CHECK_NE(ctx->Nr, 0u);
+  for (size_t i = 0; i < ctx->Nr - 1; i++) {
     ADD_ROUND_KEY_4();
     FMAKEWORD(0);
     FMAKEWORD(1);
@@ -493,14 +493,14 @@
                      (Sboxinv[(block[(i + C3) % Nb]) & 0xFF])))
 
 void aes_decrypt_nb_4(CRYPT_aes_context* ctx, uint32_t* block) {
-  int i;
   const int C1 = 4 - 1;
   const int C2 = 4 - 2;
   const int C3 = 4 - 3;
   const int Nb = 4;
   uint32_t* keysched = ctx->invkeysched.data();
   uint32_t newstate[4];
-  for (i = 0; i < ctx->Nr - 1; i++) {
+  CHECK_NE(ctx->Nr, 0);
+  for (size_t i = 0; i < ctx->Nr - 1; i++) {
     ADD_ROUND_KEY_4();
     FMAKEWORD(0);
     FMAKEWORD(1);
@@ -527,19 +527,16 @@
 
 }  // namespace
 
-void CRYPT_AESSetKey(CRYPT_aes_context* ctx,
-                     const uint8_t* key,
-                     uint32_t keylen) {
-  DCHECK(keylen == 16 || keylen == 24 || keylen == 32);
-  auto keyspan = UNSAFE_TODO(pdfium::span(key, keylen));
-  int Nk = keylen / 4;
+void CRYPT_AESSetKey(CRYPT_aes_context* ctx, pdfium::span<const uint8_t> key) {
+  CHECK(key.size() == 16 || key.size() == 24 || key.size() == 32);
+  size_t Nk = key.size() / 4;
   ctx->Nb = 4;
   ctx->Nr = 6 + (ctx->Nb > Nk ? ctx->Nb : Nk);
   int rconst = 1;
-  for (int i = 0; i < (ctx->Nr + 1) * ctx->Nb; i++) {
+  for (size_t i = 0; i < (ctx->Nr + 1) * ctx->Nb; i++) {
     if (i < Nk) {
       ctx->keysched[i] =
-          fxcrt::GetUInt32MSBFirst(keyspan.subspan(4u * i).first<4u>());
+          fxcrt::GetUInt32MSBFirst(key.subspan(4u * i).first<4u>());
     } else {
       uint32_t temp = ctx->keysched[i - 1];
       if (i % Nk == 0) {
@@ -565,10 +562,9 @@
       ctx->keysched[i] = ctx->keysched[i - Nk] ^ temp;
     }
   }
-  for (int i = 0; i <= ctx->Nr; i++) {
-    for (int j = 0; j < ctx->Nb; j++) {
-      uint32_t temp;
-      temp = ctx->keysched[(ctx->Nr - i) * ctx->Nb + j];
+  for (size_t i = 0; i <= ctx->Nr; i++) {
+    for (size_t j = 0; j < ctx->Nb; j++) {
+      uint32_t temp = ctx->keysched[(ctx->Nr - i) * ctx->Nb + j];
       if (i != 0 && i != ctx->Nr) {
         int a = (temp >> 24) & 0xFF;
         int b = (temp >> 16) & 0xFF;
@@ -584,39 +580,34 @@
   }
 }
 
-void CRYPT_AESSetIV(CRYPT_aes_context* ctx, const uint8_t* iv) {
-  for (int i = 0; i < ctx->Nb; i++) {
-    // TODO(tsepez): Pass actual span.
-    ctx->iv[i] = fxcrt::GetUInt32MSBFirst(
-        UNSAFE_TODO(pdfium::span(iv + 4u * i, 4u).first<4u>()));
+void CRYPT_AESSetIV(CRYPT_aes_context* ctx,
+                    pdfium::span<const uint8_t, 16> iv) {
+  for (size_t i = 0; i < ctx->Nb; i++) {
+    ctx->iv[i] = fxcrt::GetUInt32MSBFirst(iv.subspan(4u * i).first<4u>());
   }
 }
 
 void CRYPT_AESDecrypt(CRYPT_aes_context* ctx,
-                      uint8_t* dest,
-                      const uint8_t* src,
-                      uint32_t size) {
+                      pdfium::span<uint8_t> dest,
+                      pdfium::span<const uint8_t> src) {
   uint32_t iv[4];
   uint32_t x[4];
   uint32_t ct[4];
-  int i;
-  CHECK_EQ((size & 15), 0);
+  CHECK_EQ((src.size() & 15), 0);
+  CHECK_EQ(src.size(), dest.size());
   UNSAFE_TODO({
     FXSYS_memcpy(iv, ctx->iv.data(), sizeof(iv));
-    while (size != 0) {
-      for (i = 0; i < 4; i++) {
-        x[i] = ct[i] =
-            fxcrt::GetUInt32MSBFirst(pdfium::span(src + 4 * i, 4u).first<4u>());
+    while (!src.empty()) {
+      for (size_t i = 0; i < 4; i++) {
+        x[i] = ct[i] = fxcrt::GetUInt32MSBFirst(src.first<4u>());
+        src = src.subspan<4u>();
       }
       aes_decrypt_nb_4(ctx, x);
-      for (i = 0; i < 4; i++) {
-        fxcrt::PutUInt32MSBFirst(iv[i] ^ x[i],
-                                 pdfium::span(dest + 4 * i, 4u).first<4u>());
+      for (size_t i = 0; i < 4; i++) {
+        fxcrt::PutUInt32MSBFirst(iv[i] ^ x[i], dest.first<4u>());
+        dest = dest.subspan<4u>();
         iv[i] = ct[i];
       }
-      dest += 16;
-      src += 16;
-      size -= 16;
     }
     FXSYS_memcpy(ctx->iv.data(), iv, sizeof(iv));
   });
diff --git a/core/fdrm/fx_crypt_aes.h b/core/fdrm/fx_crypt_aes.h
index ab673d2..5f1e4ca 100644
--- a/core/fdrm/fx_crypt_aes.h
+++ b/core/fdrm/fx_crypt_aes.h
@@ -18,21 +18,18 @@
   static constexpr int kMaxNr = 14;
   static constexpr int kSchedSize = (kMaxNr + 1) * kMaxNb;
 
-  int Nb;
-  int Nr;
+  size_t Nb;
+  size_t Nr;
   std::array<uint32_t, kSchedSize> keysched;
   std::array<uint32_t, kSchedSize> invkeysched;
   std::array<uint32_t, kMaxNb> iv;
 };
 
-void CRYPT_AESSetKey(CRYPT_aes_context* ctx,
-                     const uint8_t* key,
-                     uint32_t keylen);
-void CRYPT_AESSetIV(CRYPT_aes_context* ctx, const uint8_t* iv);
+void CRYPT_AESSetKey(CRYPT_aes_context* ctx, pdfium::span<const uint8_t> key);
+void CRYPT_AESSetIV(CRYPT_aes_context* ctx, pdfium::span<const uint8_t, 16> iv);
 void CRYPT_AESDecrypt(CRYPT_aes_context* ctx,
-                      uint8_t* dest,
-                      const uint8_t* src,
-                      uint32_t size);
+                      pdfium::span<uint8_t> dest,
+                      pdfium::span<const uint8_t> src);
 void CRYPT_AESEncrypt(CRYPT_aes_context* ctx,
                       pdfium::span<uint8_t> dest,
                       pdfium::span<const uint8_t> src);
diff --git a/core/fdrm/fx_crypt_unittest.cpp b/core/fdrm/fx_crypt_unittest.cpp
index e5f1a226..e799be6 100644
--- a/core/fdrm/fx_crypt_unittest.cpp
+++ b/core/fdrm/fx_crypt_unittest.cpp
@@ -628,15 +628,14 @@
   std::vector<uint8_t> actual_ciphertext(plaintext_.size());
   std::vector<uint8_t> decrypted_plaintext(expected_ciphertext_.size());
 
-  CRYPT_AESSetKey(&encrypt_ctx_, key_.data(), key_.size());
-  CRYPT_AESSetIV(&encrypt_ctx_, iv_.data());
+  CRYPT_AESSetKey(&encrypt_ctx_, key_);
+  CRYPT_AESSetIV(&encrypt_ctx_, pdfium::span(iv_).first<16u>());
   CRYPT_AESEncrypt(&encrypt_ctx_, actual_ciphertext, plaintext_);
   ASSERT_EQ(actual_ciphertext, expected_ciphertext_);
 
-  CRYPT_AESSetKey(&decrypt_ctx_, key_.data(), key_.size());
-  CRYPT_AESSetIV(&decrypt_ctx_, iv_.data());
-  CRYPT_AESDecrypt(&decrypt_ctx_, decrypted_plaintext.data(),
-                   expected_ciphertext_.data(), expected_ciphertext_.size());
+  CRYPT_AESSetKey(&decrypt_ctx_, key_);
+  CRYPT_AESSetIV(&decrypt_ctx_, pdfium::span(iv_).first<16u>());
+  CRYPT_AESDecrypt(&decrypt_ctx_, decrypted_plaintext, expected_ciphertext_);
   EXPECT_EQ(decrypted_plaintext, plaintext_);
 }
 
diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.cpp b/core/fpdfapi/parser/cpdf_crypto_handler.cpp
index c76ce9d..baeb0f2 100644
--- a/core/fpdfapi/parser/cpdf_crypto_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_crypto_handler.cpp
@@ -70,8 +70,12 @@
     realkeylen = std::min(key_len_ + 5, sizeof(realkey));
   }
   if (cipher_ == Cipher::kAES) {
-    CRYPT_AESSetKey(aes_context_.get(),
-                    key_len_ == 32 ? encrypt_key_.data() : realkey, key_len_);
+    if (key_len_ == 32) {
+      CRYPT_AESSetKey(aes_context_.get(), encrypt_key_);
+    } else {
+      CRYPT_AESSetKey(aes_context_.get(),
+                      UNSAFE_TODO(pdfium::span(realkey, key_len_)));
+    }
 
     static constexpr size_t kIVSize = 16;
     static constexpr size_t kPaddingSize = 16;
@@ -80,15 +84,14 @@
 
     DataVector<uint8_t> dest(kIVSize + source_data_size + kPaddingSize);
     auto dest_span = pdfium::span(dest);
-    auto dest_iv_span = dest_span.first(kIVSize);
+    auto dest_iv_span = dest_span.first<kIVSize>();
     auto dest_data_span = dest_span.subspan(kIVSize, source_data_size);
     auto dest_padding_span = dest_span.subspan(kIVSize + source_data_size);
 
     for (auto& v : dest_iv_span) {
       v = static_cast<uint8_t>(rand());
     }
-    CRYPT_AESSetIV(aes_context_.get(), dest_iv_span.data());
-
+    CRYPT_AESSetIV(aes_context_.get(), dest_iv_span);
     CRYPT_AESEncrypt(aes_context_.get(), dest_data_span,
                      source.first(source_data_size));
 
@@ -120,7 +123,7 @@
     AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);
     pContext->iv_ = true;
     pContext->block_offset_ = 0;
-    CRYPT_AESSetKey(&pContext->context_, encrypt_key_.data(), 32);
+    CRYPT_AESSetKey(&pContext->context_, encrypt_key_);
     return pContext;
   }
   uint8_t key1[48];
@@ -139,7 +142,7 @@
     AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1);
     pContext->iv_ = true;
     pContext->block_offset_ = 0;
-    CRYPT_AESSetKey(&pContext->context_, realkey, 16);
+    CRYPT_AESSetKey(&pContext->context_, realkey);
     return pContext;
   }
   CRYPT_rc4_context* pContext = FX_Alloc(CRYPT_rc4_context, 1);
@@ -186,7 +189,7 @@
         pContext->block_offset_ = 0;
       } else if (src_off < source.size()) {
         uint8_t block_buf[16];
-        CRYPT_AESDecrypt(&pContext->context_, block_buf, pContext->block_, 16);
+        CRYPT_AESDecrypt(&pContext->context_, block_buf, pContext->block_);
         dest_buf.AppendSpan(block_buf);
         pContext->block_offset_ = 0;
       }
@@ -214,7 +217,7 @@
   auto* pContext = static_cast<AESCryptContext*>(context);
   if (pContext->block_offset_ == 16) {
     uint8_t block_buf[16];
-    CRYPT_AESDecrypt(&pContext->context_, block_buf, pContext->block_, 16);
+    CRYPT_AESDecrypt(&pContext->context_, block_buf, pContext->block_);
     if (block_buf[15] < 16) {
       dest_buf.AppendSpan(pdfium::span(block_buf).first(
           static_cast<size_t>(16 - block_buf[15])));
diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp
index 2b7616d..1cee21fb4 100644
--- a/core/fpdfapi/parser/cpdf_security_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler.cpp
@@ -127,9 +127,9 @@
 
   DataVector<uint8_t> encrypted_output;
   DataVector<uint8_t> inter_digest;
-  uint8_t* input = digest;
-  uint8_t* key = input;
-  uint8_t* iv = UNSAFE_TODO(input + 16);
+  pdfium::span<uint8_t> input(digest);
+  auto key = input.first<16u>();
+  auto iv = input.subspan<16u, 16u>();
   int i = 0;
   size_t block_size = 32;
   CRYPT_aes_context aes = {};
@@ -145,14 +145,15 @@
       UNSAFE_TODO({
         content.insert(std::end(content), password.unsigned_str(),
                        password.unsigned_str() + password.GetLength());
-        content.insert(std::end(content), input, input + block_size);
+        content.insert(std::end(content), input.data(),
+                       input.data() + block_size);
         if (vector) {
           content.insert(std::end(content), vector, vector + 48);
         }
       });
     }
     CHECK_EQ(content.size(), encrypted_output.size());
-    CRYPT_AESSetKey(&aes, key, 16);
+    CRYPT_AESSetKey(&aes, key);
     CRYPT_AESSetIV(&aes, iv);
     CRYPT_AESEncrypt(&aes, encrypted_output_span, content);
 
@@ -170,13 +171,13 @@
         inter_digest = CRYPT_SHA512Generate(encrypted_output_span);
         break;
     }
-    input = inter_digest.data();
-    key = input;
-    iv = UNSAFE_TODO(input + 16);
+    input = inter_digest;
+    key = input.first<16u>();
+    iv = input.subspan<16u, 16u>();
     ++i;
   } while (i < 64 || i - 32 < encrypted_output.back());
   if (hash) {
-    UNSAFE_TODO(FXSYS_memcpy(hash, input, 32));
+    UNSAFE_TODO(FXSYS_memcpy(hash, input.data(), 32));
   }
 }
 
@@ -385,11 +386,11 @@
   }
 
   CRYPT_aes_context aes = {};
-  CRYPT_AESSetKey(&aes, digest, sizeof(digest));
+  CRYPT_AESSetKey(&aes, digest);
   uint8_t iv[16] = {};
   CRYPT_AESSetIV(&aes, iv);
-  CRYPT_AESDecrypt(&aes, encrypt_key_.data(), ekey.unsigned_str(), 32);
-  CRYPT_AESSetKey(&aes, encrypt_key_.data(), encrypt_key_.size());
+  CRYPT_AESDecrypt(&aes, encrypt_key_, ekey.unsigned_span());
+  CRYPT_AESSetKey(&aes, encrypt_key_);
   CRYPT_AESSetIV(&aes, iv);
   ByteString perms = encrypt_dict_->GetByteStringFor("Perms");
   if (perms.IsEmpty()) {
@@ -401,7 +402,7 @@
       std::min(sizeof(perms_buf), static_cast<size_t>(perms.GetLength()));
   UNSAFE_TODO(FXSYS_memcpy(perms_buf, perms.unsigned_str(), copy_len));
   uint8_t buf[16];
-  CRYPT_AESDecrypt(&aes, buf, perms_buf, 16);
+  CRYPT_AESDecrypt(&aes, buf, perms_buf);
   if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') {
     return false;
   }
@@ -672,7 +673,7 @@
     CRYPT_SHA256Finish(&sha2, pdfium::span(digest1).first<32>());
   }
   CRYPT_aes_context aes = {};
-  CRYPT_AESSetKey(&aes, digest1, 32);
+  CRYPT_AESSetKey(&aes, pdfium::span(digest1).first<32>());
   uint8_t iv[16] = {};
   CRYPT_AESSetIV(&aes, iv);
   CRYPT_AESEncrypt(&aes, digest1, encrypt_key_);
@@ -703,7 +704,7 @@
               pdfium::span(buf).subspan<12, 4>());
 
   CRYPT_aes_context aes = {};
-  CRYPT_AESSetKey(&aes, encrypt_key_.data(), encrypt_key_.size());
+  CRYPT_AESSetKey(&aes, encrypt_key_);
 
   uint8_t iv[16] = {};
   CRYPT_AESSetIV(&aes, iv);