Merge "Modify unit tests to run on-device as well as on the dev machine."
diff --git a/ecdsa_operation.cpp b/ecdsa_operation.cpp
index e1397d6..7ed64a0 100644
--- a/ecdsa_operation.cpp
+++ b/ecdsa_operation.cpp
@@ -37,7 +37,8 @@
         }
 
         keymaster_digest_t digest;
-        if (!ecdsa_key->authorizations().GetTagValue(TAG_DIGEST, &digest)) {
+        if (!ecdsa_key->authorizations().GetTagValue(TAG_DIGEST, &digest) &&
+            !ecdsa_key->authorizations().GetTagValue(TAG_DIGEST_OLD, &digest)) {
             *error = KM_ERROR_UNSUPPORTED_DIGEST;
             return NULL;
         }
@@ -67,7 +68,8 @@
         }
 
         keymaster_digest_t digest;
-        if (!ecdsa_key->authorizations().GetTagValue(TAG_DIGEST, &digest)) {
+        if (!ecdsa_key->authorizations().GetTagValue(TAG_DIGEST, &digest) &&
+            !ecdsa_key->authorizations().GetTagValue(TAG_DIGEST_OLD, &digest)) {
             *error = KM_ERROR_UNSUPPORTED_DIGEST;
             return NULL;
         }
diff --git a/include/keymaster/authorization_set.h b/include/keymaster/authorization_set.h
index 3ff34eb..81ceecc 100644
--- a/include/keymaster/authorization_set.h
+++ b/include/keymaster/authorization_set.h
@@ -212,6 +212,18 @@
     }
 
     /**
+     * If exactly one instance of the specified enumeration-typed \p tag exists, places its value in
+     * \p val and returns true.  If \p tag is not present or if multiple copies are present, leaves
+     * \p val unmodified and returns false.
+     */
+    template <keymaster_tag_t Tag, typename T>
+    bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, T* val) const {
+        if (GetTagCount(tag) != 1)
+            return false;
+        return GetTagValueEnumRep(tag, 0, reinterpret_cast<uint32_t*>(val));
+    }
+
+    /**
      * If the specified date-typed \p tag exists, places its value in \p val and returns
      * true.  If \p tag is not present, leaves \p val unmodified and returns false.
      */
diff --git a/include/keymaster/keymaster_tags.h b/include/keymaster/keymaster_tags.h
index f3a7c21..da28e72 100644
--- a/include/keymaster/keymaster_tags.h
+++ b/include/keymaster/keymaster_tags.h
@@ -63,6 +63,11 @@
 
 namespace keymaster {
 
+// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have.  We
+// need these old values to be able to support old keys that use them.
+static const keymaster_tag_t KM_TAG_DIGEST_OLD = static_cast<keymaster_tag_t>(KM_ENUM | 5);
+static const keymaster_tag_t KM_TAG_PADDING_OLD = static_cast<keymaster_tag_t>(KM_ENUM | 7);
+
 // Until we have C++11, fake std::static_assert.
 template <bool b> struct StaticAssert {};
 template <> struct StaticAssert<true> {
@@ -189,9 +194,11 @@
 
 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PURPOSE, keymaster_purpose_t);
 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ALGORITHM, keymaster_algorithm_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOCK_MODE, keymaster_block_mode_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_DIGEST, keymaster_digest_t);
-DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_PADDING, keymaster_padding_t);
+DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_BLOCK_MODE, keymaster_block_mode_t);
+DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_DIGEST, keymaster_digest_t);
+DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_DIGEST_OLD, keymaster_digest_t);
+DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PADDING, keymaster_padding_t);
+DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_PADDING_OLD, keymaster_padding_t);
 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RESCOPING_ADD, keymaster_tag_t);
 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RESCOPING_DEL, keymaster_tag_t);
 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOB_USAGE_REQUIREMENTS,
diff --git a/keymaster_enforcement.cpp b/keymaster_enforcement.cpp
index 5b5cb3d..5b3af69 100644
--- a/keymaster_enforcement.cpp
+++ b/keymaster_enforcement.cpp
@@ -59,6 +59,12 @@
 
     for (unsigned int i = 0; i < auth_set.size(); i++) {
         keymaster_key_param_t param = auth_set[i];
+
+        // KM_TAG_PADDING_OLD and KM_TAG_DIGEST_OLD aren't actually members of the enum, so we can't
+        // switch on them.  There's nothing to validate for them, though, so just ignore them.
+        if (param.tag == KM_TAG_PADDING_OLD || param.tag == KM_TAG_DIGEST_OLD)
+            continue;
+
         switch (param.tag) {
         case KM_TAG_ACTIVE_DATETIME:
             return_error = Active(param, current_time);
diff --git a/rsa_operation.cpp b/rsa_operation.cpp
index 373ccaa..3c4209a 100644
--- a/rsa_operation.cpp
+++ b/rsa_operation.cpp
@@ -50,7 +50,11 @@
 bool RsaOperationFactory::GetAndValidatePadding(const Key& key, keymaster_padding_t* padding,
                                                 keymaster_error_t* error) const {
     *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
-    if (!key.authorizations().GetTagValue(TAG_PADDING, padding) || !supported(*padding))
+    if (!key.authorizations().GetTagValue(TAG_PADDING, padding) &&
+        !key.authorizations().GetTagValue(TAG_PADDING_OLD, padding))
+        return false;
+
+    if (!supported(*padding))
         return false;
 
     *error = KM_ERROR_OK;
@@ -60,7 +64,11 @@
 bool RsaOperationFactory::GetAndValidateDigest(const Key& key, keymaster_digest_t* digest,
                                                keymaster_error_t* error) const {
     *error = KM_ERROR_UNSUPPORTED_DIGEST;
-    if (!key.authorizations().GetTagValue(TAG_DIGEST, digest) || !supported(*digest))
+    if (!key.authorizations().GetTagValue(TAG_DIGEST, digest) &&
+        !key.authorizations().GetTagValue(TAG_DIGEST_OLD, digest))
+        return false;
+
+    if (!supported(*digest))
         return false;
 
     *error = KM_ERROR_OK;