bignum_mod_raw.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /*
  2. * Low-level modular bignum functions
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. */
  7. #include "common.h"
  8. #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
  9. #include <string.h>
  10. #include "mbedtls/error.h"
  11. #include "mbedtls/platform_util.h"
  12. #include "mbedtls/platform.h"
  13. #include "bignum_core.h"
  14. #include "bignum_mod_raw.h"
  15. #include "bignum_mod.h"
  16. #include "constant_time_internal.h"
  17. #include "bignum_mod_raw_invasive.h"
  18. void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
  19. const mbedtls_mpi_uint *A,
  20. const mbedtls_mpi_mod_modulus *N,
  21. unsigned char assign)
  22. {
  23. mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));
  24. }
  25. void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
  26. mbedtls_mpi_uint *Y,
  27. const mbedtls_mpi_mod_modulus *N,
  28. unsigned char swap)
  29. {
  30. mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));
  31. }
  32. int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
  33. const mbedtls_mpi_mod_modulus *N,
  34. const unsigned char *input,
  35. size_t input_length,
  36. mbedtls_mpi_mod_ext_rep ext_rep)
  37. {
  38. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  39. switch (ext_rep) {
  40. case MBEDTLS_MPI_MOD_EXT_REP_LE:
  41. ret = mbedtls_mpi_core_read_le(X, N->limbs,
  42. input, input_length);
  43. break;
  44. case MBEDTLS_MPI_MOD_EXT_REP_BE:
  45. ret = mbedtls_mpi_core_read_be(X, N->limbs,
  46. input, input_length);
  47. break;
  48. default:
  49. return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
  50. }
  51. if (ret != 0) {
  52. goto cleanup;
  53. }
  54. if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) {
  55. ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
  56. goto cleanup;
  57. }
  58. cleanup:
  59. return ret;
  60. }
  61. int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
  62. const mbedtls_mpi_mod_modulus *N,
  63. unsigned char *output,
  64. size_t output_length,
  65. mbedtls_mpi_mod_ext_rep ext_rep)
  66. {
  67. switch (ext_rep) {
  68. case MBEDTLS_MPI_MOD_EXT_REP_LE:
  69. return mbedtls_mpi_core_write_le(A, N->limbs,
  70. output, output_length);
  71. case MBEDTLS_MPI_MOD_EXT_REP_BE:
  72. return mbedtls_mpi_core_write_be(A, N->limbs,
  73. output, output_length);
  74. default:
  75. return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
  76. }
  77. }
  78. void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
  79. const mbedtls_mpi_uint *A,
  80. const mbedtls_mpi_uint *B,
  81. const mbedtls_mpi_mod_modulus *N)
  82. {
  83. mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs);
  84. (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
  85. }
  86. MBEDTLS_STATIC_TESTABLE
  87. void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
  88. const mbedtls_mpi_mod_modulus *N)
  89. {
  90. mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
  91. (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
  92. }
  93. void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
  94. const mbedtls_mpi_uint *A,
  95. const mbedtls_mpi_uint *B,
  96. const mbedtls_mpi_mod_modulus *N,
  97. mbedtls_mpi_uint *T)
  98. {
  99. /* Standard (A * B) multiplication stored into pre-allocated T
  100. * buffer of fixed limb size of (2N + 1).
  101. *
  102. * The space may not not fully filled by when
  103. * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */
  104. const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2;
  105. switch (N->int_rep) {
  106. case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
  107. mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
  108. N->rep.mont.mm, T);
  109. break;
  110. case MBEDTLS_MPI_MOD_REP_OPT_RED:
  111. mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs);
  112. /* Optimised Reduction */
  113. (*N->rep.ored.modp)(T, T_limbs);
  114. /* Convert back to canonical representation */
  115. mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N);
  116. memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint));
  117. break;
  118. default:
  119. break;
  120. }
  121. }
  122. size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)
  123. {
  124. /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent,
  125. * which will be the same size as the modulus and input (AN_limbs),
  126. * and additional space to pass to mbedtls_mpi_core_exp_mod(). */
  127. return AN_limbs +
  128. mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs);
  129. }
  130. void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,
  131. const mbedtls_mpi_uint *A,
  132. const mbedtls_mpi_uint *N,
  133. size_t AN_limbs,
  134. const mbedtls_mpi_uint *RR,
  135. mbedtls_mpi_uint *T)
  136. {
  137. /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and
  138. * |G| = N - 1, so we want
  139. * g^(|G|-1) = g^(N - 2)
  140. */
  141. /* Use the first AN_limbs of T to hold N - 2 */
  142. mbedtls_mpi_uint *Nminus2 = T;
  143. (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs);
  144. /* Rest of T is given to exp_mod for its working space */
  145. mbedtls_mpi_core_exp_mod(X,
  146. A, N, AN_limbs, Nminus2, AN_limbs,
  147. RR, T + AN_limbs);
  148. }
  149. void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
  150. const mbedtls_mpi_uint *A,
  151. const mbedtls_mpi_uint *B,
  152. const mbedtls_mpi_mod_modulus *N)
  153. {
  154. mbedtls_mpi_uint carry, borrow;
  155. carry = mbedtls_mpi_core_add(X, A, B, N->limbs);
  156. borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
  157. (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow));
  158. }
  159. int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
  160. mbedtls_mpi_uint *X,
  161. const mbedtls_mpi_mod_modulus *N)
  162. {
  163. switch (N->int_rep) {
  164. case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
  165. return mbedtls_mpi_mod_raw_to_mont_rep(X, N);
  166. case MBEDTLS_MPI_MOD_REP_OPT_RED:
  167. return 0;
  168. default:
  169. return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
  170. }
  171. }
  172. int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
  173. mbedtls_mpi_uint *X,
  174. const mbedtls_mpi_mod_modulus *N)
  175. {
  176. switch (N->int_rep) {
  177. case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
  178. return mbedtls_mpi_mod_raw_from_mont_rep(X, N);
  179. case MBEDTLS_MPI_MOD_REP_OPT_RED:
  180. return 0;
  181. default:
  182. return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
  183. }
  184. }
  185. int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
  186. mbedtls_mpi_uint min,
  187. const mbedtls_mpi_mod_modulus *N,
  188. int (*f_rng)(void *, unsigned char *, size_t),
  189. void *p_rng)
  190. {
  191. int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng);
  192. if (ret != 0) {
  193. return ret;
  194. }
  195. return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N);
  196. }
  197. int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
  198. const mbedtls_mpi_mod_modulus *N)
  199. {
  200. mbedtls_mpi_uint *T;
  201. const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
  202. if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
  203. return MBEDTLS_ERR_MPI_ALLOC_FAILED;
  204. }
  205. mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,
  206. N->rep.mont.mm, N->rep.mont.rr, T);
  207. mbedtls_zeroize_and_free(T, t_limbs * ciL);
  208. return 0;
  209. }
  210. int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
  211. const mbedtls_mpi_mod_modulus *N)
  212. {
  213. const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
  214. mbedtls_mpi_uint *T;
  215. if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
  216. return MBEDTLS_ERR_MPI_ALLOC_FAILED;
  217. }
  218. mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);
  219. mbedtls_zeroize_and_free(T, t_limbs * ciL);
  220. return 0;
  221. }
  222. void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
  223. const mbedtls_mpi_uint *A,
  224. const mbedtls_mpi_mod_modulus *N)
  225. {
  226. mbedtls_mpi_core_sub(X, N->p, A, N->limbs);
  227. /* If A=0 initially, then X=N now. Detect this by
  228. * subtracting N and catching the carry. */
  229. mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
  230. (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);
  231. }
  232. #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */