Improve test coverage.

Change-Id: I3523a48dc9ddb972055b6218724a63d443669c1b
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index 2748656..c6fddcf 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -44,6 +44,32 @@
 namespace keymaster {
 namespace test {
 
+// Note that these DSA generator, p and q values must match the values from dsa_privkey_pk8.der.
+const uint8_t dsa_g[] = {
+    0x19, 0x1C, 0x71, 0xFD, 0xE0, 0x03, 0x0C, 0x43, 0xD9, 0x0B, 0xF6, 0xCD, 0xD6, 0xA9, 0x70, 0xE7,
+    0x37, 0x86, 0x3A, 0x78, 0xE9, 0xA7, 0x47, 0xA7, 0x47, 0x06, 0x88, 0xB1, 0xAF, 0xD7, 0xF3, 0xF1,
+    0xA1, 0xD7, 0x00, 0x61, 0x28, 0x88, 0x31, 0x48, 0x60, 0xD8, 0x11, 0xEF, 0xA5, 0x24, 0x1A, 0x81,
+    0xC4, 0x2A, 0xE2, 0xEA, 0x0E, 0x36, 0xD2, 0xD2, 0x05, 0x84, 0x37, 0xCF, 0x32, 0x7D, 0x09, 0xE6,
+    0x0F, 0x8B, 0x0C, 0xC8, 0xC2, 0xA4, 0xB1, 0xDC, 0x80, 0xCA, 0x68, 0xDF, 0xAF, 0xD2, 0x90, 0xC0,
+    0x37, 0x58, 0x54, 0x36, 0x8F, 0x49, 0xB8, 0x62, 0x75, 0x8B, 0x48, 0x47, 0xC0, 0xBE, 0xF7, 0x9A,
+    0x92, 0xA6, 0x68, 0x05, 0xDA, 0x9D, 0xAF, 0x72, 0x9A, 0x67, 0xB3, 0xB4, 0x14, 0x03, 0xAE, 0x4F,
+    0x4C, 0x76, 0xB9, 0xD8, 0x64, 0x0A, 0xBA, 0x3B, 0xA8, 0x00, 0x60, 0x4D, 0xAE, 0x81, 0xC3, 0xC5,
+};
+const uint8_t dsa_p[] = {
+    0xA3, 0xF3, 0xE9, 0xB6, 0x7E, 0x7D, 0x88, 0xF6, 0xB7, 0xE5, 0xF5, 0x1F, 0x3B, 0xEE, 0xAC, 0xD7,
+    0xAD, 0xBC, 0xC9, 0xD1, 0x5A, 0xF8, 0x88, 0xC4, 0xEF, 0x6E, 0x3D, 0x74, 0x19, 0x74, 0xE7, 0xD8,
+    0xE0, 0x26, 0x44, 0x19, 0x86, 0xAF, 0x19, 0xDB, 0x05, 0xE9, 0x3B, 0x8B, 0x58, 0x58, 0xDE, 0xE5,
+    0x4F, 0x48, 0x15, 0x01, 0xEA, 0xE6, 0x83, 0x52, 0xD7, 0xC1, 0x21, 0xDF, 0xB9, 0xB8, 0x07, 0x66,
+    0x50, 0xFB, 0x3A, 0x0C, 0xB3, 0x85, 0xEE, 0xBB, 0x04, 0x5F, 0xC2, 0x6D, 0x6D, 0x95, 0xFA, 0x11,
+    0x93, 0x1E, 0x59, 0x5B, 0xB1, 0x45, 0x8D, 0xE0, 0x3D, 0x73, 0xAA, 0xF2, 0x41, 0x14, 0x51, 0x07,
+    0x72, 0x3D, 0xA2, 0xF7, 0x58, 0xCD, 0x11, 0xA1, 0x32, 0xCF, 0xDA, 0x42, 0xB7, 0xCC, 0x32, 0x80,
+    0xDB, 0x87, 0x82, 0xEC, 0x42, 0xDB, 0x5A, 0x55, 0x24, 0x24, 0xA2, 0xD1, 0x55, 0x29, 0xAD, 0xEB,
+};
+const uint8_t dsa_q[] = {
+    0xEB, 0xEA, 0x17, 0xD2, 0x09, 0xB3, 0xD7, 0x21, 0x9A, 0x21,
+    0x07, 0x82, 0x8F, 0xAB, 0xFE, 0x88, 0x71, 0x68, 0xF7, 0xE3,
+};
+
 class KeymasterTest : public testing::Test {
   protected:
     KeymasterTest() : device(5, new StdoutLogger) { RAND_seed("foobar", 6); }
@@ -235,6 +261,56 @@
     EXPECT_TRUE(contains(rsp.unenforced, KM_TAG_CREATION_DATETIME));
 }
 
+TEST_F(NewKeyGeneration, RsaDefaultSize) {
+    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_USER_ID, 7),
+        Authorization(TAG_USER_AUTH_ID, 8),
+        Authorization(TAG_APPLICATION_ID, "app_id", 6),
+        Authorization(TAG_APPLICATION_DATA, "app_data", 8),
+        Authorization(TAG_AUTH_TIMEOUT, 300),
+    };
+    GenerateKeyRequest req;
+    req.key_description.Reinitialize(params, array_length(params));
+    GenerateKeyResponse rsp;
+
+    device.GenerateKey(req, &rsp);
+
+    ASSERT_EQ(KM_ERROR_OK, rsp.error);
+    EXPECT_EQ(0U, rsp.enforced.size());
+    EXPECT_EQ(12U, rsp.enforced.SerializedSize());
+    EXPECT_GT(rsp.unenforced.SerializedSize(), 12U);
+
+    // Check specified tags are all present in unenforced characteristics
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_SIGN));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_VERIFY));
+
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_ALGORITHM, KM_ALGORITHM_RSA));
+
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_ID, 7));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_AUTH_ID, 8));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 300));
+
+    // Verify that App ID, App data and ROT are NOT included.
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_ROOT_OF_TRUST));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_APPLICATION_ID));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_APPLICATION_DATA));
+
+    // Just for giggles, check that some unexpected tags/values are NOT present.
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 301));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_RESCOPE_AUTH_TIMEOUT));
+
+    // Now check that unspecified, defaulted tags are correct.
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_RSA_PUBLIC_EXPONENT, 65537));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_ORIGIN, KM_ORIGIN_SOFTWARE));
+    EXPECT_TRUE(contains(rsp.unenforced, KM_TAG_CREATION_DATETIME));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_KEY_SIZE, 2048));
+}
+
 TEST_F(NewKeyGeneration, Dsa) {
     keymaster_key_param_t params[] = {
         Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
@@ -294,12 +370,145 @@
     EXPECT_EQ(20U, q.data_length);
 }
 
+TEST_F(NewKeyGeneration, DsaDefaultSize) {
+    keymaster_key_param_t params[] = {
+        Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+        Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+        Authorization(TAG_ALGORITHM, KM_ALGORITHM_DSA),
+        Authorization(TAG_USER_ID, 7),
+        Authorization(TAG_USER_AUTH_ID, 8),
+        Authorization(TAG_APPLICATION_ID, "app_id", 6),
+        Authorization(TAG_APPLICATION_DATA, "app_data", 8),
+        Authorization(TAG_AUTH_TIMEOUT, 300),
+    };
+    GenerateKeyRequest req;
+    req.key_description.Reinitialize(params, array_length(params));
+    GenerateKeyResponse rsp;
+
+    device.GenerateKey(req, &rsp);
+
+    ASSERT_EQ(KM_ERROR_OK, rsp.error);
+    EXPECT_EQ(0U, rsp.enforced.size());
+    EXPECT_EQ(12U, rsp.enforced.SerializedSize());
+    EXPECT_GT(rsp.unenforced.SerializedSize(), 12U);
+
+    // Check specified tags are all present in unenforced characteristics
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_SIGN));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_VERIFY));
+
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_ALGORITHM, KM_ALGORITHM_DSA));
+
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_ID, 7));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_AUTH_ID, 8));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 300));
+
+    // Verify that App ID, App data and ROT are NOT included.
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_ROOT_OF_TRUST));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_APPLICATION_ID));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_APPLICATION_DATA));
+
+    // Just for giggles, check that some unexpected tags/values are NOT present.
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 301));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_RESCOPE_AUTH_TIMEOUT));
+
+    // Now check that unspecified, defaulted tags are correct.
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_ORIGIN, KM_ORIGIN_SOFTWARE));
+    EXPECT_TRUE(contains(rsp.unenforced, KM_TAG_CREATION_DATETIME));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_KEY_SIZE, 2048));
+
+    // Generator should have created DSA params.
+    keymaster_blob_t g, p, q;
+    EXPECT_TRUE(rsp.unenforced.GetTagValue(TAG_DSA_GENERATOR, &g));
+    EXPECT_TRUE(rsp.unenforced.GetTagValue(TAG_DSA_P, &p));
+    EXPECT_TRUE(rsp.unenforced.GetTagValue(TAG_DSA_Q, &q));
+    EXPECT_TRUE(g.data_length >= 255 && g.data_length <= 256);
+    EXPECT_EQ(256U, p.data_length);
+    EXPECT_EQ(32U, q.data_length);
+}
+
+TEST_F(NewKeyGeneration, Dsa_ParamsSpecified) {
+    keymaster_key_param_t params[] = {
+        Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+        Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+        Authorization(TAG_ALGORITHM, KM_ALGORITHM_DSA),
+        Authorization(TAG_KEY_SIZE, 256),
+        Authorization(TAG_USER_ID, 7),
+        Authorization(TAG_USER_AUTH_ID, 8),
+        Authorization(TAG_APPLICATION_ID, "app_id", 6),
+        Authorization(TAG_APPLICATION_DATA, "app_data", 8),
+        Authorization(TAG_AUTH_TIMEOUT, 300),
+        Authorization(TAG_DSA_GENERATOR, dsa_g, array_size(dsa_g)),
+        Authorization(TAG_DSA_P, dsa_p, array_size(dsa_p)),
+        Authorization(TAG_DSA_Q, dsa_q, array_size(dsa_q)),
+    };
+    GenerateKeyRequest req;
+    req.key_description.Reinitialize(params, array_length(params));
+    GenerateKeyResponse rsp;
+
+    device.GenerateKey(req, &rsp);
+
+    ASSERT_EQ(KM_ERROR_OK, rsp.error);
+    EXPECT_EQ(0U, rsp.enforced.size());
+    EXPECT_EQ(12U, rsp.enforced.SerializedSize());
+    EXPECT_GT(rsp.unenforced.SerializedSize(), 12U);
+
+    // Check specified tags are all present in unenforced characteristics
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_SIGN));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_VERIFY));
+
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_ALGORITHM, KM_ALGORITHM_DSA));
+
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_ID, 7));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_AUTH_ID, 8));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_KEY_SIZE, 256));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 300));
+
+    // Verify that App ID, App data and ROT are NOT included.
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_ROOT_OF_TRUST));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_APPLICATION_ID));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_APPLICATION_DATA));
+
+    // Just for giggles, check that some unexpected tags/values are NOT present.
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 301));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_RESCOPE_AUTH_TIMEOUT));
+
+    // Now check that unspecified, defaulted tags are correct.
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_ORIGIN, KM_ORIGIN_SOFTWARE));
+    EXPECT_TRUE(contains(rsp.unenforced, KM_TAG_CREATION_DATETIME));
+}
+
+TEST_F(NewKeyGeneration, Dsa_SomeParamsSpecified) {
+    keymaster_key_param_t params[] = {
+        Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+        Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+        Authorization(TAG_ALGORITHM, KM_ALGORITHM_DSA),
+        Authorization(TAG_KEY_SIZE, 256),
+        Authorization(TAG_USER_ID, 7),
+        Authorization(TAG_USER_AUTH_ID, 8),
+        Authorization(TAG_APPLICATION_ID, "app_id", 6),
+        Authorization(TAG_APPLICATION_DATA, "app_data", 8),
+        Authorization(TAG_AUTH_TIMEOUT, 300),
+        Authorization(TAG_DSA_P, dsa_p, array_size(dsa_p)),
+        Authorization(TAG_DSA_Q, dsa_q, array_size(dsa_q)),
+    };
+    GenerateKeyRequest req;
+    req.key_description.Reinitialize(params, array_length(params));
+    GenerateKeyResponse rsp;
+
+    device.GenerateKey(req, &rsp);
+    ASSERT_EQ(KM_ERROR_INVALID_DSA_PARAMS, rsp.error);
+}
+
 TEST_F(NewKeyGeneration, Ecdsa) {
     keymaster_key_param_t params[] = {
         Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
         Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
         Authorization(TAG_ALGORITHM, KM_ALGORITHM_ECDSA),
-        Authorization(TAG_KEY_SIZE, 256),
+        Authorization(TAG_KEY_SIZE, 192),
         Authorization(TAG_USER_ID, 7),
         Authorization(TAG_USER_AUTH_ID, 8),
         Authorization(TAG_APPLICATION_ID, "app_id", 6),
@@ -325,7 +534,7 @@
 
     EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_ID, 7));
     EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_AUTH_ID, 8));
-    EXPECT_TRUE(contains(rsp.unenforced, TAG_KEY_SIZE, 256));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_KEY_SIZE, 192));
     EXPECT_TRUE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 300));
 
     // Verify that App ID, App data and ROT are NOT included.
@@ -344,6 +553,100 @@
     EXPECT_TRUE(contains(rsp.unenforced, KM_TAG_CREATION_DATETIME));
 }
 
+TEST_F(NewKeyGeneration, EcdsaDefaultSize) {
+    keymaster_key_param_t params[] = {
+        Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+        Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+        Authorization(TAG_ALGORITHM, KM_ALGORITHM_ECDSA),
+        Authorization(TAG_USER_ID, 7),
+        Authorization(TAG_USER_AUTH_ID, 8),
+        Authorization(TAG_APPLICATION_ID, "app_id", 6),
+        Authorization(TAG_APPLICATION_DATA, "app_data", 8),
+        Authorization(TAG_AUTH_TIMEOUT, 300),
+    };
+    GenerateKeyRequest req;
+    req.key_description.Reinitialize(params, array_length(params));
+    GenerateKeyResponse rsp;
+
+    device.GenerateKey(req, &rsp);
+
+    ASSERT_EQ(KM_ERROR_OK, rsp.error);
+    EXPECT_EQ(0U, rsp.enforced.size());
+    EXPECT_EQ(12U, rsp.enforced.SerializedSize());
+    EXPECT_GT(rsp.unenforced.SerializedSize(), 12U);
+
+    // Check specified tags are all present in unenforced characteristics
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_SIGN));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_VERIFY));
+
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_ALGORITHM, KM_ALGORITHM_ECDSA));
+
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_ID, 7));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_USER_AUTH_ID, 8));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 300));
+
+    // Verify that App ID, App data and ROT are NOT included.
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_ROOT_OF_TRUST));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_APPLICATION_ID));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_APPLICATION_DATA));
+
+    // Just for giggles, check that some unexpected tags/values are NOT present.
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_AUTH_TIMEOUT, 301));
+    EXPECT_FALSE(contains(rsp.unenforced, TAG_RESCOPE_AUTH_TIMEOUT));
+
+    // Now check that unspecified, defaulted tags are correct.
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_ORIGIN, KM_ORIGIN_SOFTWARE));
+    EXPECT_TRUE(contains(rsp.unenforced, KM_TAG_CREATION_DATETIME));
+    EXPECT_TRUE(contains(rsp.unenforced, TAG_KEY_SIZE, 224));
+}
+
+TEST_F(NewKeyGeneration, EcdsaInvalidSize) {
+    keymaster_key_param_t params[] = {
+        Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+        Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+        Authorization(TAG_ALGORITHM, KM_ALGORITHM_ECDSA),
+        Authorization(TAG_USER_ID, 7),
+        Authorization(TAG_USER_AUTH_ID, 8),
+        Authorization(TAG_APPLICATION_ID, "app_id", 6),
+        Authorization(TAG_APPLICATION_DATA, "app_data", 8),
+        Authorization(TAG_AUTH_TIMEOUT, 300),
+        Authorization(TAG_KEY_SIZE, 190),
+    };
+    GenerateKeyRequest req;
+    req.key_description.Reinitialize(params, array_length(params));
+    GenerateKeyResponse rsp;
+
+    device.GenerateKey(req, &rsp);
+
+    ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_SIZE, rsp.error);
+}
+
+TEST_F(NewKeyGeneration, EcdsaAllValidSizes) {
+    keymaster_key_param_t params[] = {
+        Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+        Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+        Authorization(TAG_ALGORITHM, KM_ALGORITHM_ECDSA),
+        Authorization(TAG_USER_ID, 7),
+        Authorization(TAG_USER_AUTH_ID, 8),
+        Authorization(TAG_APPLICATION_ID, "app_id", 6),
+        Authorization(TAG_APPLICATION_DATA, "app_data", 8),
+        Authorization(TAG_AUTH_TIMEOUT, 300),
+    };
+
+    size_t valid_sizes[] = {192, 224, 256, 384, 521};
+
+    GenerateKeyRequest req;
+    for (size_t size : valid_sizes) {
+        req.key_description.Reinitialize(params, array_length(params));
+        req.key_description.push_back(Authorization(TAG_KEY_SIZE, size));
+        GenerateKeyResponse rsp;
+        device.GenerateKey(req, &rsp);
+        EXPECT_EQ(KM_ERROR_OK, rsp.error) << "Failed to generate size: " << size;
+    }
+}
+
 typedef KeymasterTest GetKeyCharacteristics;
 TEST_F(GetKeyCharacteristics, SimpleRsa) {
     keymaster_key_param_t params[] = {
@@ -738,7 +1041,7 @@
 }
 
 TEST_F(VerificationOperationsTest, EcdsaSuccess) {
-    GenerateKey(KM_ALGORITHM_ECDSA, KM_DIGEST_NONE, KM_PAD_NONE, 256 /* key size */);
+    GenerateKey(KM_ALGORITHM_ECDSA, KM_DIGEST_NONE, KM_PAD_NONE, 192 /* key size */);
     const char message[] = "123456789012345678901234567890123456789012345678";
     SignMessage(message, array_size(message) - 1);
     ASSERT_TRUE(signature() != NULL);
@@ -931,6 +1234,54 @@
     EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
 }
 
+TEST_F(ImportKeyTest, RsaKeySizeMismatch) {
+    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_KEY_SIZE, 2048),  // Doesn't match key
+        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("rsa_privkey_pk8.der");
+    ASSERT_EQ(633U, 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_IMPORT_PARAMETER_MISMATCH, import_response.error);
+}
+
+TEST_F(ImportKeyTest, RsaPublicExponenMismatch) {
+    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_RSA_PUBLIC_EXPONENT, 3),   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("rsa_privkey_pk8.der");
+    ASSERT_EQ(633U, 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_IMPORT_PARAMETER_MISMATCH, import_response.error);
+}
+
 TEST_F(ImportKeyTest, DsaSuccess) {
     keymaster_key_param_t params[] = {
         Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
@@ -1001,6 +1352,138 @@
     EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
 }
 
+TEST_F(ImportKeyTest, DsaParametersMatch) {
+    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),
+        Authorization(TAG_KEY_SIZE, 1024),
+        Authorization(TAG_DSA_GENERATOR, dsa_g, array_size(dsa_g)),
+        Authorization(TAG_DSA_P, dsa_p, array_size(dsa_p)),
+        Authorization(TAG_DSA_Q, dsa_q, array_size(dsa_q)),
+    };
+
+    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));
+}
+
+uint8_t dsa_wrong_q[] = {
+    0xC0, 0x66, 0x64, 0xF9, 0x05, 0x38, 0x64, 0x38, 0x4A, 0x17,
+    0x66, 0x79, 0xDD, 0x7F, 0x6E, 0x55, 0x22, 0x2A, 0xDF, 0xC5,
+};
+
+TEST_F(ImportKeyTest, DsaParameterMismatch) {
+    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),
+        Authorization(TAG_KEY_SIZE, 1024),
+        Authorization(TAG_DSA_Q, dsa_wrong_q, array_size(dsa_wrong_q)),
+    };
+
+    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_IMPORT_PARAMETER_MISMATCH, import_response.error);
+}
+
+TEST_F(ImportKeyTest, DsaKeySizeMismatch) {
+    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),
+        Authorization(TAG_KEY_SIZE, 2048),
+    };
+
+    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_IMPORT_PARAMETER_MISMATCH, import_response.error);
+}
+
 TEST_F(ImportKeyTest, EcdsaSuccess) {
     keymaster_key_param_t params[] = {
         Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
@@ -1071,5 +1554,102 @@
     EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, device.AbortOperation(begin_response.op_handle));
 }
 
+TEST_F(ImportKeyTest, EcdsaSizeSpecified) {
+    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),
+        Authorization(TAG_KEY_SIZE, 256),
+    };
+
+    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));
+}
+
+TEST_F(ImportKeyTest, EcdsaSizeMismatch) {
+    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),
+        Authorization(TAG_KEY_SIZE, 192),
+    };
+
+    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_IMPORT_PARAMETER_MISMATCH, import_response.error);
+}
+
 }  // namespace test
 }  // namespace keymaster