trusty: keymaster: Implement upgrade_key

Test: builds
Change-Id: I2ce86be1cd2c2c35ded371b21cb6546c31e0014e
diff --git a/trusty/keymaster/keymaster_ipc.h b/trusty/keymaster/keymaster_ipc.h
index 6a7378c..b38eb05 100644
--- a/trusty/keymaster/keymaster_ipc.h
+++ b/trusty/keymaster/keymaster_ipc.h
@@ -43,6 +43,7 @@
     KM_GET_SUPPORTED_EXPORT_FORMATS = (14 << KEYMASTER_REQ_SHIFT),
     KM_GET_KEY_CHARACTERISTICS      = (15 << KEYMASTER_REQ_SHIFT),
     KM_ATTEST_KEY                   = (16 << KEYMASTER_REQ_SHIFT),
+    KM_UPGRADE_KEY                  = (17 << KEYMASTER_REQ_SHIFT),
     KM_CONFIGURE                    = (18 << KEYMASTER_REQ_SHIFT),
 };
 
diff --git a/trusty/keymaster/trusty_keymaster_device.cpp b/trusty/keymaster/trusty_keymaster_device.cpp
index 08a1c6a..2132ae1 100644
--- a/trusty/keymaster/trusty_keymaster_device.cpp
+++ b/trusty/keymaster/trusty_keymaster_device.cpp
@@ -426,6 +426,34 @@
                                                      const keymaster_key_param_set_t* upgrade_params,
                                                      keymaster_key_blob_t* upgraded_key) {
     ALOGD("Device received upgrade_key");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!key_to_upgrade || !upgrade_params) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!upgraded_key) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    UpgradeKeyRequest request;
+    request.SetKeyMaterial(*key_to_upgrade);
+    request.upgrade_params.Reinitialize(*upgrade_params);
+
+    UpgradeKeyResponse response;
+    keymaster_error_t err = Send(KM_UPGRADE_KEY, request, &response);
+    if (err != KM_ERROR_OK) {
+        return err;
+    }
+
+    upgraded_key->key_material_size = response.upgraded_key.key_material_size;
+    upgraded_key->key_material = DuplicateBuffer(response.upgraded_key.key_material,
+                                                 response.upgraded_key.key_material_size);
+    if (!upgraded_key->key_material) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+
     return KM_ERROR_OK;
 }