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