xref: /optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c (revision b0563631928755fe864b97785160fb3088e9efdc)
132b31808SJens Wiklander /*
232b31808SJens Wiklander  *  Low-level modular bignum functions
332b31808SJens Wiklander  *
432b31808SJens Wiklander  *  Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
632b31808SJens Wiklander  */
732b31808SJens Wiklander 
832b31808SJens Wiklander #include "common.h"
932b31808SJens Wiklander 
10*b0563631STom Van Eyck #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
1132b31808SJens Wiklander 
1232b31808SJens Wiklander #include <string.h>
1332b31808SJens Wiklander 
1432b31808SJens Wiklander #include "mbedtls/error.h"
1532b31808SJens Wiklander #include "mbedtls/platform_util.h"
1632b31808SJens Wiklander 
1732b31808SJens Wiklander #include "mbedtls/platform.h"
1832b31808SJens Wiklander 
1932b31808SJens Wiklander #include "bignum_core.h"
2032b31808SJens Wiklander #include "bignum_mod_raw.h"
2132b31808SJens Wiklander #include "bignum_mod.h"
2232b31808SJens Wiklander #include "constant_time_internal.h"
2332b31808SJens Wiklander 
2432b31808SJens Wiklander #include "bignum_mod_raw_invasive.h"
2532b31808SJens Wiklander 
mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_mod_modulus * N,unsigned char assign)2632b31808SJens Wiklander void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
2732b31808SJens Wiklander                                      const mbedtls_mpi_uint *A,
2832b31808SJens Wiklander                                      const mbedtls_mpi_mod_modulus *N,
2932b31808SJens Wiklander                                      unsigned char assign)
3032b31808SJens Wiklander {
31*b0563631STom Van Eyck     mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));
3232b31808SJens Wiklander }
3332b31808SJens Wiklander 
mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint * X,mbedtls_mpi_uint * Y,const mbedtls_mpi_mod_modulus * N,unsigned char swap)3432b31808SJens Wiklander void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
3532b31808SJens Wiklander                                    mbedtls_mpi_uint *Y,
3632b31808SJens Wiklander                                    const mbedtls_mpi_mod_modulus *N,
3732b31808SJens Wiklander                                    unsigned char swap)
3832b31808SJens Wiklander {
39*b0563631STom Van Eyck     mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));
4032b31808SJens Wiklander }
4132b31808SJens Wiklander 
mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N,const unsigned char * input,size_t input_length,mbedtls_mpi_mod_ext_rep ext_rep)4232b31808SJens Wiklander int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
4332b31808SJens Wiklander                              const mbedtls_mpi_mod_modulus *N,
4432b31808SJens Wiklander                              const unsigned char *input,
4532b31808SJens Wiklander                              size_t input_length,
4632b31808SJens Wiklander                              mbedtls_mpi_mod_ext_rep ext_rep)
4732b31808SJens Wiklander {
4832b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4932b31808SJens Wiklander 
5032b31808SJens Wiklander     switch (ext_rep) {
5132b31808SJens Wiklander         case MBEDTLS_MPI_MOD_EXT_REP_LE:
5232b31808SJens Wiklander             ret = mbedtls_mpi_core_read_le(X, N->limbs,
5332b31808SJens Wiklander                                            input, input_length);
5432b31808SJens Wiklander             break;
5532b31808SJens Wiklander         case MBEDTLS_MPI_MOD_EXT_REP_BE:
5632b31808SJens Wiklander             ret = mbedtls_mpi_core_read_be(X, N->limbs,
5732b31808SJens Wiklander                                            input, input_length);
5832b31808SJens Wiklander             break;
5932b31808SJens Wiklander         default:
6032b31808SJens Wiklander             return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
6132b31808SJens Wiklander     }
6232b31808SJens Wiklander 
6332b31808SJens Wiklander     if (ret != 0) {
6432b31808SJens Wiklander         goto cleanup;
6532b31808SJens Wiklander     }
6632b31808SJens Wiklander 
6732b31808SJens Wiklander     if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) {
6832b31808SJens Wiklander         ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
6932b31808SJens Wiklander         goto cleanup;
7032b31808SJens Wiklander     }
7132b31808SJens Wiklander 
7232b31808SJens Wiklander cleanup:
7332b31808SJens Wiklander 
7432b31808SJens Wiklander     return ret;
7532b31808SJens Wiklander }
7632b31808SJens Wiklander 
mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint * A,const mbedtls_mpi_mod_modulus * N,unsigned char * output,size_t output_length,mbedtls_mpi_mod_ext_rep ext_rep)7732b31808SJens Wiklander int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
7832b31808SJens Wiklander                               const mbedtls_mpi_mod_modulus *N,
7932b31808SJens Wiklander                               unsigned char *output,
8032b31808SJens Wiklander                               size_t output_length,
8132b31808SJens Wiklander                               mbedtls_mpi_mod_ext_rep ext_rep)
8232b31808SJens Wiklander {
8332b31808SJens Wiklander     switch (ext_rep) {
8432b31808SJens Wiklander         case MBEDTLS_MPI_MOD_EXT_REP_LE:
8532b31808SJens Wiklander             return mbedtls_mpi_core_write_le(A, N->limbs,
8632b31808SJens Wiklander                                              output, output_length);
8732b31808SJens Wiklander         case MBEDTLS_MPI_MOD_EXT_REP_BE:
8832b31808SJens Wiklander             return mbedtls_mpi_core_write_be(A, N->limbs,
8932b31808SJens Wiklander                                              output, output_length);
9032b31808SJens Wiklander         default:
9132b31808SJens Wiklander             return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
9232b31808SJens Wiklander     }
9332b31808SJens Wiklander }
9432b31808SJens Wiklander 
mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_uint * B,const mbedtls_mpi_mod_modulus * N)9532b31808SJens Wiklander void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
9632b31808SJens Wiklander                              const mbedtls_mpi_uint *A,
9732b31808SJens Wiklander                              const mbedtls_mpi_uint *B,
9832b31808SJens Wiklander                              const mbedtls_mpi_mod_modulus *N)
9932b31808SJens Wiklander {
10032b31808SJens Wiklander     mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs);
10132b31808SJens Wiklander 
10232b31808SJens Wiklander     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
10332b31808SJens Wiklander }
10432b31808SJens Wiklander 
10532b31808SJens Wiklander MBEDTLS_STATIC_TESTABLE
mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)10632b31808SJens Wiklander void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
10732b31808SJens Wiklander                                              const mbedtls_mpi_mod_modulus *N)
10832b31808SJens Wiklander {
10932b31808SJens Wiklander     mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
11032b31808SJens Wiklander 
11132b31808SJens Wiklander     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
11232b31808SJens Wiklander }
11332b31808SJens Wiklander 
11432b31808SJens Wiklander 
mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_uint * B,const mbedtls_mpi_mod_modulus * N,mbedtls_mpi_uint * T)11532b31808SJens Wiklander void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
11632b31808SJens Wiklander                              const mbedtls_mpi_uint *A,
11732b31808SJens Wiklander                              const mbedtls_mpi_uint *B,
11832b31808SJens Wiklander                              const mbedtls_mpi_mod_modulus *N,
11932b31808SJens Wiklander                              mbedtls_mpi_uint *T)
12032b31808SJens Wiklander {
121*b0563631STom Van Eyck     /* Standard (A * B) multiplication stored into pre-allocated T
122*b0563631STom Van Eyck      * buffer of fixed limb size of (2N + 1).
123*b0563631STom Van Eyck      *
124*b0563631STom Van Eyck      * The space may not not fully filled by when
125*b0563631STom Van Eyck      * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */
126*b0563631STom Van Eyck     const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2;
127*b0563631STom Van Eyck     switch (N->int_rep) {
128*b0563631STom Van Eyck         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
12932b31808SJens Wiklander             mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
13032b31808SJens Wiklander                                      N->rep.mont.mm, T);
131*b0563631STom Van Eyck             break;
132*b0563631STom Van Eyck         case MBEDTLS_MPI_MOD_REP_OPT_RED:
133*b0563631STom Van Eyck             mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs);
134*b0563631STom Van Eyck 
135*b0563631STom Van Eyck             /* Optimised Reduction */
136*b0563631STom Van Eyck             (*N->rep.ored.modp)(T, T_limbs);
137*b0563631STom Van Eyck 
138*b0563631STom Van Eyck             /* Convert back to canonical representation */
139*b0563631STom Van Eyck             mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N);
140*b0563631STom Van Eyck             memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint));
141*b0563631STom Van Eyck             break;
142*b0563631STom Van Eyck         default:
143*b0563631STom Van Eyck             break;
14432b31808SJens Wiklander     }
14532b31808SJens Wiklander 
146*b0563631STom Van Eyck }
14732b31808SJens Wiklander 
mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)14832b31808SJens Wiklander size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)
14932b31808SJens Wiklander {
15032b31808SJens Wiklander     /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent,
15132b31808SJens Wiklander      * which will be the same size as the modulus and input (AN_limbs),
15232b31808SJens Wiklander      * and additional space to pass to mbedtls_mpi_core_exp_mod(). */
15332b31808SJens Wiklander     return AN_limbs +
15432b31808SJens Wiklander            mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs);
15532b31808SJens Wiklander }
15632b31808SJens Wiklander 
mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_uint * N,size_t AN_limbs,const mbedtls_mpi_uint * RR,mbedtls_mpi_uint * T)15732b31808SJens Wiklander void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,
15832b31808SJens Wiklander                                    const mbedtls_mpi_uint *A,
15932b31808SJens Wiklander                                    const mbedtls_mpi_uint *N,
16032b31808SJens Wiklander                                    size_t AN_limbs,
16132b31808SJens Wiklander                                    const mbedtls_mpi_uint *RR,
16232b31808SJens Wiklander                                    mbedtls_mpi_uint *T)
16332b31808SJens Wiklander {
16432b31808SJens Wiklander     /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and
16532b31808SJens Wiklander      *                       |G| = N - 1, so we want
16632b31808SJens Wiklander      *                 g^(|G|-1) = g^(N - 2)
16732b31808SJens Wiklander      */
16832b31808SJens Wiklander 
16932b31808SJens Wiklander     /* Use the first AN_limbs of T to hold N - 2 */
17032b31808SJens Wiklander     mbedtls_mpi_uint *Nminus2 = T;
17132b31808SJens Wiklander     (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs);
17232b31808SJens Wiklander 
17332b31808SJens Wiklander     /* Rest of T is given to exp_mod for its working space */
17432b31808SJens Wiklander     mbedtls_mpi_core_exp_mod(X,
17532b31808SJens Wiklander                              A, N, AN_limbs, Nminus2, AN_limbs,
17632b31808SJens Wiklander                              RR, T + AN_limbs);
17732b31808SJens Wiklander }
17832b31808SJens Wiklander 
mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_uint * B,const mbedtls_mpi_mod_modulus * N)17932b31808SJens Wiklander void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
18032b31808SJens Wiklander                              const mbedtls_mpi_uint *A,
18132b31808SJens Wiklander                              const mbedtls_mpi_uint *B,
18232b31808SJens Wiklander                              const mbedtls_mpi_mod_modulus *N)
18332b31808SJens Wiklander {
18432b31808SJens Wiklander     mbedtls_mpi_uint carry, borrow;
18532b31808SJens Wiklander     carry  = mbedtls_mpi_core_add(X, A, B, N->limbs);
18632b31808SJens Wiklander     borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
18732b31808SJens Wiklander     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow));
18832b31808SJens Wiklander }
18932b31808SJens Wiklander 
mbedtls_mpi_mod_raw_canonical_to_modulus_rep(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)19032b31808SJens Wiklander int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
19132b31808SJens Wiklander     mbedtls_mpi_uint *X,
19232b31808SJens Wiklander     const mbedtls_mpi_mod_modulus *N)
19332b31808SJens Wiklander {
19432b31808SJens Wiklander     switch (N->int_rep) {
19532b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
19632b31808SJens Wiklander             return mbedtls_mpi_mod_raw_to_mont_rep(X, N);
19732b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_OPT_RED:
19832b31808SJens Wiklander             return 0;
19932b31808SJens Wiklander         default:
20032b31808SJens Wiklander             return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
20132b31808SJens Wiklander     }
20232b31808SJens Wiklander }
20332b31808SJens Wiklander 
mbedtls_mpi_mod_raw_modulus_to_canonical_rep(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)20432b31808SJens Wiklander int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
20532b31808SJens Wiklander     mbedtls_mpi_uint *X,
20632b31808SJens Wiklander     const mbedtls_mpi_mod_modulus *N)
20732b31808SJens Wiklander {
20832b31808SJens Wiklander     switch (N->int_rep) {
20932b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
21032b31808SJens Wiklander             return mbedtls_mpi_mod_raw_from_mont_rep(X, N);
21132b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_OPT_RED:
21232b31808SJens Wiklander             return 0;
21332b31808SJens Wiklander         default:
21432b31808SJens Wiklander             return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
21532b31808SJens Wiklander     }
21632b31808SJens Wiklander }
21732b31808SJens Wiklander 
mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint * X,mbedtls_mpi_uint min,const mbedtls_mpi_mod_modulus * N,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)21832b31808SJens Wiklander int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
21932b31808SJens Wiklander                                mbedtls_mpi_uint min,
22032b31808SJens Wiklander                                const mbedtls_mpi_mod_modulus *N,
22132b31808SJens Wiklander                                int (*f_rng)(void *, unsigned char *, size_t),
22232b31808SJens Wiklander                                void *p_rng)
22332b31808SJens Wiklander {
22432b31808SJens Wiklander     int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng);
22532b31808SJens Wiklander     if (ret != 0) {
22632b31808SJens Wiklander         return ret;
22732b31808SJens Wiklander     }
22832b31808SJens Wiklander     return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N);
22932b31808SJens Wiklander }
23032b31808SJens Wiklander 
mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)23132b31808SJens Wiklander int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
23232b31808SJens Wiklander                                     const mbedtls_mpi_mod_modulus *N)
23332b31808SJens Wiklander {
23432b31808SJens Wiklander     mbedtls_mpi_uint *T;
23532b31808SJens Wiklander     const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
23632b31808SJens Wiklander 
23732b31808SJens Wiklander     if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
23832b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
23932b31808SJens Wiklander     }
24032b31808SJens Wiklander 
24132b31808SJens Wiklander     mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,
24232b31808SJens Wiklander                                  N->rep.mont.mm, N->rep.mont.rr, T);
24332b31808SJens Wiklander 
244*b0563631STom Van Eyck     mbedtls_zeroize_and_free(T, t_limbs * ciL);
24532b31808SJens Wiklander     return 0;
24632b31808SJens Wiklander }
24732b31808SJens Wiklander 
mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)24832b31808SJens Wiklander int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
24932b31808SJens Wiklander                                       const mbedtls_mpi_mod_modulus *N)
25032b31808SJens Wiklander {
25132b31808SJens Wiklander     const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
25232b31808SJens Wiklander     mbedtls_mpi_uint *T;
25332b31808SJens Wiklander 
25432b31808SJens Wiklander     if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
25532b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
25632b31808SJens Wiklander     }
25732b31808SJens Wiklander 
25832b31808SJens Wiklander     mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);
25932b31808SJens Wiklander 
260*b0563631STom Van Eyck     mbedtls_zeroize_and_free(T, t_limbs * ciL);
26132b31808SJens Wiklander     return 0;
26232b31808SJens Wiklander }
26332b31808SJens Wiklander 
mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_mod_modulus * N)26432b31808SJens Wiklander void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
26532b31808SJens Wiklander                              const mbedtls_mpi_uint *A,
26632b31808SJens Wiklander                              const mbedtls_mpi_mod_modulus *N)
26732b31808SJens Wiklander {
26832b31808SJens Wiklander     mbedtls_mpi_core_sub(X, N->p, A, N->limbs);
26932b31808SJens Wiklander 
27032b31808SJens Wiklander     /* If A=0 initially, then X=N now. Detect this by
27132b31808SJens Wiklander      * subtracting N and catching the carry. */
27232b31808SJens Wiklander     mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
27332b31808SJens Wiklander     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);
27432b31808SJens Wiklander }
27532b31808SJens Wiklander 
276*b0563631STom Van Eyck #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */
277