Add some "fuzzing" tests for deserialization, and fixes for all of the
problems discovered.
Change-Id: I050344f6c6d0a19b7f3304d23729b4ca71c05042
diff --git a/key_blob.cpp b/key_blob.cpp
index f1d9ce5..3f354e3 100644
--- a/key_blob.cpp
+++ b/key_blob.cpp
@@ -38,7 +38,8 @@
KeyBlob::KeyBlob(const AuthorizationSet& enforced, const AuthorizationSet& unenforced,
const AuthorizationSet& hidden, const keymaster_key_blob_t& key,
const keymaster_key_blob_t& master_key, const uint8_t nonce[NONCE_LENGTH])
- : error_(KM_ERROR_OK), enforced_(enforced), unenforced_(unenforced), hidden_(hidden) {
+ : error_(KM_ERROR_OK), nonce_(new uint8_t[NONCE_LENGTH]), tag_(new uint8_t[TAG_LENGTH]),
+ enforced_(enforced), unenforced_(unenforced), hidden_(hidden) {
if (enforced_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE ||
unenforced_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE ||
hidden_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE) {
@@ -56,24 +57,23 @@
if (!ExtractKeyCharacteristics())
return;
- memcpy(nonce_, nonce, NONCE_LENGTH);
-
key_material_length_ = key.key_material_size;
key_material_.reset(new uint8_t[key_material_length_]);
encrypted_key_material_.reset(new uint8_t[key_material_length_]);
- if (key_material_.get() == NULL || encrypted_key_material_.get() == NULL) {
+ if (!key_material_.get() || !encrypted_key_material_.get() || !nonce_.get() || !tag_.get()) {
error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
return;
}
+ memcpy(nonce_.get(), nonce, NONCE_LENGTH);
memcpy(key_material_.get(), key.key_material, key_material_length_);
EncryptKey(master_key);
}
KeyBlob::KeyBlob(const keymaster_key_blob_t& key, const AuthorizationSet& hidden,
const keymaster_key_blob_t& master_key)
- : hidden_(hidden) {
+ : nonce_(new uint8_t[NONCE_LENGTH]), tag_(new uint8_t[TAG_LENGTH]), hidden_(hidden) {
const uint8_t* p = key.key_material;
if (!Deserialize(&p, key.key_material + key.key_material_size))
return;
@@ -97,13 +97,11 @@
}
bool KeyBlob::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- uint8_t* tmp_key_ptr = NULL;
- if (!copy_from_buf(buf_ptr, end, nonce_, NONCE_LENGTH) ||
+ UniquePtr<uint8_t[]> tmp_key_ptr;
+ if (!copy_from_buf(buf_ptr, end, nonce_.get(), NONCE_LENGTH) ||
!copy_size_and_data_from_buf(buf_ptr, end, &key_material_length_, &tmp_key_ptr) ||
- !copy_from_buf(buf_ptr, end, tag_, TAG_LENGTH) || !enforced_.Deserialize(buf_ptr, end) ||
- !unenforced_.Deserialize(buf_ptr, end)) {
- if (tmp_key_ptr != NULL)
- delete[] tmp_key_ptr;
+ !copy_from_buf(buf_ptr, end, tag_.get(), TAG_LENGTH) ||
+ !enforced_.Deserialize(buf_ptr, end) || !unenforced_.Deserialize(buf_ptr, end)) {
error_ = KM_ERROR_INVALID_KEY_BLOB;
return false;
}
@@ -111,7 +109,7 @@
if (!ExtractKeyCharacteristics())
return false;
- encrypted_key_material_.reset(tmp_key_ptr);
+ encrypted_key_material_.reset(tmp_key_ptr.release());
key_material_.reset(new uint8_t[key_material_length_]);
return true;
}
@@ -121,9 +119,9 @@
if (error_ != KM_ERROR_OK)
return;
- int ae_err = ae_encrypt(ctx.get(), nonce_, key_material(), key_material_length(),
+ int ae_err = ae_encrypt(ctx.get(), nonce_.get(), key_material(), key_material_length(),
NULL /* additional data */, 0 /* additional data length */,
- encrypted_key_material_.get(), tag_, 1 /* final */);
+ encrypted_key_material_.get(), tag_.get(), 1 /* final */);
if (ae_err < 0) {
error_ = KM_ERROR_UNKNOWN_ERROR;
return;
@@ -137,9 +135,10 @@
if (error_ != KM_ERROR_OK)
return;
- int ae_err = ae_decrypt(ctx.get(), nonce_, encrypted_key_material(), key_material_length(),
- NULL /* additional data */, 0 /* additional data length */,
- key_material_.get(), tag(), 1 /* final */);
+ int ae_err =
+ ae_decrypt(ctx.get(), nonce_.get(), encrypted_key_material(), key_material_length(),
+ NULL /* additional data */, 0 /* additional data length */, key_material_.get(),
+ tag_.get(), 1 /* final */);
if (ae_err == AE_INVALID) {
// Authentication failed! Decryption probably succeeded(ish), but we don't want to return
// any data when the authentication fails, so clear it.
@@ -150,7 +149,7 @@
error_ = KM_ERROR_UNKNOWN_ERROR;
return;
}
- assert(ae_err == static_cast<int>(key_material_length_));
+ assert(ae_err == static_cast<int>(key_material_length()));
error_ = KM_ERROR_OK;
}