Skip to content

Commit 3cdb3da

Browse files
Merge pull request #297 from gilles-peskine-arm/asn1_get_int-undefined_shift
Fix int overflow in mbedtls_asn1_get_int
2 parents e5e9081 + 37570e8 commit 3cdb3da

File tree

3 files changed

+160
-17
lines changed

3 files changed

+160
-17
lines changed

library/asn1parse.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,26 @@ int mbedtls_asn1_get_int( unsigned char **p,
149149
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
150150
return( ret );
151151

152-
if( len == 0 || ( **p & 0x80 ) != 0 )
152+
/* len==0 is malformed (0 must be represented as 020100). */
153+
if( len == 0 )
154+
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
155+
/* This is a cryptography library. Reject negative integers. */
156+
if( ( **p & 0x80 ) != 0 )
153157
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
154158

159+
/* Skip leading zeros. */
155160
while( len > 0 && **p == 0 )
156161
{
157162
++( *p );
158163
--len;
159164
}
165+
166+
/* Reject integers that don't fit in an int. This code assumes that
167+
* the int type has no padding bit. */
160168
if( len > sizeof( int ) )
161169
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
170+
if( len == sizeof( int ) && ( **p & 0x80 ) != 0 )
171+
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
162172

163173
*val = 0;
164174
while( len-- > 0 )

tests/suites/test_suite_asn1parse.data

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -164,36 +164,23 @@ Not BOOLEAN
164164
get_boolean:"020101":0:MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
165165

166166
Empty INTEGER
167-
depends_on:SUPPORT_NEGATIVE_INTEGERS
168-
get_integer:"0200":"":MBEDTLS_ERR_ASN1_INVALID_LENGTH
167+
empty_integer:"0200"
169168

170169
INTEGER 0
171170
get_integer:"020100":"0":0
172171

173172
INTEGER 0, extra leading 0
174173
get_integer:"02020000":"0":0
175174

176-
INTEGER -0
177-
depends_on:SUPPORT_NEGATIVE_INTEGERS
178-
get_integer:"020180":"0":0
179-
180175
INTEGER 1
181176
get_integer:"020101":"1":0:
182177

183178
INTEGER 1, extra leading 0
184179
get_integer:"02020001":"1":0:
185180

186-
INTEGER -1
187-
depends_on:SUPPORT_NEGATIVE_INTEGERS
188-
get_integer:"020181":"-1":0
189-
190181
INTEGER 0x7f
191182
get_integer:"02017f":"7f":0
192183

193-
INTEGER -0x7f
194-
depends_on:SUPPORT_NEGATIVE_INTEGERS
195-
get_integer:"0201ff":"-7f":0
196-
197184
INTEGER 0x80
198185
get_integer:"02020080":"80":0
199186

@@ -212,9 +199,30 @@ get_integer:"020412345678":"12345678":0
212199
INTEGER 0x12345678, extra leading 0
213200
get_integer:"02050012345678":"12345678":0
214201

202+
INTEGER 0x7fffffff
203+
get_integer:"02047fffffff":"7fffffff":0
204+
205+
INTEGER 0x7fffffff, extra leading 0
206+
get_integer:"0205007fffffff":"7fffffff":0
207+
208+
INTEGER 0x80000000
209+
get_integer:"02050080000000":"80000000":0
210+
211+
INTEGER 0xffffffff
212+
get_integer:"020500ffffffff":"ffffffff":0
213+
214+
INTEGER 0x100000000
215+
get_integer:"02050100000000":"0100000000":0
216+
215217
INTEGER 0x123456789abcdef0
216218
get_integer:"0208123456789abcdef0":"123456789abcdef0":0
217219

220+
INTEGER 0xfedcab9876543210
221+
get_integer:"020900fedcab9876543210":"fedcab9876543210":0
222+
223+
INTEGER 0x1fedcab9876543210
224+
get_integer:"020901fedcab9876543210":"1fedcab9876543210":0
225+
218226
INTEGER with 127 value octets
219227
get_integer:"027f0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd":0
220228

@@ -227,6 +235,51 @@ get_integer:"0281800123456789abcdef0123456789abcdef0123456789abcdef0123456789abc
227235
INTEGER with 128 value octets (leading 0 in length)
228236
get_integer:"028200800123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":0
229237

238+
INTEGER -1
239+
get_integer:"0201ff":"-1":0
240+
241+
INTEGER -1, extra leading ff
242+
get_integer:"0202ffff":"-1":0
243+
244+
INTEGER -0x7f
245+
get_integer:"020181":"-7f":0
246+
247+
INTEGER -0x80
248+
get_integer:"020180":"-80":0
249+
250+
INTEGER -0x81
251+
get_integer:"0202ff7f":"-81":0
252+
253+
INTEGER -0xff
254+
get_integer:"0202ff01":"-ff":0
255+
256+
INTEGER -0x100
257+
get_integer:"0202ff00":"-100":0
258+
259+
INTEGER -0x7fffffff
260+
get_integer:"020480000001":"-7fffffff":0
261+
262+
INTEGER -0x80000000
263+
get_integer:"020480000000":"-80000000":0
264+
265+
INTEGER -0x80000001
266+
get_integer:"0205ff7fffffff":"-80000001":0
267+
268+
INTEGER -0xffffffff
269+
get_integer:"0205ff00000001":"-ffffffff":0
270+
271+
INTEGER -0x100000000
272+
get_integer:"0205ff00000000":"-100000000":0
273+
274+
INTEGER -0x123456789abcdef0
275+
get_integer:"0208edcba98765432110":"-123456789abcdef0":0
276+
277+
INTEGER -0xfedcba9876543210
278+
get_integer:"0209ff0123456789abcdf0":"-fedcba9876543210":0
279+
280+
INTEGER -0x1fedcab9876543210
281+
get_integer:"0209fe0123546789abcdf0":"-1fedcab9876543210":0
282+
230283
Not INTEGER
231284
get_integer:"010101":"":MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
232285

tests/suites/test_suite_asn1parse.function

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ static int nested_parse( unsigned char **const p,
5959
*p = start;
6060
ret = mbedtls_asn1_get_mpi( p, end, &mpi );
6161
mbedtls_mpi_free( &mpi );
62+
#else
63+
*p = start + 1;
64+
ret = mbedtls_asn1_get_len( p, end, &len );
65+
*p += len;
6266
#endif
6367
/* If we're sure that the number fits in an int, also
6468
* call mbedtls_asn1_get_int(). */
@@ -246,6 +250,41 @@ void get_boolean( const data_t *input,
246250
}
247251
/* END_CASE */
248252

253+
/* BEGIN_CASE */
254+
void empty_integer( const data_t *input )
255+
{
256+
unsigned char *p;
257+
#if defined(MBEDTLS_BIGNUM_C)
258+
mbedtls_mpi actual_mpi;
259+
#endif
260+
int val;
261+
262+
#if defined(MBEDTLS_BIGNUM_C)
263+
mbedtls_mpi_init( & actual_mpi );
264+
#endif
265+
266+
/* An INTEGER with no content is not valid. */
267+
p = input->x;
268+
TEST_EQUAL( mbedtls_asn1_get_int( &p, input->x + input->len, &val ),
269+
MBEDTLS_ERR_ASN1_INVALID_LENGTH );
270+
271+
#if defined(MBEDTLS_BIGNUM_C)
272+
/* INTEGERs are sometimes abused as bitstrings, so the library accepts
273+
* an INTEGER with empty content and gives it the value 0. */
274+
p = input->x;
275+
TEST_EQUAL( mbedtls_asn1_get_mpi( &p, input->x + input->len, &actual_mpi ),
276+
0 );
277+
TEST_EQUAL( mbedtls_mpi_cmp_int( &actual_mpi, 0 ), 0 );
278+
#endif
279+
280+
exit:
281+
#if defined(MBEDTLS_BIGNUM_C)
282+
mbedtls_mpi_free( &actual_mpi );
283+
#endif
284+
/*empty cleanup in some configurations*/ ;
285+
}
286+
/* END_CASE */
287+
249288
/* BEGIN_CASE */
250289
void get_integer( const data_t *input,
251290
const char *expected_hex, int expected_result )
@@ -254,16 +293,18 @@ void get_integer( const data_t *input,
254293
#if defined(MBEDTLS_BIGNUM_C)
255294
mbedtls_mpi expected_mpi;
256295
mbedtls_mpi actual_mpi;
296+
mbedtls_mpi complement;
297+
int expected_result_for_mpi = expected_result;
257298
#endif
258299
long expected_value;
259300
int expected_result_for_int = expected_result;
260-
int expected_result_for_mpi = expected_result;
261301
int val;
262302
int ret;
263303

264304
#if defined(MBEDTLS_BIGNUM_C)
265305
mbedtls_mpi_init( &expected_mpi );
266306
mbedtls_mpi_init( &actual_mpi );
307+
mbedtls_mpi_init( &complement );
267308
#endif
268309

269310
errno = 0;
@@ -275,6 +316,16 @@ void get_integer( const data_t *input,
275316
#endif
276317
) )
277318
{
319+
/* The library returns the dubious error code INVALID_LENGTH
320+
* for integers that are out of range. */
321+
expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
322+
}
323+
if( expected_result == 0 && expected_value < 0 )
324+
{
325+
/* The library does not support negative INTEGERs and
326+
* returns the dubious error code INVALID_LENGTH.
327+
* Test that we preserve the historical behavior. If we
328+
* decide to change the behavior, we'll also change this test. */
278329
expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
279330
}
280331

@@ -300,7 +351,34 @@ void get_integer( const data_t *input,
300351
TEST_EQUAL( ret, expected_result_for_mpi );
301352
if( ret == 0 )
302353
{
303-
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &actual_mpi , &expected_mpi ) == 0 );
354+
if( expected_value >= 0 )
355+
{
356+
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &actual_mpi,
357+
&expected_mpi ) == 0 );
358+
}
359+
else
360+
{
361+
/* The library ignores the sign bit in ASN.1 INTEGERs
362+
* (which makes sense insofar as INTEGERs are sometimes
363+
* abused as bit strings), so the result of parsing them
364+
* is a positive integer such that expected_mpi +
365+
* actual_mpi = 2^n where n is the length of the content
366+
* of the INTEGER. (Leading ff octets don't matter for the
367+
* expected value, but they matter for the actual value.)
368+
* Test that we don't change from this behavior. If we
369+
* decide to fix the library to change the behavior on
370+
* negative INTEGERs, we'll fix this test code. */
371+
unsigned char *q = input->x + 1;
372+
size_t len;
373+
TEST_ASSERT( mbedtls_asn1_get_len( &q, input->x + input->len,
374+
&len ) == 0 );
375+
TEST_ASSERT( mbedtls_mpi_lset( &complement, 1 ) == 0 );
376+
TEST_ASSERT( mbedtls_mpi_shift_l( &complement, len * 8 ) == 0 );
377+
TEST_ASSERT( mbedtls_mpi_add_mpi( &complement, &complement,
378+
&expected_mpi ) == 0 );
379+
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &complement,
380+
&actual_mpi ) == 0 );
381+
}
304382
TEST_ASSERT( p == input->x + input->len );
305383
}
306384
#endif
@@ -309,7 +387,9 @@ exit:
309387
#if defined(MBEDTLS_BIGNUM_C)
310388
mbedtls_mpi_free( &expected_mpi );
311389
mbedtls_mpi_free( &actual_mpi );
390+
mbedtls_mpi_free( &complement );
312391
#endif
392+
/*empty cleanup in some configurations*/ ;
313393
}
314394
/* END_CASE */
315395

0 commit comments

Comments
 (0)