Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActivateCredential error on non-6.1.1 versions (Esys Finish ErrorCode (0x00000101)) #285

Closed
lkatalin opened this issue Nov 4, 2021 · 12 comments · Fixed by #292
Closed
Assignees

Comments

@lkatalin
Copy link

lkatalin commented Nov 4, 2021

Mentioned in #277 while trying to test draft PR #281.
First noticed last month on Sept 29 and documented here.

System info: Running this on a Fedora 34 VM using swtpm with chardev.

I am getting this error while running code that uses the tss-esapi as a dependency. This error occurs when using tss-esapi = "7.0.0-alpha.1" in our Cargo.toml or when trying to pin to any commit from GitHub, ex. tss-esapi = { git = "https://github.com/parallaxsecond/rust-tss-esapi.git", commit = "3e42b49f772f296150d0421998af1e8d55bb2478"} (even pinning to commits older than Sept. 29). The error does not occur when using tss-esapi = "6.1.1".

WARNING:esys:src/tss2-esys/api/Esys_ActivateCredential.c:321:Esys_ActivateCredential_Finish()
 Received TPM Error 
ERROR:esys:src/tss2-esys/api/Esys_ActivateCredential.c:105:Esys_ActivateCredential() Esys 
Finish ErrorCode (0x00000101) 
Error: Tpm { err: Tss2Error(FormatZero(FormatZeroResponseCode { .0: 257, error_number: 1, 
format_selector: false, version: true, tcg_vendor_indicator: false, severity: false })), kind: 
Some(Failure), message: "commands not being accepted because of a TPM failure. NOTE:
 This may be returned by TPM2_GetTestResult() as the testResultparameter" }

I notice that when switching between tss-esapi = "6.1.1" as a dependency vs any other version or commit, some minor code changes are necessary in Keylime due to some reorganization and the new Public type in the tss-esapi. Otherwise these compilation errors result:

error[E0432]: unresolved imports `tss_esapi::interface_types::algorithm::SignatureScheme`, `tss_esapi::utils::Signature`
 --> src/tpm.rs:36:60
  |
36 |         algorithm::{AsymmetricAlgorithm, HashingAlgorithm, SignatureScheme},
  |                                                            ^^^^^^^^^^^^^^^ no `SignatureScheme` in `interface_types::algorithm`
...
50 |     utils::{PcrData, Signature},
  |                      ^^^^^^^^^ no `Signature` in `utils`

error[E0308]: mismatched types
  --> src/tpm.rs:113:34
   |
113 |     let tpm_pub_vec = pub_to_vec(tpm_pub);
   |                                  ^^^^^^^ expected struct `TPM2B_PUBLIC`, found enum `tss_esapi::structures::Public`

error[E0308]: mismatched types
  --> src/tpm.rs:247:35
   |
247 |     let tpm2_pub_vec = pub_to_vec(ak_tpm2b_pub);
   |                                   ^^^^^^^^^^^^ expected struct `TPM2B_PUBLIC`, found enum `tss_esapi::structures::Public`


Once I resolve the compilation errors and I'm able to build using a tss-esapi version other than 6.1.1, I run the Keylime agent and get the ActivateCredential error.

It is entirely possible that the error stems from my changes in Keylime not using the updated tss-esapi properly and I am still trying to investigate that. Unfortunately I'm under some time constraints so I'm not sure how far I can dive into it immediately. @ueno is pretty knowledgeable about the Rust Keylime codebase as well and may have ideas.

@ionut-arm Regarding your question about the self-test, did you mean tpm2_selftest? This seems to succeed and values from tpm2_pcrread look normal also:

[root@fedora ~]# tpm2_selftest
[root@fedora ~]# echo $?
0
@ionut-arm ionut-arm self-assigned this Nov 8, 2021
@ionut-arm
Copy link
Member

I'll try this out locally, hopefully today, to see if I can make sense of what's happening

@ionut-arm
Copy link
Member

ionut-arm commented Nov 8, 2021

Are there some instructions somewhere on what to set up to get to that error? I've tried simply running the Keylime agent binary without any extra parameters, but got

Error: Reqwest(reqwest::Error { kind: Request, url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(8890), path: "/v1.0/agents/d432fbb3-d2f1-4a97-9ef7-75bd81c00000", query: None, fragment: None }, source: hyper::Error(Connect, ConnectError("tcp connect error", Os { code: 111, kind: ConnectionRefused, message: "Connection refused" })) })

EDIT: I also ran the tests in that repo, but they seemed to go well.

@lkatalin
Copy link
Author

lkatalin commented Nov 8, 2021

Ah, yes, I think that makes sense as it would be trying to talk to the other Keylime components, which are housed in a separate repo. Apologies as we're still working to make this convenient to spin up. I have some instructions that I can try to make into a bash script here shortly.

@lkatalin
Copy link
Author

lkatalin commented Nov 8, 2021

Alternatively, it may be more straightforward for me to try and make a "minimum viable" POC for this error, though this would take longer.

@lkatalin
Copy link
Author

lkatalin commented Nov 8, 2021

Ah, yes, I think that makes sense as it would be trying to talk to the other Keylime components, which are housed in a separate repo. Apologies as we're still working to make this convenient to spin up. I have some instructions that I can try to make into a bash script here shortly.

The very short fix is to install and run the missing components: the Keylime server-side (Keylime verifier, Keylime registrar) as the agent will try to connect to these. This can be done by:

git clone https://github.com/keylime/keylime.git && cd keylime
./installer.sh

then run

keylime_verifier
keylime_registrar

while those are running, try running the Rust agent.

There is a lot that can go wrong here, so if that does not work easily I want to help create some easier example.

@lkatalin
Copy link
Author

lkatalin commented Nov 9, 2021

I made an attempt to reproduce the error with more minimal code here, which is based partially on our code and partially on the test_create_and_use_ak() test. But the example actually failed to reproduce it: it works with 6.1.1 and 7.0.0-alpha.1.

At least this gives a better starting point to see what's going wrong by comparing the minimal example to our actual code. I'll continue to investigate as time permits. Thanks for what you've done so far in checking this out.

@ionut-arm ionut-arm mentioned this issue Nov 15, 2021
16 tasks
@ionut-arm
Copy link
Member

Interesting find:

I was working on some other stuff related to ActivateCredential, also implementing some tests (PR: #284 ) and for one of them I check that the TPM rejects an ActivateCredential call where the data passed as credential_blob and secret is just random bytes ( https://github.com/parallaxsecond/rust-tss-esapi/pull/284/files#diff-f8ae95b2a1bf843aed32b3ce14e3bbd877626fee8f07a5f49a3e8e4cb41a4917R842 ). On Ubuntu (using the IBM software TPM) I get TPM_RC_VALUE, however in Fedora (using swtpm) it fails with a different code, TPM_RC_FAILURE:

2021-11-17T11:24:23.0630806Z ERROR:esys:src/tss2-esys/api/Esys_ActivateCredential.c:105:Esys_ActivateCredential() Esys Finish ErrorCode (0x00000101) 
2021-11-17T11:24:23.0634574Z [2021-11-17T11:24:23Z ERROR tss_esapi::context::tpm_commands::object_commands] Error when activating credential: commands not being accepted because of a TPM failure. NOTE: This may be returned by TPM2_GetTestResult() as the testResultparameter

This makes me believe swtpm isn't sending the right code there, so your issue might be similar.

@lkatalin
Copy link
Author

Interesting find:

I was working on some other stuff related to ActivateCredential, also implementing some tests (PR: #284 ) and for one of them I check that the TPM rejects an ActivateCredential call where the data passed as credential_blob and secret is just random bytes ( https://github.com/parallaxsecond/rust-tss-esapi/pull/284/files#diff-f8ae95b2a1bf843aed32b3ce14e3bbd877626fee8f07a5f49a3e8e4cb41a4917R842 ). On Ubuntu (using the IBM software TPM) I get TPM_RC_VALUE, however in Fedora (using swtpm) it fails with a different code, TPM_RC_FAILURE:

2021-11-17T11:24:23.0630806Z ERROR:esys:src/tss2-esys/api/Esys_ActivateCredential.c:105:Esys_ActivateCredential() Esys Finish ErrorCode (0x00000101) 
2021-11-17T11:24:23.0634574Z [2021-11-17T11:24:23Z ERROR tss_esapi::context::tpm_commands::object_commands] Error when activating credential: commands not being accepted because of a TPM failure. NOTE: This may be returned by TPM2_GetTestResult() as the testResultparameter

This makes me believe swtpm isn't sending the right code there, so your issue might be similar.

@ionut-arm That is very interesting, this is the same error. Any idea if the way 7.0.0-alpha interacts with the swtpm changed compared to 6.1.1? I tried to look for this but have not found anything. Also, am I understanding correctly that TPM_RC_VALUE is the result you expect on that test?

@ionut-arm
Copy link
Member

Also, am I understanding correctly that TPM_RC_VALUE is the result you expect on that test?

Yes. Looking at the most recent spec for the commands which includes the code for them, for TPM2_ActivateCredential, page 70, TPM_RC_FAILURE is not listed among the response codes that might be returned. When secret fails to decrypt properly under an RSA key (which is the case in my test at least), the result should be TPM_RC_VALUE.

However... on line 40 of the code which follows that table you can see it being returned. The weird thing is, at least looking at the libtpms implementation, CryptSecretDecrypt cannot return TPM_RC_KEY, yet it can return TPM_RC_FAILURE, which in turn would be returned as-is given this implementation of RcSafeAddToResult. However, digging further into CryptSecretDecrypt I fail to find a place where TPM_RC_FAILURE would actually be returned for an RSA decryption. This is somewhat frustrating 🙃

Any idea if the way 7.0.0-alpha interacts with the swtpm changed compared to 6.1.1?

My best guess, at least stemming from this theory that what's causing your error is a mangled secret being fed to ActivateCredential, I think the problem might be in the public exponent used to encrypt that secret. I had a suspicion about it being related to public exponents, but couldn't somehow link it to your issue. Let me run some tests and I'll update. One thing you could try that might help, if you can test with a local version of tss-esapi, try changing value from 2 ^ 16 + 1 to 0 here.

@lkatalin
Copy link
Author

lkatalin commented Nov 17, 2021

One thing you could try that might help, if you can test with a local version of tss-esapi, try changing value from 2 ^ 16 + 1 to 0 here.

Yes, let me give this a try.

@lkatalin
Copy link
Author

@ionut-arm Fascinating results: you are right, changing that one line to hold a value of 0 makes the error disappear!

@ionut-arm
Copy link
Member

yeah, ok, we really need to change that, I had some headaches because of it when making some changes for Parsec too... Will put up a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants