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);