Menu

Unable to seal to pcrpolicy correctly

oba
2017-05-23
2017-05-23
  • oba

    oba - 2017-05-23

    I'm having problems implementing a seal/unseal procedure using the seal to pcr approach. For some reason, the sealed object is released from the TPM with no regrads to the PCR state.... This is a bog problem, as data sealed to the TPM should not be released when the PCR registers do not contains the correct values. I suspect that somehow the seal utils uses password based seal/unseal.

    Things to consider:
    1. The TPM is "owned", and is TPM2 varient, on an intel motherboard. The TPM is from Intel.
    2. The Process was adapted from the testunseal.sh from the test scripts provided in this project.
    3. I created a permanent handle at 81000001, as the sealed key will be used between reboots.

    This is the test script:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #!/bin/bash
    #
    echo ""
    echo "Seal and Unseal to PCRs"
    echo ""
    ./pcrread -halg sha1 -ns -ha 16 
    echo "Create a sealed data object sha1"
    ./create -hp 81000001 -nalg sha1 -bl -kt f -kt p -opr tmppriv.bin -opu tmppub.bin -if sealed_key.bin -pol ./pcr-policy1.bin 
    
    echo "Load the sealed data object"
    ./load -hp 81000001 -ipr tmppriv.bin -ipu tmppub.bin 
    
    echo "PCR 16 Reset"
    ./pcrreset -ha 16 
    ./pcrread -halg sha1 -ns -ha 16 
    
    echo "Start a policy session sha1"
    ./startauthsession -se p -halg sha1 
    echo "Unseal the data blob - policy failure, policypcr not run"
    ./unseal -ha 80000001 -of tmp.bin 
    
    echo "Policy PCR, update with the wrong PCR 16 value"
    ./policypcr -halg sha1 -ha 03000000 -bm 10000 
    
    echo "Unseal the data blob - policy failure, PCR 16 incorrect"
    ./unseal -ha 80000001 -of tmp.bin 
    cat tmp.bin
    echo "Extend PCR 16 to correct value"
    ./pcrextend -halg sha1 -ha 16 -if sealed_key.bin
    ./pcrread -halg sha1 -ns -ha 16 
    
    echo "Policy restart, set back to zero"
    ./policyrestart -ha 03000000  
    
    echo "Policy PCR, update with the correct PCR 16 value"
    ./policypcr -halg sha1 -ha 03000000 -bm 10000 
    
    echo "Unseal the data blob"
    ./unseal -ha 80000001 -of test.bin
    
    echo "Verify the unsealed result"
    cat test.bin
    
    echo "Flush the sealed object"
    ./flushcontext -ha 80000001 
    
    echo "Flush the policy session"
    ./flushcontext -ha 03000000 
    

    content of the policy file:

    0000017f000000010004030000018fdad396c72fee6a54aa7e3da75f5cf4e4b55e39
    

    The output:

    Seal and Unseal to PCRs
    
    59a4ea34e5351fe8b35669162fac808c9c10d352
    Create a sealed data object sha1
    Load the sealed data object
    Handle 80000001
    PCR 16 Reset
    0000000000000000000000000000000000000000
    Start a policy session sha1
    Handle 03000000
    Unseal the data blob - policy failure, policypcr not run
    Policy PCR, update with the wrong PCR 16 value
    Unseal the data blob - policy failure, PCR 16 incorrect
    1234567890abcdef
    Extend PCR 16 to correct value
    59a4ea34e5351fe8b35669162fac808c9c10d352
    Policy restart, set back to zero
    Policy PCR, update with the correct PCR 16 value
    Unseal the data blob
    Verify the unsealed result
    1234567890abcdef
    Flush the sealed object
    Flush the policy session
    
     
    • Ken Goldman

      Ken Goldman - 2017-05-23

      I think that you expected ./unseal -ha 80000001 -of tmp.bin to fail because you used a password session rather than the policy session.

      If so, the create utility (what you call the seal utility) currently sets the attribute userWithAuth. This says that either password or policy can be used. There are two solutions:

      1. Change the code in objecttemplates to not set userWithAuth.
      2. Give me an email address and I can send you a not-yet-released enhancement that has a command line option to clear the flag.
       
      • oba

        oba - 2017-05-23

        First of all - Thanks for the quick reply!
        1. I'm not sure how to do that. Do you mean that I need to go find where in the sources this flag is set, patch, and recomplie?
        2. Please use oba2cat4 [at] gmail [dot] com.

        Thanks again!

         
        • Ken Goldman

          Ken Goldman - 2017-05-23

          Yes, the line is in objecttemplates.c It will look something like this. Comment it out, and recompile.

          publicArea->objectAttributes.val |= TPMA_OBJECT_USERWITHAUTH;
          

          Note that this is just a currently missing feature in the sample utilities. The TSS library itself supports all the options.

          Did you want a tarball with the updated create utility? It has a -uwa option to clear the flag. If you don't need the option, commenting out the code should be faster for you.

           
          • oba

            oba - 2017-05-24

            For my use case (based on this blog post:tpm2-sealed-luks), a recompile will be enough.
            But in any case, can you send me the the tarball with the utility in any case?

            Thanks!

             
      • oba

        oba - 2017-05-23

        Using the example test script, this is the way to create (or "seal") to a Policy. I'm not sure why it is wrong.

        this is the line from the testuneal.sh script, where ${HALG} is either sha1 or sha256:

        create -hp 80000000 -nalg ${HALG} -bl -kt f -kt p -opr tmppriv.bin -opu\ tmppub.bin -pwdp pps -pwdk sea -if msg.bin -pol\
        policies/policypcr16aaa${HALG}.bin > run.out
        

        and my create line:

        ./create -hp 81000001 -nalg sha1 -bl -kt f -kt p -da \
        -pol ./pcr_policy.bin -opr tmppriv.bin -opu tmppub.bin \
        -if sealed_key.bin
        

        There is another odd thing that I encountered, regarding policydigest vs policymakerpcr output. It should be the same, for a preset pcrs values and mask, but it isn't. I will open a new discussion, if I can replicate.

         
        • Ken Goldman

          Ken Goldman - 2017-05-23

          You are sealing to a policy, but the utility currently creates the sealed blob such that it can be unsealed by either a policy or a password/HMAC session. To remove the "or password" authorization, userWithAuth has to be clear.

           
        • Ken Goldman

          Ken Goldman - 2017-05-23

          The policy digest (output of PolicyGetDigest) will not be the same as the output of policymakerpcr.

          policymakerpcr creates an AND term that is used as an input to policymaker. It contains the command code, PCR selection, and digest of the selected PCRs. It's not the final policy digest.

           
      • oba

        oba - 2017-05-25

        now the sequence fails with :
        TPM_RC_AUTH_UNAVAILABLE - authValue or authPolicy is not available for selected entity.
        It seems to me, that commenting out the flag is not enough...

        Commenting out the line, recompiling, and using the resulting binaries to create with a policy this way:

        # echo "blablabla00000" > sealed_key.bin
        # ./pcrread -halg sha1 -ns -ha 16 > ./pcrs.txt
        # ./policymakerpcr -halg sha1 -bm 10000 -if ./pcrs.txt -of ./pcr-policy.txt
        # ./policymaker -halg sha1 -if ./pcr-policy.txt -of ./pcr-policy.bin
        # ./create -v -hp 81000001 -nalg sha1 -uwa -bl -pol ./pcr-policy.bin -if ./sealed_key.bin -opr ./priv.key -opu ./pub.key
        

        and the resulting output from the unseal sequence:

        # ./load -hp 81000001 -ipr ./priv.key -ipu ./pub.key
        Handle 80000001
        # ./startauthsession -halg sha1 -se p
        Handle 03000000
        # ./policypcr -halg sha1 -ha 03000000 -bm 10000
        # ./unseal -ha 80000001 -se2 03000000 1 -of /dev/stdout
        unseal: failed, rc 0000012f
        TPM_RC_AUTH_UNAVAILABLE - authValue or authPolicy is not available for selected entity.
        

        verbose output for the create:

        TSS_Execute: Command 00000153 marshal
        TSS_Execute_valist: Step 1: initialization
        TSS_Execute_valist: Step 2: authorization 0
        TSS_Execute_valist: session 0 handle 40000009
        TSS_Execute_valist: Step 5: command encrypt
        TSS_Sessions_GetDecryptSession: Found 0 decrypt sessions at 0
        TSS_Execute_valist: Step 6 calculate HMACs
        TSS_HmacSession_SetHMAC: Step 6 session 40000009
        TSS_Execute_valist: Step 7 set command authorizations
        TSS_Execute_valist: Step 8: process the command
        TSS_AuthExecute: Executing TPM2_Create
        TSS_Dev_Open: Opening /dev/tpm0
        TSS_Dev_SendCommand: TPM2_Create
         TSS_Dev_SendCommand length 90
         80 02 00 00 00 5a 00 00 01 53 81 00 00 01 00 00
         00 09 40 00 00 09 00 00 00 00 00 00 13 00 00 00
         0f 62 6c 61 62 6c 61 62 6c 61 30 30 30 30 30 0a
         00 22 00 08 00 04 00 00 04 00 00 14 69 f4 6a d7
         33 b6 8c 47 24 45 d1 69 8c 00 d1 7a 24 c8 c3 e8
         00 10 00 00 00 00 00 00 00 00
        TSS_Dev_ReceiveCommand:
         TSS_Dev_ReceiveCommand length 353
         80 02 00 00 01 61 00 00 00 00 00 00 01 4e 00 6d
         00 20 14 66 6c 24 de 17 ee 75 c1 4b 3f 23 58 ff
         7a 65 fb 60 57 5e ee 51 04 27 72 f7 0d a8 33 af
         0f fc 00 10 9d ac 16 a2 c3 bc 07 e9 f0 8d 62 5e
         74 cf a6 54 1c bc 9c fb d9 be 05 d4 e1 5a 47 c0
         e3 79 c0 d0 b9 05 67 f1 32 ab f9 db 64 8a 03 fc
         46 b9 1d 52 46 e5 ee 50 9e 78 58 87 38 68 d3 5a
         37 34 1b 96 63 8b 49 4f b6 f6 df 37 05 00 36 00
         08 00 04 00 00 04 00 00 14 69 f4 6a d7 33 b6 8c
         47 24 45 d1 69 8c 00 d1 7a 24 c8 c3 e8 00 10 00
         14 1f 2c 08 9c 84 93 03 63 29 ae 9c b5 00 ee c3
         bb db 3b a6 f7 00 67 00 00 00 00 00 14 da 39 a3
         ee 5e 6b 4b 0d 32 55 bf ef 95 60 18 90 af d8 07
         09 01 00 0b 00 22 00 0b d9 cf 58 3c d6 25 63 2f
         ee b2 09 bf 8d 4e e0 d8 06 58 59 cb 20 db dc f1
         b5 74 6b 4f 0e a1 e0 03 00 22 00 0b f3 36 a3 16
         c6 57 7d d5 0b 23 06 e6 ae a9 7c ad 89 56 56 b0
         ae 3f 13 aa ab 1a c5 28 23 bf 88 82 00 00 00 14
         32 2b 79 0e 0d 7a d8 eb 83 41 2f d8 03 d3 9d 08
         16 da e0 da 80 21 40 00 00 01 00 20 6d cd fc 0f
         71 28 a6 55 3e 75 2c a7 4f ce be d5 37 b4 6d 79
         1b 03 97 e3 92 6d 67 46 d7 60 d8 ed 00 00 01 00
         00
        TSS_Dev_ReceiveCommand: rc 00000000
        TSS_Execute_valist: Step 9 get response authorizations
        TSS_Execute_valist: Step 10: process response authorization 40000009
        TSS_Execute_valist: Step 13: response decryption
        TSS_Sessions_GetEncryptSession: Found 0 encrypt sessions at 0
        TSS_Execute: Command 00000153 unmarshal
        TSS_Execute: Command 00000153 post processor
        TSS_Dev_Close: Closing /dev/tpm0
        create: success
        

        and verbose output for the unseal:

        TSS_Execute: Command 0000015e marshal
        TSS_Execute_valist: Step 1: initialization
        TSS_Execute_valist: Step 2: authorization 0
        TSS_Execute_valist: session 0 handle 40000009
        TSS_Execute_valist: Step 5: command encrypt
        TSS_Sessions_GetDecryptSession: Found 0 decrypt sessions at 0
        TSS_Execute_valist: Step 6 calculate HMACs
        TSS_HmacSession_SetHMAC: Step 6 session 40000009
        TSS_Execute_valist: Step 7 set command authorizations
        TSS_Execute_valist: Step 8: process the command
        TSS_AuthExecute: Executing TPM2_Unseal
        TSS_Dev_Open: Opening /dev/tpm0
        TSS_Dev_SendCommand: TPM2_Unseal
         TSS_Dev_SendCommand length 27
         80 02 00 00 00 1b 00 00 01 5e 80 00 00 01 00 00
         00 09 40 00 00 09 00 00 00 00 00
        TSS_Dev_ReceiveCommand:
         TSS_Dev_ReceiveCommand length 10
         80 01 00 00 00 0a 00 00 01 2f
        TSS_Dev_ReceiveCommand: rc 0000012f
        TSS_Dev_Close: Closing /dev/tpm0
        unseal: failed, rc 0000012f
        TPM_RC_AUTH_UNAVAILABLE - authValue or authPolicy is not available for selected entity.
        
         
        • Ken Goldman

          Ken Goldman - 2017-05-25

          Trivial typo:
          ./unseal -ha 80000001 -se2 03000000 1 -of /dev/stdout
          should be -se0

          For unseal, the authorization session has to be the first session (-se0). There can be other sessions for response encryption or audit.

          In general, the authorization sessions have to be the first sessions, while encrypt, decrypt, and audit sessions come later. The authorization session can also be used for parameter encrypt, decrypt, and sometimes for audit.

           
  • oba

    oba - 2017-05-25

    That was not a typo. for some reason the se0 and se1 cause a different error:

    # ./load -hp 81000001 -ipr ./priv.key -ipu ./pub.key
    Handle 80000001
    # ./startauthsession -halg sha1 -se p
    Handle 03000000
    # ./policypcr -halg sha1 -ha 03000000 -bm 10000
    # ./unseal -ha 80000001 -se0 03000000 1 -of /dev/stdout
    TSS_AES_Decrypt: Error, illegal pad length
    unseal: failed, rc 000b0057
    TSS_RC_AES_DECRYPT_FAILURE - AES decryption failed
    # ./unseal -ha 80000001 -se1 03000000 1 -of /dev/stdout
    TSS_AES_Decrypt: Error, illegal pad length
    unseal: failed, rc 000b0057
    TSS_RC_AES_DECRYPT_FAILURE - AES decryption failed
    # ./unseal -ha 80000001 -se2 03000000 1 -of /dev/stdout
    unseal: failed, rc 0000012f
    TPM_RC_AUTH_UNAVAILABLE - authValue or authPolicy is not available for selected entity.
    
     
    • Ken Goldman

      Ken Goldman - 2017-05-25

      You didn't show the entire script this time. However, I can confirm that when I ran your original script with -se0, the unseal succeeded. -se1 got the same error as -se2. I can't explain why -se0 is trying to do parameter encryption for you.

      Suggestions:

      1. Forget -se2. Unseal needs an authorization session. -se0 is correct.
      2. Post the entire script. Use -se0
      3. Post the failing step with -v

      Could it be possible that you did some code modifications that you did not undo?

       
      • oba

        oba - 2017-05-26

        I made modifications to the 966 code, but for this test I used 1013, without any mods. I looked at the code, and 1013 does clear the flag correctly.
        Just a small note - to work with my tpm, I made some change to the Makefile. This should not have any effect for this problem. In case you want to review the makefile, I uploaded it here:
        makefile gist

        1. it is the same script as before. it creates a bl, then trys to unseal witout a session (should fail), then unseal with -se0 (should succed).
        2. here is the entire sequence:
        # ./pcrread -halg sha1 -ns -ha 16 > ./pcrs.txt
        # ./policymakerpcr -halg sha1 -bm 10000 -if ./pcrs.txt -of ./pcr-policy.txt
        # ./policymaker -halg sha1 -pr -if ./pcr-policy.txt -of ./pcr-policy.bin
         policy digest length 20
         85 33 11 83 19 03 12 f5 e8 3c 60 43 34 6f 9f 37
         21 04 76 8e
        # ./create -hp 81000001 -nalg sha1 -uwa -bl -kt p -kt f -pol ./pcr-policy.bin -if ./sealed_key.bin -opr ./priv.key -opu ./pub.key
        
        # ./load -hp 81000001 -ipr ./priv.key -ipu ./pub.key
        Handle 80000001
        # ./unseal -ha 80000001 -of /dev/stdout
        unseal: failed, rc 0000012f
        TPM_RC_AUTH_UNAVAILABLE - authValue or authPolicy is not available for selected entity.
        # ./flushcontext -ha 80000001 >/dev/null 2>&1
        
        # ./load -hp 81000001 -ipr ./priv.key -ipu ./pub.key
        Handle 80000001
        # ./startauthsession -halg sha1 -se p
        Handle 03000000
        # ./policypcr -halg sha1 -ha 03000000 -bm 10000
        # ./unseal -ha 80000001 -se0 03000000 1 -of /dev/stdout
        TSS_AES_Decrypt: Error, illegal pad length
        unseal: failed, rc 000b0057
        TSS_RC_AES_DECRYPT_FAILURE - AES decryption failed
        # ./flushcontext -ha 80000001 >/dev/null 2>&1
        # ./flushcontext -ha 03000000 >/dev/null 2>&1
        

        and the verbose output from the failed step:

        ./unseal -v -ha 80000001 -se0 03000000 1 -of /dev/stdout
        TSS_Execute: Command 0000015e marshal
        TSS_Execute_valist: Step 1: initialization
        TSS_Execute_valist: Step 2: authorization 0
        TSS_Execute_valist: session 0 handle 03000000
        TSS_Name_GetAllNames: commandHandleCount 1
        TSS_Name_GetAllNames: commandHandle 0 80000001
        TSS_Name_GetName: Handle 80000001
        TSS_Name_Load: File ./h80000001.bin
         TSS_Name_GetName:  length 22
         00 04 89 8b 41 c0 a3 a5 b3 91 93 c5 ae 98 f8 13
         e3 8b 79 a8 7f 46
        TSS_HmacSession_LoadSession: handle 03000000
        TSS_AES_Decrypt: Error, illegal pad length
        unseal: failed, rc 000b0057
        TSS_RC_AES_DECRYPT_FAILURE - AES decryption failed
        
         
        • Ken Goldman

          Ken Goldman - 2017-05-26

          I think this is an easy one. It's failing to load the (encrypted) session state.

          Did you do the steps in the manual Application Notes section 4.9. Encrypted Session State?

          Earlier, it says:

          See 4.9 Encrypted Session State for the special case of using the command line utilities. That section is not applicable when using the TSS library in programs.

          I'll change the section name to "Command Line Utilities" so hopefully it will be easier to notice.

           
  • oba

    oba - 2017-05-26

    It looks be working after I compiled using the -DTPM_ENCRYPT_SESSIONS_DEFAULT="\"0\"" in the makefile. I will do more testing and report.
    Thanks very much!

     
  • oba

    oba - 2017-06-01

    Tests are now done. All is as it should be. Thanks for the Help!

     

Log in to post a comment.