Revert "Remove DSA support from keymaster."

This reverts commit 5e0579c2d4437b6f3c03872a643d12cb08a7bc79.
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index adc931e..4dca97a 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -268,6 +268,78 @@
     EXPECT_TRUE(contains(rsp_.unenforced, TAG_KEY_SIZE, 2048));
 }
 
+TEST_F(NewKeyGeneration, Dsa) {
+    req_.key_description.push_back(Authorization(TAG_ALGORITHM, KM_ALGORITHM_DSA));
+    req_.key_description.push_back(Authorization(TAG_KEY_SIZE, 256));
+    device.GenerateKey(req_, &rsp_);
+
+    CheckBaseParams(rsp_);
+
+    // Check specified tags are all present in unenforced characteristics
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_ALGORITHM, KM_ALGORITHM_DSA));
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_KEY_SIZE, 256));
+
+    // 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 >= 63 && g.data_length <= 64);
+    EXPECT_EQ(64U, p.data_length);
+    EXPECT_EQ(20U, q.data_length);
+}
+
+TEST_F(NewKeyGeneration, DsaDefaultSize) {
+    req_.key_description.push_back(Authorization(TAG_ALGORITHM, KM_ALGORITHM_DSA));
+    device.GenerateKey(req_, &rsp_);
+
+    CheckBaseParams(rsp_);
+
+    // Check specified tags are all present in unenforced characteristics
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_ALGORITHM, KM_ALGORITHM_DSA));
+
+    // Now check that unspecified, defaulted tags are correct.
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_KEY_SIZE, 2048));
+    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) {
+    req_.key_description.push_back(Authorization(TAG_ALGORITHM, KM_ALGORITHM_DSA));
+    req_.key_description.push_back(Authorization(TAG_KEY_SIZE, 256));
+    req_.key_description.push_back(Authorization(TAG_DSA_GENERATOR, dsa_g, array_size(dsa_g)));
+    req_.key_description.push_back(Authorization(TAG_DSA_P, dsa_p, array_size(dsa_p)));
+    req_.key_description.push_back(Authorization(TAG_DSA_Q, dsa_q, array_size(dsa_q)));
+    device.GenerateKey(req_, &rsp_);
+
+    CheckBaseParams(rsp_);
+
+    // Check specified tags are all present in unenforced characteristics
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_ALGORITHM, KM_ALGORITHM_DSA));
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_KEY_SIZE, 256));
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_DSA_GENERATOR,
+                         std::string(reinterpret_cast<const char*>(dsa_g), array_size(dsa_g))));
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_DSA_P,
+                         std::string(reinterpret_cast<const char*>(dsa_p), array_size(dsa_p))));
+    EXPECT_TRUE(contains(rsp_.unenforced, TAG_DSA_Q,
+                         std::string(reinterpret_cast<const char*>(dsa_q), array_size(dsa_q))));
+}
+
+TEST_F(NewKeyGeneration, Dsa_SomeParamsSpecified) {
+    req_.key_description.push_back(Authorization(TAG_ALGORITHM, KM_ALGORITHM_DSA));
+    req_.key_description.push_back(Authorization(TAG_KEY_SIZE, 256));
+    req_.key_description.push_back(Authorization(TAG_DSA_P, dsa_p, array_size(dsa_p)));
+    req_.key_description.push_back(Authorization(TAG_DSA_Q, dsa_q, array_size(dsa_q)));
+    device.GenerateKey(req_, &rsp_);
+
+    ASSERT_EQ(KM_ERROR_INVALID_DSA_PARAMS, rsp_.error);
+}
+
 TEST_F(NewKeyGeneration, Ecdsa) {
     req_.key_description.push_back(Authorization(TAG_ALGORITHM, KM_ALGORITHM_ECDSA));
     req_.key_description.push_back(Authorization(TAG_KEY_SIZE, 224));
@@ -505,6 +577,12 @@
     SignMessage(message, array_size(message) - 1);
 }
 
+TEST_F(SigningOperationsTest, DsaSuccess) {
+    GenerateKey(KM_ALGORITHM_DSA, KM_DIGEST_NONE, KM_PAD_NONE, 256 /* key size */);
+    const char message[] = "123456789012345678901234567890123456789012345678";
+    SignMessage(message, array_size(message) - 1);
+}
+
 TEST_F(SigningOperationsTest, EcdsaSuccess) {
     GenerateKey(KM_ALGORITHM_ECDSA, KM_DIGEST_NONE, KM_PAD_NONE, 224 /* key size */);
     const char message[] = "123456789012345678901234567890123456789012345678";
@@ -672,6 +750,13 @@
     VerifyMessage(message, array_size(message) - 1);
 }
 
+TEST_F(VerificationOperationsTest, DsaSuccess) {
+    GenerateKey(KM_ALGORITHM_DSA, KM_DIGEST_NONE, KM_PAD_NONE, 256 /* key size */);
+    const char message[] = "123456789012345678901234567890123456789012345678";
+    SignMessage(message, array_size(message) - 1);
+    VerifyMessage(message, array_size(message) - 1);
+}
+
 TEST_F(VerificationOperationsTest, EcdsaSuccess) {
     GenerateKey(KM_ALGORITHM_ECDSA, KM_DIGEST_NONE, KM_PAD_NONE, 224 /* key size */);
     const char message[] = "123456789012345678901234567890123456789012345678";
@@ -696,6 +781,22 @@
     // TODO(swillden): Verify that the exported key is actually usable to verify signatures.
 }
 
+TEST_F(ExportKeyTest, DsaSuccess) {
+    GenerateKey(KM_ALGORITHM_DSA, KM_DIGEST_NONE, KM_PAD_NONE, 1024 /* key size */);
+
+    ExportKeyRequest request;
+    ExportKeyResponse response;
+    AddClientParams(&request.additional_params);
+    request.key_format = KM_KEY_FORMAT_X509;
+    request.SetKeyMaterial(key_blob());
+
+    device.ExportKey(request, &response);
+    ASSERT_EQ(KM_ERROR_OK, response.error);
+    EXPECT_TRUE(response.key_data != NULL);
+
+    // TODO(swillden): Verify that the exported key is actually usable to verify signatures.
+}
+
 TEST_F(ExportKeyTest, EcdsaSuccess) {
     GenerateKey(KM_ALGORITHM_ECDSA, KM_DIGEST_NONE, KM_PAD_NONE, 224 /* key size */);
 
@@ -833,6 +934,136 @@
     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), 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);
+    VerifyMessage(import_response.key_blob, message.get(), message_len);
+}
+
+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);
+    VerifyMessage(import_response.key_blob, message.get(), message_len);
+}
+
+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), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),