tpm2-software / tpm2-tools

The source repository for the Trusted Platform Module (TPM2.0) tools
https://tpm2-software.github.io
716 stars 378 forks source link

Seal data object using a PCR policy #313

Closed martinezjavier closed 7 years ago

martinezjavier commented 7 years ago

Hello, I've a question similar to issue #56 and #80. Basically I want to seal a data object to a set of PCR values. So what I did is to create a policy file with:

$ tpm2_createpolicy -f policy.file -P -i 9 -g 0x4

And then pass the policy file to tpm2_create using the -L option:

tpm2_create -g 0x0004 -G 0x0008 -o opu_0x000B_0x0008 -O opr_0x000B_0x0008 -I secret.data -c context.p_0x0004_0x0001 -L policy.file -A 0x492

The command succeeds and also tpm2_load, but trying to unseal the object fails:

$ tpm2_unseal -c ctx_load_out_0x0004_0x0001-0x000B_0x0008 -o usl_ctx_load_out_0x0004_0x0001-0x000B_0x0008
ERROR: Sys_Unseal failed. Error Code: 0x12f
$ tpm2_rc_decode 0x12f
error layer
  hex: 0x0
  identifier: TSS2_TPM_ERROR_LEVEL
  description: Error produced by the TPM
format 0 error code
  hex: 0x2f
  name: TPM_RC_AUTH_UNAVAILABLE
  description: authValue or authPolicy is not available for selected entity.

IIUC the problem is that tpm2_unseal uses a password authorization (TPM_RS_PW) session handle. I tried to change tpm2_unseal to instead use a policy session (TPM_SE_POLICY) created with tpm_session_start_auth_with_param(), but now it fails with a TPM_RC_POLICY_FAIL error.

$ tpm2_unseal -c ctx_load_out_0x0004_0x0001-0x000B_0x0008 -o usl_ctx_load_out_0x0004_0x0001-0x000B_0x0008
ERROR: Sys_Unseal failed. Error Code: 0x99d
$ tpm2_rc_decode 0x99d
error layer
  hex: 0x0
  identifier: TSS2_TPM_ERROR_LEVEL
  description: Error produced by the TPM
format 1 error code
  hex: 0x1d
  identifier: TPM_RC_POLICY_FAIL
  description: a policy check failed
session
  hex: 0x100
  identifier: TPM_RC_1
  description:  (null)
idesai commented 7 years ago

Is this with device tcti?

martinezjavier commented 7 years ago

@idesai yes, this is with the device TCTI and using the new in-kernel resource manager (/dev/tpmrm0).

idesai commented 7 years ago

ok, i believe the policy digests mismatched the following time. Can you dump the policy digests when you created the object and when you tried to authenticate?

martinezjavier commented 7 years ago

@idesai I was only passing the policy digest to Tss2_Sys_Create() but no to Tss2_Sys_Unseal(), but IIUC what you are saying then I should also look how to pass the policy digest when doing the object unseal?

In any case, then is correct my assumption that with the current tpm2.0-tools there's no way to seal and unseal an object using a PCR policy?

Following is the exact commands I was using FYI:

$ echo foo > secret.data
$ tpm2_takeownership -c
$ tpm2_createprimary -A e -g 0x0004 -G 0x0001 -C context.p_0x0004_0x0001
$ tpm2_createpolicy -f policy.file -P -i 9 -g 0x4
$ tpm2_create -g 0x000B -G 0x0008 -o opu_0x000B_0x0008 -O opr_0x000B_0x0008  -I secret.data -c context.p_0x0004_0x0001 -L policy.file -A 0x492
$ tpm2_load -c context.p_0x0004_0x0001  -u opu_0x000B_0x0008  -r opr_0x000B_0x0008 -n name.load_0x0004_0x0001-0x000B_0x0008 -C ctx_load_out_0x0004_0x0001-0x000B_0x0008
$ tpm2_unseal -c ctx_load_out_0x0004_0x0001-0x000B_0x0008 -o usl_ctx_load_out_0x0004_0x0001-0x000B_0x0008
idesai commented 7 years ago

@martinezjavier. Right. With the commands above, the object is properly sealed with pcr policy. But cannot be unsealed. Stay tuned for some updates on this soon.

martinezjavier commented 7 years ago

@idesai awesome, I was about to look what was missing but I can now leave in your capable hands :-)

BTW, following is the exact change I did in tpm2_unseal to use a a policy session instead of an authorization session, that led me to the TPM_RC_POLICY_FAIL I mentioned in my first comment.

diff --git a/tools/tpm2_unseal.c b/tools/tpm2_unseal.c
index 21fc277789fb..e3ee8c7a70d5 100644
--- a/tools/tpm2_unseal.c
+++ b/tools/tpm2_unseal.c
@@ -44,6 +44,7 @@
 #include "main.h"
 #include "options.h"
 #include "password_util.h"
+#include "tpm_session.h"

 typedef struct tpm_unseal_ctx tpm_unseal_ctx;
 struct tpm_unseal_ctx {
@@ -195,7 +196,24 @@ int execute_tool(int argc, char *argv[], char *envp[], common_opts_t *opts,
             .sapi_context = sapi_context
     };

-    ctx.sessionData.sessionHandle = TPM_RS_PW;
+    SESSION *policy_session;
+    TPM2B_ENCRYPTED_SECRET encryptedSalt = { { 0 }, };
+    TPMT_SYM_DEF symmetric = { .algorithm = TPM_ALG_NULL, };
+
+    TPM2B_NONCE nonceCaller = { { 0, } };
+    nonceCaller.t.size = 0;
+
+    // Start policy session.
+    TPM_RC rval = tpm_session_start_auth_with_params(ctx.sapi_context,
+            &policy_session, TPM_RH_NULL, 0, TPM_RH_NULL, 0, &nonceCaller,
+            &encryptedSalt, TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256);
+
+    if (rval != TPM_RC_SUCCESS) {
+        LOG_ERR("Failed tpm session start auth with params\n");
+        return rval;
+    }
+
+    ctx.sessionData.sessionHandle = policy_session->sessionHandle;

     bool result = init(argc, argv, &ctx);
     if (!result) {
dguerri commented 7 years ago

Hi @martinezjavier, I am not sure this fixes your issue (I haven't looked into how the policy digest is created), but a problem I can see is that nonceCaller is zero length. Can you try initialising the nonceCaller with the size of SHA256_DIGEST_SIZE? This would be nonceCaller.t.size = SHA256_DIGEST_SIZE;

initial nonceCaller, sets nonce size for the session shall be at least 16 octets

martinezjavier commented 7 years ago

@dguerri thanks a lot for your comment. Yes, I've tried that but it made no difference.

dguerri commented 7 years ago

Np, sorry it didn't help. BTW, After creating the session, you should call Tss2_Sys_PolicyPCR on it (I can't see the code after session creation).

I have this working, and I do something like:

Tss2_Sys_StartAuthSession(...);

Tss2_Sys_PCR_Read(...);
// calculate the hash of PCR values, this is your policyPCR_digest (or load it from a file)

Tss2_Sys_PolicyPCR( ... session_handle, ..., policyPCR_digest, ..., PCR_selection, ...);

Where PCR_selection is a TPML_PCR_SELECTION and it's the list of the PCRs that you used to create the policyPCR_digest. The TPM will validate your session based on the actual content of the PCRs.

martinezjavier commented 7 years ago

@dguerri thanks for your help, it worked!

I was calling Tss2_Sys_PolicyPCR() but was passing the policyPCR digest as read from the policy file generated by tpm2_createpolicy. But even when it matched the digest passed to Tss2_Sys_Create() in tpm2_create, I was getting that TPM_RC_POLICY_FAIL error on tpm2_unseal when calling Tss2_Sys_Unseal().

But after using Tss2_Sys_PCR_Read() as you suggested instead and calculating the digest using the tpm_hash_sequence() helper, the digest matched the one passed to Tss2_Sys_PolicyPCR() in tpm2_createpolicy and now Tss2_Sys_Unseal() succeeds.

@idesai do you want me to clean up my patch and propose a change to allow tpm2_unseal to use a PCR policy for unsealing or are you already working on this?

idesai commented 7 years ago

@martinezjavier @dguerri nice, Thanks. @martinezjavier have your patch ready with a test script. The PR I was working on for this one is from a test code i was refactoring. I am hoping to use your test scripts for sanitizing the PR.

martinezjavier commented 7 years ago

@idesai Ok, I'll wait for your PR then. Thanks!

BTW the commands I was using were mostly taken from test_tpm2_unreal.sh, so I would just extend that test to cover unsealing both with and without a PCR policy.

idesai commented 7 years ago

@martinezjavier that'd be perfect, thanks!

martinezjavier commented 7 years ago

@idesai sorry, I have been busy with other stuff but I've pushed a branch now on my github repo that extended the test_tpm2_unseal.sh to also cover sealing/unsealing using a PCR policy:

https://github.com/martinezjavier/tpm2.0-tools/commits/test-tpm2-unseal-policy

The branch also has some cleanups and fixes for this test, I already created a pull request for those. I didn't include the commit extending the test in the PR because it will fail until your changes are integrated.

idesai commented 7 years ago

@martinezjavier thanks, np. I got pulled away on stuff as well. hopefully today is better. I will merge from cea286d(is it?) and create a PR. Thanks!

martinezjavier commented 7 years ago

@idesai that's correct.

dguerri commented 7 years ago

@idesai, @martinezjavier cool! On a related note, the policy digest created by tpm2_createpolicy should work... otherwise, the ability to seal TPM secrets when the TPM is not in the "target" state is lost. For instance (not saying it's a common use case, still...) think about OS upgrades, we can seal a key for a policy PCR digest that we know will work when the machine is restated.

martinezjavier commented 7 years ago

@dguerri I absolutely agree.

I'll first review and test @idesai latest pull request, but after that I want to look again why the policy created by tpm2_createpolicy works as is for tpm2_create but no for tpm2_unseal.

idesai commented 7 years ago

@martinezjavier @dguerri I have created a PR #342 without the test for this that is good for device-tcti or socket-tcti for now. There is a dependency on another pending PR for the create policy tool. The create policy tool should now take input from raw pcrs file or read current pcrs to both create the policy or start the policy session and output a policy session handle. The unseal tool takes an additional input for a session handle and unseals the secret. Here is the set of steps i took to test it. @martinezjavier will need your help to test it on your hardware as am having some issues with mine. Additionally your test script will need a slight modification due to this design change. Here are the steps I took on the simulator test: tpm2_listpcrs -L 0x4:0 -o pcr0.bin -T socket tpm2_createpolicy -P -L 0x4:0 -F pcr0.bin -f policy.digest -T socket Execute create object with above policy.digest and made it persistent at location 0x81010001(optional, can also give unseal context instead of persistent handle) sessionHandle=0 sessionHandle=$(tpm2_createpolicy -P -L 0x4:0 -a -e -T socket| grep EXTENDED | grep -o "0x[a-f0-9A-F]{1,}") tpm2_unseal -H 0x81010001 -o secret.unsealed -S $sessionHandle -T socket hexdump -Cv secret.unsealed

williamcroberts commented 7 years ago

It's important to note, that policy things get tricky when a resource manager is involved as it will flush the tpm context when the command exits. This is why we have a very early, WIP tpm_shell branch on my github that rolls the commands into a lua shell: https://github.com/williamcroberts/tpm2.0-tools/tree/tpm-shell/tpm_shell

martinezjavier commented 7 years ago

@idesai Ok, I'll test it tomorrow!

@williamcroberts do you know how this works with the in-kernel resource manager?

williamcroberts commented 7 years ago

@martinezjavier It should work the same as any resource manager. When a tool exits, the connection with the resource manager is terminated, and the resource manager calls TSS_FlushContext(). Essentially, the command nuked your tpm session. More details can be found here: http://academlib.com/24842/computer_science/context-management_commands

Also of note, I am pretty stupid when it comes to the tpm and ramping up on it. So if something I say doesn't jive, call it out and don't always take me at face value.

idesai commented 7 years ago

@martinezjavier Please use PR#334 instead. I merged all the changes into that PR since unseal tool had a dependency on the refactored tpm2_creapolicy tool.

martinezjavier commented 7 years ago

@williamcroberts thanks a lot for the reference to the book. So far I've just reading the TCG spec docs but this book seems to be much more easier to digest.

@idesai I've give it a try to your branch, but it didn't work for me (although maybe I'm doing something wrong). This is what I tried:

tpm2_listpcrs -L 0x4:0 -o pcr0.bin
tpm2_createpolicy -P -L 0x4:0 -F pcr0.bin -f policy.digest
tpm2_createprimary -A e -g 0x0004 -G 0x0001 -C primary.context
tpm2_create -g 0x000B -G 0x0008 -o obj.pub -O obj.priv -c primary.context -L policy.digest -A 0x492 -I- <<< "foobar"
tpm2_load -c primary.context -u obj.pub -r obj.priv -n load.name -C load.context

SESSION=$(tpm2_createpolicy -P -L 0x4:0 -a -e | grep EXTENDED | cut -d ' ' -f2)
echo $SESSION

tpm2_unseal -c load.context -S $SESSION

And this is the error I get:

0x03000000
ERROR: Sys_Unseal failed. Error Code: 0x918

$ tpm2_rc_decode 0x918
error layer
  hex: 0x0
  identifier: TSS2_TPM_ERROR_LEVEL
  description: Error produced by the TPM
format 0 warning code
  hex: 0x18
  name: TPM_RC_REFERENCE_S0
  description: the 1st authorization session handle references a session that is not loaded

Is this related to what @williamcroberts said? that the session has already been flushed from the TPM and so isn't loaded anymore by the time tpm2_unseal is called?

martinezjavier commented 7 years ago

@idesai Ok, I had some time to look at this. What worked for me is to create a new policy session, calculate the digest and call Tss2_Sys_PolicyPCR().

I've modified tpm2_unseal on top of your changes to get a list of PCR banks and the PCR hashes as generated by tpm2_listpcrs.

So now it works for me with this set of commands:

tpm2_listpcrs -L 0x4:0 -o pcr0.bin
tpm2_createpolicy -P -L 0x4:0 -F pcr0.bin -f policy.digest
tpm2_createprimary -A e -g 0x0004 -G 0x0001 -C primary.context
tpm2_create -g 0x000B -G 0x0008 -o obj.pub -O obj.priv -c primary.context -L policy.digest -A 0x492 -I- <<< "foobar"
tpm2_load -c primary.context -u obj.pub -r obj.priv -n load.name -C load.context

tpm2_unseal -c load.context -L 0x4:0 -f pcr0.bin

And this is the change (very rough but I can clean it up and propose as a formal patch if you think that's the right approach). For convenience I've also pushed it here.

diff --git a/tools/tpm2_unseal.c b/tools/tpm2_unseal.c
index a14d9b858f42..6c0b1e786dab 100644
--- a/tools/tpm2_unseal.c
+++ b/tools/tpm2_unseal.c
@@ -44,12 +44,17 @@
 #include "main.h"
 #include "options.h"
 #include "password_util.h"
+#include "tpm_session.h"
+#include "tpm_policy.h"
+#include "pcr.h"
+#include "tpm_hash.h"

 typedef struct tpm_unseal_ctx tpm_unseal_ctx;
 struct tpm_unseal_ctx {
     TPMS_AUTH_COMMAND sessionData;
     TPMI_DH_OBJECT itemHandle;
     char *outFilePath;
+    TPM2B_DIGEST pcr_digest;
     TSS2_SYS_CONTEXT *sapi_context;
 };

@@ -90,13 +95,14 @@ bool unseal_and_save(tpm_unseal_ctx *ctx) {

 static bool init(int argc, char *argv[], tpm_unseal_ctx *ctx) {

-    static const char *optstring = "H:P:o:c:S:X";
+    static const char *optstring = "H:P:o:f:c:L:X";
     static const struct option long_options[] = {
       {"item",1,NULL,'H'},
       {"pwdi",1,NULL,'P'},
       {"outfile",1,NULL,'o'},
+      {"digest", 1, NULL, 'f'},
       {"itemContext",1,NULL,'c'},
-      {"input-session-handle",1,NULL,'S'},
+      { "set-list", 1, NULL, 'L' },
       {"passwdInHex",0,NULL,'X'},
       {0,0,0,0}
     };
@@ -111,6 +117,7 @@ static bool init(int argc, char *argv[], tpm_unseal_ctx *ctx) {
             UINT8 H : 1;
             UINT8 c : 1;
             UINT8 P : 1;
+            UINT8 f : 1;
         };
         UINT8 all;
     } flags = { .all = 0 };
@@ -118,6 +125,8 @@ static bool init(int argc, char *argv[], tpm_unseal_ctx *ctx) {
     int opt;
     bool hexPasswd = false;
     char *contextItemFile = NULL;
+    PCR_POLICY_OPTIONS pcr_policy_options;
+    TPM2B_DIGEST pcr_hashes = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
     while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
         switch (opt) {
         case 'H': {
@@ -147,19 +156,21 @@ static bool init(int argc, char *argv[], tpm_unseal_ctx *ctx) {
             ctx->outFilePath = optarg;
         }
             break;
+        case 'f':
+            if(!files_load_bytes_from_file(optarg, pcr_hashes.t.buffer, &pcr_hashes.t.size)) {
+                return false;
+            }
+            flags.f = 1;
+            break;
         case 'c':
             contextItemFile = optarg;
             flags.c = 1;
             break;
-        case 'S': {
-            bool result = tpm2_util_string_to_uint32(optarg,
-                &ctx->sessionData.sessionHandle);
-            if (!result) {
-                LOG_ERR("Could not convert session handle to number, got: \"%s\"",
-                        optarg);
+        case 'L':
+            if (pcr_parse_selections(optarg, &pcr_policy_options.pcr_selections) != 0) {
+                showArgError(optarg, argv[0]);
                 return false;
             }
-        }
             break;
         case 'X':
             hexPasswd = true;
@@ -197,6 +208,41 @@ static bool init(int argc, char *argv[], tpm_unseal_ctx *ctx) {
         }
     }

+    if (flags.f) {
+        SESSION *policy_session;
+        TPM2B_ENCRYPTED_SECRET encryptedSalt = { { 0 }, };
+        TPMT_SYM_DEF symmetric = { .algorithm = TPM_ALG_NULL, };
+
+        TPM2B_NONCE nonceCaller = { { 0, } };
+        nonceCaller.t.size = 0;
+
+        TPM_RC rval = tpm_session_start_auth_with_params(ctx->sapi_context,
+                                                         &policy_session, TPM_RH_NULL,
+                                                         0, TPM_RH_NULL, 0, &nonceCaller,
+                                                         &encryptedSalt, TPM_SE_POLICY,
+                                                         &symmetric, TPM_ALG_SHA256);
+
+        if (rval != TPM_RC_SUCCESS) {
+            LOG_ERR("Failed tpm session start auth with params\n");
+            return rval;
+        }
+
+        ctx->sessionData.sessionHandle = policy_session->sessionHandle;
+
+        TPM2B_DIGEST pcr_digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
+
+        rval = tpm_hash_sequence(ctx->sapi_context,
+                                 policy_session->authHash,
+                                 pcr_policy_options.pcr_selections.count,
+                                 &pcr_hashes, &pcr_digest);
+        if (rval != TPM_RC_SUCCESS) {
+            return rval;
+        }
+
+        rval = Tss2_Sys_PolicyPCR(ctx->sapi_context, policy_session->sessionHandle, 0,
+                                  &pcr_digest, &pcr_policy_options.pcr_selections, 0);
+    }
+
     return true;
 }
williamcroberts commented 7 years ago

The problem with making each tool deal with policy, is that it makes doing compound tasks a lot harder. Due to my ignorance of TPM, I am likely not the best one to comment here. @idesai can likely lay out use cases that involve multiple commands working together.

The only reason to really do this (AFAICT), is to get around the resource manager calling flush when the connection with the RM is terminated. This RM issue, we're looking at solving on the tpm_shell branch at my fork: https://github.com/williamcroberts/tpm2.0-tools/tree/tpm-shell

This is a lua shell that provides the tools in a way that won't cause the RM to call flush.

idesai commented 7 years ago

@williamcroberts aptly, the rationale for the design choice. Although PCR sealed secret is a very common use case that @martinezjavier has suggested. Should we then make an exception for tpm2_unseal alone? For the rest, I concur that we need to be able to have the flexibility to chain them and yet centralize it to avoid code duplication and compound the policies. I will add the test scripts for the PR with socket tcti for now.

martinezjavier commented 7 years ago

@williamcroberts @idesai,

I'm still very ignorant about TPM2 in general and these projects in particular so please forgive me if I say something wrong or silly, but I'll share my opinion.

I understand that the problem is that the session is flushed when the SAPI and TCTI contexts are destroyed. And so is good to have the tools being ran under an execution environment to prevent this (like the LUA shell, but possibly others as long as the exec env calls sapi_init_from_options to create the contexts, keep a reference to it and pass it to the tools when calling execute_tool).

But since there are also command line tools as standalone programs, I think that people will expect these to be equipotent to the ones that can be executed from within the tpm-shell (even if that means additional options to store and load data needed to re-create the sessions, just like you need to choose the TCTI for each program execution but you only pass these once to the tpm-shell when tpm_open).

IOW, I believe that one should be able to combine the tools using a script or executing them from an (OS) shell and have the same features that would have if those tools were ran from a different execution environment (e.g: the mentioned LUA tpm-shell).

williamcroberts commented 7 years ago

Sure, I get that and I agree mostly. The tools will work as prescribed as long as there isn't an RM so if you specify --tcti=device or --tcti=socket (use the simulator directly), then there is no issues. However, as we understand, it all goes downhill once an RM is introduced and how the RM communication occurs.

The question is, where do we solve the problem:

  1. The tools itself. Pro's consistency. Cons: difficult to handle compound commands.
  2. External to the tools - Pros: compound commands work. Cons: difference with behavior if an RM is enabled, additional complexity on non-OS shell.
  3. TCTI itself - One could solve it in the TCTI itself by having it spin off a daemon to keep the context open.. and ignore teardowns.... quite awful IMHO but possible.

@idesai had an example with nvread/write/define (IIRC) a few weeks back that used policy, but the tool interface ended up getting clunky and complex when you needed the session across multiple operations. It ended up turning into a tool that was executing its own mini language. At that point, the concept of the tpm shell was created.

@idesai can you elaborate on that?

martinezjavier commented 7 years ago

@williamcroberts one clarification on top of your comment, you said that no RM is used when specifying --tcti=device but that's not always true. For instance, I'm using the device TCTI but with the in-kernel resource manager that landed in Linux 4.12.

I haven't had time yet to study both the D-Bus based user-space RM and the kernel RM to understand the similarities and differences between the two implementations, but the fact that you can use a TPM directly (/dev/tpm?) and through the kernel resource manager interface (/dev/tpmrm?) should also be taken into account when exploring the approaches to solve the session issue.

martinezjavier commented 7 years ago

For some context on why I'm using the in-kernel resource manager, you can refer to issue #303.

williamcroberts commented 7 years ago

Currently --tcti=device defaults to /dev/tpm0 unless specified otherwise via --device-file on the command line, TPM2TOOLS_DEVICE_FILE env variable.

Both the user-space and kernel-space resource managers, will call a flush when the client process disconnects. This is seen in tpmrm-dev.c for the release call, which calls --> tpm2_del_space --> tpm2_flush_sessions.

If you look at Chapter 12 and Chapter 13 of the Practical Guide to TPM2.0, it may require multiple TPM2_Policy* commands to satisfy the policy. So a simple example is something that can be done in one call, but what if you need to:

  1. Start an auth session
  2. Perform N policy updates, perhaps going to things like a bio-metric reader
  3. write an nv index
  4. Perform more policy updates.
  5. read an nv index

It's at step 2 and 4, where having it in one command would be hard while keeping the session alive through the RM.

There was something floating on TCG with respect to saving the state to start a session over again, but our conjecture has that it would require keeping a log of every command, and replaying them every-time, a very expensive and slow operation that may not even be possible all the time.

idesai commented 7 years ago

Indeed, a group of operations aka profiles necessary to for example setup systems with taking ownership, retrieving endorsement certificates, etc. all of which are individual tools can be constructed as an audit digest that can be attested with the TPM as a root of trust for reporting.

martinezjavier commented 7 years ago

@williamcroberts yes, I know what's the default TPM device used and how to change it... but my point was that using the device TCTI doesn't imply that a resource manager isn't used.

@idesai @williamcroberts thanks a lot for the explanation. I understand that more complex scenarios needing multiple commands may not be possible with the tools due the RM flushing the sessions, but what I'm not understanding is why that should prevent adding support for the simpler user cases that will succeed.

For example, my use case is to seal a LUKS volume master key to a PCR state, making sure that the the partition can only be unlock if the system has not been tamper with. I think that's a very common use case (I expect writing and reading NV data using a PCR policy to be another common use case).

So far I can seal the LUKS volume master key and unseal it to unlock the volume without typing a passphrase, but what I'm missing is to take the PCR hashes into account. With @idesai latest PR #334 and the patch mentioned before, I'm able to do it.

po1 commented 7 years ago

@martinezjavier @spmaniato and I have the same use case as you describe. I support @idesai 's suggestion to make a special case for tpm2_unseal, because it provides a very relevant code example (and possible a full solution) to a very common use case.

Along these lines, I would also suggest a tpm2_seal tool as a shortcut for sealing data with a PCR policy in one command. As much as I value the knowledge that I gained reading the Practical guide to TPM as a result of being unable to understand and use the tpm2 tools out of the box, I think there are very common use cases that should not require in-depth knowledge of how all of this works. If that is something that could indeed benefit this repository, I'd be happy to contribute that tool.

williamcroberts commented 7 years ago

@martinezjavier - As long as you understand the limitations and that it's not a generic policy solution, I am OK with taking a PR that adds PCR policy support to tpm2_unseal command. Just make sure the documentation is added. If we can, I'd like to make sure that the policy options are used consistently across tools as well.

martinezjavier commented 7 years ago

@williamcroberts yes, I absolutely agree. It should be documented that for more complex (e.g: compound commands) use cases, an execution environment is needed to keep the context alive instead of running the commands as standalone. This will only be to cover the common use case as mentioned by @po1.

I'll wait for @idesai PR #334 to land and then I'll do it on top of his changes.

williamcroberts commented 7 years ago

@martinezjavier do you want to also add in #348 as well?

Please add a test for any of these.

martinezjavier commented 7 years ago

@williamcroberts yes, I'll also take a look to #348. But I'll do it after I've proposed a PR for this issue.

williamcroberts commented 7 years ago

@martinezjavier @idesai I was speaking with @flihp a couple of days ago. It turns out this is a bug in the resource manager. Whenever a process calls Tss2_Sys_ContextSave, that context should be saved for 1 use later via ContextLoad. Ie each command needs to save the context or its gets flushed. This will allow the tools, in its current shell environment to work properly.

With that said, context saving and loading should likely move to the main entry point with common controls.

policy support in the tools themselves can go away, and a single policy tool is all that is needed, ie this commit can go away: https://github.com/01org/tpm2-tools/commit/5435e1d79662fde77e077d1e8ca9241068d9ffec

idesai commented 7 years ago

@williamcroberts agreed! So tools would only need a session handle input to satisfy the policy and those tools creating the objects would simply need the policy digest. Both of which can be output with the create policy tool. When is the change coming in the resourcemgr?

martinezjavier commented 7 years ago

@williamcroberts I'm using the in-kernel resource manager though. Is the behaviour you describe part of the TCG spec or just something you want to add to the user-space resource manager?

idesai commented 7 years ago

@jsakkine-intel any comments on how context saving and loading in the kernel resource manager is managed?

flihp commented 7 years ago

We're discussing / presenting this @ the upcoming LPC. If you're looking for the details there's a thread from a few months back on the tpmdd mailing list that goes into the details. There's also a draft spec on the TCG website that describes the resource management strategies in detail (where I found my mistake).

My goal is to get this implemented in the user-space resource manager ASAP. I figure this is on the order of weeks (after LPC).

martinezjavier commented 7 years ago

@flihp a reference to the thread in the tpmdd-devel would be great (I did a quick search but didn't find anything relevant). But yes, if both the user-space and kernel resource manager gets the support described, then we could get rid of the mentioned commit.

I wanted to be at LPC for the TPM microconf but at the end I won't be able to attend for personal reasons.

ghost commented 7 years ago

documented here https://lkml.org/lkml/2017/3/3/403

ghost commented 7 years ago

cover letter for the whole patch set https://lkml.org/lkml/2017/3/3/396