mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2024-12-28 06:19:27 +00:00
Merge pull request #6233 from tom-cosgrove-arm/issue-6226-core-mul
Bignum: extract core_mul from the prototype
This commit is contained in:
commit
13c73de6de
@ -1136,7 +1136,8 @@ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
|
||||
MPI_VALIDATE_RET(A != NULL);
|
||||
MPI_VALIDATE_RET(B != NULL);
|
||||
|
||||
mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
|
||||
mbedtls_mpi_init(&TA);
|
||||
mbedtls_mpi_init(&TB);
|
||||
|
||||
if (X == A) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
|
||||
@ -1166,13 +1167,7 @@ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
|
||||
|
||||
for (size_t k = 0; k < j; k++) {
|
||||
/* We know that there cannot be any carry-out since we're
|
||||
* iterating from bottom to top. */
|
||||
(void) mbedtls_mpi_core_mla(X->p + k, i + 1,
|
||||
A->p, i,
|
||||
B->p[k]);
|
||||
}
|
||||
mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
|
||||
|
||||
/* If the result is 0, we don't shortcut the operation, which reduces
|
||||
* but does not eliminate side channels leaking the zero-ness. We do
|
||||
|
@ -448,6 +448,17 @@ mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *d, size_t d_len,
|
||||
return c;
|
||||
}
|
||||
|
||||
void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X,
|
||||
const mbedtls_mpi_uint *A, size_t A_limbs,
|
||||
const mbedtls_mpi_uint *B, size_t B_limbs)
|
||||
{
|
||||
memset(X, 0, (A_limbs + B_limbs) * ciL);
|
||||
|
||||
for (size_t i = 0; i < B_limbs; i++) {
|
||||
(void) mbedtls_mpi_core_mla(X + i, A_limbs + 1, A, A_limbs, B[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast Montgomery initialization (thanks to Tom St Denis).
|
||||
*/
|
||||
|
@ -398,6 +398,26 @@ mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs,
|
||||
const mbedtls_mpi_uint *A, size_t A_limbs,
|
||||
mbedtls_mpi_uint b);
|
||||
|
||||
/**
|
||||
* \brief Perform a known-size multiplication
|
||||
*
|
||||
* \p X may not be aliased to any of the inputs for this function.
|
||||
* \p A may be aliased to \p B.
|
||||
*
|
||||
* \param[out] X The pointer to the (little-endian) array to receive
|
||||
* the product of \p A_limbs and \p B_limbs.
|
||||
* This must be of length \p A_limbs + \p B_limbs.
|
||||
* \param[in] A The pointer to the (little-endian) array
|
||||
* representing the first factor.
|
||||
* \param A_limbs The number of limbs in \p A.
|
||||
* \param[in] B The pointer to the (little-endian) array
|
||||
* representing the second factor.
|
||||
* \param B_limbs The number of limbs in \p B.
|
||||
*/
|
||||
void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X,
|
||||
const mbedtls_mpi_uint *A, size_t A_limbs,
|
||||
const mbedtls_mpi_uint *B, size_t B_limbs);
|
||||
|
||||
/**
|
||||
* \brief Calculate initialisation value for fast Montgomery modular
|
||||
* multiplication
|
||||
|
@ -68,7 +68,8 @@ def bound_mpi_limbs(limbs: int, bits_in_limb: int) -> int:
|
||||
|
||||
def limbs_mpi(val: int, bits_in_limb: int) -> int:
|
||||
"""Return the number of limbs required to store value."""
|
||||
return (val.bit_length() + bits_in_limb - 1) // bits_in_limb
|
||||
bit_length = max(val.bit_length(), 1)
|
||||
return (bit_length + bits_in_limb - 1) // bits_in_limb
|
||||
|
||||
def combination_pairs(values: List[T]) -> List[Tuple[T, T]]:
|
||||
"""Return all pair combinations from input values."""
|
||||
|
@ -230,6 +230,31 @@ class BignumCoreMLA(BignumCoreTarget, bignum_common.OperationCommon):
|
||||
yield cur_op.create_test_case()
|
||||
|
||||
|
||||
class BignumCoreMul(BignumCoreTarget, bignum_common.OperationCommon):
|
||||
"""Test cases for bignum core multiplication."""
|
||||
count = 0
|
||||
input_style = "arch_split"
|
||||
symbol = "*"
|
||||
test_function = "mpi_core_mul"
|
||||
test_name = "mbedtls_mpi_core_mul"
|
||||
arity = 2
|
||||
unique_combinations_only = True
|
||||
|
||||
def format_arg(self, val: str) -> str:
|
||||
return val
|
||||
|
||||
def format_result(self, res: int) -> str:
|
||||
res_str = '{:x}'.format(res)
|
||||
a_limbs = bignum_common.limbs_mpi(self.int_a, self.bits_in_limb)
|
||||
b_limbs = bignum_common.limbs_mpi(self.int_b, self.bits_in_limb)
|
||||
hex_digits = bignum_common.hex_digits_for_limb(a_limbs + b_limbs, self.bits_in_limb)
|
||||
return bignum_common.quote_str(self.format_arg(res_str).zfill(hex_digits))
|
||||
|
||||
def result(self) -> List[str]:
|
||||
result = self.int_a * self.int_b
|
||||
return [self.format_result(result)]
|
||||
|
||||
|
||||
class BignumCoreMontmul(BignumCoreTarget, test_data_generation.BaseTest):
|
||||
"""Test cases for Montgomery multiplication."""
|
||||
count = 0
|
||||
|
@ -1057,6 +1057,72 @@ exit:
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void mpi_core_mul(char *input_A,
|
||||
char *input_B,
|
||||
char *result)
|
||||
{
|
||||
mbedtls_mpi_uint *A = NULL;
|
||||
mbedtls_mpi_uint *A_orig = NULL;
|
||||
mbedtls_mpi_uint *B = NULL;
|
||||
mbedtls_mpi_uint *B_orig = NULL;
|
||||
mbedtls_mpi_uint *R = NULL;
|
||||
mbedtls_mpi_uint *X = NULL;
|
||||
size_t A_limbs, B_limbs, R_limbs;
|
||||
|
||||
TEST_EQUAL(mbedtls_test_read_mpi_core(&A, &A_limbs, input_A), 0);
|
||||
TEST_EQUAL(mbedtls_test_read_mpi_core(&B, &B_limbs, input_B), 0);
|
||||
TEST_EQUAL(mbedtls_test_read_mpi_core(&R, &R_limbs, result), 0);
|
||||
|
||||
TEST_EQUAL(R_limbs, A_limbs + B_limbs);
|
||||
|
||||
const size_t X_limbs = A_limbs + B_limbs;
|
||||
const size_t X_bytes = X_limbs * sizeof(mbedtls_mpi_uint);
|
||||
ASSERT_ALLOC(X, X_limbs);
|
||||
|
||||
const size_t A_bytes = A_limbs * sizeof(mbedtls_mpi_uint);
|
||||
ASSERT_ALLOC(A_orig, A_limbs);
|
||||
memcpy(A_orig, A, A_bytes);
|
||||
|
||||
const size_t B_bytes = B_limbs * sizeof(mbedtls_mpi_uint);
|
||||
ASSERT_ALLOC(B_orig, B_limbs);
|
||||
memcpy(B_orig, B, B_bytes);
|
||||
|
||||
/* Set result to something that is unlikely to be correct */
|
||||
memset(X, '!', X_bytes);
|
||||
|
||||
/* 1. X = A * B - result should be correct, A and B unchanged */
|
||||
mbedtls_mpi_core_mul(X, A, A_limbs, B, B_limbs);
|
||||
ASSERT_COMPARE(X, X_bytes, R, X_bytes);
|
||||
ASSERT_COMPARE(A, A_bytes, A_orig, A_bytes);
|
||||
ASSERT_COMPARE(B, B_bytes, B_orig, B_bytes);
|
||||
|
||||
/* 2. A == B: alias A and B - result should be correct, A and B unchanged */
|
||||
if (A_bytes == B_bytes && memcmp(A, B, A_bytes) == 0) {
|
||||
memset(X, '!', X_bytes);
|
||||
mbedtls_mpi_core_mul(X, A, A_limbs, A, A_limbs);
|
||||
ASSERT_COMPARE(X, X_bytes, R, X_bytes);
|
||||
ASSERT_COMPARE(A, A_bytes, A_orig, A_bytes);
|
||||
}
|
||||
/* 3. X = B * A - result should be correct, A and B unchanged */
|
||||
else {
|
||||
memset(X, '!', X_bytes);
|
||||
mbedtls_mpi_core_mul(X, B, B_limbs, A, A_limbs);
|
||||
ASSERT_COMPARE(X, X_bytes, R, X_bytes);
|
||||
ASSERT_COMPARE(A, A_bytes, A_orig, A_bytes);
|
||||
ASSERT_COMPARE(B, B_bytes, B_orig, B_bytes);
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_free(A);
|
||||
mbedtls_free(A_orig);
|
||||
mbedtls_free(B);
|
||||
mbedtls_free(B_orig);
|
||||
mbedtls_free(R);
|
||||
mbedtls_free(X);
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN MERGE SLOT 1 */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
|
Loading…
Reference in New Issue
Block a user