sys: allow Tss2_Sys_Execute to be called repeatedly

Allow commands to be reissued by calling Execute or ExecuteFinish
again after a TPM returns an error. This should simplify ESAPI retry
logic in response to TPM_RC_RETRY. This behavior in described in SAPI
specification 1.1 rev 24.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
diff --git a/src/tss2-sys/api/Tss2_Sys_Execute.c b/src/tss2-sys/api/Tss2_Sys_Execute.c
index b29571c..94e9c96 100644
--- a/src/tss2-sys/api/Tss2_Sys_Execute.c
+++ b/src/tss2-sys/api/Tss2_Sys_Execute.c
@@ -5,6 +5,7 @@
  ***********************************************************************/
 
 #include <inttypes.h>
+#include <string.h>
 
 #include "tss2_tpm2_types.h"
 #include "tss2_mu.h"
@@ -30,6 +31,11 @@
     if (rval)
         return rval;
 
+    /* Keep a copy of the cmd header to be able reissue the command
+     * after receiving a TPM error
+     */
+    memcpy(ctx->cmd_header, ctx->cmdBuffer, sizeof(ctx->cmd_header));
+
     ctx->previousStage = CMD_STAGE_SEND_COMMAND;
 
     return rval;
@@ -130,16 +136,21 @@
 
     rval = ctx->rsp_header.responseCode;
 
-    /* If we received a TPM error other than CANCELED or if we didn't
-     * receive enough response bytes, reset SAPI state machine to
+    /* If didn't receive enough response bytes, reset SAPI state machine to
      * CMD_STAGE_PREPARE. There's nothing else we can do for current command.
      */
     if (ctx->rsp_header.responseSize < sizeof(TPM20_Header_Out)) {
         ctx->previousStage = CMD_STAGE_PREPARE;
         return TSS2_SYS_RC_INSUFFICIENT_RESPONSE;
     }
-    if (rval == TPM2_RC_CANCELED) {
+
+    /* If we received a TPM error then reset SAPI state machine to
+     * CMD_STAGE_PREPARE, and restore the command header so the command
+     * can be reissued without going through the usual *_prepare stage.
+     */
+    if (rval && rval != TPM2_RC_INITIALIZE) {
         ctx->previousStage = CMD_STAGE_PREPARE;
+        memcpy(ctx->cmdBuffer, ctx->cmd_header, sizeof(ctx->cmd_header));
         return rval;
     }
 
diff --git a/src/tss2-sys/sysapi_util.h b/src/tss2-sys/sysapi_util.h
index eb5c1b2..ea5b751 100644
--- a/src/tss2-sys/sysapi_util.h
+++ b/src/tss2-sys/sysapi_util.h
@@ -40,6 +40,7 @@
     TSS2_TCTI_CONTEXT *tctiContext;
     UINT8 *cmdBuffer;
     UINT32 maxCmdSize;
+    UINT8 cmd_header[sizeof(TPM20_Header_In)]; /* Copy of the cmd header to allow reissue */
     TPM20_Header_Out rsp_header;
 
     TPM2_CC commandCode;    /* In host endian */