Ok, so the original plan was to make mpi_inv_mod() the smallest block that
could not be divided. Updated plan is that the smallest block will be either:
- ecp_normalize_jac_many() (one mpi_inv_mod() + a number or mpi_mul_mpi()s)
- or the second loop in ecp_precompute_comb()
With default settings, the minimum non-restartable sequence is:
- for P-256: 222M
- for P-384: 341M
This is within a 2-3x factor of originally planned value of 120M. However,
that value can be approached, at the cost of some performance, by setting
ECP_WINDOW_SIZE (w below) lower than the default of 6. For example:
- w=4 -> 166M for any curve (perf. impact < 10%)
- w=2 -> 130M for any curve (perf. impact ~ 30%)
My opinion is that the current state with w=4 is a good compromise, and the
code complexity need to attain 120M is not warranted by the 1.4 factor between
that and the current minimum with w=4 (which is close to optimal perf).
This is the easy part: with the current steps, all information between steps
is passed via T which is already saved. Next we'll need to split at least the
first loop, and maybe calls to normalize_jac_many() and/or the second loop.
Separating main computation from filling of the auxiliary array makes things
clearer and easier to restart as we don't have to remember the in-progress
auxiliary array.
Previously there were only two states:
- T unallocated
- T allocated and valid
Now there are three:
- T unallocated
- T allocated and in progress
- T allocated and valid
Introduce new bool T_ok to distinguish the last two states.
Free it as soon as it's no longer needed, but as a backup free it in
ecp_group_free(), in case ecp_mul() is not called again after returning
ECP_IN_PROGRESS.
So far we only remember it when it's fully computed, next step is to be able
to compute it in multiple steps.
In case of argument change, freeing everything is not the most efficient
(wastes one free()+calloc()) but makes the code simpler, which is probably
more important here
We'll need to store MPIs and other things that allocate memory in this
context, so we need a place to free it. We can't rely on doing it before
returning from ecp_mul() as we might return MBEDTLS_ERR_ECP_IN_PROGRESS (thus
preserving the context) and never be called again (for example, TLS handshake
aborted for another reason). So, ecp_group_free() looks like a good place to
do this, if the restart context is part of struct ecp_group.
This means it's not possible to use the same ecp_group structure in different
threads concurrently, but:
- that's already the case (and documented) for other reasons
- this feature is precisely intended for environments that lack threading
An alternative option would be for the caller to have to allocate/free the
restart context and pass it explicitly, but this means creating new functions
that take a context argument, and putting a burden on the user.
The plan is to count basic operations as follows:
- call to ecp_add_mixed() -> 11
- call to ecp_double_jac() -> 8
- call to mpi_mul_mpi() -> 1
- call to mpi_inv_mod() -> 120
- everything else -> not counted
The counts for ecp_add_mixed() and ecp_double_jac() are based on the actual
number of calls to mpi_mul_mpi() they they make.
The count for mpi_inv_mod() is based on timing measurements on K64F and
LPC1768 boards, and are consistent with the usual very rough estimate of one
inversion = 100 multiplications. It could be useful to repeat that measurement
on a Cortex-M0 board as those have smaller divider and multipliers, so the
result could be a bit different but should be the same order of magnitude.
The documented limitation of 120 basic ops is due to the calls to mpi_inv_mod()
which are currently not interruptible nor planned to be so far.
Protecting the ECP hardware acceleratior with mutexes is inconsistent with the
philosophy of the library. Pre-existing hardware accelerator interfaces
leave concurrency support to the underlying platform.
Fixes#863
Protecting the ECP hardware acceleratior with mutexes is inconsistent with the
philosophy of the library. Pre-existing hardware accelerator interfaces
leave concurrency support to the underlying platform.
Fixes#863
With this commit the Elliptic Curve Point interface is rewised. Two
compile time options has been removed to simplify the interface and
the function names got a new prefix that indicates that these functions
are for internal use and not part of the public interface.
The intended use of the abstraction layer for Elliptic Curve Point
arithmetic is to enable using hardware cryptographic accelerators.
These devices are a shared resource and the driver code rarely provides
thread safety.
This commit adds mutexes to the abstraction layer to protect the device
in a multi-threaded environment.
The compile time macros enabling the initialisation and deinitialisation
in the alternative Elliptic Curve Point arithmetic implementation had
names that did not end with '_ALT' as required by check-names.sh.
* development: (73 commits)
Bump yotta dependencies version
Fix typo in documentation
Corrected misleading fn description in ssl_cache.h
Corrected URL/reference to MPI library
Fix yotta dependencies
Fix minor spelling mistake in programs/pkey/gen_key.c
Bump version to 2.1.2
Fix CVE number in ChangeLog
Add 'inline' workaround where needed
Fix references to non-standard SIZE_T_MAX
Fix yotta version dependencies again
Upgrade yotta dependency versions
Fix compile error in net.c with musl libc
Add missing warning in doc
Remove inline workaround when not useful
Fix macroization of inline in C++
Changed attribution for Guido Vranken
Merge of IOTSSL-476 - Random malloc in pem_read()
Fix for IOTSSL-473 Double free error
Fix potential overflow in CertificateRequest
...
Conflicts:
include/mbedtls/ssl_internal.h
library/ssl_cli.c
- Improve optimization for special case A == -3.
- Add optimization for special case A == 0.
- Use alternative base formula, saving several additions.
- Reduce temp variables to 4 (from 6).