Trusty KeyMint: support boot,vendor patchlevels

 - Add CONFIGURE_{VENDOR,BOOT}_PATCHLEVEL messages to
   keymaster_ipc.h
 - Map CONFIGURE_{VENDOR,BOOT}_PATCHLEVEL messages through to
   AndroidKeymaster::Configure{Vendor,Boot}Patchlevel()
 - Implement {Get,Set}{Vendor,Boot}PatchLevels() methods for
   TrustyKeymasterContext
 - Optionally include {vendor,boot}_patchlevel in
   TrustyKeymasterContext::SetAuthorizations().
 - Optionally check {vendor,boot}_patchlevel in
   TrustyKeymastercontext::UpgradeKeyBlob().

Test: pending device availability
Bug: 193423844
Change-Id: I13902cd6fd12620c0db0065750e1a6c9cfbf7df6
diff --git a/ipc/keymaster_ipc.cpp b/ipc/keymaster_ipc.cpp
index 97daa2e..0b74166 100644
--- a/ipc/keymaster_ipc.cpp
+++ b/ipc/keymaster_ipc.cpp
@@ -616,14 +616,26 @@
                            out, out_size);
 
     case KM_GENERATE_RKP_KEY:
-        LOG_D("Dispatching KM_GENERATE_RKP_KEY, side %d", payload_size);
+        LOG_D("Dispatching KM_GENERATE_RKP_KEY, size %d", payload_size);
         return do_dispatch(&TrustyKeymaster::GenerateRkpKey, msg, payload_size,
                            out, out_size);
 
     case KM_GENERATE_CSR:
-        LOG_D("Dispatching KM_GENERATE_CSR, side %d", payload_size);
+        LOG_D("Dispatching KM_GENERATE_CSR, size %d", payload_size);
         return do_dispatch(&TrustyKeymaster::GenerateCsr, msg, payload_size,
                            out, out_size);
+
+    case KM_CONFIGURE_VENDOR_PATCHLEVEL:
+        LOG_D("Dispatching KM_CONFIGURE_VENDOR_PATCHLEVEL, size %d",
+              payload_size);
+        return do_dispatch(&TrustyKeymaster::ConfigureVendorPatchlevel, msg,
+                           payload_size, out, out_size);
+
+    case KM_CONFIGURE_BOOT_PATCHLEVEL:
+        LOG_D("Dispatching KM_CONFIGURE_BOOT_PATCHLEVEL, size %d",
+              payload_size);
+        return do_dispatch(&TrustyKeymaster::ConfigureBootPatchlevel, msg,
+                           payload_size, out, out_size);
     }
 
     LOG_E("Cannot dispatch unknown command %d", msg->cmd);
diff --git a/ipc/keymaster_ipc.h b/ipc/keymaster_ipc.h
index 4915123..aa3025f 100644
--- a/ipc/keymaster_ipc.h
+++ b/ipc/keymaster_ipc.h
@@ -58,6 +58,7 @@
     KM_DEVICE_LOCKED = (30 << KEYMASTER_REQ_SHIFT),
     KM_GENERATE_RKP_KEY = (31 << KEYMASTER_REQ_SHIFT),
     KM_GENERATE_CSR = (32 << KEYMASTER_REQ_SHIFT),
+    KM_CONFIGURE_VENDOR_PATCHLEVEL = (33 << KEYMASTER_REQ_SHIFT),
 
     // Bootloader calls.
     KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT),
@@ -72,6 +73,7 @@
     KM_CLEAR_ATTESTATION_CERT_CHAIN = (0xa000 << KEYMASTER_REQ_SHIFT),
     KM_SET_WRAPPED_ATTESTATION_KEY = (0xb000 << KEYMASTER_REQ_SHIFT),
     KM_SET_ATTESTATION_IDS = (0xc000 << KEYMASTER_REQ_SHIFT),
+    KM_CONFIGURE_BOOT_PATCHLEVEL = (0xd0000 << KEYMASTER_REQ_SHIFT),
 };
 
 /**
diff --git a/trusty_keymaster_context.cpp b/trusty_keymaster_context.cpp
index d61ba46..1f7d96f 100644
--- a/trusty_keymaster_context.cpp
+++ b/trusty_keymaster_context.cpp
@@ -299,10 +299,17 @@
     hw_enforced->push_back(TAG_ORIGIN, origin);
 
     // these values will be 0 if not set by bootloader
-    // TODO(swillden): set VENDOR and BOOT patchlevels.
     hw_enforced->push_back(TAG_OS_VERSION, boot_params_.boot_os_version);
     hw_enforced->push_back(TAG_OS_PATCHLEVEL, boot_params_.boot_os_patchlevel);
 
+    if (vendor_patchlevel_.has_value()) {
+        hw_enforced->push_back(TAG_VENDOR_PATCHLEVEL,
+                               vendor_patchlevel_.value());
+    }
+    if (boot_patchlevel_.has_value()) {
+        hw_enforced->push_back(TAG_BOOT_PATCHLEVEL, boot_patchlevel_.value());
+    }
+
     if (sw_enforced->is_valid() != AuthorizationSet::OK)
         return TranslateAuthorizationSetError(sw_enforced->is_valid());
     if (hw_enforced->is_valid() != AuthorizationSet::OK)
@@ -415,7 +422,13 @@
     if (!UpgradeIntegerTag(TAG_OS_VERSION, boot_params_.boot_os_version,
                            &key->hw_enforced(), &set_changed) ||
         !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, boot_params_.boot_os_patchlevel,
-                           &key->hw_enforced(), &set_changed)) {
+                           &key->hw_enforced(), &set_changed) ||
+        (vendor_patchlevel_.has_value() &&
+         !UpgradeIntegerTag(TAG_VENDOR_PATCHLEVEL, vendor_patchlevel_.value(),
+                            &key->hw_enforced(), &set_changed)) ||
+        (boot_patchlevel_.has_value() &&
+         !UpgradeIntegerTag(TAG_BOOT_PATCHLEVEL, boot_patchlevel_.value(),
+                            &key->hw_enforced(), &set_changed))) {
         // One of the version fields would have been a downgrade. Not allowed.
         return KM_ERROR_INVALID_ARGUMENT;
     }
diff --git a/trusty_keymaster_context.h b/trusty_keymaster_context.h
index 11d1c77..c4bf4b3 100644
--- a/trusty_keymaster_context.h
+++ b/trusty_keymaster_context.h
@@ -150,6 +150,34 @@
         return trusty_remote_provisioning_context_.get();
     }
 
+    keymaster_error_t SetVendorPatchlevel(uint32_t vendor_patchlevel) override {
+        if (vendor_patchlevel_.has_value() &&
+            vendor_patchlevel != vendor_patchlevel_.value()) {
+            // Can't set patchlevel to a different value.
+            return KM_ERROR_INVALID_ARGUMENT;
+        }
+        vendor_patchlevel_ = vendor_patchlevel;
+        return KM_ERROR_OK;
+    }
+
+    keymaster_error_t SetBootPatchlevel(uint32_t boot_patchlevel) override {
+        if (boot_patchlevel_.has_value() &&
+            boot_patchlevel != boot_patchlevel_.value()) {
+            // Can't set patchlevel to a different value.
+            return KM_ERROR_INVALID_ARGUMENT;
+        }
+        boot_patchlevel_ = boot_patchlevel;
+        return KM_ERROR_OK;
+    }
+
+    std::optional<uint32_t> GetVendorPatchlevel() const override {
+        return vendor_patchlevel_;
+    }
+
+    std::optional<uint32_t> GetBootPatchlevel() const override {
+        return boot_patchlevel_;
+    }
+
 private:
     bool SeedRngIfNeeded() const;
     bool ShouldReseedRng() const;
@@ -212,6 +240,8 @@
             .device_locked = false};
     UniquePtr<TrustyRemoteProvisioningContext>
             trusty_remote_provisioning_context_;
+    std::optional<uint32_t> vendor_patchlevel_;
+    std::optional<uint32_t> boot_patchlevel_;
 };
 
 }  // namespace keymaster