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

TPM2: ECC Support (won't merge here) #14

Closed
wants to merge 28 commits into from

Conversation

reneme
Copy link
Collaborator

@reneme reneme commented Oct 1, 2024

This is just for self-review. The branch will be squashed and incorporated into randombit#4337 later.

Logix64 and others added 8 commits August 2, 2024 22:33
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.
Copy link
Collaborator Author

@reneme reneme left a 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.

src/lib/prov/tpm2/tpm2_algo_mappings.h Outdated Show resolved Hide resolved
src/lib/prov/tpm2/tpm2_algo_mappings.h Outdated Show resolved Hide resolved
src/lib/prov/tpm2/tpm2_algo_mappings.h Outdated Show resolved Hide resolved
src/lib/prov/tpm2/tpm2_ecc/info.txt Outdated Show resolved Hide resolved
src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.cpp Outdated Show resolved Hide resolved
src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.cpp Outdated Show resolved Hide resolved
src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.h Outdated Show resolved Hide resolved
src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.cpp Outdated Show resolved Hide resolved
src/scripts/ci/start_tpm2_simulator.sh Outdated Show resolved Hide resolved
src/scripts/ci/start_tpm2_simulator.sh Outdated Show resolved Hide resolved
reneme and others added 3 commits October 1, 2024 16:55
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
Copy link
Collaborator Author

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.

Copy link
Collaborator

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

@reneme reneme force-pushed the feature/tpm2_support branch 2 times, most recently from 0198e61 to 51fd5dd Compare October 2, 2024 13:48
@atreiber94
Copy link
Collaborator

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);
Copy link
Collaborator Author

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.

Copy link
Collaborator

@atreiber94 atreiber94 Oct 4, 2024

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-toolsdoes 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.

Comment on lines 603 to 607
// 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;
}
Copy link
Collaborator Author

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.

Copy link
Collaborator

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

Comment on lines 614 to 615
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);
Copy link
Collaborator Author

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));
}();

Copy link
Collaborator

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);
Copy link
Collaborator Author

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.

Copy link
Collaborator

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).

Comment on lines 583 to 584
const auto curve_order_byte_size =
Botan::TPM2::curve_id_order_byte_size(key->publicArea.parameters.eccDetail.curveID);
Copy link
Collaborator Author

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.

Copy link
Collaborator

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)).

@reneme
Copy link
Collaborator Author

reneme commented Oct 3, 2024

On a more general note (regarding RSA and ECC support in the crypto backend): I think we should consider disentangling the availability of the tpm2_rsa and tpm2_ecc modules from support for the respective key exchanges in the crypto backend. I.e. a build configuration with --enable-modules=tpm2_crypto_backend,rsa,ecdh --disable-modules=tpm2_rsa,tpm2_ecc should probably still be able to do RSA and ECDH exchanges.

As far as I could see, we just need the public_key_from_tpm2_public() methods from the respective adapters. We could put those more centrally and guard them with #if defined(BOTAN_HAS_RSA) and #if defined(BOTAN_HAS_ECDSA) || defined(BOTAN_HAS_ECDH).

What do you think?

@atreiber94
Copy link
Collaborator

On a more general note (regarding RSA and ECC support in the crypto backend): I think we should consider disentangling the availability of the tpm2_rsa and tpm2_ecc modules from support for the respective key exchanges in the crypto backend. I.e. a build configuration with --enable-modules=tpm2_crypto_backend,rsa,ecdh --disable-modules=tpm2_rsa,tpm2_ecc should probably still be able to do RSA and ECDH exchanges.

As far as I could see, we just need the public_key_from_tpm2_public() methods from the respective adapters. We could put those more centrally and guard them with #if defined(BOTAN_HAS_RSA) and #if defined(BOTAN_HAS_ECDSA) || defined(BOTAN_HAS_ECDH).

What do you think?

I agree that we should disentangle TPM2_{ECC/RSA}_ADAPTER and RSA/ECC and implemented the suggestion in 46f063c.

That way, all kinds of build configurations work, e.g., you could do EC key exchange in the crypto backend (if BOTAN_HAS_ECDH; otherwise it fails) without having TPM2_ECC_ADAPTER.

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 tpm2_rsa resp. tpm2_ecc to load the key as input to the authenticated session. So to me it seems that having the tpm2 adapter is functionally necessary to use the corresponding backend key exchange and therefore I don't see a functional benefit. (One could further disentangle this for just using the keys as parents / for sessions vs. sign/encrypt operations but this would become very complicated. Or do you think we should strive for this kind of configurability?)

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: aes,cfb,sha1,sha2_64,aead,hmac ,rsa,eme_pkcs1,eme_oaep to enable RSA key exchange, and ecdh for EC key exchange. We should discuss which modes should be required by the crypto backend module and which should not be a requirement. I'd favor requiring everything except the key exchange modules because these may not be necessary when using crypto callbacks.

@reneme
Copy link
Collaborator Author

reneme commented Oct 7, 2024

We should discuss which modes should be required by the crypto backend module and which should not be a requirement.

The minimalist's answer would be: only the base modules whose headers are included directly (e.g. hash,mac, ...) should be hard requirements. Then the user is in charge (and has maximum flexibility) which concrete algorithms should be available (e.g. sha1 yay/nay?). On the other hand this requires the user to "know" which algorithms are necessary and perhaps wade through several "not implemented" errors to find a working module set.

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 --with-recommendations --enable-modules=tpm2_rsa.

Copy link
Collaborator Author

@reneme reneme left a 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.

randombit and others added 8 commits October 7, 2024 06:11
…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
@atreiber94
Copy link
Collaborator

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.

randombit and others added 3 commits October 7, 2024 08:04
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.
@atreiber94 atreiber94 force-pushed the feature/tpm2_ecc branch 2 times, most recently from e587545 to 44692fb Compare October 7, 2024 14:24
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.
@reneme reneme force-pushed the feature/tpm2_ecc branch 2 times, most recently from 49afb70 to 8cc8c3d Compare October 7, 2024 15:24
@reneme
Copy link
Collaborator Author

reneme commented Oct 8, 2024

ECC implementation and internal review done. @atreiber94 will open a PR in randombit/botan. Closing....

@reneme reneme closed this Oct 8, 2024
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 this pull request may close these issues.

6 participants