feat(app/device_assignment): add transition pdev from has_key to ready
Add support in pdev_communicate RMI handler to transition pdev state
from RMI_PDEV_STATE_HAS_KEY to RMI_PDEV_STATE_READY.
If pdev_communicate is called when the state is RMI_PDEV_STATE_HAS_KEY
then it issues SPDM_SECURE_SESSION command to establish a secure
session.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I81849fa52671016c8ec95921dbc01af99a6cd512
diff --git a/app/device_assignment/el0_app/src/dev_assign_cmds.c b/app/device_assignment/el0_app/src/dev_assign_cmds.c
index 94f4101..0cb7469 100644
--- a/app/device_assignment/el0_app/src/dev_assign_cmds.c
+++ b/app/device_assignment/el0_app/src/dev_assign_cmds.c
@@ -141,9 +141,70 @@
return (int)LIBSPDM_STATUS_SUCCESS;
}
+/* dev_assign_cmd_start_session_main */
+int dev_assign_cmd_start_session_main(struct dev_assign_info *info)
+{
+ uint32_t session_id = 0U;
+ libspdm_return_t status;
+
+ /*
+ * Call libspdm_challenge() as it helps to validate spdm_cert_chain_hash
+ * and public key before key_exchange call. Useful for debugging.
+ */
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ status = libspdm_challenge(info->libspdm_ctx, NULL, 0,
+ SPDM_CHALLENGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH,
+ NULL, NULL);
+ VERBOSE("libspdm_challenge: 0x%x\n", status);
+ if (status != LIBSPDM_STATUS_SUCCESS) {
+ return DEV_ASSIGN_STATUS_ERROR;
+ }
+#endif
+
+ /*
+ * Start SPDM session. Set session policy to 0, this terminates the
+ * session upon device firmware or configuration update.
+ */
+ status = libspdm_start_session(info->libspdm_ctx,
+ false, /* use_psk */
+ NULL, /* psk_hint */
+ 0, /* psk_hint size */
+ SPDM_REQUEST_NO_MEASUREMENT_SUMMARY_HASH, /* meas hash type */
+ info->cert_slot_id, /* slot id */
+ 0, /* session policy */
+ &session_id,
+ NULL, /* hbeat period */
+ NULL /* measurement_hash */);
+ if (status == LIBSPDM_STATUS_SUCCESS) {
+ info->session_id = session_id;
+ VERBOSE("SPDM secure session id: 0x%x\n", info->session_id);
+ return DEV_ASSIGN_STATUS_SUCCESS;
+ }
+
+ return DEV_ASSIGN_STATUS_ERROR;
+}
+
/* dev_assign_cmd_stop_connection_main */
int dev_assign_cmd_stop_connection_main(struct dev_assign_info *info)
{
+ int rc = DEV_ASSIGN_STATUS_SUCCESS;
+
+ if (info->session_id != 0U) {
+ /* Terminate the connection. This closes the secure session */
+ libspdm_return_t status = libspdm_stop_session(info->libspdm_ctx,
+ info->session_id,
+ 0 /* end_session_attributes */);
+
+ if (status != LIBSPDM_STATUS_SUCCESS) {
+ ERROR("SPDM_END_SESSION failed: 0x%x\n", status);
+ rc = DEV_ASSIGN_STATUS_ERROR;
+ /*assert(false);*/
+ } else {
+ INFO("SPDM_END_SESSION completed: 0x%x\n", status);
+ info->session_id = 0U;
+ }
+ }
+
/* Send GET_VERSION, this resets the SPDM connection */
(void)libspdm_init_connection(info->libspdm_ctx, true);
@@ -156,5 +217,5 @@
/* Clean up the cma spdm connection state */
init_connection_cleanup(info, true);
- return DEV_ASSIGN_STATUS_SUCCESS;
+ return rc;
}
diff --git a/app/device_assignment/el0_app/src/dev_assign_el0_app.c b/app/device_assignment/el0_app/src/dev_assign_el0_app.c
index 5a26820..e48390c 100644
--- a/app/device_assignment/el0_app/src/dev_assign_el0_app.c
+++ b/app/device_assignment/el0_app/src/dev_assign_el0_app.c
@@ -698,6 +698,7 @@
}
info->spdm_cert_chain_digest_length = 0;
info->pk_ctx.initialised = false;
+ info->session_id = 0U;
info->psa_hash_algo = rmi_to_psa_hash_algo(params->rmi_hash_algo);
@@ -869,6 +870,9 @@
case DEVICE_ASSIGN_APP_FUNC_ID_CONNECT_INIT:
ret = (unsigned long)dev_assign_cmd_init_connection_main(info);
break;
+ case DEVICE_ASSIGN_APP_FUNC_ID_SECURE_SESSION:
+ ret = (unsigned long)dev_assign_cmd_start_session_main(info);
+ break;
case DEVICE_ASSIGN_APP_FUNC_ID_STOP_CONNECTION:
ret = (unsigned long)dev_assign_cmd_stop_connection_main(info);
break;
@@ -910,6 +914,7 @@
(struct dev_assign_params *)shared);
}
case DEVICE_ASSIGN_APP_FUNC_ID_CONNECT_INIT:
+ case DEVICE_ASSIGN_APP_FUNC_ID_SECURE_SESSION:
case DEVICE_ASSIGN_APP_FUNC_ID_STOP_CONNECTION:
return dev_assign_communicate_cmd_cmn(func_id, heap);
case DEVICE_ASSIGN_APP_FUNC_SET_PUBLIC_KEY:
diff --git a/app/device_assignment/el0_app/src/dev_assign_private.h b/app/device_assignment/el0_app/src/dev_assign_private.h
index 4afbcb5..2c33ec8 100644
--- a/app/device_assignment/el0_app/src/dev_assign_private.h
+++ b/app/device_assignment/el0_app/src/dev_assign_private.h
@@ -292,6 +292,7 @@
};
int dev_assign_cmd_init_connection_main(struct dev_assign_info *info);
+int dev_assign_cmd_start_session_main(struct dev_assign_info *info);
int dev_assign_cmd_stop_connection_main(struct dev_assign_info *info);
void dev_assign_unset_pubkey(struct dev_assign_info *info);
diff --git a/app/device_assignment/rmm_stub/include/dev_assign_structs.h b/app/device_assignment/rmm_stub/include/dev_assign_structs.h
index b46e162..14acd8e 100644
--- a/app/device_assignment/rmm_stub/include/dev_assign_structs.h
+++ b/app/device_assignment/rmm_stub/include/dev_assign_structs.h
@@ -128,6 +128,14 @@
#define DEVICE_ASSIGN_APP_FUNC_ID_DEINIT 4
/*
+ * App function ID to start a libspdm session
+ *
+ * ret0 == DEV_ASSIGN_STATUS_SUCCESS if the session is started successfully.
+ * DEV_ASSIGN_STATUS_ERROR if libspdm returned error.
+ */
+#define DEVICE_ASSIGN_APP_FUNC_ID_SECURE_SESSION 11
+
+/*
* App function ID to stop the libspdm session that is associated with this app
* instance.
*
diff --git a/app/device_assignment/rmm_stub/src/dev_assign_app_stub.c b/app/device_assignment/rmm_stub/src/dev_assign_app_stub.c
index 5f3d407..8c8673a 100644
--- a/app/device_assignment/rmm_stub/src/dev_assign_app_stub.c
+++ b/app/device_assignment/rmm_stub/src/dev_assign_app_stub.c
@@ -59,7 +59,8 @@
assert((dev_cmd == DEVICE_ASSIGN_APP_FUNC_ID_RESUME) ||
(dev_cmd == DEVICE_ASSIGN_APP_FUNC_ID_CONNECT_INIT) ||
- (dev_cmd == DEVICE_ASSIGN_APP_FUNC_ID_STOP_CONNECTION));
+ (dev_cmd == DEVICE_ASSIGN_APP_FUNC_ID_STOP_CONNECTION) ||
+ (dev_cmd == DEVICE_ASSIGN_APP_FUNC_ID_SECURE_SESSION));
app_map_shared_page(app_data);
shared = app_data->el2_shared_page;
diff --git a/runtime/rmi/pdev.c b/runtime/rmi/pdev.c
index c5dde93..cc20131 100644
--- a/runtime/rmi/pdev.c
+++ b/runtime/rmi/pdev.c
@@ -441,6 +441,10 @@
rc = dev_assign_dev_communicate(&pd->da_app_data, enter_args,
exit_args, comm_digest_ptr, DEVICE_ASSIGN_APP_FUNC_ID_CONNECT_INIT);
break;
+ case RMI_PDEV_STATE_HAS_KEY:
+ rc = dev_assign_dev_communicate(&pd->da_app_data, enter_args,
+ exit_args, comm_digest_ptr, DEVICE_ASSIGN_APP_FUNC_ID_SECURE_SESSION);
+ break;
case RMI_PDEV_STATE_STOPPING:
rc = dev_assign_dev_communicate(&pd->da_app_data, enter_args,
exit_args, comm_digest_ptr, DEVICE_ASSIGN_APP_FUNC_ID_STOP_CONNECTION);
@@ -566,6 +570,8 @@
case DEV_COMM_IDLE:
if (pd->rmi_state == RMI_PDEV_STATE_NEW) {
pd->rmi_state = RMI_PDEV_STATE_NEEDS_KEY;
+ } else if (pd->rmi_state == RMI_PDEV_STATE_HAS_KEY) {
+ pd->rmi_state = RMI_PDEV_STATE_READY;
} else if (pd->rmi_state == RMI_PDEV_STATE_STOPPING) {
pd->rmi_state = RMI_PDEV_STATE_STOPPED;
} else {