1 /**
2 * Modular bignum functions
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include "common.h"
21
22 #if defined(MBEDTLS_BIGNUM_C)
23
24 #include <string.h>
25
26 #include "mbedtls/platform_util.h"
27 #include "mbedtls/error.h"
28 #include "mbedtls/bignum.h"
29
30 #include "mbedtls/platform.h"
31
32 #include "bignum_core.h"
33 #include "bignum_mod.h"
34 #include "bignum_mod_raw.h"
35 #include "constant_time_internal.h"
36
mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue * r,const mbedtls_mpi_mod_modulus * m,mbedtls_mpi_uint * p,size_t p_limbs)37 int mbedtls_mpi_mod_residue_setup( mbedtls_mpi_mod_residue *r,
38 const mbedtls_mpi_mod_modulus *m,
39 mbedtls_mpi_uint *p,
40 size_t p_limbs )
41 {
42 if( p_limbs != m->limbs || !mbedtls_mpi_core_lt_ct( p, m->p, m->limbs ) )
43 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
44
45 r->limbs = m->limbs;
46 r->p = p;
47
48 return( 0 );
49 }
50
mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue * r)51 void mbedtls_mpi_mod_residue_release( mbedtls_mpi_mod_residue *r )
52 {
53 if( r == NULL )
54 return;
55
56 r->limbs = 0;
57 r->p = NULL;
58 }
59
mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus * m)60 void mbedtls_mpi_mod_modulus_init( mbedtls_mpi_mod_modulus *m )
61 {
62 if( m == NULL )
63 return;
64
65 m->p = NULL;
66 m->limbs = 0;
67 m->bits = 0;
68 m->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
69 }
70
mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus * m)71 void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m )
72 {
73 if( m == NULL )
74 return;
75
76 switch( m->int_rep )
77 {
78 case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
79 if (m->rep.mont.rr != NULL)
80 {
81 mbedtls_platform_zeroize( (mbedtls_mpi_uint *) m->rep.mont.rr,
82 m->limbs );
83 mbedtls_free( (mbedtls_mpi_uint *)m->rep.mont.rr );
84 m->rep.mont.rr = NULL;
85 }
86 m->rep.mont.mm = 0;
87 break;
88 case MBEDTLS_MPI_MOD_REP_OPT_RED:
89 mbedtls_free( m->rep.ored );
90 break;
91 case MBEDTLS_MPI_MOD_REP_INVALID:
92 break;
93 }
94
95 m->p = NULL;
96 m->limbs = 0;
97 m->bits = 0;
98 m->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
99 }
100
set_mont_const_square(const mbedtls_mpi_uint ** X,const mbedtls_mpi_uint * A,size_t limbs)101 static int set_mont_const_square( const mbedtls_mpi_uint **X,
102 const mbedtls_mpi_uint *A,
103 size_t limbs )
104 {
105 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
106 mbedtls_mpi N;
107 mbedtls_mpi RR;
108 *X = NULL;
109
110 mbedtls_mpi_init( &N );
111 mbedtls_mpi_init( &RR );
112
113 if( A == NULL || limbs == 0 || limbs >= ( MBEDTLS_MPI_MAX_LIMBS / 2 ) - 2 )
114 goto cleanup;
115
116 if( mbedtls_mpi_grow( &N, limbs ) )
117 goto cleanup;
118
119 memcpy( N.p, A, sizeof(mbedtls_mpi_uint) * limbs );
120
121 ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
122
123 if( ret == 0 )
124 {
125 *X = RR.p;
126 RR.p = NULL;
127 }
128
129 cleanup:
130 mbedtls_mpi_free(&N);
131 mbedtls_mpi_free(&RR);
132 ret = ( ret != 0 ) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
133 return( ret );
134 }
135
mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus * m,const mbedtls_mpi_uint * p,size_t p_limbs,mbedtls_mpi_mod_rep_selector int_rep)136 int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
137 const mbedtls_mpi_uint *p,
138 size_t p_limbs,
139 mbedtls_mpi_mod_rep_selector int_rep )
140 {
141 int ret = 0;
142
143 m->p = p;
144 m->limbs = p_limbs;
145 m->bits = mbedtls_mpi_core_bitlen( p, p_limbs );
146
147 switch( int_rep )
148 {
149 case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
150 m->int_rep = int_rep;
151 m->rep.mont.mm = mbedtls_mpi_core_montmul_init( m->p );
152 ret = set_mont_const_square( &m->rep.mont.rr, m->p, m->limbs );
153 break;
154 case MBEDTLS_MPI_MOD_REP_OPT_RED:
155 m->int_rep = int_rep;
156 m->rep.ored = NULL;
157 break;
158 default:
159 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
160 goto exit;
161 }
162
163 exit:
164
165 if( ret != 0 )
166 {
167 mbedtls_mpi_mod_modulus_free( m );
168 }
169
170 return( ret );
171 }
172
173 /* BEGIN MERGE SLOT 1 */
174
175 /* END MERGE SLOT 1 */
176
177 /* BEGIN MERGE SLOT 2 */
178
179 /* END MERGE SLOT 2 */
180
181 /* BEGIN MERGE SLOT 3 */
mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue * X,const mbedtls_mpi_mod_residue * A,const mbedtls_mpi_mod_residue * B,const mbedtls_mpi_mod_modulus * N)182 int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X,
183 const mbedtls_mpi_mod_residue *A,
184 const mbedtls_mpi_mod_residue *B,
185 const mbedtls_mpi_mod_modulus *N )
186 {
187 if( X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs )
188 return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
189
190 mbedtls_mpi_mod_raw_sub( X->p, A->p, B->p, N );
191
192 return( 0 );
193 }
194 /* END MERGE SLOT 3 */
195
196 /* BEGIN MERGE SLOT 4 */
197
198 /* END MERGE SLOT 4 */
199
200 /* BEGIN MERGE SLOT 5 */
201
202 /* END MERGE SLOT 5 */
203
204 /* BEGIN MERGE SLOT 6 */
205
206 /* END MERGE SLOT 6 */
207
208 /* BEGIN MERGE SLOT 7 */
mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue * r,const mbedtls_mpi_mod_modulus * m,const unsigned char * buf,size_t buflen,mbedtls_mpi_mod_ext_rep ext_rep)209 int mbedtls_mpi_mod_read( mbedtls_mpi_mod_residue *r,
210 const mbedtls_mpi_mod_modulus *m,
211 const unsigned char *buf,
212 size_t buflen,
213 mbedtls_mpi_mod_ext_rep ext_rep )
214 {
215 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
216
217 /* Do our best to check if r and m have been set up */
218 if( r->limbs == 0 || m->limbs == 0 )
219 goto cleanup;
220 if( r->limbs != m->limbs )
221 goto cleanup;
222
223 ret = mbedtls_mpi_mod_raw_read( r->p, m, buf, buflen, ext_rep );
224 if( ret != 0 )
225 goto cleanup;
226
227 r->limbs = m->limbs;
228
229 if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
230 ret = mbedtls_mpi_mod_raw_to_mont_rep( r->p, m );
231
232 cleanup:
233 return ( ret );
234 }
235
mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue * r,const mbedtls_mpi_mod_modulus * m,unsigned char * buf,size_t buflen,mbedtls_mpi_mod_ext_rep ext_rep)236 int mbedtls_mpi_mod_write( const mbedtls_mpi_mod_residue *r,
237 const mbedtls_mpi_mod_modulus *m,
238 unsigned char *buf,
239 size_t buflen,
240 mbedtls_mpi_mod_ext_rep ext_rep )
241 {
242 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
243
244 /* Do our best to check if r and m have been set up */
245 if( r->limbs == 0 || m->limbs == 0 )
246 goto cleanup;
247 if( r->limbs != m->limbs )
248 goto cleanup;
249
250 if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
251 {
252 ret = mbedtls_mpi_mod_raw_from_mont_rep( r->p, m );
253 if( ret != 0 )
254 goto cleanup;
255 }
256
257 ret = mbedtls_mpi_mod_raw_write( r->p, m, buf, buflen, ext_rep );
258
259 if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
260 {
261 /* If this fails, the value of r is corrupted and we want to return
262 * this error (as opposed to the error code from the write above) to
263 * let the caller know. If it succeeds, we want to return the error
264 * code from write above. */
265 int conv_ret = mbedtls_mpi_mod_raw_to_mont_rep( r->p, m );
266 if( ret == 0 )
267 ret = conv_ret;
268 }
269
270 cleanup:
271
272 return ( ret );
273 }
274 /* END MERGE SLOT 7 */
275
276 /* BEGIN MERGE SLOT 8 */
277
278 /* END MERGE SLOT 8 */
279
280 /* BEGIN MERGE SLOT 9 */
281
282 /* END MERGE SLOT 9 */
283
284 /* BEGIN MERGE SLOT 10 */
285
286 /* END MERGE SLOT 10 */
287
288 #endif /* MBEDTLS_BIGNUM_C */
289