Add HMAC-SHA256 support.
Change-Id: I64c7bdf77388e3cb491b702c52c6746d32f317b0
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index 596aeed..1ee9c02 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -85,6 +85,14 @@
keymaster_device* device() { return reinterpret_cast<keymaster_device*>(device_.hw_device()); }
+ void GenerateKey(AuthorizationSet* params) {
+ FreeKeyBlob();
+ FreeCharacteristics();
+ AddClientParams(params);
+ EXPECT_EQ(KM_ERROR_OK, device()->generate_key(device(), params->data(), params->size(),
+ &blob_, &characteristics_));
+ }
+
keymaster_error_t BeginOperation(keymaster_purpose_t purpose,
const keymaster_key_blob_t& key_blob) {
return device()->begin(device(), purpose, &key_blob, client_params_,
@@ -133,6 +141,8 @@
blob_.key_material = NULL;
}
+ void AddClientParams(AuthorizationSet* set) { set->push_back(TAG_APPLICATION_ID, "app_id", 6); }
+
const keymaster_key_blob_t& key_blob() { return blob_; }
SoftKeymasterDevice device_;
@@ -488,7 +498,6 @@
Authorization(TAG_MAC_LENGTH, 16), Authorization(TAG_PADDING, KM_PAD_NONE),
};
params_.Reinitialize(params, array_length(params));
- params_.Reinitialize(params, array_length(params));
EXPECT_EQ(KM_ERROR_OK, device()->generate_key(device(), params_.data(), params_.size(), &blob_,
&characteristics_));
@@ -531,6 +540,16 @@
}
}
+TEST_F(NewKeyGeneration, HmacSha256) {
+ keymaster_key_param_t params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC), Authorization(TAG_KEY_SIZE, 128),
+ Authorization(TAG_MAC_LENGTH, 16), Authorization(TAG_DIGEST, KM_DIGEST_SHA_2_256),
+ };
+ EXPECT_EQ(KM_ERROR_OK, device()->generate_key(device(), params, array_length(params), &blob_,
+ &characteristics_));
+}
+
typedef KeymasterTest GetKeyCharacteristics;
TEST_F(GetKeyCharacteristics, SimpleRsa) {
keymaster_key_param_t params[] = {
@@ -564,6 +583,9 @@
FreeSignature();
}
+ // TODO(swillden): Refactor and move common test utils to KeymasterTest
+ using KeymasterTest::GenerateKey;
+
void GenerateKey(keymaster_algorithm_t algorithm, keymaster_digest_t digest,
keymaster_padding_t padding, uint32_t key_size) {
params_.push_back(Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN));
@@ -602,6 +624,8 @@
signature_ = NULL;
}
+ const keymaster_key_blob_t& key_blob() { return blob_; }
+
void corrupt_key_blob() {
uint8_t* tmp = const_cast<uint8_t*>(blob_.key_material);
++tmp[blob_.key_material_size / 2];
@@ -669,6 +693,54 @@
EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device()->abort(device(), op_handle_));
}
+TEST_F(SigningOperationsTest, HmacSha256Success) {
+ keymaster_key_param_t params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC), Authorization(TAG_KEY_SIZE, 128),
+ Authorization(TAG_MAC_LENGTH, 32), Authorization(TAG_DIGEST, KM_DIGEST_SHA_2_256),
+ Authorization(TAG_USER_ID, 7), Authorization(TAG_USER_AUTH_ID, 8),
+ Authorization(TAG_AUTH_TIMEOUT, 300),
+ };
+ params_.Reinitialize(params, array_length(params));
+ GenerateKey(¶ms_);
+ const char message[] = "12345678901234567890123456789012";
+ string signature;
+ SignMessage(message, array_size(message) - 1);
+ ASSERT_EQ(32, signature_length_);
+}
+
+// TODO(swillden): Add an HMACSHA256 test that validates against the test vectors from RFC4231.
+// Doing that requires being able to import keys, rather than just generate them
+// randomly.
+
+TEST_F(SigningOperationsTest, HmacSha256NoTag) {
+ keymaster_key_param_t params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC), Authorization(TAG_KEY_SIZE, 128),
+ Authorization(TAG_MAC_LENGTH, 16), Authorization(TAG_DIGEST, KM_DIGEST_SHA_2_256),
+ Authorization(TAG_USER_ID, 7), Authorization(TAG_USER_AUTH_ID, 8),
+ Authorization(TAG_AUTH_TIMEOUT, 300),
+ };
+ params_.Reinitialize(params, array_length(params));
+ GenerateKey(¶ms_);
+ const char message[] = "12345678901234567890123456789012";
+ string signature;
+ SignMessage(message, array_size(message) - 1);
+}
+
+TEST_F(SigningOperationsTest, HmacSha256TooLargeTag) {
+ keymaster_key_param_t params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC), Authorization(TAG_KEY_SIZE, 128),
+ Authorization(TAG_MAC_LENGTH, 33), Authorization(TAG_DIGEST, KM_DIGEST_SHA_2_256),
+ Authorization(TAG_USER_ID, 7), Authorization(TAG_USER_AUTH_ID, 8),
+ Authorization(TAG_AUTH_TIMEOUT, 300),
+ };
+ params_.Reinitialize(params, array_length(params));
+ GenerateKey(¶ms_);
+ ASSERT_EQ(KM_ERROR_UNSUPPORTED_MAC_LENGTH, BeginOperation(KM_PURPOSE_SIGN, key_blob()));
+}
+
TEST_F(SigningOperationsTest, RsaTooShortMessage) {
GenerateKey(KM_ALGORITHM_RSA, KM_DIGEST_NONE, KM_PAD_NONE, 256 /* key size */);
ASSERT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, key_blob()));
@@ -718,6 +790,22 @@
VerifyMessage(message, array_size(message) - 1);
}
+TEST_F(VerificationOperationsTest, HmacSha256Success) {
+ keymaster_key_param_t params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC), Authorization(TAG_KEY_SIZE, 128),
+ Authorization(TAG_MAC_LENGTH, 16), Authorization(TAG_DIGEST, KM_DIGEST_SHA_2_256),
+ Authorization(TAG_USER_ID, 7), Authorization(TAG_USER_AUTH_ID, 8),
+ Authorization(TAG_AUTH_TIMEOUT, 300),
+ };
+ params_.Reinitialize(params, array_length(params));
+ GenerateKey(¶ms_);
+ const char message[] = "123456789012345678901234567890123456789012345678";
+ string signature;
+ SignMessage(message, array_size(message) - 1);
+ VerifyMessage(message, array_size(message) - 1);
+}
+
typedef VerificationOperationsTest ExportKeyTest;
TEST_F(ExportKeyTest, RsaSuccess) {
GenerateKey(KM_ALGORITHM_RSA, KM_DIGEST_NONE, KM_PAD_NONE, 256 /* key size */);
@@ -900,13 +988,8 @@
*/
class EncryptionOperationsTest : public KeymasterTest {
protected:
- void GenerateKey(AuthorizationSet* params) {
- FreeKeyBlob();
- FreeCharacteristics();
- AddClientParams(params);
- EXPECT_EQ(KM_ERROR_OK, device()->generate_key(device(), params->data(), params->size(),
- &blob_, &characteristics_));
- }
+ // TODO(swillden): Refactor and move common test utils to KeymasterTest
+ using KeymasterTest::GenerateKey;
void GenerateKey(keymaster_algorithm_t algorithm, keymaster_padding_t padding,
uint32_t key_size) {
@@ -962,8 +1045,6 @@
return ProcessMessage(KM_PURPOSE_DECRYPT, blob_, ciphertext.c_str(), ciphertext.length());
}
- void AddClientParams(AuthorizationSet* set) { set->push_back(TAG_APPLICATION_ID, "app_id", 6); }
-
const void corrupt_key_blob() {
uint8_t* tmp = const_cast<uint8_t*>(blob_.key_material);
++tmp[blob_.key_material_size / 2];