-
Notifications
You must be signed in to change notification settings - Fork 381
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
[RFC] tools: add tpm2_policy tool for invoking libpolicy #2831
base: master
Are you sure you want to change the base?
[RFC] tools: add tpm2_policy tool for invoking libpolicy #2831
Conversation
Wondering if this can be part of tpm2_createpolicy tool. There too we take an input to specify policy type. Except we rely on the TPM trial session to calculate the policy -- So that needs to change and also need to add the json parser to iterate through the policies. What were the thoughts on executing policies? Why do we need this? I think we should limit the extent of this tool to calculate policies. It can quickly get complicated when the policy engine needs to interleave to record parameters set by other commands/ tools. |
The My preference would be something like this:
A way to specify files from which to get passwords for any passwords that need prompting might be useful. I would use a JSON file for that too, or I would provide an option to set the passwords right in the policy file (which can be done with jq or whatever). I recommend leaving a policy creation CLI for last. Alternation (
I believe you'll find that for commands like As for FAPI, I think the context setup function takes a URI string value that currently has to be This is why I like the |
I want to make this very clear: this is not using FAPI. What it's doing is ripping out the policy engine part of FAPI to make it a consumable library. You pass it the policy file, and eventually through callbacks into the tool for things like passwords will happen. So I think you could program it with expect or we could come up with another interface. This will handle all the complexities of policies. Ill have to read through the rest of comments and think about this more. |
Got it. Thanks. |
BTW, I do like the idea of policies expressible in JSON, but it's not a very human readable language. The language I've been play-thinking about looks like this:
The idea is that each policy command is almost like a shell command, but with the ability to reference various data, some defined inline, some obtained by prompting, some obtained by running some external command. Conjunction would be done using I've got an implementation of a significantly simpler subset, written in bash. Bash is not a good language for this. But bash + jq is a decent combination for implementing an evaluator for policies expressed in JSON. |
FWIW: osresearch/safeboot#144 This is an exploration of what I'd like in a policy language. Yes, it's a prototype written in Bash (because it's in Safeboot, which is Bash). Things I definitely want:
I don't need looping. Conditionals are mostly interesting for reasons to do with Safeboot.dev PR #144 isn't ready, and may well never finish, but it has much of the above and could easily be extended to do what it doesn't already. |
UPDATE: Working: Initial test working: If you get the tpm2_policy tool from the tss pr, this should work: tpm2 policy /path/to/tpm2-tss/test/data/fapi/policy/pol_pcr16_0.json Their are still many todo's to go through, but let's figure out the interface into the library and go from there. Create a tpm2_policy tool that can read the FAPI JSON style policies and: 1. Instantiate them -> This process fills in anything missing in the template. TODO: How does this get handled, do we need to tweak any of the callbacks? 2. Calculate them -> This process produces a list of hashes... TODO: Why? Is this a list of all the subordinate policies or can the json file have N policies where N > 1? 3. Execute them -> Execute the policy on a session. TODO: Who is supposed to start the policy session as it seems to be 0? Their are a lot of TODO items in this code. I'm looking for how we want to use this, different tools, like tpm2_policyinit tpm2_policycalc and tpm2_policyexec? Or an all in-one tool. Currently note that ONLY the Execute needs an ESYS context, but instantiate should be filling stuff in so it likely needs a context or the callbacks handled? Signed-off-by: William Roberts <[email protected]>
1c4a201
to
7de60c9
Compare
…y ctx Signed-off-by: William Roberts <[email protected]>
Signed-off-by: William Roberts <[email protected]>
Signed-off-by: William Roberts <[email protected]>
Signed-off-by: William Roberts <[email protected]>
Signed-off-by: William Roberts <[email protected]>
An epiphany I had recently is that for most TPM use cases there is one or maybe two commands that one wishes to execute with some saved key(s) that might have policies associated with them that might use other keys that have policies associated with them, and so on. It's not just TPM 2.0 EA policy that needs a language, but that even a sequence of desired commands, each with various parameters, needs a language. Given such a language it should be possible to have a trivial API/CLI to execute the desired commands and all the possibly many commands impliedly necessary. The only things the user should have to furnish are:
Then using TPMs could be very very easy. One thing I think we need to never lose track of is the need to as much as possible always use a |
That sounds suspiciously like a programming language. The proposal would be some language to instruct which commands the host processor should send to the TPM.
Yes a meta language could be useful, but I don't see it making the TPM 2.0 easier to use. the CLI tools currently imply and figure out a lot of things based on what the user passes for options. The Python API is simpler compared to the C API as
Bind key can be just as valid and since it's started off of a secret theirs no need to verify it. The secret is never sent over the wire as well.
Their was discussions on making a TCTI that modifies the commands being set to include session encryption and protections. This was users just get support without needing to worry about anything. FAPI does this as well for users. |
There's no need for conditionals, loops, subroutines, lambdas, or variables, so it wouldn't be a programming language. But it would be a language, yes, or a schema for JSON (or XML, or YAML, or...). In JSON imagine something like: {
"command":"TPM2_Sign",
"keypriv":"...",
"keypub":"...",
"keypolicy":{"key policy description here":"..."}
} or maybe {
"command":"TPM2_Sign",
"key":"/path/to/key/description.json"
} with the key descriptor having the key private/public/context parts and the policy descriptor. If the key has an The policy descriptor itself might reference other keys. For example, a I believe a schema general enough for this is feasible. |
That's a whole other topic for discussion. There is an enormous impedance mismatch between PKCS#11 and TPM 2.0 called policies. The only way to use a key with a complex policy through PKCS#11 would be if the only thing to prompt for is a password so that that can be the PKCS#11 PIN, and any other interactions would have to be out of band (like modal dialogs in a GUI display). Also, the tpm2-pkcs11 provider only supports keys created via it, and that makes it very difficult to do things like: create keys with some duplication policy, or import duplicated or external keys. |
It's very dangerous to use a |
How could that possibly work if the app uses a |
Yes, the CLI tools are quite smart, but once you add a policy language (which is what this issue is about), you'll need to make sure that you have enough metadata about keys referenced by policies that the policy executor can be as smart as the utilities. |
It would be very easy to build something with pytss |
I mean yes, but that's just PKCS11 and it has a provision that allows this in the spec. Some smartcards or readers have the pin pad or fingerprint readers, etc. It would all be out of band, but doable. Add a field for the key that contains the JSON policy and execute it, setting the callbacks to some out of band mechanism.
That's not true, you can link in other keys from tpm2-tools or openssl engine/provider. You can even import raw keys. As long as the auth for the key is a simple password, it should just work. |
If one it relying on bindKey, the auth shouldn't be trivial. That's on the user, so while it can be dangerous, theirs a lot of dangers in crypto. |
Ah excellent. Sorry I got that wrong! |
FAPI tss2 tools bind the policy to the key, while the tpm2-tools don't with the policy engine one could provide it as a separate argument and it would be on the caller to keep those things coupled unfortunately. However, if we add support for the tss2 pem format, I think we did IIRC, we could make a version that contains the JSON policy as well to couple things more easily. |
I would recommend building something with pytss, and then make tpm2py-tools package [1]. I would love to re-write a set of command line tools in Python, while they can't be used everywhere, they'd be much simpler and way simpler to add features than the C tools. Or even Rust, now where rust is, i'd have no qualms using that language.
|
One really has to always use HMAC sessions with There's a chicken-egg situation, of course, in that the first time one learns the public area of a EDIT: Imagine using a fast networked TPM for doing things like password validation in high-traffic sites. Clearly one would not use a slow, local dTPM for such things -- too slow, that! But if you're using a TPM over a network... OK, one could use TLS, and one probably should, but There have been highly publicized active, local, on-the-bus attack techniques to compromise servers. It is essential, for example, that BMCs and BIOSes use |
My colleagues and I have completely soured on Python for these things primarily on account of the bloat it leads to. For example, Safeboot is mostly bash-coded using tpm2-tools utilities so as to make it very small. Nowadays Rust and Go would be much better choices. @osresearch is particularly interested in keeping boot images small enough to be able to realistically use for PXE booting. |
Yeah if your environment is early boot, Python is usually out and even Go isn't optimal for size constraints. Rust would be a good choice. |
As long as the boot image can be <10MB it's probably fine. Python easily blows right through that. |
Sure, bindKey only means you must have strong entropy as that is the only protection you have. But in some environments you may not have or can afford the time costs of asymmetric crypto.
TOFU is generally the model a lot of folks gravitate towards, myself included. I just recently added this into systemd, waiting on the PR to get merged: systemd/systemd#26185
With the cmd TCTI it's easy, you can get an SSH tunnel to the endpoint and then, I always suggest using sessions so you get those protections within the endpoint. Ie you don't need to trust your end point, just the TPM. The endpoint could only dos you.
Yep, totally agree. I am in favor of the tpmKey and salted sessions when possible. I also prefer sessions over things like SPDM, because their are parts of designs where you may be concerned about introspection/alteration not on the bus itself. Consider an SGX/TDX design where bytes leaving the "enclave" are of concern, SPDM doesn't help you there. |
Right, and for that one should first use a session with a
Some platforms have platform certificates, but there's no standard way to retrieve them :( Still, if provided a platform certificate, it'd be good to use it for bootstrapping trust!
|
Yes, that's what FAPI does. Unfortunately in early boot requirements it's difficult to validate the whole cert chain.
Yeah, I think that's it. It's essentially bus level protection. |
If the app enables sessions you leave it be, else you modify the command and response buffers. |
But the app might be using an HMAC session in order to satisfy an authorization requirement that it prove knowledge of an It's important to separate session keying for over-the-bus (or over-the-network) security from proving knowledge of weak passwords. |
Yes, it's a best effort. We won't be able to do it for every invocation based on the callers use of sessions. Our idea was to run in pedantic mode and return an error if we can't, so users know where things could be weak, then allow an ignore mode to bypass it. The goal would be able to take a.legacy app that makes no use of sessions other than the implicitly started password session and enable session protections for them. |
A worthy goal, but if you also provide the library that the apps use why not just do it all in the library? I fear that trying to add security in the TCTI layer is going to make people unjustifiably feel good about weak applications. This also adds a fair bit of complexity at that layer. |
We did, it's called FAPI
It would be a pluggable tcti like all the others, so it would just layer in, use it or don't. Yes, we don't want folks to get a false sense of security, that's why we would run in pedantic mode by default. |
Create a tpm2_policy tool that can read the FAPI JSON style policies
and:
Instantiate them -> This process fills in anything missing in the
template. TODO: How does this get handled, do we need to tweak any
of the callbacks?
Calculate them -> This process produces a list of hashes... TODO:
Why? Is this a list of all the subordinate policies or can the json file
have N policies where N > 1?
Execute them -> Execute the policy on a session. TODO: Who is
supposed to start the policy session as it seems to be 0?
Their are a lot of TODO items in this code. I'm looking for how we want
to use this, different tools, like tpm2_policyinit tpm2_policycalc and
tpm2_policyexec? Or an all in-one tool. Currently note that ONLY the
Execute needs an ESYS context, but instantiate should be filling stuff
in so it likely needs a context or the callbacks handled?
Signed-off-by: William Roberts [email protected]