am 994a7fc4: Update OEMCrypto Offset Tests
* commit '994a7fc4c1f696226e08fe2d9f1e4852fca147bc': Update OEMCrypto Offset Tests
This commit is contained in:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user