]> git.proxmox.com Git - swtpm.git/commitdiff
swtpm: Implement two more control channel commands.
authorStefan Berger <stefanb@us.ibm.com>
Thu, 24 Mar 2016 13:33:47 +0000 (09:33 -0400)
committerStefan Berger <stefanb@us.ibm.com>
Thu, 24 Mar 2016 13:34:59 +0000 (09:34 -0400)
Implement two more control channel commands:
- CMD_STORE_VOLATILE
- CMD_HASH_DATA

Implement test cases.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
include/swtpm/tpm_ioctl.h
src/swtpm/ctrlchannel.c
tests/test_ctrlchannel

index abc01ad227199a653773dc10882014e0a4be749c..ce30f6295ce6729fc1d5618c50def3653210da22 100644 (file)
@@ -213,7 +213,14 @@ enum {
 };
 
 /*
- * Comments used by the non-CUSE TPMs
+ * Commands used by the non-CUSE TPMs
+ *
+ * All messages container big-endian data.
+ *
+ * The return messages only contain the 'resp' part of the unions
+ * in the data structures above. Besides that the limits in the
+ * buffers above (ptm_hdata:u.req.data and ptm_get_state:u.resp.data
+ * and ptm_set_state:u.req.data) are 0xffffffff.
  */
 enum {
     CMD_GET_CAPABILITY = 1,
@@ -222,9 +229,11 @@ enum {
     CMD_GET_TPMESTABLISHED,
     CMD_SET_LOCALITY,
     CMD_HASH_START,
-    CMD_HASH_END = 8 ,
+    CMD_HASH_DATA,
+    CMD_HASH_END,
     CMD_CANCEL_TPM_CMD,
-    CMD_RESET_TPMESTABLISHED = 11,
+    CMD_STORE_VOLATILE,
+    CMD_RESET_TPMESTABLISHED,
     CMD_STOP = 13,
     CMD_GET_CONFIG,
 };
index 9507e5a15281a6b506931c30ef76ee5a34c05ead..2d6c7d90cccbea9d4089b06e1993529e2caec8dc 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdio.h>
 /*
  * ctrlchannel.c -- control channel implementation
  *
@@ -103,9 +104,11 @@ int ctrlchannel_process_fd(int fd,
     ptm_init *init_p;
     ptm_reset_est *re;
     ptm_getconfig *pgc;
+    ptm_hdata *data;
 
     size_t out_len = 0;
     TPM_RESULT res;
+    uint32_t remain;
 
     if (fd < 0)
         return -1;
@@ -133,7 +136,8 @@ int ctrlchannel_process_fd(int fd,
             PTM_CAP_GET_TPMESTABLISHED |
             PTM_CAP_RESET_TPMESTABLISHED |
             PTM_CAP_HASHING |
-            PTM_CAP_CANCEL_TPM_CMD);
+            PTM_CAP_CANCEL_TPM_CMD |
+            PTM_CAP_STORE_VOLATILE);
 
         out_len = sizeof(*ptm_caps);
         break;
@@ -226,6 +230,37 @@ int ctrlchannel_process_fd(int fd,
 
         break;
 
+    case CMD_HASH_DATA:
+        if (!*tpm_running)
+             goto err_not_running;
+
+        data = (ptm_hdata *)&input.body;
+        remain = htobe32(data->u.req.length);
+        n -= sizeof(data->u.req.length);
+        /* n has the available number of bytes to hash */
+
+        while (true) {
+            res = TPM_IO_Hash_Data(data->u.req.data, n);
+            if (res)
+                break;
+            remain -= n;
+            if (!remain)
+                break;
+
+            n = read(fd, &data->u.req.data, sizeof(data->u.req.data));
+            if (n <= 0) {
+                res = TPM_IOERROR;
+                break;
+            }
+        }
+
+        data = (ptm_hdata *)&output.body;
+
+        data->u.resp.tpm_result = htobe32(res);
+        out_len = sizeof(data->u.resp.tpm_result);
+
+        break;
+
     case CMD_HASH_END:
         if (!*tpm_running)
             goto err_not_running;
@@ -247,6 +282,14 @@ int ctrlchannel_process_fd(int fd,
         out_len = sizeof(ptm_res);
         break;
 
+    case CMD_STORE_VOLATILE:
+        if (!*tpm_running)
+            goto err_not_running;
+
+        *res_p = htobe32(SWTPM_NVRAM_Store_Volatile());
+        out_len = sizeof(ptm_res);
+        break;
+
     case CMD_GET_CONFIG:
         pgc = (ptm_getconfig *)output.body;
 
@@ -262,7 +305,7 @@ int ctrlchannel_process_fd(int fd,
 
     default:
         logprintf(STDERR_FILENO,
-                  "Error: Unknown command\n");
+                  "Error: Unknown command: 0x%08x\n", be32toh(input.cmd));
 
         *res_p = htobe32(TPM_BAD_ORDINAL);
         out_len = sizeof(ptm_res);
index 85ee4fe01b3f0cc5fa17f4dae64af0faeb0c36fa..8e950180331ab7d1394546cd86f8cee4fa2701b0 100755 (executable)
@@ -43,7 +43,7 @@ socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CLIENT:$SOCK_PATH 2>&1 | \
        sed -n '/^ /p' | \
        tail -n1 > $RESP_PATH
 res="$(cat $RESP_PATH)"
-exp=" 00 00 00 00 00 00 04 b7"
+exp=" 00 00 00 00 00 00 04 f7"
 if [ "$res" != "$exp" ]; then
        echo "Error: Unexpected response from CMD_GET_CAPABILITY:"
        echo "       actual  : $res"
@@ -79,6 +79,25 @@ if [ "$res" != "$exp" ]; then
        exit 1
 fi
 
+# Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a
+/bin/echo -en '\x00\x00\x00\x0a' >$CMD_PATH
+socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CLIENT:$SOCK_PATH 2>&1 | \
+       sed -n '/^ /p' | \
+       tail -n1 > $RESP_PATH
+res="$(cat $RESP_PATH)"
+exp=" 00 00 00 00"
+if [ "$res" != "$exp" ]; then
+       echo "Error: Unexpected response from CMD_STORE_VOLATILE:"
+       echo "       actual  : $res"
+       echo "       expected: $exp"
+       exit 1
+fi
+
+if [ ! -r $TPMDIR/tpm-00.volatilestate ]; then
+       echo "Error: Socket TPM: Did not write volatile state file"
+       exit 1
+fi
+
 # Send stop command to the TPM: CMD_STOP = 00 00 00 0d
 echo -en '\x00\x00\x00\x0d' > $CMD_PATH
 socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CONNECT:$SOCK_PATH 2>&1 | \
@@ -161,7 +180,7 @@ socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CLIENT:$SOCK_PATH 2>&1 | \
        sed -n '/^ /p' | \
        tail -n1 > $RESP_PATH
 res="$(cat $RESP_PATH)"
-exp=" 00 00 00 00 00 00 04 b7"
+exp=" 00 00 00 00 00 00 04 f7"
 if [ "$res" != "$exp" ]; then
        echo "Error: Socket TPM: Unexpected response from CMD_GET_CAPABILITY:"
        echo "       actual  : $res"
@@ -209,6 +228,25 @@ if [ "$RES" != "$exp" ]; then
        exit 1
 fi
 
+# Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a
+/bin/echo -en '\x00\x00\x00\x0a' >$CMD_PATH
+socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CLIENT:$SOCK_PATH 2>&1 | \
+       sed -n '/^ /p' | \
+       tail -n1 > $RESP_PATH
+res="$(cat $RESP_PATH)"
+exp=" 00 00 00 00"
+if [ "$res" != "$exp" ]; then
+       echo "Error: Socket TPM: Unexpected response from CMD_STORE_VOLATILE:"
+       echo "       actual  : $res"
+       echo "       expected: $exp"
+       exit 1
+fi
+
+if [ ! -r $TPMDIR/tpm-00.volatilestate ]; then
+       echo "Error: Socket TPM: Did not write volatile state file"
+       exit 1
+fi
+
 # 1. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04
 echo -en '\x00\x00\x00\x04' > $CMD_PATH
 cat $RESP_PATH
@@ -226,7 +264,6 @@ fi
 
 # 2. Send command to start HASH : CMD_HASH_START = 00 00 00 06
 echo -en '\x00\x00\x00\x06' > $CMD_PATH
-cat $RESP_PATH
 socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CONNECT:$SOCK_PATH 2>&1 | \
        sed -n '/^ /p' | \
        tail -n1 > $RESP_PATH
@@ -239,6 +276,22 @@ if [ "$res" != "$exp" ]; then
        exit 1
 fi
 
+# 2.1. Send command to hash data : CMD_HASH_DATA = 00 00 00 07 uint32(length) data
+# We send 0x100 null bytes
+echo -en '\x00\x00\x00\x07\x00\x00\x20\x00' > $CMD_PATH
+dd if=/dev/zero count=$((0x2000)) bs=1 >> $CMD_PATH 2>/dev/null
+socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CONNECT:$SOCK_PATH 2>&1 | \
+       sed -n '/^ /p' | \
+       tail -n1 > $RESP_PATH
+res="$(cat $RESP_PATH)"
+exp=" 00 00 00 00"
+if [ "$res" != "$exp" ]; then
+       echo "Error: Socket TPM: Unexpected response from sending CMD_HASH_DATA command:"
+       echo "       actual  : $res"
+       echo "       expected: $exp"
+       exit 1
+fi
+
 # 3. Send command to end HASH : CMD_HASH_END = 00 00 00 08
 echo -en '\x00\x00\x00\x08' > $CMD_PATH
 cat $RESP_PATH
@@ -303,7 +356,7 @@ fi
 exec 100<>/dev/tcp/localhost/65530
 echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
 RES=$(cat <&100 | od -t x1 -A n | tr -d "\n")
-exp=' 00 c4 00 00 00 1e 00 00 00 00 31 a2 dc 4c 22 f9 c5 44 4a 41 62 5d 05 f9 58 98 e0 55 f7 50'
+exp=' 00 c4 00 00 00 1e 00 00 00 00 c4 e1 e1 c9 81 c0 cd b1 e0 43 df 97 20 72 f9 5d a9 ff 06 ff'
 if [ "$RES" != "$exp" ]; then
        echo "Error: (1) Did not get expected result from TPM_PCRRead(17)"
        echo "expected: $exp"