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

Bignum: Montgomery multiplication from bignum prototype #6083

Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
82d3f1e
Remove bignum_internal.h, moving contents to bignum_core.h
tom-cosgrove-arm Aug 23, 2022
71f4b0d
Add bignum_new.c starting with MPI_CORE(montmul) for Montgomery multi…
Aug 23, 2022
90c426b
Tidy up, removing MPI_CORE(), and using the new mbedtls_mpi_core_mla()
tom-cosgrove-arm Aug 23, 2022
7e655f7
Use new mbedtls_mpi_core_sub() instead of old static mpi_sub_hlp()
tom-cosgrove-arm Jul 20, 2022
268f96b
Fix Windows builds, which were getting "possible loss of data"
tom-cosgrove-arm Jul 31, 2022
0cc7865
Add unit tests for the new function mbedtls_mpi_core_add_if() in bign…
tom-cosgrove-arm Aug 23, 2022
2a65b85
Add unit tests for the new function mbedtls_mpi_core_sub() in bignum_…
tom-cosgrove-arm Aug 17, 2022
659c84a
Add unit tests for the new function mbedtls_mpi_core_mla() in bignum_…
tom-cosgrove-arm Aug 17, 2022
79b70f6
Make a public version of mpi_montg_init() in bignum_new.c and add uni…
tom-cosgrove-arm Aug 17, 2022
f334d96
Add unit tests for bignum_new.c:mbedtls_mpi_core_montmul()
tom-cosgrove-arm Aug 17, 2022
9384284
Use mbedtls_mpi_core_montmul() in mpi_montmul()
tom-cosgrove-arm Aug 5, 2022
40d2294
Tidy up doc comments on existing function mpi_montmul()
tom-cosgrove-arm Aug 17, 2022
4641ec6
Fix style following review comments
tom-cosgrove-arm Aug 17, 2022
f88b47e
Remove 'const' qualifier from temporary for mpi_montmul()
tom-cosgrove-arm Aug 17, 2022
2523791
Better constant-time properties for mbedtls_mpi_core_montmul()
tom-cosgrove-arm Aug 19, 2022
958fd3d
Remove bignum_new.c, moving contents to bignum_core.c
tom-cosgrove-arm Aug 24, 2022
f0ffb15
Have mbedtls_mpi_montg_init() take the modulus, rather than just its …
tom-cosgrove-arm Aug 24, 2022
7259463
Apply the function parameter naming convention
tom-cosgrove-arm Aug 24, 2022
b2c06f4
Remove stale comment, and fix whitespace issue
tom-cosgrove-arm Aug 24, 2022
ecbb124
Fix incorrect parameter name in mbedtls_mpi_core_add_if() doc comment
tom-cosgrove-arm Aug 25, 2022
d932de8
Remove incorrect constant-time claim from doc for mbedtls_mpi_core_ad…
tom-cosgrove-arm Aug 25, 2022
b496486
Reorder functions in bignum_core.[ch]
tom-cosgrove-arm Aug 30, 2022
5dd97e6
Update comments following code review
tom-cosgrove-arm Aug 30, 2022
f0c8a8c
One statement per line
tom-cosgrove-arm Aug 30, 2022
9354990
Don't use multiplication by condition in even a semi-constant time fu…
tom-cosgrove-arm Aug 30, 2022
ed43c6c
In add_if(), B MAY be aliased to A. Also update another comment for c…
tom-cosgrove-arm Aug 31, 2022
630110a
Fix documentation where ciL should be biL
tom-cosgrove-arm Aug 31, 2022
5eefc3d
Move macros to come before function declarations
tom-cosgrove-arm Aug 31, 2022
f0b2231
Update comments at the end of montmul following Gilles' feedback
tom-cosgrove-arm Aug 31, 2022
9339f05
Swap arguments of TEST_EQUAL() where it improves readability
tom-cosgrove-arm Sep 1, 2022
b0fb17a
Use ASSERT_COMPARE() instead of memcmp() in new tests
tom-cosgrove-arm Sep 1, 2022
1b2947a
Remove mbedtls_ prefix from bignum test cases
tom-cosgrove-arm Sep 2, 2022
eceb4cc
Rename variables and update comments in mpi_core_add_if test
tom-cosgrove-arm Sep 2, 2022
a043aeb
Rename variables and update comments in mpi_core_sub test
tom-cosgrove-arm Sep 2, 2022
42dfac6
Rename variables and update comments in mpi_core_mla test
tom-cosgrove-arm Sep 2, 2022
1135b20
Add mbedtls_mpi_core_add_if() tests for when inputs are aliased
tom-cosgrove-arm Sep 2, 2022
67c9247
Move the T++ in mbedtls_mpi_core_montmul() to within the loop body
tom-cosgrove-arm Sep 2, 2022
2b17792
Use ASSERT_ALLOC() in tests
tom-cosgrove-arm Sep 15, 2022
1feb5ac
Switch to using TEST_LE_S() and TEST_LE_U() in tests
tom-cosgrove-arm Sep 15, 2022
50c477b
Use S and sum (rather than X/expected) in mpi_core_add_if()
tom-cosgrove-arm Sep 15, 2022
be7209d
Remove unnecessary casts
tom-cosgrove-arm Sep 15, 2022
e2159f2
Use the MAX() macro
tom-cosgrove-arm Sep 15, 2022
359feb0
Better wording for the reason why we use an input MPI for a scalar value
tom-cosgrove-arm Sep 15, 2022
818d992
Note that T must not overlap other parameters of mbedtls_mpi_core_mon…
tom-cosgrove-arm Sep 15, 2022
2701dea
Use mbedtls_ct_mpi_uint_mask() rather than rolling our own
tom-cosgrove-arm Sep 15, 2022
b7438d1
Update name of mbedtls_mpi_montg_init()
tom-cosgrove-arm Sep 15, 2022
17f1fdc
Update comments in mpi_core_add_if() test
tom-cosgrove-arm Sep 15, 2022
dbc1561
Don't bother to test b + a after testing a + b if a == b
tom-cosgrove-arm Sep 15, 2022
c71ca0c
Remove some unnecessary whitespace (two spaces after commas)
tom-cosgrove-arm Sep 15, 2022
5c0e810
Prefer 'fixed-size' to 'known-size' in doc comments
tom-cosgrove-arm Sep 15, 2022
3bd7bc3
Use X rather than A for accumulator-style input (and output!) params,…
tom-cosgrove-arm Sep 15, 2022
f2b3818
Test when all three inputs to mbedtls_mpi_core_sub() are aliased
tom-cosgrove-arm Sep 20, 2022
ea45c1d
Document and test aliasing of output for mbedtls_mpi_core_montmul()
tom-cosgrove-arm Sep 20, 2022
b0b77e1
Document and test aliasing of the bignums given to mbedtls_mpi_core_m…
tom-cosgrove-arm Sep 20, 2022
4782823
Ensure we explicitly document the modulus for fixed-width arithmetic
tom-cosgrove-arm Sep 20, 2022
c573882
Merge remote-tracking branch 'upstream/development' into issue-6015-m…
tom-cosgrove-arm Sep 21, 2022
119eae2
Update names of test cases in generate_bignum_tests.py
tom-cosgrove-arm Sep 21, 2022
4386ead
Correct the aliasing requirements in doc for mbedtls_mpi_core_montmul…
tom-cosgrove-arm Sep 29, 2022
6da3a3b
Fix doc regarding aliasing of modulus input to mbedtls_mpi_core_montm…
tom-cosgrove-arm Sep 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 8 additions & 134 deletions library/bignum.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
#if defined(MBEDTLS_BIGNUM_C)

#include "mbedtls/bignum.h"
#include "bignum_internal.h"
#include "bignum_core.h"
#include "bn_mul.h"
#include "mbedtls/platform_util.h"
Expand Down Expand Up @@ -962,40 +961,6 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
return( ret );
}

/**
* Helper for mbedtls_mpi subtraction.
*
* Calculate l - r where l and r have the same size.
* This function operates modulo (2^ciL)^n and returns the carry
* (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
*
* d may be aliased to l or r.
*
* \param n Number of limbs of \p d, \p l and \p r.
* \param[out] d The result of the subtraction.
* \param[in] l The left operand.
* \param[in] r The right operand.
*
* \return 1 if `l < r`.
* 0 if `l >= r`.
*/
static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
mbedtls_mpi_uint *d,
const mbedtls_mpi_uint *l,
const mbedtls_mpi_uint *r )
{
size_t i;
mbedtls_mpi_uint c = 0, t, z;

for( i = 0; i < n; i++ )
{
z = ( l[i] < c ); t = l[i] - c;
c = ( t < r[i] ) + z; d[i] = t - r[i];
}

return( c );
}

/*
* Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
*/
Expand Down Expand Up @@ -1028,7 +993,7 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
if( X->n > A->n )
memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );

carry = mpi_sub_hlp( n, X->p, A->p, B->p );
carry = mbedtls_mpi_core_sub( X->p, A->p, B->p, n );
if( carry != 0 )
{
/* Propagate the carry to the first nonzero limb of X. */
Expand Down Expand Up @@ -1157,38 +1122,6 @@ int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint
return( mbedtls_mpi_sub_mpi( X, A, &B ) );
}

mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len,
const mbedtls_mpi_uint *s, size_t s_len,
mbedtls_mpi_uint b )
{
mbedtls_mpi_uint c = 0; /* carry */
size_t excess_len = d_len - s_len;

size_t steps_x8 = s_len / 8;
size_t steps_x1 = s_len & 7;

while( steps_x8-- )
{
MULADDC_X8_INIT
MULADDC_X8_CORE
MULADDC_X8_STOP
}

while( steps_x1-- )
{
MULADDC_X1_INIT
MULADDC_X1_CORE
MULADDC_X1_STOP
}

while( excess_len-- )
{
*d += c; c = ( *d < c ); d++;
}

return( c );
}

/*
* Baseline multiplication: X = A * B (HAC 14.12)
*/
Expand Down Expand Up @@ -1612,21 +1545,9 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_
return( 0 );
}

/*
* Fast Montgomery initialization (thanks to Tom St Denis)
*/
static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not go one step further and elimitate this trivial auxiliary function, as was done for mpi_sub_hlp? Likewise for mpi_montmul.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my understanding RR and mm will be pre-calcuated during mbedtls_mod_modulus_setup() phase.

There is also the consideration of adjusting them to a more efficient computionally logic. So it makes it simpler to keep them as small single purpose service functions, which can be absorbed later on when the new interface is the standard.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not go one step further and eliminate this trivial auxiliary function

Very specifically, for this PR to have minimal, obvious, easily-reviewable changes. The legacy bignum interface will be retired at some point, and then these will just vanish.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is so trivial, mathematically it is quite involved. I would prefer to have it in a separate function and document it better in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mean to eliminate mbedtls_mpi_montg_init, which is where the mathematics happen. I meant to eliminate this function, mpi_montg_init, and call mbedtls_mpi_montg_init directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said above, my goal was for this PR to have minimal, obvious, easily-reviewable changes. Making the existing function marshal its arguments and call the new function is (to me) the minimal, obvious, way to do this.

Since mpi_montg_init() is static, the compiler inlines it (at least on -O2), and there is no code-size impact.

And in the future, all of this is going away.

So I don't see the benefit of changing the caller of mbedtls_mpi_montg_init()

{
mbedtls_mpi_uint x, m0 = N->p[0];
unsigned int i;

x = m0;
x += ( ( m0 + 2 ) & 4 ) << 1;

for( i = biL; i >= 8; i /= 2 )
x *= ( 2 - ( m0 * x ) );

*mm = ~x + 1;
*mm = mbedtls_mpi_montg_init( N->p );
}

/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
Expand All @@ -1640,67 +1561,20 @@ static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
* \param[in] B One of the numbers to multiply.
* It must be nonzero and must not have more limbs than N
* (B->n <= N->n).
* \param[in] N The modulo. N must be odd.
* \param[in] N The modulus. \p N must be odd.
* \param mm The value calculated by `mpi_montg_init(&mm, N)`.
* This is -N^-1 mod 2^ciL.
* \param[in,out] T A bignum for temporary storage.
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
* It must be at least twice the limb size of N plus 1
* (T->n >= 2 * N->n + 1).
* Its initial content is unused and
* its final content is indeterminate.
* Note that unlike the usual convention in the library
* for `const mbedtls_mpi*`, the content of T can change.
*/
static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
const mbedtls_mpi *T )
static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B,
const mbedtls_mpi *N, mbedtls_mpi_uint mm,
mbedtls_mpi *T )
{
size_t n, m;
mbedtls_mpi_uint *d;

memset( T->p, 0, T->n * ciL );

d = T->p;
n = N->n;
m = ( B->n < n ) ? B->n : n;

for( size_t i = 0; i < n; i++ )
{
mbedtls_mpi_uint u0, u1;

/*
* T = (T + u0*B + u1*N) / 2^biL
*/
u0 = A->p[i];
u1 = ( d[0] + u0 * B->p[0] ) * mm;

(void) mbedtls_mpi_core_mla( d, n + 2,
B->p, m,
u0 );
(void) mbedtls_mpi_core_mla( d, n + 2,
N->p, n,
u1 );
d++;
}

/* At this point, d is either the desired result or the desired result
* plus N. We now potentially subtract N, avoiding leaking whether the
* subtraction is performed through side channels. */

/* Copy the n least significant limbs of d to A, so that
* A = d if d < N (recall that N has n limbs). */
memcpy( A->p, d, n * ciL );
/* If d >= N then we want to set A to d - N. To prevent timing attacks,
* do the calculation without using conditional tests. */
/* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
d[n] += 1;
d[n] -= mpi_sub_hlp( n, d, d, N->p );
/* If d0 < N then d < (2^biL)^n
* so d[n] == 0 and we want to keep A as it is.
* If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
* so d[n] == 1 and we want to set A to the result of the subtraction
* which is d - (2^biL)^n, i.e. the n least significant limbs of d.
* This exactly corresponds to a conditional assignment. */
mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
mbedtls_mpi_core_montmul( A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p );
}

/*
Expand All @@ -1709,7 +1583,7 @@ static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi
* See mpi_montmul() regarding constraints and guarantees on the parameters.
*/
static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
mbedtls_mpi_uint mm, const mbedtls_mpi *T )
mbedtls_mpi_uint mm, mbedtls_mpi *T )
{
mbedtls_mpi_uint z = 1;
mbedtls_mpi U;
Expand Down
137 changes: 137 additions & 0 deletions library/bignum_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#endif

#include "bignum_core.h"
#include "bn_mul.h"
#include "constant_time_internal.h"

size_t mbedtls_mpi_core_clz( mbedtls_mpi_uint a )
{
Expand Down Expand Up @@ -291,4 +293,139 @@ int mbedtls_mpi_core_write_be( const mbedtls_mpi_uint *X,
return( 0 );
}

void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X,
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t B_limbs,
const mbedtls_mpi_uint *N,
size_t AN_limbs,
mbedtls_mpi_uint mm,
mbedtls_mpi_uint *T )
{
memset( T, 0, ( 2 * AN_limbs + 1 ) * ciL );
minosgalanakis marked this conversation as resolved.
Show resolved Hide resolved

for( size_t i = 0; i < AN_limbs; i++, T++ )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subjective: I would find the code easier to understand if T was a constant and the code here instead used T + i (possibly with a new name for T + AN_limbs after the loop).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me T++ is more intuitive, as I feel that it conveys the arithmetic meaning of the operation better: we are dividing T by 2^biL.

That said, we could make this clearer by doing it at the end of the loop block and not in the loop header. And possibly we could add a comment to remind to the arithmetic meaning.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Janos. I find the division each iteration more intuitive. I've left this as-is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how T++ conveys dividing by 2^biL any better than T + i does. And there is, generically, an advantage in not modifying a parameter (single assignment).

I don't consider this a blocker. But please at least move T++ out of the for line as Janos suggests. Right now there's a classic “for(start; stop; increment)” loop, except for the additional T++ stuck on which is easy to miss. If the fact that T changes was more visible it wouldn't be so bad.

{
mbedtls_mpi_uint u0, u1;
/* T = (T + u0*B + u1*N) / 2^biL */
u0 = A[i];
u1 = ( T[0] + u0 * B[0] ) * mm;

(void) mbedtls_mpi_core_mla( T, AN_limbs + 2, B, B_limbs, u0 );
(void) mbedtls_mpi_core_mla( T, AN_limbs + 2, N, AN_limbs, u1 );
}

/* It's possible that the result in T is > N, and so we might need to subtract N */

mbedtls_mpi_uint carry = T[AN_limbs];
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub( X, T, N, AN_limbs );

/*
* Both carry and borrow can only be 0 or 1.
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
*
* If carry = 1, the result in T must be > N by definition, and the subtraction
* using only AN_limbs limbs will create borrow, but that will have the correct
* final result.
*
* i.e. (carry, borrow) of (1, 1) => return X
*
* If carry = 0, then we want to use the result of the subtraction iff
minosgalanakis marked this conversation as resolved.
Show resolved Hide resolved
* borrow = 0.
*
* i.e. (carry, borrow) of (0, 0) => return X
* (0, 1) => return T
*
* We've confirmed that the unit tests exercise this function with all 3 of
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
* the valid (carry, borrow) combinations (listed above), and that we don't
* see (carry, borrow) = (1, 0).
*
* So the correct return value is already in X if (carry ^ borrow) = 0,
* but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1.
*/
mbedtls_ct_mpi_uint_cond_assign( AN_limbs, X, T, (unsigned char) ( carry ^ borrow ) );
Copy link

@hanno-becker hanno-becker Sep 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was initially an add_if. Why was it switched to cond_assign?

This function is the most performance critical routine throughout ECC -- any change has to be considered very carefully, not only from a security, but also from a performance perspective. Has it been analyzed what using mbedtls_ct_mpi_uint_cond_assign() does here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original version used mbedtls_ct_mpi_uint_cond_assign() which is clearly constant time. To make add_if constant time requires more thought and work, which we don't want to spend right now, but definitely want to do later.

With mbedtls_ct_mpi_uint_cond_assign() we are the same in both security and performance where we were on development and that is perfectly fine for now. The first pass is refactoring, which by nature will come with security and performance improvements, but dedicated efforts in these directions will come later.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, your call!

}

/*
* Fast Montgomery initialization (thanks to Tom St Denis).
*/
mbedtls_mpi_uint mbedtls_mpi_montg_init( const mbedtls_mpi_uint *N )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why take a pointer as an argument and not the limb value?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this function calculates N^-1 mod 2^biL and technically we only need the last limb of N for doing this, but I think passing a pointer to N makes it more intuitive, makes it easier to read. Like this we have the whole computation in this function as opposed to the caller calculating and passing N mod 2^biL and this function calculating the rest.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As Janos says, this is a function calculating a value based on the MPI N. The fact it only needs the least significant limb (LSL) of N is incidental. It is premature optimisation for the caller to extract the LSL - it is likely that this function will be inlined eventually.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think passing a pointer to N makes it more intuitive, makes it easier to read

It certainly doesn't. When I see this function I wonder why we're passing a pointer to a read-only scalar. It looks like it's a a pointer to an array, and seeing that it's a pointer to bignum limbs it sure like it's part of an array, but then I'd expect a size. It's not a blocker, but I do feel the code is gratuitously hard to read here.

{
mbedtls_mpi_uint x = N[0];

x += ( ( N[0] + 2 ) & 4 ) << 1;

for( unsigned int i = biL; i >= 8; i /= 2 )
x *= ( 2 - ( N[0] * x ) );

return( ~x + 1 );
}

mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len,
Copy link
Contributor Author

@tom-cosgrove-arm tom-cosgrove-arm Aug 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't updated the parameter names here to match those in the header because they are directly used by the MULADDC macros (and changing them seems a very high risk, given we can't build every platform)

const mbedtls_mpi_uint *s, size_t s_len,
mbedtls_mpi_uint b )
{
mbedtls_mpi_uint c = 0; /* carry */
if( d_len < s_len )
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
s_len = d_len;
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
size_t excess_len = d_len - s_len;
size_t steps_x8 = s_len / 8;
size_t steps_x1 = s_len & 7;

while( steps_x8-- )
{
MULADDC_X8_INIT
MULADDC_X8_CORE
MULADDC_X8_STOP
}

while( steps_x1-- )
{
MULADDC_X1_INIT
MULADDC_X1_CORE
MULADDC_X1_STOP
}

while( excess_len-- )
{
*d += c; c = ( *d < c ); d++;
}

return( c );
}

mbedtls_mpi_uint mbedtls_mpi_core_sub( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs )
{
mbedtls_mpi_uint c = 0;

for( size_t i = 0; i < limbs; i++ )
{
mbedtls_mpi_uint z = ( A[i] < c );
mbedtls_mpi_uint t = A[i] - c;
c = ( t < B[i] ) + z;
X[i] = t - B[i];
}

return( c );
}

mbedtls_mpi_uint mbedtls_mpi_core_add_if( mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs,
unsigned cond )
{
mbedtls_mpi_uint c = 0, t;
for( size_t i = 0; i < limbs; i++ )
minosgalanakis marked this conversation as resolved.
Show resolved Hide resolved
{
mbedtls_mpi_uint add = cond * B[i];
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
t = c;
t += A[i]; c = ( t < A[i] );
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
t += add; c += ( t < add );
A[i] = t;
}
return( c );
}

#endif /* MBEDTLS_BIGNUM_C */
Loading