]> git.proxmox.com Git - swtpm.git/commitdiff
Use TPMLIB_SetState to set state blobs
authorStefan Berger <stefanb@linux.vnet.ibm.com>
Mon, 14 May 2018 13:03:09 +0000 (09:03 -0400)
committerStefan Berger <stefanb@linux.vnet.ibm.com>
Mon, 14 May 2018 13:22:11 +0000 (09:22 -0400)
Rather than writing to files directly and having to validate the state in
those files using TPMLIB_ValidatetState(), we now use the new
TPMLIB_SetState() call to set the TPM's state blobs. The advantage of this
call is that it doesn't overwrite state files and ends up leaving state in
files that the TPM cannot use. Instead, it validates the state immediately
when the blob is set and returns an error in case the state cannot be
accepted.

We need to adapt one test case that now gets a failure earlier than before.
Before the TPM_INIT failed, now setting the encrypted blob fails because it
cannot be decrypted and thus cannot be accepted by the TPM.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
src/swtpm/ctrlchannel.c
src/swtpm/cuse_tpm.c
src/swtpm/swtpm_nvfile.c
src/swtpm/swtpm_nvfile.h
src/swtpm/tpmlib.c
src/swtpm/tpmlib.h
tests/_test_migration_key

index 1303fb3aa0d68f843756932eca9e96d665041539..23e89929d87eae3e611186d19f9b0e4f0001e26e 100644 (file)
@@ -199,7 +199,6 @@ static int ctrlchannel_return_state(ptm_getstate *pgs, int fd)
 static int ctrlchannel_receive_state(ptm_setstate *pss, ssize_t n, int fd)
 {
     uint32_t blobtype = be32toh(pss->u.req.type);
-    const char *blobname = tpmlib_get_blobname(blobtype);
     uint32_t tpm_number = 0;
     unsigned char *blob = NULL;
     uint32_t blob_length = be32toh(pss->u.req.length);
@@ -240,9 +239,7 @@ static int ctrlchannel_receive_state(ptm_setstate *pss, ssize_t n, int fd)
     }
 
     res = SWTPM_NVRAM_SetStateBlob(blob, blob_length, is_encrypted,
-                                   tpm_number, blobname);
-    if (res == TPM_SUCCESS && blob_length)
-        res = tpmlib_validate_blob(blobtype);
+                                   tpm_number, blobtype);
 
 err_send_resp:
     pss->u.resp.tpm_result = htobe32(res);
index e8e79b266617cd672bc2fea6a9c5bd07e603280d..3bd168db8a323e042a7a4f9a0c7d7cd9170df823 100644 (file)
@@ -602,7 +602,6 @@ ptm_set_stateblob_append(uint32_t blobtype,
                          const unsigned char *data, uint32_t length,
                          bool is_encrypted, bool is_last)
 {
-    const char *blobname;
     TPM_RESULT res = 0;
     static struct stateblob stateblob;
 
@@ -641,20 +640,12 @@ ptm_set_stateblob_append(uint32_t blobtype,
         /* full packet -- expecting more data */
         return res;
     }
-    blobname = tpmlib_get_blobname(blobtype);
-
-    if (blobname) {
-        res = SWTPM_NVRAM_SetStateBlob(stateblob.data,
-                                       stateblob.length,
-                                       stateblob.is_encrypted,
-                                       0 /* tpm_number */,
-                                       blobname);
-        if (res == TPM_SUCCESS && stateblob.length)
-            res = tpmlib_validate_blob(blobtype);
-    } else {
-        res = TPM_BAD_PARAMETER;
-    }
 
+    res = SWTPM_NVRAM_SetStateBlob(stateblob.data,
+                                   stateblob.length,
+                                   stateblob.is_encrypted,
+                                   0 /* tpm_number */,
+                                   blobtype);
 
     TPM_Free(stateblob.data);
     stateblob.data = NULL;
index e4ba203877902a7e610868c50e0c9005e08c30aa..066e975b9445fab8a50df655917304a3c4a59436 100644 (file)
@@ -81,6 +81,7 @@
 #include "key.h"
 #include "logging.h"
 #include "tpmstate.h"
+#include "tpmlib.h"
 
 /* local structures */
 typedef struct {
@@ -901,52 +902,97 @@ TPM_RESULT SWTPM_NVRAM_SetStateBlob(unsigned char *data,
                                     uint32_t length,
                                     TPM_BOOL is_encrypted,
                                     uint32_t tpm_number,
-                                    const char *name)
+                                    uint32_t blobtype)
 {
-    TPM_BOOL encrypt = !is_encrypted;
     TPM_RESULT res;
     uint32_t dataoffset;
-    unsigned char *plain = NULL;
-    uint32_t plain_len = 0;
+    unsigned char *plain = NULL, *mig_decrypt = NULL;
+    uint32_t plain_len = 0, mig_decrypt_len = 0;
     uint16_t hdrflags;
+    enum TPMLIB_StateType st = tpmlib_blobtype_to_statetype(blobtype);
+    const char *blobname = tpmlib_get_blobname(blobtype);
 
-    if (length == 0) {
-        /* with 0 bytes length we delete any existing file */
-        SWTPM_NVRAM_DeleteName(tpm_number, name, FALSE);
-        return TPM_SUCCESS;
+    if (st == 0) {
+        logprintf(STDERR_FILENO,
+                  "Unknown blob type %u\n", blobtype);
+        return TPM_BAD_PARAMETER;
     }
 
+    if (length == 0)
+        return TPMLIB_SetState(st, NULL, 0);
+
     res = SWTPM_NVRAM_CheckHeader(data, length, &dataoffset, &hdrflags);
     if (res != TPM_SUCCESS)
         return res;
 
+    if (length - dataoffset == 0)
+        return TPMLIB_SetState(st, NULL, 0);
+
     /*
      * We allow setting of blobs that were not encrypted before;
      * we just will not decrypt them even if the migration key is
      * set. This allows to 'upgrade' to encryption. 'Downgrading'
      * will not be possible once a migration key was used.
      */
-    if ((hdrflags & BLOB_FLAG_MIGRATION_ENCRYPTED) && migrationkey.symkey.valid) {
-         /*
-          * we first need to decrypt the data with the migration key
-          */
-         res = SWTPM_NVRAM_DecryptData(&migrationkey,
-                                       &plain, &plain_len,
-                                       &data[dataoffset], length - dataoffset);
-         if (res != 0)
+    if ((hdrflags & BLOB_FLAG_MIGRATION_ENCRYPTED)) {
+        /*
+         * we first need to decrypt the data with the migration key
+         */
+        if (!SWTPM_NVRAM_Has_MigrationKey()) {
+            logprintf(STDERR_FILENO,
+                      "Missing migration key to decrypt %s\n", blobname);
+            return TPM_KEYNOTFOUND;
+        }
+
+        res = SWTPM_NVRAM_DecryptData(&migrationkey,
+                                      &mig_decrypt, &mig_decrypt_len,
+                                      &data[dataoffset], length - dataoffset);
+        if (res != 0) {
+            logprintf(STDERR_FILENO,
+                      "Decrypting the %s blob with the migration key failed; "
+                      "res = %d\n", blobname, res);
+            return res;
+        }
+    } else {
+        mig_decrypt = &data[dataoffset];
+        mig_decrypt_len = length - dataoffset;
+    }
+
+    /*
+     * Migration key has decrytped the data; if they are still encrypted
+     * with the state encryption key, we need to decrypt them using that
+     * key now.
+     */
+    if (is_encrypted) {
+        if (!SWTPM_NVRAM_Has_FileKey()) {
             logprintf(STDERR_FILENO,
-                      "SWTPM_NVRAM_LoadData: Decrypting the state blob "
-                      "failed res = %d\n", res);
-         if (res == TPM_SUCCESS) {
-             res = SWTPM_NVRAM_StoreData_Intern(plain, plain_len,
-                                                tpm_number,
-                                                name,
-                                                encrypt);
-             TPM_Free(plain);
-         }
-         return res;
-    }
-
-    return SWTPM_NVRAM_StoreData_Intern(&data[dataoffset], length - dataoffset,
-                                        tpm_number, name, encrypt);
+                      "Missing state key to decrypt %s\n", blobname);
+            res = TPM_KEYNOTFOUND;
+            goto cleanup;
+        }
+        res = SWTPM_NVRAM_DecryptData(&filekey,
+                                      &plain, &plain_len,
+                                      mig_decrypt, mig_decrypt_len);
+        if (res != 0) {
+            logprintf(STDERR_FILENO,
+                      "Decrypting the %s blob with the state key "
+                      "failed; res = %d\n", blobname, res);
+            goto cleanup;
+        }
+    } else {
+        plain_len = mig_decrypt_len;
+        plain = mig_decrypt;
+    }
+
+    /* SetState will make a copy of the buffer */
+    res = TPMLIB_SetState(st, plain, plain_len);
+
+    if (plain != mig_decrypt)
+        TPM_Free(plain);
+
+cleanup:
+    if (mig_decrypt != &data[dataoffset])
+        TPM_Free(mig_decrypt);
+
+    return res;
 }
index 404a21126e2a5a35ae0900c2f9368f574afca908..ea129c5d5e5f1118732fe7131ce6896acb475854 100644 (file)
@@ -89,7 +89,7 @@ TPM_RESULT SWTPM_NVRAM_SetStateBlob(unsigned char *data,
                                     uint32_t length,
                                     TPM_BOOL is_encrypted,
                                     uint32_t tpm_number,
-                                    const char *name);
+                                    uint32_t blobtype);
 
 TPM_BOOL SWTPM_NVRAM_Has_FileKey(void);
 TPM_BOOL SWTPM_NVRAM_Has_MigrationKey(void);
index c6c9ee620fdb82523b65808624a437c32630fd26..efd80255c2ca4dd3da1ba49cd39f865441aac68f 100644 (file)
@@ -309,19 +309,15 @@ TPM_RESULT tpmlib_process(unsigned char **rbuffer,
 
 #endif /* WITH_VTPM_PROXY */
 
-/* validate_blob calls libtpms to ensure that it can use the
-   state blobs once we invoke TPM_INIT. This is useful to
-   be able to fail TPM state migration early.
- */
-TPM_RESULT tpmlib_validate_blob(uint32_t blobtype)
+enum TPMLIB_StateType tpmlib_blobtype_to_statetype(uint32_t blobtype)
 {
     switch (blobtype) {
     case PTM_BLOB_TYPE_PERMANENT:
-        return TPMLIB_ValidateState(TPMLIB_STATE_PERMANENT, 0);
+        return TPMLIB_STATE_PERMANENT;
     case PTM_BLOB_TYPE_VOLATILE:
-        return TPMLIB_ValidateState(TPMLIB_STATE_VOLATILE, 0);
+        return TPMLIB_STATE_VOLATILE;
     case PTM_BLOB_TYPE_SAVESTATE:
-        return TPMLIB_ValidateState(TPMLIB_STATE_SAVE_STATE, 0);
+        return TPMLIB_STATE_SAVE_STATE;
     }
-    return TPM_FAIL;
+    return 0;
 }
index 1626606ae7dd4bef20e8d0513f1fab43e78b8f94..0650c81d53813ae50d56c5352310347a70d752ac 100644 (file)
@@ -44,6 +44,7 @@
 #include <libtpms/tpm_library.h>
 
 const char *tpmlib_get_blobname(uint32_t blobtype);
+enum TPMLIB_StateType tpmlib_blobtype_to_statetype(uint32_t blobtype);
 TPM_RESULT tpmlib_register_callbacks(struct libtpms_callbacks *cbs);
 TPM_RESULT tpmlib_start(uint32_t flags);
 int tpmlib_get_tpm_property(enum TPMLIB_TPMProperty prop);
@@ -66,7 +67,6 @@ TPM_RESULT tpmlib_process(unsigned char **rbuffer, uint32_t *rlength,
                           uint32_t locality_flags,
                           TPM_MODIFIER_INDICATOR *locality);
 
-TPM_RESULT tpmlib_validate_blob(uint32_t blobtype);
 
 struct tpm_req_header {
     uint16_t tag;
index 56d2cd298105016168d18e2ad2a6e29131912594..3ce881b01a68fd91b8ac226cea5101170642df6f 100755 (executable)
@@ -232,14 +232,6 @@ if [ $? -eq 0 ]; then
        exit 1
 fi
 
-# Now init the TPM; this must fail since the volatile state does not
-# match with the integrity hash it is expecting to find
-run_swtpm_ioctl ${SWTPM_INTERFACE} -i
-if [ $? -eq 0 ]; then
-       echo "Error: Initializing the ${SWTPM_INTERFACE} TPM should have failed."
-       exit 1
-fi
-
 run_swtpm_ioctl ${SWTPM_INTERFACE} -s
 if [ $? -ne 0 ]; then
        echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM."