Browse Source

[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 years ago
parent
commit
3ec773cd2b
5 changed files with 99 additions and 40 deletions
  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 View File

@@ -35,12 +35,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
35 35
  * @v multiplier0	Element 0 of big integer to be multiplied
36 36
  * @v modulus0		Element 0 of big integer modulus
37 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 41
 void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
40 42
 			       const bigint_element_t *multiplier0,
41 43
 			       const bigint_element_t *modulus0,
42 44
 			       bigint_element_t *result0,
43
-			       unsigned int size ) {
45
+			       unsigned int size, void *tmp ) {
44 46
 	const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
45 47
 		( ( const void * ) multiplicand0 );
46 48
 	const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
@@ -49,30 +51,35 @@ void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
49 51
 		( ( const void * ) modulus0 );
50 52
 	bigint_t ( size ) __attribute__ (( may_alias )) *result =
51 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 58
 	int rotation;
55 59
 	int i;
56 60
 
61
+	/* Sanity check */
62
+	assert ( sizeof ( *temp ) == bigint_mod_multiply_tmp_len ( modulus ) );
63
+
57 64
 	/* Perform multiplication */
58
-	bigint_multiply ( multiplicand, multiplier, &temp_result );
65
+	bigint_multiply ( multiplicand, multiplier, &temp->result );
59 66
 
60 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 71
 	for ( i = 0 ; i < rotation ; i++ )
65
-		bigint_rol ( &temp_modulus );
72
+		bigint_rol ( &temp->modulus );
66 73
 
67 74
 	/* Subtract multiples of modulus */
68 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 81
 	/* Resize result */
75
-	bigint_shrink ( &temp_result, result );
82
+	bigint_shrink ( &temp->result, result );
76 83
 
77 84
 	/* Sanity check */
78 85
 	assert ( bigint_is_geq ( modulus, result ) );
@@ -87,13 +94,14 @@ void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
87 94
  * @v result0		Element 0 of big integer to hold result
88 95
  * @v size		Number of elements in base, modulus, and result
89 96
  * @v exponent_size	Number of elements in exponent
97
+ * @v tmp		Temporary working space
90 98
  */
91 99
 void bigint_mod_exp_raw ( const bigint_element_t *base0,
92 100
 			  const bigint_element_t *modulus0,
93 101
 			  const bigint_element_t *exponent0,
94 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 105
 	const bigint_t ( size ) __attribute__ (( may_alias )) *base =
98 106
 		( ( const void * ) base0 );
99 107
 	const bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
@@ -102,21 +110,25 @@ void bigint_mod_exp_raw ( const bigint_element_t *base0,
102 110
 		*exponent = ( ( const void * ) exponent0 );
103 111
 	bigint_t ( size ) __attribute__ (( may_alias )) *result =
104 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 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 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 View File

@@ -123,11 +123,15 @@ static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
123 123
 		       size_t exponent_len ) {
124 124
 	unsigned int size = bigint_required_size ( modulus_len );
125 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 129
 	struct {
127 130
 		bigint_t ( size ) modulus;
128 131
 		bigint_t ( exponent_size ) exponent;
129 132
 		bigint_t ( size ) input;
130 133
 		bigint_t ( size ) output;
134
+		uint8_t tmp[tmp_len];
131 135
 	} __attribute__ (( packed )) *dynamic;
132 136
 
133 137
 	/* Free any existing dynamic storage */
@@ -147,6 +151,7 @@ static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
147 151
 	context->exponent_size = exponent_size;
148 152
 	context->input0 = &dynamic->input.element[0];
149 153
 	context->output0 = &dynamic->output.element[0];
154
+	context->tmp = &dynamic->tmp;
150 155
 
151 156
 	return 0;
152 157
 }
@@ -309,7 +314,7 @@ static void rsa_cipher ( struct rsa_context *context,
309 314
 	bigint_init ( input, in, context->max_len );
310 315
 
311 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 319
 	/* Copy out result */
315 320
 	bigint_done ( output, out, context->max_len );

+ 41
- 8
src/include/ipxe/bigint.h View File

@@ -197,16 +197,30 @@ FILE_LICENCE ( GPL2_OR_LATER );
197 197
  * @v multiplier	Big integer to be multiplied
198 198
  * @v modulus		Big integer modulus
199 199
  * @v result		Big integer to hold result
200
+ * @v tmp		Temporary working space
200 201
  */
201 202
 #define bigint_mod_multiply( multiplicand, multiplier, modulus,		\
202
-			     result ) do {				\
203
+			     result, tmp ) do {				\
203 204
 	unsigned int size = bigint_size (multiplicand);			\
204 205
 	bigint_mod_multiply_raw ( (multiplicand)->element,		\
205 206
 				  (multiplier)->element,		\
206 207
 				  (modulus)->element,			\
207
-				  (result)->element, size );		\
208
+				  (result)->element, size, tmp );	\
208 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 225
  * Perform modular exponentiation of big integers
212 226
  *
@@ -214,15 +228,34 @@ FILE_LICENCE ( GPL2_OR_LATER );
214 228
  * @v modulus		Big integer modulus
215 229
  * @v exponent		Big integer exponent
216 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 234
 	unsigned int size = bigint_size (base);				\
220 235
 	unsigned int exponent_size = bigint_size (exponent);		\
221 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 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 259
 #include <bits/bigint.h>
227 260
 
228 261
 void bigint_init_raw ( bigint_element_t *value0, unsigned int size,
@@ -257,12 +290,12 @@ void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
257 290
 			       const bigint_element_t *multiplier0,
258 291
 			       const bigint_element_t *modulus0,
259 292
 			       bigint_element_t *result0,
260
-			       unsigned int size );
293
+			       unsigned int size, void *tmp );
261 294
 void bigint_mod_exp_raw ( const bigint_element_t *base0,
262 295
 			  const bigint_element_t *modulus0,
263 296
 			  const bigint_element_t *exponent0,
264 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 301
 #endif /* _IPXE_BIGINT_H */

+ 2
- 0
src/include/ipxe/rsa.h View File

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

+ 13
- 6
src/tests/bigint_test.c View File

@@ -162,7 +162,8 @@ void bigint_mod_multiply_sample ( const bigint_element_t *multiplicand0,
162 162
 				  const bigint_element_t *multiplier0,
163 163
 				  const bigint_element_t *modulus0,
164 164
 				  bigint_element_t *result0,
165
-				  unsigned int size ) {
165
+				  unsigned int size,
166
+				  void *tmp ) {
166 167
 	const bigint_t ( size ) *multiplicand __attribute__ (( may_alias ))
167 168
 		= ( ( const void * ) multiplicand0 );
168 169
 	const bigint_t ( size ) *multiplier __attribute__ (( may_alias ))
@@ -172,14 +173,15 @@ void bigint_mod_multiply_sample ( const bigint_element_t *multiplicand0,
172 173
 	bigint_t ( size ) *result __attribute__ (( may_alias ))
173 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 179
 void bigint_mod_exp_sample ( const bigint_element_t *base0,
179 180
 			     const bigint_element_t *modulus0,
180 181
 			     const bigint_element_t *exponent0,
181 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 185
 	const bigint_t ( size ) *base __attribute__ (( may_alias ))
184 186
 		= ( ( const void * ) base0 );
185 187
 	const bigint_t ( size ) *modulus __attribute__ (( may_alias ))
@@ -189,7 +191,7 @@ void bigint_mod_exp_sample ( const bigint_element_t *base0,
189 191
 	bigint_t ( size ) *result __attribute__ (( may_alias ))
190 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,6 +473,8 @@ void bigint_mod_exp_sample ( const bigint_element_t *base0,
471 473
 	bigint_t ( size ) multiplier_temp;				\
472 474
 	bigint_t ( size ) modulus_temp;					\
473 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 478
 	{} /* Fix emacs alignment */					\
475 479
 									\
476 480
 	assert ( bigint_size ( &multiplier_temp ) ==			\
@@ -490,7 +494,7 @@ void bigint_mod_exp_sample ( const bigint_element_t *base0,
490 494
 	DBG_HDA ( 0, &multiplier_temp, sizeof ( multiplier_temp ) );	\
491 495
 	DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) );		\
492 496
 	bigint_mod_multiply ( &multiplicand_temp, &multiplier_temp,	\
493
-			      &modulus_temp, &result_temp );		\
497
+			      &modulus_temp, &result_temp, tmp );	\
494 498
 	DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) );		\
495 499
 	bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
496 500
 									\
@@ -520,6 +524,9 @@ void bigint_mod_exp_sample ( const bigint_element_t *base0,
520 524
 	bigint_t ( size ) modulus_temp;					\
521 525
 	bigint_t ( exponent_size ) exponent_temp;			\
522 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 530
 	{} /* Fix emacs alignment */					\
524 531
 									\
525 532
 	assert ( bigint_size ( &modulus_temp ) ==			\
@@ -536,7 +543,7 @@ void bigint_mod_exp_sample ( const bigint_element_t *base0,
536 543
 	DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) );		\
537 544
 	DBG_HDA ( 0, &exponent_temp, sizeof ( exponent_temp ) );	\
538 545
 	bigint_mod_exp ( &base_temp, &modulus_temp, &exponent_temp,	\
539
-			 &result_temp );				\
546
+			 &result_temp, tmp );				\
540 547
 	DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) );		\
541 548
 	bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\
542 549
 									\

Loading…
Cancel
Save