Add RSA signing support.
Change-Id: Icdcbd978d58c8764618b995571d1e8b649959ef0
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index 945a0e6..4c8c28e 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -37,7 +37,8 @@
class KeymasterTest : public testing::Test {
protected:
- KeymasterTest() {
+ KeymasterTest() : device(5) {
+ RAND_seed("foobar", 6);
}
~KeymasterTest() {
}
@@ -237,7 +238,7 @@
Authorization(TAG_KEY_SIZE, 256),
Authorization(TAG_USER_ID, 7),
Authorization(TAG_USER_AUTH_ID, 8),
- Authorization(TAG_APPLICATION_ID, reinterpret_cast<const uint8_t*>("app_id"), 6),
+ Authorization(TAG_APPLICATION_ID, "app_id", 6),
Authorization(TAG_AUTH_TIMEOUT, 300),
};
@@ -246,13 +247,11 @@
GenerateKeyResponse gen_rsp;
device.GenerateKey(gen_req, &gen_rsp);
+ ASSERT_EQ(KM_ERROR_OK, gen_rsp.error);
GetKeyCharacteristicsRequest req;
req.key_blob = gen_rsp.key_blob;
- req.client_id.data = reinterpret_cast<const uint8_t*>("app_id");
- req.client_id.data_length = 6;
- req.app_data.data = NULL;
- req.app_data.data_length = 0;
+ req.additional_params.push_back(TAG_APPLICATION_ID, "app_id", 6);
GetKeyCharacteristicsResponse rsp;
device.GetKeyCharacteristics(req, &rsp);
@@ -262,5 +261,186 @@
EXPECT_EQ(gen_rsp.unenforced, rsp.unenforced);
}
+class SigningOperationsTest : public KeymasterTest {
+ protected:
+ keymaster_key_blob_t* GenerateKey(keymaster_digest_t digest, keymaster_padding_t padding,
+ uint32_t key_size) {
+ keymaster_key_param_t params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
+ Authorization(TAG_KEY_SIZE, key_size),
+ Authorization(TAG_USER_ID, 7),
+ Authorization(TAG_USER_AUTH_ID, 8),
+ Authorization(TAG_APPLICATION_ID, "app_id", 6),
+ Authorization(TAG_AUTH_TIMEOUT, 300),
+ };
+ GenerateKeyRequest generate_request;
+ generate_request.key_description.Reinitialize(params, array_length(params));
+ if (digest != -1)
+ generate_request.key_description.push_back(TAG_DIGEST, digest);
+ if (padding != -1)
+ generate_request.key_description.push_back(TAG_PADDING, padding);
+ device.GenerateKey(generate_request, &generate_response_);
+ EXPECT_EQ(KM_ERROR_OK, generate_response_.error);
+
+ // This is safe because generate_response_ lives as long as the test and will keep the key
+ // blob around.
+ return &generate_response_.key_blob;
+ }
+
+ private:
+ GenerateKeyResponse generate_response_;
+};
+
+TEST_F(SigningOperationsTest, RsaSuccess) {
+ keymaster_key_blob_t* key = GenerateKey(KM_DIGEST_NONE, KM_PAD_NONE, 256 /* key size */);
+ ASSERT_TRUE(key != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.key_blob = *key;
+ begin_request.purpose = KM_PURPOSE_SIGN;
+ begin_request.additional_params.push_back(TAG_APPLICATION_ID, "app_id", 6);
+
+ 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("012345678901234567890123456789012", 32);
+ EXPECT_EQ(32U, 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());
+
+ FinishOperationResponse finish_response;
+ device.FinishOperation(begin_response.op_handle, &finish_response);
+ ASSERT_EQ(KM_ERROR_OK, finish_response.error);
+ EXPECT_GT(finish_response.signature.available_read(), 0U);
+ EXPECT_EQ(0U, finish_response.output.available_read());
+
+ EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
+}
+
+TEST_F(SigningOperationsTest, RsaAbort) {
+ keymaster_key_blob_t* key = GenerateKey(KM_DIGEST_NONE, KM_PAD_NONE, 256 /* key size */);
+ ASSERT_TRUE(key != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.key_blob = *key;
+ begin_request.purpose = KM_PURPOSE_SIGN;
+ begin_request.additional_params.push_back(TAG_APPLICATION_ID, "app_id", 6);
+
+ device.BeginOperation(begin_request, &begin_response);
+ ASSERT_EQ(KM_ERROR_OK, begin_response.error);
+
+ EXPECT_EQ(KM_ERROR_OK, device.AbortOperation(begin_response.op_handle));
+
+ // Another abort should fail
+ EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
+}
+
+TEST_F(SigningOperationsTest, RsaUnsupportedDigest) {
+ keymaster_key_blob_t* key = GenerateKey(KM_DIGEST_SHA_2_256, KM_PAD_NONE, 256 /* key size */);
+ ASSERT_TRUE(key != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.purpose = KM_PURPOSE_SIGN;
+ begin_request.key_blob = *key;
+ begin_request.additional_params.push_back(TAG_APPLICATION_ID, "app_id", 6);
+
+ device.BeginOperation(begin_request, &begin_response);
+ ASSERT_EQ(KM_ERROR_UNSUPPORTED_DIGEST, begin_response.error);
+
+ EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
+}
+
+TEST_F(SigningOperationsTest, RsaUnsupportedPadding) {
+ keymaster_key_blob_t* key = GenerateKey(KM_DIGEST_NONE, KM_PAD_RSA_OAEP, 256 /* key size */);
+ ASSERT_TRUE(key != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.purpose = KM_PURPOSE_SIGN;
+ begin_request.key_blob = *key;
+ begin_request.additional_params.push_back(TAG_APPLICATION_ID, "app_id", 6);
+
+ device.BeginOperation(begin_request, &begin_response);
+ ASSERT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, begin_response.error);
+
+ EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
+}
+
+TEST_F(SigningOperationsTest, RsaNoDigest) {
+ keymaster_key_blob_t* key =
+ GenerateKey(static_cast<keymaster_digest_t>(-1), KM_PAD_NONE, 256 /* key size */);
+ ASSERT_TRUE(key != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.purpose = KM_PURPOSE_SIGN;
+ begin_request.key_blob = *key;
+ begin_request.additional_params.push_back(TAG_APPLICATION_ID, "app_id", 6);
+
+ device.BeginOperation(begin_request, &begin_response);
+ ASSERT_EQ(KM_ERROR_UNSUPPORTED_DIGEST, begin_response.error);
+
+ EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
+}
+
+TEST_F(SigningOperationsTest, RsaNoPadding) {
+ keymaster_key_blob_t* key =
+ GenerateKey(KM_DIGEST_NONE, static_cast<keymaster_padding_t>(-1), 256 /* key size */);
+ ASSERT_TRUE(key != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.purpose = KM_PURPOSE_SIGN;
+ begin_request.key_blob = *key;
+ begin_request.additional_params.push_back(TAG_APPLICATION_ID, "app_id", 6);
+
+ device.BeginOperation(begin_request, &begin_response);
+ ASSERT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, begin_response.error);
+
+ EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
+}
+
+TEST_F(SigningOperationsTest, RsaTooShortMessage) {
+ keymaster_key_blob_t* key = GenerateKey(KM_DIGEST_NONE, KM_PAD_NONE, 256 /* key size */);
+ ASSERT_TRUE(key != NULL);
+
+ BeginOperationRequest begin_request;
+ BeginOperationResponse begin_response;
+ begin_request.key_blob = *key;
+ begin_request.purpose = KM_PURPOSE_SIGN;
+ begin_request.additional_params.push_back(TAG_APPLICATION_ID, "app_id", 6);
+
+ 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("01234567890123456789012345678901", 31);
+ EXPECT_EQ(31U, 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());
+
+ FinishOperationResponse finish_response;
+ device.FinishOperation(begin_response.op_handle, &finish_response);
+ ASSERT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, finish_response.error);
+ EXPECT_EQ(0U, finish_response.signature.available_read());
+ 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