On 16/04/2020 20:49, Torsten Schuetze wrote:
On 15/04/2020 22:00, Gilles Peskine wrote:
As a general design principle, context types in Mbed TLS 3 will be opaque. This will let us, for example, redesign mbedtls_aes_context and mbedtls_cipher_context.
Hmm, this just means that you access it with dedicated functions only and that the internals can change at any time. Empirical knowledge shows that some people will nevertheless use the internal structure
Sure, but if you rely on the internal structure, the burden is on you to rewrite your code every time a new version comes out.
In this context, I was only talking about ECDSA signature verification. And this is, of course, deterministic. Specifically, I wanted to use the CAVP test from SigVer.rsp in 186-3ecdsatestvectors.zip. My strategy with NIST CAVP tests is, that I take the simple response files (text) and built just with search and replace a structure that can be compiled within a program. So, no file system access, no perl or python (at least not at the target system). In the ECDSA case, this looks like
[snip]
And for this, I couldn't find any example with mbedTLS. It isn't that difficult, but as always with ECC you have several interfaces to consider.
[snip]
Most crypto standards have KATs in this raw form. With the structure above (it even works for very long strings, at least with gcc), you just copy and paste. And the code compiles. The mbedTLS unit test examples in tests/suites/test_suite_ecdsa.data or test_suite_ecdsa.function are similar, but not self explaining and (data) cannot be compiled on their own.
In this way, I implemented all relevant CAVP tests for me. And they fit onto the target (Cortex M4 with 384 kB RAM). On a smaller M3 smart card processor, you often have problems with code size and/or RAM.
Ah, I see. There is an example in programs/pkey/ecdsa.c, but it uses the ASN.1 representation of signatures. For an interface where you can easily plug in values, the test suites are how we do it, and there are a few algorithms where at least some of the test data is from a regexp-replace from a CAVP response file. Indeed the test code is not always self-explaining. I think the biggest problem would actually be to find the function that does what you want: it isn't easy to tell which functions implement simple calculations and which functions exercise corner cases. For the PSA crypto tests, we split the two for hash functions, but even there the test code isn't documented.
- While debugging mbedtls_ecdsa_verify() in my example program, I found out, that the ECDSA, ECC and MPI operations are very, let's say, nested. So, IMHO there is a lot of function call overhead and special cases. It would be interesting to see what's the performance impact of a clean, straight-forward mbedtls_ecdsa_verify without restartable code, etc. to the current one.
As far as I remember, the refactoring done to add the restartable code had no measurable impact on performance. What does have a significant impact on performance is that the bignum module uses malloc all the time. We would like to completely rewrite bignum operations at some point during the 3.x series, not only for performance but also because its design makes it hard not to leak information through side channels.
The mbedTLS mpi design is inspired by GMP, right? Some years ago, when microprocessors were smaller and/or malloc was strictly forbidden within deeply embedded devices (automotive) I liked the MIRACL mpi design very much. Or the good old Fortran way (one huge work array, index calculation by hand). Just joking.
The origin of Mbed TLS's MPI module is well before my time, but given its age (early 2000s) I guess GMP would have been the open source state of the art. I actually do favor this "Fortran" approach in terms of memory layout, but it is painful to work with in C when you have variable-size objects and can't use a struct.
- Just a minor issue: I only needed ECDSA signature verification, therefore I only included MBEDTLS_ASN1_PARSE_C. But it is not possible to compile without MBEDTLS_ASN1_WRITE_C needed for ECDSA signature generation.
I'm not sure if I've written it down anywhere, but I'd like to remove the dependency of ECDSA on ASN1 altogether. Parsing and writing a SEQUENCE of two INTEGERs can be done with ad hoc code. Likewise for what little ASN1 the RSA module uses. And then asn1*.o can move out of libmbedcrypto and libpsacrypto, and into libmbedx509 where it belongs.
I completely agree with you. ASN.1 isn't crypto (and there was a time when every two or three weeks, there was a bug in ASN.1 parsing). But I don't know where to draw the line between raw public keys and PEM/DER/PKCS#8, for example.
PKCS#8 is "obviously" about parsing ASN.1 and is practically X.509, not crypto. That is, until you throw PKCS#12 into the mix. Because if you have crypto in its own process/partition/enclave, and it needs to decrypt private keys without extruding the password or the private key, it needs to do the parsing of the encrypted private key, and that gets a bit complex for ad hoc ASN.1 parsing.Right. Also maintainable code and minimal code size, because minimal code size comes from letting the application developer #ifdef out everything that they don't care about, but this is a nightmare to test. It's one of the topics we're thinking about for Mbed TLS 3 and beyond.
In general, Mbed TLS is primarily targeted at embedded systems, and is likely to privilege 1. security (including side channel resistance) and 2. code size. This doesn't mean that we don't care about performance, just that it isn't our top priority.
I hope I haven't been misunderstood. We choose mbedTLS in the first place because of its modular structure. I wouldn't have had a chance to port all the crypto of OpenSSL, for example, to my SoC. There is a fine balance between performance and simplicity/maintainability/portability.
Oh, the ability to select exactly which algorithms to include in a build is definitely here to stay. But do we really need 4 different ways to build aes.c with different ROM/RAM/speed/security compromises, not counting the ability to make some parts optional? And the ability to choose a faster or smaller SHA-256, and _independently_ the same ability for SHA-512? Should we have generic ECC code that's instantiated with specific curves at runtime, or should we have specialized code for each curve, which is better for applications that use a single curve but bloats the code for applications that include all the curves (such as devices where the crypto code lives in a separate partition that is signed by the manufacturer)? Is a 10% speed gain on ECDSA signature on Cortex-M3 worth a 10% size increase of ecdsa.o? Those are choices where we don't have an obvious answer.
-- Gilles Peskine Mbed TLS developer
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.