am 994a7fc4: Update OEMCrypto Offset Tests

* commit '994a7fc4c1f696226e08fe2d9f1e4852fca147bc':
  Update OEMCrypto Offset Tests
This commit is contained in:
Fred Gylys-Colwell
2015-06-01 15:48:41 +00:00
committed by Android Git Automerger

View File

@@ -1342,7 +1342,7 @@ class Session {
int status = RSA_public_encrypt(session_key.size(), &session_key[0],
&(enc_session_key->front()), public_rsa_,
RSA_PKCS1_OAEP_PADDING);
if (status != RSA_size(public_rsa_)) {
if (static_cast<unsigned>(status) != RSA_size(public_rsa_)) {
cout << "GenerateRSASessionKey error encrypting session key. ";
dump_openssl_error();
return false;
@@ -2282,7 +2282,7 @@ TEST_F(OEMCryptoSessionTests, QueryKeyControl) {
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
const char *key_id = "no_key";
size = sizeof(block);
ASSERT_EQ(OEMCrypto_ERROR_NO_CONTENT_KEY,
ASSERT_NE(OEMCrypto_SUCCESS,
OEMCrypto_QueryKeyControl(
s.session_id(), reinterpret_cast<const uint8_t*>(key_id),
strlen(key_id), reinterpret_cast<uint8_t*>(&block), &size));
@@ -2444,148 +2444,180 @@ TEST_F(OEMCryptoSessionTests, DecryptZeroDuration) {
s.TestDecryptCTR();
}
TEST_F(OEMCryptoSessionTests, DecryptWithOffset) {
OEMCryptoResult sts;
Session s;
s.open();
s.GenerateTestSessionKeys();
s.FillSimpleMessage(kDuration, 0, 0);
s.EncryptAndSign();
s.LoadTestKeys();
// Select the key (from FillSimpleMessage)
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// Set up our expected input and output
// This is dummy encrypted data.
vector<uint8_t> encryptedData = wvcdm::a2b_hex(
"c17055d4e3ab8e892b40ca2deed7cd46b406cd41d50f23d5877b36"
"ad351887df2b3774dc413904afd958ba766cc6ab51a3ffd8f845296c5d8326ee"
"39c9d0fec79885515e6b8a12911831d9fb158ca2fd3dfcfcf228741a63734685"
"8dffc30f5871260c5cef8be61cfa08b191c837901f077046664c0c56db81d412"
"98b59e5655cd94871c3c226dc3565144297f1459cddba069d5d2d6206cfd5798"
"eda4b82e01a9966d48984d6ef3fbd326ba0f6fcbe52c95786d478c2f33398c62"
"ae5210c7472d7d8dc7d12f981679f4ea9793736f354747ef14165367b94e07fc"
"4bcc7bd14746304fea100dc6465ab51241355bb19e6c2cfb2bb6bbf709765d13");
vector<uint8_t> encryptionIv = wvcdm::a2b_hex(
"c09454479a280829c946df3c22f25539");
// This is the expected decrypted data.
vector<uint8_t> unencryptedData = wvcdm::a2b_hex(
"f344d9cfe336c94cf4e3ea9e3446d1427bc02d2debe6dec5b272b8"
"a4004b696c4b37e01d7418510abf32bb071f9a4bc0d2ad7e874b648e50bd0e4f"
"7085b70bf9ad2c7f37025dd45f93e90304739b1ce098a52e7b99a90f92544a9b"
"dca6f49e0006c80a0cfa018600523ad30e483141fe720d045394815d5c875ad4"
"b4387b8d09b6119bd0943e51b0b9103034496b3a83ba593f79baa188aeb6e08f"
"f6475933e9ce1bb95fbb526424e7966e25830c20da73c65c6fbff110b08e4def"
"eae94f98296770275b0d738207a8217cd6118f6ebc6e393428f2268cfedf800e"
"a7ebc606471b9a9dfccd1589e86d88fde508261eaf190efd20554ce9e14ff3c9");
// Describe the output
uint8_t outputBuffer[256];
OEMCrypto_DestBufferDesc destBuffer;
destBuffer.type = OEMCrypto_BufferType_Clear;
destBuffer.buffer.clear.address = outputBuffer;
destBuffer.buffer.clear.max_length = sizeof(outputBuffer);
// Decrypt the data
sts = OEMCrypto_DecryptCTR(
s.session_id(), &encryptedData[0], encryptedData.size(), true,
&encryptionIv[0], 5, &destBuffer,
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer,
unencryptedData.size()));
}
// Increment counter for AES-CTR. The CENC spec specifies we increment only
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This is
// different from the OpenSSL implementation, so we implement the CTR loop
// ourselves.
void ctr128_inc64(uint8_t* counter) {
uint32_t n = 16;
do {
if (++counter[--n] != 0) return;
} while (n > 8);
}
vector<uint8_t> EncryptCTR(const vector<uint8_t>& key,
const vector<uint8_t>& iv, const vector<uint8_t>& in,
size_t block_offset) {
AES_KEY aes_key;
AES_set_encrypt_key(&key[0], AES_BLOCK_SIZE * 8, &aes_key);
uint8_t aes_iv[AES_BLOCK_SIZE];
memcpy(aes_iv, &iv[0], AES_BLOCK_SIZE);
// Encrypt the IV.
uint8_t ecount_buf[AES_BLOCK_SIZE];
vector<uint8_t> out(in.size());
size_t cipher_data_length = in.size();
size_t l = 0;
while (l < cipher_data_length) {
AES_encrypt(aes_iv, ecount_buf, &aes_key);
for (int n = block_offset; n < AES_BLOCK_SIZE && l < cipher_data_length;
++n, ++l) {
out[l] = in[l] ^ ecount_buf[n];
}
ctr128_inc64(aes_iv);
block_offset = 0;
class OEMCryptoSessionTestsDecryptEdgeCases : public OEMCryptoSessionTests {
public:
// Increment counter for AES-CTR. The CENC spec specifies we increment only
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This is
// different from the OpenSSL implementation, so we implement the CTR loop
// ourselves.
void ctr128_inc64(int64_t increaseBy, uint8_t* iv) {
uint64_t* counterBuffer = reinterpret_cast<uint64_t*>(&iv[8]);
(*counterBuffer) = wvcdm::ntohll64(wvcdm::ntohll64(*counterBuffer) +
increaseBy);
}
return out;
size_t FindTotalSize(const vector<size_t>& subsample_size) {
size_t total_size = 0;
for(size_t i=0; i < subsample_size.size(); i++)
total_size += subsample_size[i];
return total_size;
}
void EncryptCTR(const vector<uint8_t>& key, const vector<uint8_t>& iv,
const vector<uint8_t>& in, vector<uint8_t>* out) {
AES_KEY aes_key;
AES_set_encrypt_key(&key[0], AES_BLOCK_SIZE * 8, &aes_key);
uint8_t aes_iv[AES_BLOCK_SIZE];
memcpy(aes_iv, &iv[0], AES_BLOCK_SIZE);
// Encrypt the IV.
uint8_t ecount_buf[AES_BLOCK_SIZE];
out->resize(in.size());
size_t cipher_data_length = in.size();
size_t l = 0;
while (l < cipher_data_length) {
AES_encrypt(aes_iv, ecount_buf, &aes_key);
for (int n = 0; n < AES_BLOCK_SIZE && l < cipher_data_length;
++n, ++l) {
(*out)[l] = in[l] ^ ecount_buf[n];
}
ctr128_inc64(1, aes_iv);
}
}
void TestDecrypt(const vector<uint8_t>& unencryptedData,
const vector<uint8_t>& encryptedData,
const vector<uint8_t>& encryptionIv,
size_t total_size, const vector<size_t> subsample_size) {
OEMCryptoResult sts;
Session s;
s.open();
s.GenerateTestSessionKeys();
s.FillSimpleMessage(kDuration, 0, 0);
s.EncryptAndSign();
s.LoadTestKeys();
// Select the key (from FillSimpleMessage)
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// We decrypt three subsamples, each with a block offset.
vector<uint8_t> outputBuffer(total_size, 0xaa);
// buffer_offset is the offset of the current subsample from the beginning
// of the whole sample's buffer.
size_t buffer_offset = 0;
for(size_t i=0; i < subsample_size.size(); i++) {
const size_t block_offset = buffer_offset % AES_BLOCK_SIZE;
uint8_t subsample_flags = 0;
if (i == 0) subsample_flags |= OEMCrypto_FirstSubsample;
if (i == subsample_size.size()-1) {
subsample_flags |= OEMCrypto_LastSubsample;
}
OEMCrypto_DestBufferDesc destBuffer;
destBuffer.type = OEMCrypto_BufferType_Clear;
destBuffer.buffer.clear.address = &outputBuffer[buffer_offset];
destBuffer.buffer.clear.max_length = subsample_size[i];
uint8_t aes_iv[AES_BLOCK_SIZE];
// encryptionIv is the IV for the beginning of the whole sample.
memcpy(aes_iv, &encryptionIv[0], AES_BLOCK_SIZE);
// iv_increment is the number of blocks from the beginning of the sample.
size_t iv_increment = buffer_offset / AES_BLOCK_SIZE;
// Their sum is the IV for the block at the beginning of this subsample.
ctr128_inc64(iv_increment, aes_iv);
sts = OEMCrypto_DecryptCTR(
s.session_id(), &encryptedData[buffer_offset], subsample_size[i],
true, aes_iv, block_offset, &destBuffer, subsample_flags);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
buffer_offset += subsample_size[i];
}
EXPECT_EQ(0, memcmp(&unencryptedData[0], &outputBuffer[0], total_size));
// If there was a problem, compare the outputBuffer at the offset with the
// correct data at 0. A common error is to ignore the offset when
// decrypting.
if (0 != memcmp(&unencryptedData[0], &outputBuffer[0], total_size)
&& 2*subsample_size[0] < total_size
&& 0 == memcmp(&unencryptedData[0], &outputBuffer[subsample_size[0]],
subsample_size[0])){
printf("The first %zd bytes are repeating. This is an indication \n",
subsample_size[0]);
printf("that DecryptCTR is ignoring the offset.\n");
}
}
};
TEST_F(OEMCryptoSessionTestsDecryptEdgeCases, EvenOffset) {
vector<size_t> subsample_size;
subsample_size.push_back(8);
subsample_size.push_back(32);
subsample_size.push_back(50);
const size_t total_size = FindTotalSize(subsample_size);
vector<uint8_t> unencryptedData(total_size, 0);
vector<uint8_t> encryptedData(total_size, 0);
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE, 0);
vector<uint8_t> key = wvcdm::a2b_hex("39AD33E5719656069F9EDE9EBBA7A77D");
// Note: DecryptCTR is self-inverse -- ie it's the same as EncryptCTR.
// So we can pick the encrypted data and compute the unencrypted data if we
// want. By picking the encrypted data to be all 0, it is easier to
// re-encrypt the data and debug problems.
EncryptCTR(key, encryptionIv, encryptedData, &unencryptedData);
TestDecrypt(unencryptedData, encryptedData, encryptionIv, total_size,
subsample_size);
}
TEST_F(OEMCryptoSessionTests, DecryptWithNearWrap) {
OEMCryptoResult sts;
Session s;
s.open();
s.GenerateTestSessionKeys();
s.FillSimpleMessage(kDuration, 0, 0);
s.EncryptAndSign();
s.LoadTestKeys();
// Select the key (from FillSimpleMessage)
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// Set up our expected input and output
// This tests the ability to decrypt multiple subsamples with no offset.
TEST_F(OEMCryptoSessionTestsDecryptEdgeCases, NoOffset) {
vector<size_t> subsample_size;
subsample_size.push_back(64);
subsample_size.push_back(64);
subsample_size.push_back(64);
const size_t total_size = FindTotalSize(subsample_size);
vector<uint8_t> unencryptedData(total_size, 0);
vector<uint8_t> encryptedData(total_size, 0);
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE, 0);
encryptionIv = wvcdm::a2b_hex("c09454479a280829c946df3c22f25539");
for(size_t i=0; i < total_size; i++) unencryptedData[i] = i % 256;
vector<uint8_t> key = wvcdm::a2b_hex("39AD33E5719656069F9EDE9EBBA7A77D");
vector<uint8_t> encryptionIv = wvcdm::a2b_hex(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE");
// This is dummy decrypted data.
vector<uint8_t> unencryptedData = wvcdm::a2b_hex(
"f344d9cfe336c94cf4e3ea9e3446d1427bc02d2debe6dec5b272b8"
"a4004b696c4b37e01d7418510abf32bb071f9a4bc0d2ad7e874b648e50bd0e4f"
"7085b70bf9ad2c7f37025dd45f93e90304739b1ce098a52e7b99a90f92544a9b"
"dca6f49e0006c80a0cfa018600523ad30e483141fe720d045394815d5c875ad4"
"b4387b8d09b6119bd0943e51b0b9103034496b3a83ba593f79baa188aeb6e08f"
"f6475933e9ce1bb95fbb526424e7966e25830c20da73c65c6fbff110b08e4def"
"eae94f98296770275b0d738207a8217cd6118f6ebc6e393428f2268cfedf800e"
"a7ebc606471b9a9dfccd1589e86d88fde508261eaf190efd20554ce9e14ff3c9");
size_t block_offset = 5;
vector<uint8_t> encryptedData =
EncryptCTR(key, encryptionIv, unencryptedData, block_offset);
EncryptCTR(key, encryptionIv, unencryptedData, &encryptedData);
TestDecrypt(unencryptedData, encryptedData, encryptionIv, total_size,
subsample_size);
}
// Describe the output
uint8_t outputBuffer[256];
OEMCrypto_DestBufferDesc destBuffer;
destBuffer.type = OEMCrypto_BufferType_Clear;
destBuffer.buffer.clear.address = outputBuffer;
destBuffer.buffer.clear.max_length = sizeof(outputBuffer);
// If the EvenOffset test passes, but this one doesn't, then DecryptCTR might
// be using the wrong definition of offset. Adding the offset to the block
// boundary should give you the beginning of the encrypted data.
TEST_F(OEMCryptoSessionTestsDecryptEdgeCases, OddOffset) {
vector<size_t> subsample_size;
subsample_size.push_back(50);
subsample_size.push_back(75);
subsample_size.push_back(25);
const size_t total_size = FindTotalSize(subsample_size);
vector<uint8_t> unencryptedData(total_size, 0);
vector<uint8_t> encryptedData(total_size, 0);
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE, 0);
encryptionIv = wvcdm::a2b_hex("c09454479a280829c946df3c22f25539");
for(size_t i=0; i < total_size; i++) unencryptedData[i] = i % 256;
vector<uint8_t> key = wvcdm::a2b_hex("39AD33E5719656069F9EDE9EBBA7A77D");
EncryptCTR(key, encryptionIv, unencryptedData, &encryptedData);
TestDecrypt(unencryptedData, encryptedData, encryptionIv, total_size,
subsample_size);
}
// Decrypt the data
sts = OEMCrypto_DecryptCTR(
s.session_id(), &encryptedData[0], encryptedData.size(), true,
&encryptionIv[0], block_offset, &destBuffer,
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer,
unencryptedData.size()));
TEST_F(OEMCryptoSessionTestsDecryptEdgeCases, DecryptWithNearWrap) {
vector<size_t> subsample_size;
subsample_size.push_back(150);
const size_t total_size = FindTotalSize(subsample_size);
vector<uint8_t> unencryptedData(total_size, 0);
vector<uint8_t> encryptedData(total_size, 0);
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE, 0);
encryptionIv = wvcdm::a2b_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE");
for(size_t i=0; i < total_size; i++) unencryptedData[i] = i % 256;
vector<uint8_t> key = wvcdm::a2b_hex("39AD33E5719656069F9EDE9EBBA7A77D");
EncryptCTR(key, encryptionIv, unencryptedData, &encryptedData);
TestDecrypt(unencryptedData, encryptedData, encryptionIv, total_size,
subsample_size);
}
TEST_F(OEMCryptoSessionTests, DecryptUnencrypted) {
@@ -2638,9 +2670,7 @@ TEST_F(OEMCryptoSessionTests, DecryptUnencryptedNoKey) {
OEMCryptoResult sts;
Session s;
s.open();
// CLear data should be copied even if there is no key selected.
// Clear data should be copied even if there is no key selected.
// Set up our expected input and output
// This is dummy decrypted data.
vector<uint8_t> unencryptedData = wvcdm::a2b_hex(