Add rollback resistance support to keymaster impl. am: e75825de25

Change-Id: Ia6faf15a4a35eb63a1f792735727eb14f10af4a6
diff --git a/contexts/pure_soft_keymaster_context.cpp b/contexts/pure_soft_keymaster_context.cpp
index 54f93bc..d52fe2e 100644
--- a/contexts/pure_soft_keymaster_context.cpp
+++ b/contexts/pure_soft_keymaster_context.cpp
@@ -50,12 +50,12 @@
 
 namespace keymaster {
 
-PureSoftKeymasterContext::PureSoftKeymasterContext()
+PureSoftKeymasterContext::PureSoftKeymasterContext(keymaster_security_level_t security_level)
     : rsa_factory_(new RsaKeyFactory(this)), ec_factory_(new EcKeyFactory(this)),
       aes_factory_(new AesKeyFactory(this, this)),
       tdes_factory_(new TripleDesKeyFactory(this, this)),
       hmac_factory_(new HmacKeyFactory(this, this)), os_version_(0), os_patchlevel_(0),
-      soft_keymaster_enforcement_(64, 64) {}
+      soft_keymaster_enforcement_(64, 64), security_level_(security_level) {}
 
 PureSoftKeymasterContext::~PureSoftKeymasterContext() {}
 
@@ -106,20 +106,56 @@
 }
 
 keymaster_error_t PureSoftKeymasterContext::CreateKeyBlob(const AuthorizationSet& key_description,
-                                                      const keymaster_key_origin_t origin,
-                                                      const KeymasterKeyBlob& key_material,
-                                                      KeymasterKeyBlob* blob,
-                                                      AuthorizationSet* hw_enforced,
-                                                      AuthorizationSet* sw_enforced) const {
+                                                          const keymaster_key_origin_t origin,
+                                                          const KeymasterKeyBlob& key_material,
+                                                          KeymasterKeyBlob* blob,
+                                                          AuthorizationSet* hw_enforced,
+                                                          AuthorizationSet* sw_enforced) const {
+    if (key_description.GetTagValue(TAG_ROLLBACK_RESISTANCE)) {
+        return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE;
+    }
+
+    if (GetSecurityLevel() != KM_SECURITY_LEVEL_SOFTWARE) {
+        // We're pretending to be some sort of secure hardware.  Put relevant tags in hw_enforced.
+        for (auto& entry : key_description) {
+            switch (entry.tag) {
+            case KM_TAG_PURPOSE:
+            case KM_TAG_ALGORITHM:
+            case KM_TAG_KEY_SIZE:
+            case KM_TAG_RSA_PUBLIC_EXPONENT:
+            case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+            case KM_TAG_DIGEST:
+            case KM_TAG_PADDING:
+            case KM_TAG_BLOCK_MODE:
+            case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+            case KM_TAG_MAX_USES_PER_BOOT:
+            case KM_TAG_USER_SECURE_ID:
+            case KM_TAG_NO_AUTH_REQUIRED:
+            case KM_TAG_AUTH_TIMEOUT:
+            case KM_TAG_CALLER_NONCE:
+            case KM_TAG_MIN_MAC_LENGTH:
+            case KM_TAG_KDF:
+            case KM_TAG_EC_CURVE:
+            case KM_TAG_ECIES_SINGLE_HASH_MODE:
+            case KM_TAG_USER_AUTH_TYPE:
+            case KM_TAG_ORIGIN:
+            case KM_TAG_OS_VERSION:
+            case KM_TAG_OS_PATCHLEVEL:
+                hw_enforced->push_back(entry);
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
     keymaster_error_t error = SetKeyBlobAuthorizations(key_description, origin, os_version_,
                                                        os_patchlevel_, hw_enforced, sw_enforced);
-    if (error != KM_ERROR_OK)
-        return error;
+    if (error != KM_ERROR_OK) return error;
 
     AuthorizationSet hidden;
     error = BuildHiddenAuthorizations(key_description, &hidden, softwareRootOfTrust);
-    if (error != KM_ERROR_OK)
-        return error;
+    if (error != KM_ERROR_OK) return error;
 
     return SerializeIntegrityAssuredBlob(key_material, hidden, *hw_enforced, *sw_enforced, blob);
 }
diff --git a/include/keymaster/contexts/pure_soft_keymaster_context.h b/include/keymaster/contexts/pure_soft_keymaster_context.h
index d8532a8..a1951a0 100644
--- a/include/keymaster/contexts/pure_soft_keymaster_context.h
+++ b/include/keymaster/contexts/pure_soft_keymaster_context.h
@@ -43,7 +43,9 @@
         AttestationRecordContext,
         SoftwareRandomSource {
   public:
-    explicit PureSoftKeymasterContext();
+    // Security level must only be used for testing.
+    explicit PureSoftKeymasterContext(
+        keymaster_security_level_t security_level = KM_SECURITY_LEVEL_SOFTWARE);
     ~PureSoftKeymasterContext() override;
 
     /*********************************************************************************************
@@ -99,6 +101,8 @@
                                             keymaster_verified_boot_t* verified_boot_state,
                                             bool* device_locked) const override;
 
+    keymaster_security_level_t GetSecurityLevel() const override { return security_level_; }
+
   protected:
     std::unique_ptr<KeyFactory> rsa_factory_;
     std::unique_ptr<KeyFactory> ec_factory_;
@@ -108,6 +112,7 @@
     uint32_t os_version_;
     uint32_t os_patchlevel_;
     SoftKeymasterEnforcement soft_keymaster_enforcement_;
+    keymaster_security_level_t security_level_;
 };
 
 }  // namespace keymaster
diff --git a/key_blob_utils/software_keyblobs.cpp b/key_blob_utils/software_keyblobs.cpp
index c490631..60719bb 100644
--- a/key_blob_utils/software_keyblobs.cpp
+++ b/key_blob_utils/software_keyblobs.cpp
@@ -292,10 +292,16 @@
         }
     }
 
-    sw_enforced->push_back(TAG_CREATION_DATETIME, java_time(time(nullptr)));
-    sw_enforced->push_back(TAG_ORIGIN, origin);
-    sw_enforced->push_back(TAG_OS_VERSION, os_version);
-    sw_enforced->push_back(TAG_OS_PATCHLEVEL, os_patchlevel);
+    // If hw_enforced is non-empty, we're pretending to be some sort of secure hardware.
+    AuthorizationSet* pseudo_hw_enforced = (hw_enforced->empty()) ? sw_enforced : hw_enforced;
+    pseudo_hw_enforced->push_back(TAG_ORIGIN, origin);
+    pseudo_hw_enforced->push_back(TAG_OS_VERSION, os_version);
+    pseudo_hw_enforced->push_back(TAG_OS_PATCHLEVEL, os_patchlevel);
+
+    // Honor caller creation, if provided.
+    if (!sw_enforced->Contains(TAG_CREATION_DATETIME)) {
+        sw_enforced->push_back(TAG_CREATION_DATETIME, java_time(time(nullptr)));
+    }
 
     return TranslateAuthorizationSetError(sw_enforced->is_valid());
 }
diff --git a/ng/AndroidKeymaster4Device.cpp b/ng/AndroidKeymaster4Device.cpp
index 70060d6..b42a19b 100644
--- a/ng/AndroidKeymaster4Device.cpp
+++ b/ng/AndroidKeymaster4Device.cpp
@@ -211,12 +211,14 @@
 
 AndroidKeymaster4Device::AndroidKeymaster4Device(SecurityLevel securityLevel)
     : impl_(new ::keymaster::AndroidKeymaster(
-          []() -> auto {
-              auto context = new PureSoftKeymasterContext();
+          [&]() -> auto {
+              auto context = new PureSoftKeymasterContext(
+                  static_cast<keymaster_security_level_t>(securityLevel));
               context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel());
               return context;
           }(),
-          kOperationTableSize)), securityLevel_(securityLevel) {}
+          kOperationTableSize)),
+      securityLevel_(securityLevel) {}
 
 AndroidKeymaster4Device::~AndroidKeymaster4Device() {}