-
Notifications
You must be signed in to change notification settings - Fork 45
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
utils: add function to generate an EK #279
Conversation
Codecov Report
@@ Coverage Diff @@
## master #279 +/- ##
==========================================
+ Coverage 93.59% 93.61% +0.02%
==========================================
Files 15 17 +2
Lines 4665 5212 +547
Branches 592 750 +158
==========================================
+ Hits 4366 4879 +513
- Misses 218 239 +21
- Partials 81 94 +13
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the spec for the EK:
tpm2_pytss/utils.py
Outdated
@@ -226,3 +227,117 @@ def unwrap( | |||
) | |||
|
|||
return s | |||
|
|||
|
|||
def create_ek(ectx, ekalg=TPM2_ALG.ECC, session=ESYS_TR.NONE): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change this slightly to get_ek_template and be able to pass session1, session2, and session3 here so folks pass everything into the esys calls and then I would have the createprimary call be by the user. This way the session1, which is auth for the ENDORSEMENT hierarchy can be set by the caller to an HMAC session, audit session, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh and add type hints to the parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docstring with link to the generic spec landing page:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@idesai could you weigh in on this API design with your thoughts as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Something to consider... because it uses a TCG EK credential specific value for authorization policy and attributes get_tcg_ek_template might be a good name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kept only one session as the only usefulness I see of passing a session after removing create_primary is for audit and encrypt sessions.
As for the name, I prefer to keep it as close to tpm2_createek as reasonable, to keep it slightly familiar for tpm2-tools users, but I can go either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can have separate audit and encrypt sessions. I was trying to future proof the API a bit since session1,2,3 would just be the defaults and only if folks are interested in that control will they use them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'll change it to session1 and session2, but I'm worried about session3 as that wouldn't be passed to nv_read and would break expectations for session3
d16411f
to
5168cd5
Compare
tpm2_pytss/utils.py
Outdated
mtempl = b"" | ||
while left > 0: | ||
off = tpub.nvPublic.dataSize - left | ||
size = 0x300 if left > 0x300 else left |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this magic number from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that was the minimum allowed for TPM2_PT_NV_BUFFER_MAX, but when I checked again and it's apparently 512, not 768 for the PC client profile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This value should ideally be read from the capability structure
tpm2_pytss/utils.py
Outdated
while more: | ||
more, data = ectx.get_capability( | ||
TPM2_CAP.HANDLES, | ||
TPM2_HT.NV_INDEX << 24, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this one include the shift: TPM2_HC.HR_NV_INDEX
tpm2_pytss/utils.py
Outdated
nonce = nonce + bytes(data) | ||
left = left - len(data) | ||
|
||
if len(nonce) > 0 and template.publicArea.type == TPM2_ALG.RSA: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This padding is only done on RSA 2048 and ECC NIST P256 per the 2.2.1.6 "TPMT_PUBLIC Calculation"
Their are other keys possible, so I don't think we want to always do this AFAICT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code currently only supports RSA 2048 and NIST P256 keys (unless the TPM manufacturer has put a non-standard template in one of the NV template areas)
tpm2_pytss/utils.py
Outdated
session: (ESYS_TR): Optional session, for encrypt/decrypt and audit sessions, defaults to ESYS_TR.NONE | ||
|
||
Returns: | ||
The templase as a TPM2B_PUBLIC instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling, templase --> template
This pull request introduces 1 alert when merging c5ee5eb into 0f48299 - view on LGTM.com new alerts:
|
So the overall design is that it will take a callback to read the NV index and return the template. This way folks can use it with any type of TPM context (ESAPI or FAPI) and a userdata pointer. Since this is python, with closure, we don't really need to worry about passing user data just a callable. |
So would it be like something like?: def create_ek_template(ekalg, nv_read_cb):
defaults_here
nonce = nv_read_cb(nonce_index)
template = nv_read_cb(template_index)
do_rest_here |
Yes, but I forgot to mention ekalg is a string identifier that maps to one of the static templates or one of the NV indices. Let me see if I can figure out what those will be. I don't have them offhand. |
Here are the strings:
This is the callback signature: def nvread(index) So you could something like: class MyNVReader:
def __init__(ectx):
self.ectx = ectx
def __call__(self, nvindex):
return self.ectx.nvread(nvindex)
get_ek("EK-RSA2048", MyNVReader())
# or something like
ectx = ESAPI()
#.....
def my_nv_read(nvindex):
return ectx.nv_read(nvindex)
get_ek("EK-RSA2048", my_nv_read) |
If it has a nonce, it needs to call the nv reader cb for the templ and the nonce. The calling framework is responsible for handling merging those and unmarshalling everything into the final TPMT_PUBLIC. |
I'm not sure what they are going to be for the default static templates. It's not clear to me in the spec if the static templates are the the same as the ones in the NV Index. So these could be mapped to unique strings or based on if callback is None. See the templates in B.4.4 and later in: |
is it clear by the specification what should happen if the NV index isn't defined (low template/nonce) on the TPM? |
Whatever nvread failing for that condition would be. The framework would then use the static nonce. |
Also look at section "2.2.1.3" in that EK document. It lays out a table with what is and is not allowed, and things that are discouraged. |
Then the sections on LOW (2.2.1.4) and HIGH (2.2.1.5) layout more of what can be expected. Essentially for the LOW's their SHOULD be an NV index set, however if their isn't it's a default template. For the low range their MAY be a nonce to deal with. For the HIGH range, they're MAY be an NV index for the template, however if not it's the default template. |
This pull request introduces 1 alert when merging 6aaa50a into 7cd4cc0 - view on LGTM.com new alerts:
|
74ffa5f
to
7ec6d51
Compare
@williamcroberts, when you have time could you check if the code matches the the general idea? |
The callback function should check. We should probably have a specific case for this error to then go get the default template, all other errors propagate to the original caller. The framework function should never go to the TPM, only through the callback. |
This pull request introduces 1 alert when merging 41c57bc into f79d3be - view on LGTM.com new alerts:
|
794556e
to
edde6a3
Compare
This is the best I could come up with my understanding to the specification. |
tpm2_pytss/utils.py
Outdated
|
||
def __call__(self, index: Union[int, TPM2_RH]) -> bytes: | ||
if index not in self._indices: | ||
raise NoSuchIndex(index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the index was defined between the list population and now. Perhaps it's better to just try and read the NV index and look at the error code to see if it's not defined. Which also reduces the trips we need to make to the TPM. Which then, do we even need this exception class, we could just use TSS2 Exceptions that already exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I view the chance as low for this use case as new template/certificate areas shouldn't be created during runtime
The problem with letting the TPM throw an error is that it would break audit sessions (and possibly encrypted sessions) for the scenarios where create_ek_template looks for an index but shouldn't fail if there isn't one
We could have a constant of an TSS2_Exception instead, but something explicit and clear is needed, for example someone writes their own callback using FAPI instead which wouldn't throw the same exception
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I view the chance as low for this use case as new template/certificate areas shouldn't be created during runtime
It's an unlikely race condition, but it's a TOCTOU issue.
The problem with letting the TPM throw an error is that it would break audit sessions (and possibly encrypted sessions) for
I'm not following, what exactly breaks? Does a failing command invalidate the session?
the scenarios where create_ek_template looks for an index but shouldn't fail if there isn't one We could have a constant of an TSS2_Exception instead, but something explicit and clear is needed, for example someone writes their own callback using FAPI instead which wouldn't throw the same exception
True, or if they use their own custom TSS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I view the chance as low for this use case as new template/certificate areas shouldn't be created during runtime
It's an unlikely race condition, but it's a TOCTOU issue.
The problem with letting the TPM throw an error is that it would break audit sessions (and possibly encrypted sessions) for
I'm not following, what exactly breaks? Does a failing command invalidate the session?
I reread the specification and I was wrong, so that can be dropped, I'll rework the code to not check the index before trying to read and raise a NoSuchIndex exception if the TSS2_Exception matches the correct error, otherwise reraise the TSS2_Exception
tpm2_pytss/utils.py
Outdated
return f"NV index 0x{index:08x} does not exist" | ||
|
||
|
||
class nv_read_ek: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't classes be capitalized?
This pull request introduces 1 alert when merging e321a6d into 584dd8b - view on LGTM.com new alerts:
|
Signed-off-by: Erik Larsson <who+github@cnackers.org>
I have tested the standard ECC and RSA templates towards a real TPM, but the the NV nonce/template is written according to the specification/tpm2-tools so I'm not 100% they work in real life.
Draft until I add types to arguments and documentation.
Related to #203