Add support for all digests for ECDSA.

Also, switch to useing the EVP API rather than the ECDSA API.

Cherry-picked from internal.

Bug: 21048758
Change-Id: Id1bf19f469de56bbe9adcf65cebee8ab4ea84212
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index 5a4cba7..698e426 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -188,7 +188,10 @@
 
     ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_EC,
                                                            KM_PURPOSE_SIGN, &digests, &len));
-    EXPECT_TRUE(ResponseContains(KM_DIGEST_NONE, digests, len));
+    EXPECT_TRUE(
+        ResponseContains({KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+                          KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
+                         digests, len));
     free(digests);
 
     EXPECT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE,
@@ -620,6 +623,17 @@
         EXPECT_EQ(3, GetParam()->keymaster0_calls());
 }
 
+TEST_P(SigningOperationsTest, EcdsaSha256Success) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(
+                               KM_DIGEST_SHA_2_256)));
+    string message(1024, 'a');
+    string signature;
+    SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
+
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(3, GetParam()->keymaster0_calls());
+}
+
 TEST_P(SigningOperationsTest, AesEcbSign) {
     ASSERT_EQ(KM_ERROR_OK,
               GenerateKey(AuthorizationSetBuilder().AesEncryptionKey(128).Authorization(
@@ -1245,6 +1259,31 @@
         EXPECT_EQ(4, GetParam()->keymaster0_calls());
 }
 
+TEST_P(VerificationOperationsTest, EcdsaSha256Success) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .EcdsaSigningKey(256)
+                                           .Digest(KM_DIGEST_SHA_2_256)
+                                           .Digest(KM_DIGEST_NONE)));
+    string message = "123456789012345678901234567890123456789012345678";
+    string signature;
+    SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
+    VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
+
+    if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+        EXPECT_EQ(4, GetParam()->keymaster0_calls());
+
+    // Just for giggles, try verifying with the wrong digest.
+    AuthorizationSet begin_params(client_params());
+    begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
+    EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
+
+    string result;
+    size_t input_consumed;
+    EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
+    EXPECT_EQ(message.size(), input_consumed);
+    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+}
+
 TEST_P(VerificationOperationsTest, HmacSha1Success) {
     GenerateKey(AuthorizationSetBuilder().HmacKey(128).Digest(KM_DIGEST_SHA1));
     string message = "123456789012345678901234567890123456789012345678";
diff --git a/ec_key_factory.cpp b/ec_key_factory.cpp
index db094fa..e500a39 100644
--- a/ec_key_factory.cpp
+++ b/ec_key_factory.cpp
@@ -16,6 +16,8 @@
 
 #include <keymaster/ec_key_factory.h>
 
+#include <openssl/evp.h>
+
 #include <keymaster/keymaster_context.h>
 
 #include "ec_key.h"
diff --git a/ecdsa_operation.cpp b/ecdsa_operation.cpp
index a28209a..5f9767f 100644
--- a/ecdsa_operation.cpp
+++ b/ecdsa_operation.cpp
@@ -14,16 +14,19 @@
  * limitations under the License.
  */
 
+#include "ecdsa_operation.h"
+
 #include <openssl/ecdsa.h>
 
 #include "ec_key.h"
-#include "ecdsa_operation.h"
 #include "openssl_err.h"
 #include "openssl_utils.h"
 
 namespace keymaster {
 
-static const keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE};
+static const keymaster_digest_t supported_digests[] = {
+    KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,     KM_DIGEST_SHA_2_224,
+    KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
 
 Operation* EcdsaOperationFactory::CreateOperation(const Key& key,
                                                   const AuthorizationSet& begin_params,
@@ -34,23 +37,18 @@
         return nullptr;
     }
 
-    *error = KM_ERROR_UNSUPPORTED_DIGEST;
-    keymaster_digest_t digest;
-    if (!begin_params.GetTagValue(TAG_DIGEST, &digest)) {
-        LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
+    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
+    if (!ecdsa_key->InternalToEvp(pkey.get())) {
+        *error = KM_ERROR_UNKNOWN_ERROR;
         return nullptr;
-    } else if (!supported(digest)) {
-        LOG_E("Digest %d not supported", digest);
-        return nullptr;
-    } else if (!ecdsa_key->authorizations().Contains(TAG_DIGEST, digest) &&
-               !ecdsa_key->authorizations().Contains(TAG_DIGEST_OLD, digest)) {
-        LOG_E("Digest %d was specified, but not authorized by key", digest);
-        *error = KM_ERROR_INCOMPATIBLE_DIGEST;
-        return NULL;
     }
-    *error = KM_ERROR_OK;
 
-    Operation* op = InstantiateOperation(digest, ecdsa_key->key());
+    keymaster_digest_t digest;
+    if (!GetAndValidateDigest(begin_params, key, &digest, error))
+        return nullptr;
+
+    *error = KM_ERROR_OK;
+    Operation* op = InstantiateOperation(digest, pkey.release());
     if (!op)
         *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
     return op;
@@ -63,19 +61,34 @@
 
 EcdsaOperation::~EcdsaOperation() {
     if (ecdsa_key_ != NULL)
-        EC_KEY_free(ecdsa_key_);
+        EVP_PKEY_free(ecdsa_key_);
+    EVP_MD_CTX_cleanup(&digest_ctx_);
 }
 
-keymaster_error_t EcdsaOperation::Update(const AuthorizationSet& /* additional_params */,
-                                         const Buffer& input, Buffer* /* output */,
-                                         size_t* input_consumed) {
-    assert(input_consumed);
-    switch (purpose()) {
+keymaster_error_t EcdsaOperation::InitDigest() {
+    switch (digest_) {
+    case KM_DIGEST_NONE:
+        return KM_ERROR_OK;
+    case KM_DIGEST_MD5:
+        digest_algorithm_ = EVP_md5();
+        return KM_ERROR_OK;
+    case KM_DIGEST_SHA1:
+        digest_algorithm_ = EVP_sha1();
+        return KM_ERROR_OK;
+    case KM_DIGEST_SHA_2_224:
+        digest_algorithm_ = EVP_sha224();
+        return KM_ERROR_OK;
+    case KM_DIGEST_SHA_2_256:
+        digest_algorithm_ = EVP_sha256();
+        return KM_ERROR_OK;
+    case KM_DIGEST_SHA_2_384:
+        digest_algorithm_ = EVP_sha384();
+        return KM_ERROR_OK;
+    case KM_DIGEST_SHA_2_512:
+        digest_algorithm_ = EVP_sha512();
+        return KM_ERROR_OK;
     default:
-        return KM_ERROR_UNIMPLEMENTED;
-    case KM_PURPOSE_SIGN:
-    case KM_PURPOSE_VERIFY:
-        return StoreData(input, input_consumed);
+        return KM_ERROR_UNSUPPORTED_DIGEST;
     }
 }
 
@@ -87,28 +100,110 @@
     return KM_ERROR_OK;
 }
 
+keymaster_error_t EcdsaSignOperation::Begin(const AuthorizationSet& /* input_params */,
+                                            AuthorizationSet* /* output_params */) {
+    keymaster_error_t error = InitDigest();
+    if (error != KM_ERROR_OK)
+        return error;
+
+    if (digest_ == KM_DIGEST_NONE)
+        return KM_ERROR_OK;
+
+    EVP_PKEY_CTX* pkey_ctx;
+    if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
+                           ecdsa_key_) != 1)
+        return TranslateLastOpenSslError();
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t EcdsaSignOperation::Update(const AuthorizationSet& /* additional_params */,
+                                             const Buffer& input, Buffer* /* output */,
+                                             size_t* input_consumed) {
+    if (digest_ == KM_DIGEST_NONE)
+        return StoreData(input, input_consumed);
+
+    if (EVP_DigestSignUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
+        return TranslateLastOpenSslError();
+    *input_consumed = input.available_read();
+    return KM_ERROR_OK;
+}
+
 keymaster_error_t EcdsaSignOperation::Finish(const AuthorizationSet& /* additional_params */,
                                              const Buffer& /* signature */, Buffer* output) {
-    assert(output);
-    output->Reinitialize(ECDSA_size(ecdsa_key_));
-    unsigned int siglen;
-    if (!ECDSA_sign(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
-                    output->peek_write(), &siglen, ecdsa_key_))
-        return TranslateLastOpenSslError();
+    if (!output)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    size_t siglen;
+    if (digest_ == KM_DIGEST_NONE) {
+        UniquePtr<EC_KEY, EC_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
+        if (!ecdsa.get())
+            return TranslateLastOpenSslError();
+
+        output->Reinitialize(ECDSA_size(ecdsa.get()));
+        unsigned int siglen_tmp;
+        if (!ECDSA_sign(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
+                        output->peek_write(), &siglen_tmp, ecdsa.get()))
+            return TranslateLastOpenSslError();
+        siglen = siglen_tmp;
+    } else {
+        if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
+            return TranslateLastOpenSslError();
+        if (!output->Reinitialize(siglen))
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
+            return TranslateLastOpenSslError();
+    }
     output->advance_write(siglen);
     return KM_ERROR_OK;
 }
 
+keymaster_error_t EcdsaVerifyOperation::Begin(const AuthorizationSet& /* input_params */,
+                                              AuthorizationSet* /* output_params */) {
+    keymaster_error_t error = InitDigest();
+    if (error != KM_ERROR_OK)
+        return error;
+
+    if (digest_ == KM_DIGEST_NONE)
+        return KM_ERROR_OK;
+
+    EVP_PKEY_CTX* pkey_ctx;
+    if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
+                             ecdsa_key_) != 1)
+        return TranslateLastOpenSslError();
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t EcdsaVerifyOperation::Update(const AuthorizationSet& /* additional_params */,
+                                               const Buffer& input, Buffer* /* output */,
+                                               size_t* input_consumed) {
+    if (digest_ == KM_DIGEST_NONE)
+        return StoreData(input, input_consumed);
+
+    if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
+        return TranslateLastOpenSslError();
+    *input_consumed = input.available_read();
+    return KM_ERROR_OK;
+}
+
 keymaster_error_t EcdsaVerifyOperation::Finish(const AuthorizationSet& /* additional_params */,
                                                const Buffer& signature, Buffer* /* output */) {
-    int result = ECDSA_verify(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
-                              signature.peek_read(), signature.available_read(), ecdsa_key_);
-    if (result < 0)
-        return TranslateLastOpenSslError();
-    else if (result == 0)
+    if (digest_ == KM_DIGEST_NONE) {
+        UniquePtr<EC_KEY, EC_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
+        if (!ecdsa.get())
+            return TranslateLastOpenSslError();
+
+        int result =
+            ECDSA_verify(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
+                         signature.peek_read(), signature.available_read(), ecdsa.get());
+        if (result < 0)
+            return TranslateLastOpenSslError();
+        else if (result == 0)
+            return KM_ERROR_VERIFICATION_FAILED;
+    } else if (!EVP_DigestVerifyFinal(&digest_ctx_, signature.peek_read(),
+                                      signature.available_read()))
         return KM_ERROR_VERIFICATION_FAILED;
-    else
-        return KM_ERROR_OK;
+
+    return KM_ERROR_OK;
 }
 
 }  // namespace keymaster
diff --git a/ecdsa_operation.h b/ecdsa_operation.h
index db986c8..297253e 100644
--- a/ecdsa_operation.h
+++ b/ecdsa_operation.h
@@ -18,6 +18,7 @@
 #define SYSTEM_KEYMASTER_ECDSA_OPERATION_H_
 
 #include <openssl/ec.h>
+#include <openssl/evp.h>
 
 #include <UniquePtr.h>
 
@@ -27,42 +28,47 @@
 
 class EcdsaOperation : public Operation {
   public:
-    EcdsaOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EC_KEY* key)
-        : Operation(purpose), digest_(digest), ecdsa_key_(key) {}
+    EcdsaOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key)
+        : Operation(purpose), digest_(digest), ecdsa_key_(key) {
+        EVP_MD_CTX_init(&digest_ctx_);
+    }
     ~EcdsaOperation();
 
-    virtual keymaster_error_t Begin(const AuthorizationSet& /* input_params */,
-                                    AuthorizationSet* /* output_params */) {
-        if (digest_ != KM_DIGEST_NONE)
-            return KM_ERROR_UNSUPPORTED_DIGEST;
-        return KM_ERROR_OK;
-    }
-    virtual keymaster_error_t Update(const AuthorizationSet& /* additional_params */,
-                                     const Buffer& input, Buffer* output, size_t* input_consumed);
-    virtual keymaster_error_t Abort() { return KM_ERROR_OK; }
+    keymaster_error_t Abort() override { return KM_ERROR_OK; }
 
   protected:
     keymaster_error_t StoreData(const Buffer& input, size_t* input_consumed);
+    keymaster_error_t InitDigest();
 
     keymaster_digest_t digest_;
-    EC_KEY* ecdsa_key_;
+    const EVP_MD* digest_algorithm_;
+    EVP_PKEY* ecdsa_key_;
+    EVP_MD_CTX digest_ctx_;
     Buffer data_;
 };
 
 class EcdsaSignOperation : public EcdsaOperation {
   public:
-    EcdsaSignOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EC_KEY* key)
+    EcdsaSignOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key)
         : EcdsaOperation(purpose, digest, key) {}
-    virtual keymaster_error_t Finish(const AuthorizationSet& additional_params,
-                                     const Buffer& signature, Buffer* output);
+    keymaster_error_t Begin(const AuthorizationSet& input_params,
+                            AuthorizationSet* output_params) override;
+    keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
+                             Buffer* output, size_t* input_consumed) override;
+    keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& signature,
+                             Buffer* output) override;
 };
 
 class EcdsaVerifyOperation : public EcdsaOperation {
   public:
-    EcdsaVerifyOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EC_KEY* key)
+    EcdsaVerifyOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key)
         : EcdsaOperation(purpose, digest, key) {}
-    virtual keymaster_error_t Finish(const AuthorizationSet& additional_params,
-                                     const Buffer& signature, Buffer* output);
+    keymaster_error_t Begin(const AuthorizationSet& input_params,
+                            AuthorizationSet* output_params) override;
+    keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
+                             Buffer* output, size_t* input_consumed) override;
+    keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& signature,
+                             Buffer* output) override;
 };
 
 class EcdsaOperationFactory : public OperationFactory {
@@ -73,13 +79,13 @@
     const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override;
 
     virtual keymaster_purpose_t purpose() const = 0;
-    virtual Operation* InstantiateOperation(keymaster_digest_t digest, EC_KEY* key) = 0;
+    virtual Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) = 0;
 };
 
 class EcdsaSignOperationFactory : public EcdsaOperationFactory {
   private:
     keymaster_purpose_t purpose() const override { return KM_PURPOSE_SIGN; }
-    Operation* InstantiateOperation(keymaster_digest_t digest, EC_KEY* key) {
+    Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) {
         return new EcdsaSignOperation(purpose(), digest, key);
     }
 };
@@ -87,7 +93,7 @@
 class EcdsaVerifyOperationFactory : public EcdsaOperationFactory {
   public:
     keymaster_purpose_t purpose() const override { return KM_PURPOSE_VERIFY; }
-    Operation* InstantiateOperation(keymaster_digest_t digest, EC_KEY* key) {
+    Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) {
         return new EcdsaVerifyOperation(KM_PURPOSE_VERIFY, digest, key);
     }
 };