Переглянути джерело

[crypto] Force caller to provide temporary storage for modular calculations

bigint_mod_multiply() and bigint_mod_exp() require a fixed amount of
temporary storage for intermediate results.  (The amount of temporary
storage required depends upon the size of the integers involved.)

When performing calculations for 4096-bit RSA the amount of temporary
storage space required will exceed 2.5kB, which is too much to
allocate on the stack.  Avoid this problem by forcing the caller to
allocate temporary storage.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 роки тому
джерело
коміт
3ec773cd2b
5 змінених файлів з 99 додано та 40 видалено
  1. 37
    25
      src/crypto/bigint.c
  2. 6
    1
      src/crypto/rsa.c
  3. 41
    8
      src/include/ipxe/bigint.h
  4. 2
    0
      src/include/ipxe/rsa.h
  5. 13
    6
      src/tests/bigint_test.c

+ 37
- 25
src/crypto/bigint.c Переглянути файл

35
  * @v multiplier0	Element 0 of big integer to be multiplied
35
  * @v multiplier0	Element 0 of big integer to be multiplied
36
  * @v modulus0		Element 0 of big integer modulus
36
  * @v modulus0		Element 0 of big integer modulus
37
  * @v result0		Element 0 of big integer to hold result
37
  * @v result0		Element 0 of big integer to hold result
38
+ * @v size		Number of elements in base, modulus, and result
39
+ * @v tmp		Temporary working space
38
  */
40
  */
39
 void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
41
 void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
40
 			       const bigint_element_t *multiplier0,
42
 			       const bigint_element_t *multiplier0,
41
 			       const bigint_element_t *modulus0,
43
 			       const bigint_element_t *modulus0,
42
 			       bigint_element_t *result0,
44
 			       bigint_element_t *result0,
43
-			       unsigned int size ) {
45
+			       unsigned int size, void *tmp ) {
44
 	const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
46
 	const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
45
 		( ( const void * ) multiplicand0 );
47
 		( ( const void * ) multiplicand0 );
46
 	const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
48
 	const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
49
 		( ( const void * ) modulus0 );
51
 		( ( const void * ) modulus0 );
50
 	bigint_t ( size ) __attribute__ (( may_alias )) *result =
52
 	bigint_t ( size ) __attribute__ (( may_alias )) *result =
51
 		( ( void * ) result0 );
53
 		( ( void * ) result0 );
52
-	bigint_t ( size * 2 ) temp_result;
53
-	bigint_t ( size * 2 ) temp_modulus;
54
+	struct {
55
+		bigint_t ( size * 2 ) result;
56
+		bigint_t ( size * 2 ) modulus;
57
+	} *temp = tmp;
54
 	int rotation;
58
 	int rotation;
55
 	int i;
59
 	int i;
56
 
60
 
61
+	/* Sanity check */
62
+	assert ( sizeof ( *temp ) == bigint_mod_multiply_tmp_len ( modulus ) );
63
+
57
 	/* Perform multiplication */
64
 	/* Perform multiplication */
58
-	bigint_multiply ( multiplicand, multiplier, &temp_result );
65
+	bigint_multiply ( multiplicand, multiplier, &temp->result );
59
 
66
 
60
 	/* Rescale modulus to match result */
67
 	/* Rescale modulus to match result */
61
-	bigint_grow ( modulus, &temp_modulus );
62
-	rotation = ( bigint_max_set_bit ( &temp_result ) -
63
-		     bigint_max_set_bit ( &temp_modulus ) );
68
+	bigint_grow ( modulus, &temp->modulus );
69
+	rotation = ( bigint_max_set_bit ( &temp->result ) -
70
+		     bigint_max_set_bit ( &temp->modulus ) );
64
 	for ( i = 0 ; i < rotation ; i++ )
71
 	for ( i = 0 ; i < rotation ; i++ )
65
-		bigint_rol ( &temp_modulus );
72
+		bigint_rol ( &temp->modulus );
66
 
73
 
67
 	/* Subtract multiples of modulus */
74
 	/* Subtract multiples of modulus */
68
 	for ( i = 0 ; i <= rotation ; i++ ) {
75
 	for ( i = 0 ; i <= rotation ; i++ ) {
69
-		if ( bigint_is_geq ( &temp_result, &temp_modulus ) )
70
-			bigint_subtract ( &temp_modulus, &temp_result );
71
-		bigint_ror ( &temp_modulus );
76
+		if ( bigint_is_geq ( &temp->result, &temp->modulus ) )
77
+			bigint_subtract ( &temp->modulus, &temp->result );
78
+		bigint_ror ( &temp->modulus );
72
 	}
79
 	}
73
 
80
 
74
 	/* Resize result */
81
 	/* Resize result */
75
-	bigint_shrink ( &temp_result, result );
82
+	bigint_shrink ( &temp->result, result );
76
 
83
 
77
 	/* Sanity check */
84
 	/* Sanity check */
78
 	assert ( bigint_is_geq ( modulus, result ) );
85
 	assert ( bigint_is_geq ( modulus, result ) );
87
  * @v result0		Element 0 of big integer to hold result
94
  * @v result0		Element 0 of big integer to hold result
88
  * @v size		Number of elements in base, modulus, and result
95
  * @v size		Number of elements in base, modulus, and result
89
  * @v exponent_size	Number of elements in exponent
96
  * @v exponent_size	Number of elements in exponent
97
+ * @v tmp		Temporary working space
90
  */
98
  */
91
 void bigint_mod_exp_raw ( const bigint_element_t *base0,
99
 void bigint_mod_exp_raw ( const bigint_element_t *base0,
92
 			  const bigint_element_t *modulus0,
100
 			  const bigint_element_t *modulus0,
93
 			  const bigint_element_t *exponent0,
101
 			  const bigint_element_t *exponent0,
94
 			  bigint_element_t *result0,
102
 			  bigint_element_t *result0,
95
-			  unsigned int size,
96
-			  unsigned int exponent_size ) {
103
+			  unsigned int size, unsigned int exponent_size,
104
+			  void *tmp ) {
97
 	const bigint_t ( size ) __attribute__ (( may_alias )) *base =
105
 	const bigint_t ( size ) __attribute__ (( may_alias )) *base =
98
 		( ( const void * ) base0 );
106
 		( ( const void * ) base0 );
99
 	const bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
107
 	const bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
102
 		*exponent = ( ( const void * ) exponent0 );
110
 		*exponent = ( ( const void * ) exponent0 );
103
 	bigint_t ( size ) __attribute__ (( may_alias )) *result =
111
 	bigint_t ( size ) __attribute__ (( may_alias )) *result =
104
 		( ( void * ) result0 );
112
 		( ( void * ) result0 );
105
-	bigint_t ( size ) temp_base;
106
-	bigint_t ( exponent_size ) temp_exponent;
113
+	size_t mod_multiply_len = bigint_mod_multiply_tmp_len ( modulus );
114
+	struct {
115
+		bigint_t ( size ) base;
116
+		bigint_t ( exponent_size ) exponent;
117
+		uint8_t mod_multiply[mod_multiply_len];
118
+	} *temp = tmp;
107
 	static const uint8_t start[1] = { 0x01 };
119
 	static const uint8_t start[1] = { 0x01 };
108
 
120
 
109
-	memcpy ( &temp_base, base, sizeof ( temp_base ) );
110
-	memcpy ( &temp_exponent, exponent, sizeof ( temp_exponent ) );
121
+	memcpy ( &temp->base, base, sizeof ( temp->base ) );
122
+	memcpy ( &temp->exponent, exponent, sizeof ( temp->exponent ) );
111
 	bigint_init ( result, start, sizeof ( start ) );
123
 	bigint_init ( result, start, sizeof ( start ) );
112
 
124
 
113
-	while ( ! bigint_is_zero ( &temp_exponent ) ) {
114
-		if ( bigint_bit_is_set ( &temp_exponent, 0 ) ) {
115
-			bigint_mod_multiply ( result, &temp_base,
116
-					      modulus, result );
125
+	while ( ! bigint_is_zero ( &temp->exponent ) ) {
126
+		if ( bigint_bit_is_set ( &temp->exponent, 0 ) ) {
127
+			bigint_mod_multiply ( result, &temp->base, modulus,
128
+					      result, temp->mod_multiply );
117
 		}
129
 		}
118
-		bigint_ror ( &temp_exponent );
119
-		bigint_mod_multiply ( &temp_base, &temp_base, modulus,
120
-				      &temp_base );
130
+		bigint_ror ( &temp->exponent );
131
+		bigint_mod_multiply ( &temp->base, &temp->base, modulus,
132
+				      &temp->base, temp->mod_multiply );
121
 	}
133
 	}
122
 }
134
 }

+ 6
- 1
src/crypto/rsa.c Переглянути файл

123
 		       size_t exponent_len ) {
123
 		       size_t exponent_len ) {
124
 	unsigned int size = bigint_required_size ( modulus_len );
124
 	unsigned int size = bigint_required_size ( modulus_len );
125
 	unsigned int exponent_size = bigint_required_size ( exponent_len );
125
 	unsigned int exponent_size = bigint_required_size ( exponent_len );
126
+	bigint_t ( size ) *modulus;
127
+	bigint_t ( exponent_size ) *exponent;
128
+	size_t tmp_len = bigint_mod_exp_tmp_len ( modulus, exponent );
126
 	struct {
129
 	struct {
127
 		bigint_t ( size ) modulus;
130
 		bigint_t ( size ) modulus;
128
 		bigint_t ( exponent_size ) exponent;
131
 		bigint_t ( exponent_size ) exponent;
129
 		bigint_t ( size ) input;
132
 		bigint_t ( size ) input;
130
 		bigint_t ( size ) output;
133
 		bigint_t ( size ) output;
134
+		uint8_t tmp[tmp_len];
131
 	} __attribute__ (( packed )) *dynamic;
135
 	} __attribute__ (( packed )) *dynamic;
132
 
136
 
133
 	/* Free any existing dynamic storage */
137
 	/* Free any existing dynamic storage */
147
 	context->exponent_size = exponent_size;
151
 	context->exponent_size = exponent_size;
148
 	context->input0 = &dynamic->input.element[0];
152
 	context->input0 = &dynamic->input.element[0];
149
 	context->output0 = &dynamic->output.element[0];
153
 	context->output0 = &dynamic->output.element[0];
154
+	context->tmp = &dynamic->tmp;
150
 
155
 
151
 	return 0;
156
 	return 0;
152
 }
157
 }
309
 	bigint_init ( input, in, context->max_len );
314
 	bigint_init ( input, in, context->max_len );
310
 
315
 
311
 	/* Perform modular exponentiation */
316
 	/* Perform modular exponentiation */
312
-	bigint_mod_exp ( input, modulus, exponent, output );
317
+	bigint_mod_exp ( input, modulus, exponent, output, context->tmp );
313
 
318
 
314
 	/* Copy out result */
319
 	/* Copy out result */
315
 	bigint_done ( output, out, context->max_len );
320
 	bigint_done ( output, out, context->max_len );

+ 41
- 8
src/include/ipxe/bigint.h Переглянути файл

197
  * @v multiplier	Big integer to be multiplied
197
  * @v multiplier	Big integer to be multiplied
198
  * @v modulus		Big integer modulus
198
  * @v modulus		Big integer modulus
199
  * @v result		Big integer to hold result
199
  * @v result		Big integer to hold result
200
+ * @v tmp		Temporary working space
200
  */
201
  */
201
 #define bigint_mod_multiply( multiplicand, multiplier, modulus,		\
202
 #define bigint_mod_multiply( multiplicand, multiplier, modulus,		\
202
-			     result ) do {				\
203
+			     result, tmp ) do {				\
203
 	unsigned int size = bigint_size (multiplicand);			\
204
 	unsigned int size = bigint_size (multiplicand);			\
204
 	bigint_mod_multiply_raw ( (multiplicand)->element,		\
205
 	bigint_mod_multiply_raw ( (multiplicand)->element,		\
205
 				  (multiplier)->element,		\
206
 				  (multiplier)->element,		\
206
 				  (modulus)->element,			\
207
 				  (modulus)->element,			\
207
-				  (result)->element, size );		\
208
+				  (result)->element, size, tmp );	\
208
 	} while ( 0 )
209
 	} while ( 0 )
209
 
210
 
211
+/**
212
+ * Calculate temporary working space required for moduluar multiplication
213
+ *
214
+ * @v modulus		Big integer modulus
215
+ * @ret len		Length of temporary working space
216
+ */
217
+#define bigint_mod_multiply_tmp_len( modulus ) ( {			\
218
+	unsigned int size = bigint_size (modulus);			\
219
+	sizeof ( struct {						\
220
+		bigint_t ( size * 2 ) temp_result;			\
221
+		bigint_t ( size * 2 ) temp_modulus;			\
222
+	} ); } )
223
+
210
 /**
224
 /**
211
  * Perform modular exponentiation of big integers
225
  * Perform modular exponentiation of big integers
212
  *
226
  *
214
  * @v modulus		Big integer modulus
228
  * @v modulus		Big integer modulus
215
  * @v exponent		Big integer exponent
229
  * @v exponent		Big integer exponent
216
  * @v result		Big integer to hold result
230
  * @v result		Big integer to hold result
231
+ * @v tmp		Temporary working space
217
  */
232
  */
218
-#define bigint_mod_exp( base, modulus, exponent, result ) do {		\
233
+#define bigint_mod_exp( base, modulus, exponent, result, tmp ) do {	\
219
 	unsigned int size = bigint_size (base);				\
234
 	unsigned int size = bigint_size (base);				\
220
 	unsigned int exponent_size = bigint_size (exponent);		\
235
 	unsigned int exponent_size = bigint_size (exponent);		\
221
 	bigint_mod_exp_raw ( (base)->element, (modulus)->element,	\
236
 	bigint_mod_exp_raw ( (base)->element, (modulus)->element,	\
222
-			  (exponent)->element, (result)->element,	\
223
-			  size, exponent_size );			\
237
+			     (exponent)->element, (result)->element,	\
238
+			     size, exponent_size, tmp );		\
224
 	} while ( 0 )
239
 	} while ( 0 )
225
 
240
 
241
+/**
242
+ * Calculate temporary working space required for moduluar exponentiation
243
+ *
244
+ * @v modulus		Big integer modulus
245
+ * @v exponent		Big integer exponent
246
+ * @ret len		Length of temporary working space
247
+ */
248
+#define bigint_mod_exp_tmp_len( modulus, exponent ) ( {			\
249
+	unsigned int size = bigint_size (modulus);			\
250
+	unsigned int exponent_size = bigint_size (exponent);		\
251
+	size_t mod_multiply_len =					\
252
+		bigint_mod_multiply_tmp_len (modulus);			\
253
+	sizeof ( struct {						\
254
+		bigint_t ( size ) temp_base;				\
255
+		bigint_t ( exponent_size ) temp_exponent;		\
256
+		uint8_t mod_multiply[mod_multiply_len];			\
257
+	} ); } )
258
+
226
 #include <bits/bigint.h>
259
 #include <bits/bigint.h>
227
 
260
 
228
 void bigint_init_raw ( bigint_element_t *value0, unsigned int size,
261
 void bigint_init_raw ( bigint_element_t *value0, unsigned int size,
257
 			       const bigint_element_t *multiplier0,
290
 			       const bigint_element_t *multiplier0,
258
 			       const bigint_element_t *modulus0,
291
 			       const bigint_element_t *modulus0,
259
 			       bigint_element_t *result0,
292
 			       bigint_element_t *result0,
260
-			       unsigned int size );
293
+			       unsigned int size, void *tmp );
261
 void bigint_mod_exp_raw ( const bigint_element_t *base0,
294
 void bigint_mod_exp_raw ( const bigint_element_t *base0,
262
 			  const bigint_element_t *modulus0,
295
 			  const bigint_element_t *modulus0,
263
 			  const bigint_element_t *exponent0,
296
 			  const bigint_element_t *exponent0,
264
 			  bigint_element_t *result0,
297
 			  bigint_element_t *result0,
265
-			  unsigned int size,
266
-			  unsigned int exponent_size );
298
+			  unsigned int size, unsigned int exponent_size,
299
+			  void *tmp );
267
 
300
 
268
 #endif /* _IPXE_BIGINT_H */
301
 #endif /* _IPXE_BIGINT_H */

+ 2
- 0
src/include/ipxe/rsa.h Переглянути файл

129
 	bigint_element_t *input0;
129
 	bigint_element_t *input0;
130
 	/** Output buffer */
130
 	/** Output buffer */
131
 	bigint_element_t *output0;
131
 	bigint_element_t *output0;
132
+	/** Temporary working space for modular exponentiation */
133
+	void *tmp;
132
 };
134
 };
133
 
135
 
134
 extern struct pubkey_algorithm rsa_algorithm;
136
 extern struct pubkey_algorithm rsa_algorithm;

+ 13
- 6
src/tests/bigint_test.c Переглянути файл

162
 				  const bigint_element_t *multiplier0,
162
 				  const bigint_element_t *multiplier0,
163
 				  const bigint_element_t *modulus0,
163
 				  const bigint_element_t *modulus0,
164
 				  bigint_element_t *result0,
164
 				  bigint_element_t *result0,
165
-				  unsigned int size ) {
165
+				  unsigned int size,
166
+				  void *tmp ) {
166
 	const bigint_t ( size ) *multiplicand __attribute__ (( may_alias ))
167
 	const bigint_t ( size ) *multiplicand __attribute__ (( may_alias ))
167
 		= ( ( const void * ) multiplicand0 );
168
 		= ( ( const void * ) multiplicand0 );
168
 	const bigint_t ( size ) *multiplier __attribute__ (( may_alias ))
169
 	const bigint_t ( size ) *multiplier __attribute__ (( may_alias ))
172
 	bigint_t ( size ) *result __attribute__ (( may_alias ))
173
 	bigint_t ( size ) *result __attribute__ (( may_alias ))
173
 		= ( ( void * ) result0 );
174
 		= ( ( void * ) result0 );
174
 
175
 
175
-	bigint_mod_multiply ( multiplicand, multiplier, modulus, result );
176
+	bigint_mod_multiply ( multiplicand, multiplier, modulus, result, tmp );
176
 }
177
 }
177
 
178
 
178
 void bigint_mod_exp_sample ( const bigint_element_t *base0,
179
 void bigint_mod_exp_sample ( const bigint_element_t *base0,
179
 			     const bigint_element_t *modulus0,
180
 			     const bigint_element_t *modulus0,
180
 			     const bigint_element_t *exponent0,
181
 			     const bigint_element_t *exponent0,
181
 			     bigint_element_t *result0,
182
 			     bigint_element_t *result0,
182
-			     unsigned int size, unsigned int exponent_size ) {
183
+			     unsigned int size, unsigned int exponent_size,
184
+			     void *tmp ) {
183
 	const bigint_t ( size ) *base __attribute__ (( may_alias ))
185
 	const bigint_t ( size ) *base __attribute__ (( may_alias ))
184
 		= ( ( const void * ) base0 );
186
 		= ( ( const void * ) base0 );
185
 	const bigint_t ( size ) *modulus __attribute__ (( may_alias ))
187
 	const bigint_t ( size ) *modulus __attribute__ (( may_alias ))
189
 	bigint_t ( size ) *result __attribute__ (( may_alias ))
191
 	bigint_t ( size ) *result __attribute__ (( may_alias ))
190
 		= ( ( void * ) result0 );
192
 		= ( ( void * ) result0 );
191
 
193
 
192
-	bigint_mod_exp ( base, modulus, exponent, result );
194
+	bigint_mod_exp ( base, modulus, exponent, result, tmp );
193
 }
195
 }
194
 
196
 
195
 /**
197
 /**
471
 	bigint_t ( size ) multiplier_temp;				\
473
 	bigint_t ( size ) multiplier_temp;				\
472
 	bigint_t ( size ) modulus_temp;					\
474
 	bigint_t ( size ) modulus_temp;					\
473
 	bigint_t ( size ) result_temp;					\
475
 	bigint_t ( size ) result_temp;					\
476
+	size_t tmp_len = bigint_mod_multiply_tmp_len ( &modulus_temp ); \
477
+	uint8_t tmp[tmp_len];						\
474
 	{} /* Fix emacs alignment */					\
478
 	{} /* Fix emacs alignment */					\
475
 									\
479
 									\
476
 	assert ( bigint_size ( &multiplier_temp ) ==			\
480
 	assert ( bigint_size ( &multiplier_temp ) ==			\
490
 	DBG_HDA ( 0, &multiplier_temp, sizeof ( multiplier_temp ) );	\
494
 	DBG_HDA ( 0, &multiplier_temp, sizeof ( multiplier_temp ) );	\
491
 	DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) );		\
495
 	DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) );		\
492
 	bigint_mod_multiply ( &multiplicand_temp, &multiplier_temp,	\
496
 	bigint_mod_multiply ( &multiplicand_temp, &multiplier_temp,	\
493
-			      &modulus_temp, &result_temp );		\
497
+			      &modulus_temp, &result_temp, tmp );	\
494
 	DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) );		\
498
 	DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) );		\
495
 	bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
499
 	bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
496
 									\
500
 									\
520
 	bigint_t ( size ) modulus_temp;					\
524
 	bigint_t ( size ) modulus_temp;					\
521
 	bigint_t ( exponent_size ) exponent_temp;			\
525
 	bigint_t ( exponent_size ) exponent_temp;			\
522
 	bigint_t ( size ) result_temp;					\
526
 	bigint_t ( size ) result_temp;					\
527
+	size_t tmp_len = bigint_mod_exp_tmp_len ( &modulus_temp,	\
528
+						  &exponent_temp );	\
529
+	uint8_t tmp[tmp_len];						\
523
 	{} /* Fix emacs alignment */					\
530
 	{} /* Fix emacs alignment */					\
524
 									\
531
 									\
525
 	assert ( bigint_size ( &modulus_temp ) ==			\
532
 	assert ( bigint_size ( &modulus_temp ) ==			\
536
 	DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) );		\
543
 	DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) );		\
537
 	DBG_HDA ( 0, &exponent_temp, sizeof ( exponent_temp ) );	\
544
 	DBG_HDA ( 0, &exponent_temp, sizeof ( exponent_temp ) );	\
538
 	bigint_mod_exp ( &base_temp, &modulus_temp, &exponent_temp,	\
545
 	bigint_mod_exp ( &base_temp, &modulus_temp, &exponent_temp,	\
539
-			 &result_temp );				\
546
+			 &result_temp, tmp );				\
540
 	DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) );		\
547
 	DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) );		\
541
 	bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
548
 	bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
542
 									\
549
 									\

Завантаження…
Відмінити
Зберегти