Finish key import implementation.
This is the last bit of GoogleKeymaster that remained incomplete (for
the v0.3 functionality).
Change-Id: I27be52ae032883c004b2df21f0c7b229af512922
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index 3ed0129..7121f9d 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -865,7 +865,7 @@
Authorization(TAG_AUTH_TIMEOUT, 300),
};
- string pk8_key = read_file("privkey_pk8.der");
+ string pk8_key = read_file("rsa_privkey_pk8.der");
ASSERT_EQ(633U, pk8_key.size());
ImportKeyRequest import_request;
@@ -924,5 +924,145 @@
EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
}
+TEST_F(ImportKeyTest, DsaSuccess) {
+ keymaster_key_param_t params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_DIGEST, KM_DIGEST_NONE),
+ Authorization(TAG_PADDING, KM_PAD_NONE),
+ Authorization(TAG_USER_ID, 7),
+ Authorization(TAG_USER_AUTH_ID, 8),
+ Authorization(TAG_APPLICATION_ID, "app_id", 6),
+ Authorization(TAG_AUTH_TIMEOUT, 300),
+ };
+
+ string pk8_key = read_file("dsa_privkey_pk8.der");
+ ASSERT_EQ(335U, pk8_key.size());
+
+ ImportKeyRequest import_request;
+ import_request.key_description.Reinitialize(params, array_length(params));
+ import_request.key_format = KM_KEY_FORMAT_PKCS8;
+ import_request.SetKeyMaterial(pk8_key.data(), pk8_key.size());
+
+ ImportKeyResponse import_response;
+ device.ImportKey(import_request, &import_response);
+ ASSERT_EQ(KM_ERROR_OK, import_response.error);
+ EXPECT_EQ(0U, import_response.enforced.size());
+ EXPECT_GT(import_response.unenforced.size(), 0U);
+
+ // Check values derived from the key.
+ EXPECT_TRUE(contains(import_response.unenforced, TAG_ALGORITHM, KM_ALGORITHM_DSA));
+ EXPECT_TRUE(contains(import_response.unenforced, TAG_KEY_SIZE, 1024));
+
+ // And values provided by GoogleKeymaster
+ EXPECT_TRUE(contains(import_response.unenforced, TAG_ORIGIN, KM_ORIGIN_IMPORTED));
+ EXPECT_TRUE(contains(import_response.unenforced, KM_TAG_CREATION_DATETIME));
+
+ size_t message_len = 48;
+ UniquePtr<uint8_t[]> message(new uint8_t[message_len]);
+ std::fill(message.get(), message.get() + message_len, 'a');
+ SignMessage(import_response.key_blob, message.get(), message_len);
+ ASSERT_TRUE(signature() != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.SetKeyMaterial(import_response.key_blob);
+ begin_request.purpose = KM_PURPOSE_VERIFY;
+ AddClientParams(&begin_request.additional_params);
+
+ device.BeginOperation(begin_request, &begin_response);
+ ASSERT_EQ(KM_ERROR_OK, begin_response.error);
+
+ UpdateOperationRequest update_request;
+ UpdateOperationResponse update_response;
+ update_request.op_handle = begin_response.op_handle;
+ update_request.input.Reinitialize(message.get(), message_len);
+ EXPECT_EQ(message_len, update_request.input.available_read());
+
+ device.UpdateOperation(update_request, &update_response);
+ ASSERT_EQ(KM_ERROR_OK, update_response.error);
+ EXPECT_EQ(0U, update_response.output.available_read());
+
+ FinishOperationRequest finish_request;
+ finish_request.op_handle = begin_response.op_handle;
+ finish_request.signature.Reinitialize(*signature());
+ FinishOperationResponse finish_response;
+ device.FinishOperation(finish_request, &finish_response);
+ ASSERT_EQ(KM_ERROR_OK, finish_response.error);
+ EXPECT_EQ(0U, finish_response.output.available_read());
+
+ EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
+}
+
+TEST_F(ImportKeyTest, EcdsaSuccess) {
+ keymaster_key_param_t params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_DIGEST, KM_DIGEST_NONE),
+ Authorization(TAG_PADDING, KM_PAD_NONE),
+ Authorization(TAG_USER_ID, 7),
+ Authorization(TAG_USER_AUTH_ID, 8),
+ Authorization(TAG_APPLICATION_ID, "app_id", 6),
+ Authorization(TAG_AUTH_TIMEOUT, 300),
+ };
+
+ string pk8_key = read_file("ec_privkey_pk8.der");
+ ASSERT_EQ(138U, pk8_key.size());
+
+ ImportKeyRequest import_request;
+ import_request.key_description.Reinitialize(params, array_length(params));
+ import_request.key_format = KM_KEY_FORMAT_PKCS8;
+ import_request.SetKeyMaterial(pk8_key.data(), pk8_key.size());
+
+ ImportKeyResponse import_response;
+ device.ImportKey(import_request, &import_response);
+ ASSERT_EQ(KM_ERROR_OK, import_response.error);
+ EXPECT_EQ(0U, import_response.enforced.size());
+ EXPECT_GT(import_response.unenforced.size(), 0U);
+
+ // Check values derived from the key.
+ EXPECT_TRUE(contains(import_response.unenforced, TAG_ALGORITHM, KM_ALGORITHM_ECDSA));
+ EXPECT_TRUE(contains(import_response.unenforced, TAG_KEY_SIZE, 256));
+
+ // And values provided by GoogleKeymaster
+ EXPECT_TRUE(contains(import_response.unenforced, TAG_ORIGIN, KM_ORIGIN_IMPORTED));
+ EXPECT_TRUE(contains(import_response.unenforced, KM_TAG_CREATION_DATETIME));
+
+ size_t message_len = 1024 / 8;
+ UniquePtr<uint8_t[]> message(new uint8_t[message_len]);
+ std::fill(message.get(), message.get() + message_len, 'a');
+ SignMessage(import_response.key_blob, message.get(), message_len);
+ ASSERT_TRUE(signature() != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.SetKeyMaterial(import_response.key_blob);
+ begin_request.purpose = KM_PURPOSE_VERIFY;
+ AddClientParams(&begin_request.additional_params);
+
+ device.BeginOperation(begin_request, &begin_response);
+ ASSERT_EQ(KM_ERROR_OK, begin_response.error);
+
+ UpdateOperationRequest update_request;
+ UpdateOperationResponse update_response;
+ update_request.op_handle = begin_response.op_handle;
+ update_request.input.Reinitialize(message.get(), message_len);
+ EXPECT_EQ(message_len, update_request.input.available_read());
+
+ device.UpdateOperation(update_request, &update_response);
+ ASSERT_EQ(KM_ERROR_OK, update_response.error);
+ EXPECT_EQ(0U, update_response.output.available_read());
+
+ FinishOperationRequest finish_request;
+ finish_request.op_handle = begin_response.op_handle;
+ finish_request.signature.Reinitialize(*signature());
+ FinishOperationResponse finish_response;
+ device.FinishOperation(finish_request, &finish_response);
+ ASSERT_EQ(KM_ERROR_OK, finish_response.error);
+ EXPECT_EQ(0U, finish_response.output.available_read());
+
+ EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
+}
+
} // namespace test
} // namespace keymaster