Use vector to pass around keys
In the future the key size for new master keys will increase.
To maintain backwards compatibility the size of the key
can no longer be assumed. To help communicate the actual
size of the key, it will be passed around in a vector.
Bug: 121272336
Test: Ran Keystore CTS tests against Walleye
Change-Id: I4c05acb15b77959f2bf89abbdc325904fffb497a
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 8633635..4b7d6c1 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -73,12 +73,12 @@
* Encrypt 'len' data at 'in' with AES-GCM, using 128-bit key at 'key', 96-bit IV at 'iv' and write
* output to 'out' (which may be the same location as 'in') and 128-bit tag to 'tag'.
*/
-ResponseCode AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
- const uint8_t* iv, uint8_t* tag) {
+ResponseCode AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len,
+ const std::vector<uint8_t>& key, const uint8_t* iv, uint8_t* tag) {
const EVP_CIPHER* cipher = EVP_aes_128_gcm();
EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
- EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
+ EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv);
EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
std::unique_ptr<uint8_t[]> out_tmp(new uint8_t[len]);
@@ -105,12 +105,13 @@
* Decrypt 'len' data at 'in' with AES-GCM, using 128-bit key at 'key', 96-bit IV at 'iv', checking
* 128-bit tag at 'tag' and writing plaintext to 'out' (which may be the same location as 'in').
*/
-ResponseCode AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
- const uint8_t* iv, const uint8_t* tag) {
+ResponseCode AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len,
+ const std::vector<uint8_t> key, const uint8_t* iv,
+ const uint8_t* tag) {
const EVP_CIPHER* cipher = EVP_aes_128_gcm();
EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
- EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
+ EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv);
EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
@@ -296,7 +297,7 @@
}
static ResponseCode writeBlob(const std::string& filename, Blob blob, blobv3* rawBlob,
- const uint8_t* aes_key, State state) {
+ const std::vector<uint8_t>& aes_key, State state) {
ALOGV("writing blob %s", filename.c_str());
const size_t dataLength = rawBlob->length;
@@ -341,7 +342,8 @@
}
ResponseCode LockedKeyBlobEntry::writeBlobs(Blob keyBlob, Blob characteristicsBlob,
- const uint8_t* aes_key, State state) const {
+ const std::vector<uint8_t>& aes_key,
+ State state) const {
if (entry_ == nullptr) {
return ResponseCode::SYSTEM_ERROR;
}
@@ -362,7 +364,8 @@
return rc;
}
-ResponseCode Blob::readBlob(const std::string& filename, const uint8_t* aes_key, State state) {
+ResponseCode Blob::readBlob(const std::string& filename, const std::vector<uint8_t>& aes_key,
+ State state) {
ResponseCode rc;
ALOGV("reading blob %s", filename.c_str());
std::unique_ptr<blobv3> rawBlob = std::make_unique<blobv3>();
@@ -412,7 +415,7 @@
}
AES_KEY key;
- AES_set_decrypt_key(aes_key, kAesKeySize * 8, &key);
+ AES_set_decrypt_key(aes_key.data(), kAesKeySize * 8, &key);
AES_cbc_encrypt(v2blob.encrypted, v2blob.encrypted, encryptedLength, &key,
v2blob.vector, AES_DECRYPT);
key = {}; // clear key
@@ -443,8 +446,8 @@
return ResponseCode::NO_ERROR;
}
-std::tuple<ResponseCode, Blob, Blob> LockedKeyBlobEntry::readBlobs(const uint8_t* aes_key,
- State state) const {
+std::tuple<ResponseCode, Blob, Blob>
+LockedKeyBlobEntry::readBlobs(const std::vector<uint8_t>& aes_key, State state) const {
std::tuple<ResponseCode, Blob, Blob> result;
auto& [rc, keyBlob, characteristicsBlob] = result;
if (entry_ == nullptr) return rc = ResponseCode::SYSTEM_ERROR, result;
diff --git a/keystore/blob.h b/keystore/blob.h
index 86f367f..8d68fc4 100644
--- a/keystore/blob.h
+++ b/keystore/blob.h
@@ -30,6 +30,7 @@
#include <mutex>
#include <set>
#include <sstream>
+#include <vector>
constexpr size_t kValueSize = 32768;
constexpr size_t kAesKeySize = 128 / 8;
@@ -153,7 +154,8 @@
private:
std::unique_ptr<blobv3> mBlob;
- ResponseCode readBlob(const std::string& filename, const uint8_t* aes_key, State state);
+ ResponseCode readBlob(const std::string& filename, const std::vector<uint8_t>& aes_key,
+ State state);
};
/**
@@ -261,9 +263,10 @@
std::function<bool(uid_t, const std::string&)> filter =
[](uid_t, const std::string&) -> bool { return true; });
- ResponseCode writeBlobs(Blob keyBlob, Blob characteristicsBlob, const uint8_t* aes_key,
- State state) const;
- std::tuple<ResponseCode, Blob, Blob> readBlobs(const uint8_t* aes_key, State state) const;
+ ResponseCode writeBlobs(Blob keyBlob, Blob characteristicsBlob,
+ const std::vector<uint8_t>& aes_key, State state) const;
+ std::tuple<ResponseCode, Blob, Blob> readBlobs(const std::vector<uint8_t>& aes_key,
+ State state) const;
ResponseCode deleteBlobs() const;
inline operator bool() const { return entry_ != nullptr; }
diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp
index 7c3ca16..6026227 100644
--- a/keystore/user_state.cpp
+++ b/keystore/user_state.cpp
@@ -75,7 +75,7 @@
}
void UserState::zeroizeMasterKeysInMemory() {
- memset(mMasterKey, 0, sizeof(mMasterKey));
+ memset(mMasterKey.data(), 0, mMasterKey.size());
memset(mSalt, 0, sizeof(mSalt));
}
@@ -104,7 +104,7 @@
if ((*src)->getState() != STATE_NO_ERROR) {
return ResponseCode::SYSTEM_ERROR;
}
- memcpy(mMasterKey, (*src)->mMasterKey, MASTER_KEY_SIZE_BYTES);
+ mMasterKey = (*src)->mMasterKey;
setupMasterKeys();
return copyMasterKeyFile(src);
}
@@ -140,9 +140,9 @@
}
ResponseCode UserState::writeMasterKey(const android::String8& pw) {
- uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
- generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
- Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
+ std::vector<uint8_t> passwordKey(MASTER_KEY_SIZE_BYTES);
+ generateKeyFromPassword(passwordKey, pw, mSalt);
+ Blob masterKeyBlob(mMasterKey.data(), mMasterKey.size(), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
auto lockedEntry = LockedKeyBlobEntry::get(mMasterKeyEntry);
return lockedEntry.writeBlobs(masterKeyBlob, {}, passwordKey, STATE_NO_ERROR);
}
@@ -170,8 +170,9 @@
} else {
salt = nullptr;
}
- uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
- generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
+
+ std::vector<uint8_t> passwordKey(MASTER_KEY_SIZE_BYTES);
+ generateKeyFromPassword(passwordKey, pw, salt);
Blob masterKeyBlob, dummyBlob;
ResponseCode response;
std::tie(response, masterKeyBlob, dummyBlob) =
@@ -188,7 +189,9 @@
response = writeMasterKey(pw);
}
if (response == ResponseCode::NO_ERROR) {
- memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
+ mMasterKey = std::vector<uint8_t>(masterKeyBlob.getValue(),
+ masterKeyBlob.getValue() + masterKeyBlob.getLength());
+
setupMasterKeys();
}
return response;
@@ -236,7 +239,7 @@
return true;
}
-void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+void UserState::generateKeyFromPassword(std::vector<uint8_t>& key, const android::String8& pw,
uint8_t* salt) {
size_t saltSize;
if (salt != nullptr) {
@@ -251,12 +254,12 @@
const EVP_MD* digest = EVP_sha256();
// SHA1 was used prior to increasing the key size
- if (keySize == SHA1_DIGEST_SIZE_BYTES) {
+ if (key.size() == SHA1_DIGEST_SIZE_BYTES) {
digest = EVP_sha1();
}
PKCS5_PBKDF2_HMAC(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize, 8192,
- digest, keySize, key);
+ digest, key.size(), key.data());
}
bool UserState::generateSalt() {
@@ -264,7 +267,8 @@
}
bool UserState::generateMasterKey() {
- if (!RAND_bytes(mMasterKey, sizeof(mMasterKey))) {
+ mMasterKey.resize(MASTER_KEY_SIZE_BYTES);
+ if (!RAND_bytes(mMasterKey.data(), mMasterKey.size())) {
return false;
}
if (!generateSalt()) {
diff --git a/keystore/user_state.h b/keystore/user_state.h
index a1dc6a2..9403552 100644
--- a/keystore/user_state.h
+++ b/keystore/user_state.h
@@ -33,6 +33,7 @@
#include <keystore/keystore_concurrency.h>
#include <mutex>
#include <set>
+#include <vector>
namespace keystore {
@@ -66,7 +67,7 @@
ResponseCode writeMasterKey(const android::String8& pw);
ResponseCode readMasterKey(const android::String8& pw);
- const uint8_t* getEncryptionKey() const { return &mMasterKey[0]; }
+ const std::vector<uint8_t>& getEncryptionKey() const { return mMasterKey; }
bool reset();
@@ -83,7 +84,7 @@
static const int MAX_RETRY = 4;
static const size_t SALT_SIZE = 16;
- void generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+ void generateKeyFromPassword(std::vector<uint8_t>& key, const android::String8& pw,
uint8_t* salt);
bool generateSalt();
bool generateMasterKey();
@@ -95,7 +96,7 @@
State mState;
int8_t mRetry;
- uint8_t mMasterKey[MASTER_KEY_SIZE_BYTES];
+ std::vector<uint8_t> mMasterKey;
uint8_t mSalt[SALT_SIZE];
};