-
Notifications
You must be signed in to change notification settings - Fork 4
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
TPM2: ECC Support (won't merge here) #14
Conversation
This will catch linker visibility issues with shared builds
When building a specific target (e.g. 'tests'), the job dependency pointed to 'libbotan-3.so.6'. This target will explicitly build just 'libbotan-3.so.6' but fail to set up the required symlinks 'libbotan-3.so' and '.so.6.6.0'. As a result, the linker command with `-lbotan-3` will fail to find the shared object.
…bility Fix TLS::Context Visibility
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.
@atreiber94 looks really good to me. A noted a few things and nits below.
This code point falls into the 'private code point' region (RFC 8446 4.2.3) and was used by pq.cloudflareresearch.com for hybrid key exchange using X25519+KyberR3-512.
Deprecate 0xFE30 X25519/Kyber512 code point
Response files are a means to work around the limited command line length particularly on Windows. Instead of listing all to-be-linked object files on the command line, ninja will write them into a "response file" and address that in the command using the @something.txt syntax.
return { | ||
.signature_scheme = | ||
TPMT_SIG_SCHEME{ | ||
.scheme = TPM2_ALG_ECDSA, // Only support ECDSA |
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.
We might have to explicitly support TPM2_ALG_SM2
here, when we're dealing with a SM2 keys.
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.
True, actually supporting SM2 still requires some changes but I'd say the scope here is only ECDSA
c354200
to
18a9a16
Compare
0198e61
to
51fd5dd
Compare
13ba56d includes now the EC(DH) Crypto Backend. In this case we require an RNG on our part as Alice and should check what RNG we should use. |
return thunk([&] { | ||
BOTAN_UNUSED(userdata); | ||
BOTAN_ASSERT_NONNULL(key); | ||
BOTAN_ASSERT_NOMSG(key->publicArea.type == TPM2_ALG_ECC); |
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.
Not sure, but I believe this could also be TPM2_ALG_SM2
if we deal with an SM2 key... We should figure out a way to test this.
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.
Actually, type = TPM2_ALG_ECC
for all SM2/ECDSA/ECDH keys. scheme
will be different if the TPM key is restricted to a certain scheme like SM2/ECDSA/ECDH.
Starting a session with an explicit ECDH key works since the decrypt
flag can be set for this scheme. However, if we restrict the scheme to SM2 or ECDSA, tpm2-tools
does not allow to set the decrypt
flag since these are signature schemes.
=> The assert is fine, however we cannot test the backend with SM2 since we currently require our sessions to require the decrypt
key object attribute. We could have a look at that.
I removed this assert because it's already made when loading the key as a Botan::TPM2::EC_PublicKey
.
// Write public ephemeral affine coordinates to TPMS_ECC_POINT (Q) | ||
if(bn_x.bytes() != curve_order_byte_size || bn_y.bytes() != curve_order_byte_size) { | ||
// TODO: Is actually correct to check bytes() > curve_order_byte_size? | ||
return TSS2_ESYS_RC_GENERAL_FAILURE; | ||
} |
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.
As far as I remember, BigInt::bytes()
does not take zero-bytes into account. So if the coordinate has a zero byte by chance, <=
might actually be better here, as you probably imply in the TODO.
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 check is actually performed in BigInt::serialize(curve_order_byte_size)
so I removed it
const auto tpm_pub_inputs = Botan::TPM2::ecc_pubkey_from_tss2_public(key); | ||
const auto tpm_sw_pubkey = Botan::ECDH_PublicKey(tpm_pub_inputs.first, tpm_pub_inputs.second); |
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.
Somewhat nitty, but would safe a copy:
const auto tpm_sw_pubkey = [&] {
auto tpm_pub_inputs = Botan::TPM2::ecc_pubkey_from_tss2_public(key);
return Botan::ECDH_PublicKey(std::move(tpm_pub_inputs.first), std::move(tpm_pub_inputs.second));
}();
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.
clang
gives a hiccup-move-const-arg
for this because ECDH_PublicKey
takes const refs as inputs
BOTAN_ASSERT_NONNULL(key); | ||
BOTAN_ASSERT_NOMSG(key->publicArea.type == TPM2_ALG_ECC); | ||
|
||
const auto curve_name = Botan::TPM2::curve_id_tss2_to_botan(key->publicArea.parameters.eccDetail.curveID); |
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.
Perhaps it is worth considering to let curve_id_tss2_to_botan()
perform the transformation into an EC_Group
as well. I believe in the ECC code we also just transform the curve name into an EC_Group
right away.
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.
We can actually get the EC_Group
if we load the TPM EC PK first - exactly the same operation is performed there. Then, there's no redundant transformation code.
(Additionally, that way all methods in tpm2_algo_mappings.h
consistently remain mappings between algo strings/ids which makes me slightly happier than introducing methods that create instances of the algos).
const auto curve_order_byte_size = | ||
Botan::TPM2::curve_id_order_byte_size(key->publicArea.parameters.eccDetail.curveID); |
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.
... If curve_id_tss2_to_botan()
were to return an EC_Group
, this could then just take domain.get_p_bytes()
and we don't even need this extra mapping.
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.
With loading the TPM PK first, we can just use get_p_bytes()
of the TPM PK's domain (see #14 (comment)).
On a more general note (regarding RSA and ECC support in the crypto backend): I think we should consider disentangling the availability of the As far as I could see, we just need the What do you think? |
I agree that we should disentangle That way, all kinds of build configurations work, e.g., you could do EC key exchange in the crypto backend (if However, I'm not sure someone would ever want to do this: If you want to establish an authenticated session with an RSA resp. ECC key, then you need Still, I like the suggested disentanglement because it provides a much clearer distinction on dependencies (the crypto backends only require the Botan RSA/EC components and the TPM2 RSA/EC components separately provide RSA/EC functionalities based on TPM keys). I made sure that the tests works for the different kinds of minimized builds but the coverage is not complete because sometimes the SRK is loaded, which is RSA in our case. In a minimized build, one also needs to ensure modules necessary for the backend are present: |
The minimalist's answer would be: only the base modules whose headers are included directly (e.g. Side note: It would perhaps be nice to have a list of "recommended module dependencies" to provide a reasonable default that is only pulled in as dependencies when configuring |
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.
A few more suggestions.
…iles_for_link_commands Use @response_files.txt for linking in Ninja
Allow using `secure_allocator` for enum types, like `std::byte`
…xample Example fix: Use more secure KEM combination in example
…o-string Reorder/rephrase output from X509_Certificate::to_string
…ariants Deprecate various aliases for the public key padding code
…port Feature: TPM2 Support
Thanks! Applied the suggestions. Regarding the modules: Let's go with the minimalist view and only require the algos/modules that are "hard-coded" in the spec. That's actually what we already had - if a session with a specific algo/mode then the user needs a build supporting the corresponding module. |
Update Fuzzer documentation and Configuration
To add ECDH support, different TPM2-TSS methods need to be incorporated into Key Agreement PK operations. The class hierarchy of Botan's EC keys currently makes this hard since a TPM2 EC key may not be restricted to just ECDH or ECDSA.
e587545
to
44692fb
Compare
This includes disentangling the TPM2 Crypto Backend from the availability of the TPM2 RSA Adapter module. Instead, it now only depends on the software RSA/EC implementation of Botan.
49afb70
to
8cc8c3d
Compare
8cc8c3d
to
3ac8985
Compare
ECC implementation and internal review done. @atreiber94 will open a PR in randombit/botan. Closing.... |
This is just for self-review. The branch will be squashed and incorporated into randombit#4337 later.