Skip to content

Commit 7bb1a7e

Browse files
Merge pull request #307 from msopiha-linaro/development
Add ASN.1 ENUMERATED tag support
2 parents b951fd9 + 6af7bf9 commit 7bb1a7e

File tree

8 files changed

+261
-11
lines changed

8 files changed

+261
-11
lines changed

include/mbedtls/asn1.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#define MBEDTLS_ASN1_OCTET_STRING 0x04
7676
#define MBEDTLS_ASN1_NULL 0x05
7777
#define MBEDTLS_ASN1_OID 0x06
78+
#define MBEDTLS_ASN1_ENUMERATED 0x0A
7879
#define MBEDTLS_ASN1_UTF8_STRING 0x0C
7980
#define MBEDTLS_ASN1_SEQUENCE 0x10
8081
#define MBEDTLS_ASN1_SET 0x11
@@ -254,13 +255,32 @@ int mbedtls_asn1_get_bool( unsigned char **p,
254255
* a valid ASN.1 INTEGER.
255256
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
256257
* not fit in an \c int.
257-
* \return An ASN.1 error code if the input does not start with
258-
* a valid ASN.1 INTEGER.
259258
*/
260259
int mbedtls_asn1_get_int( unsigned char **p,
261260
const unsigned char *end,
262261
int *val );
263262

263+
/**
264+
* \brief Retrieve an enumerated ASN.1 tag and its value.
265+
* Updates the pointer to immediately behind the full tag.
266+
*
267+
* \param p On entry, \c *p points to the start of the ASN.1 element.
268+
* On successful completion, \c *p points to the first byte
269+
* beyond the ASN.1 element.
270+
* On error, the value of \c *p is undefined.
271+
* \param end End of data.
272+
* \param val On success, the parsed value.
273+
*
274+
* \return 0 if successful.
275+
* \return An ASN.1 error code if the input does not start with
276+
* a valid ASN.1 ENUMERATED.
277+
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
278+
* not fit in an \c int.
279+
*/
280+
int mbedtls_asn1_get_enum( unsigned char **p,
281+
const unsigned char *end,
282+
int *val );
283+
264284
/**
265285
* \brief Retrieve a bitstring ASN.1 tag and its value.
266286
* Updates the pointer to immediately behind the full tag.
@@ -367,8 +387,6 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p,
367387
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
368388
* not fit in an \c int.
369389
* \return An MPI error code if the parsed value is too large.
370-
* \return An ASN.1 error code if the input does not start with
371-
* a valid ASN.1 INTEGER.
372390
*/
373391
int mbedtls_asn1_get_mpi( unsigned char **p,
374392
const unsigned char *end,

include/mbedtls/asn1write.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,21 @@ int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start,
192192
*/
193193
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
194194

195+
/**
196+
* \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value
197+
* in ASN.1 format.
198+
*
199+
* \note This function works backwards in data buffer.
200+
*
201+
* \param p The reference to the current position pointer.
202+
* \param start The start of the buffer, for bounds-checking.
203+
* \param val The integer value to write.
204+
*
205+
* \return The number of bytes written to \p p on success.
206+
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
207+
*/
208+
int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val );
209+
195210
/**
196211
* \brief Write a string in ASN.1 format using a specific
197212
* string encoding tag.

library/asn1parse.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,20 @@ int mbedtls_asn1_get_bool( unsigned char **p,
139139
return( 0 );
140140
}
141141

142-
int mbedtls_asn1_get_int( unsigned char **p,
143-
const unsigned char *end,
144-
int *val )
142+
static int asn1_get_tagged_int( unsigned char **p,
143+
const unsigned char *end,
144+
int tag, int *val )
145145
{
146146
int ret;
147147
size_t len;
148148

149-
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
149+
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 )
150150
return( ret );
151151

152-
/* len==0 is malformed (0 must be represented as 020100). */
152+
/*
153+
* len==0 is malformed (0 must be represented as 020100 for INTEGER,
154+
* or 0A0100 for ENUMERATED tags
155+
*/
153156
if( len == 0 )
154157
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
155158
/* This is a cryptography library. Reject negative integers. */
@@ -180,6 +183,20 @@ int mbedtls_asn1_get_int( unsigned char **p,
180183
return( 0 );
181184
}
182185

186+
int mbedtls_asn1_get_int( unsigned char **p,
187+
const unsigned char *end,
188+
int *val )
189+
{
190+
return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) );
191+
}
192+
193+
int mbedtls_asn1_get_enum( unsigned char **p,
194+
const unsigned char *end,
195+
int *val )
196+
{
197+
return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) );
198+
}
199+
183200
#if defined(MBEDTLS_BIGNUM_C)
184201
int mbedtls_asn1_get_mpi( unsigned char **p,
185202
const unsigned char *end,

library/asn1write.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolea
231231
return( (int) len );
232232
}
233233

234-
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
234+
static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag )
235235
{
236236
int ret;
237237
size_t len = 0;
@@ -255,11 +255,21 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
255255
}
256256

257257
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
258-
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
258+
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
259259

260260
return( (int) len );
261261
}
262262

263+
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
264+
{
265+
return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
266+
}
267+
268+
int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val )
269+
{
270+
return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
271+
}
272+
263273
int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
264274
const char *text, size_t text_len )
265275
{

tests/suites/test_suite_asn1parse.data

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,90 @@ get_integer:"010101":"":MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
286286
INTEGER too large for mpi
287287
get_mpi_too_large:
288288

289+
ENUMERATED 0
290+
get_enum:"0A0100":"0":0
291+
292+
ENUMERATED 0, extra leading 0
293+
get_enum:"0A020000":"0":0
294+
295+
ENUMERATED 1
296+
get_enum:"0A0101":"1":0
297+
298+
ENUMERATED 1, extra leading 0
299+
get_enum:"0A020001":"1":0
300+
301+
ENUMERATED 0x7f
302+
get_enum:"0A017f":"7f":0
303+
304+
ENUMERATED 0x80
305+
get_enum:"0A020080":"80":0
306+
307+
ENUMERATED 0x80, extra leading 0
308+
get_enum:"0A03000080":"80":0
309+
310+
ENUMERATED 0xff
311+
get_enum:"0A0200ff":"ff":0
312+
313+
ENUMERATED 0x7fff
314+
get_enum:"0A027fff":"7fff":0
315+
316+
ENUMERATED 0x12345678
317+
get_enum:"0A0412345678":"12345678":0
318+
319+
ENUMERATED 0x12345678, extra leading 0
320+
get_enum:"0A050012345678":"12345678":0
321+
322+
ENUMERATED 0x7fffffff
323+
get_enum:"0A047fffffff":"7fffffff":0
324+
325+
ENUMERATED 0x7fffffff, extra leading 0
326+
get_enum:"0A05007fffffff":"7fffffff":0
327+
328+
ENUMERATED 0x80000000
329+
get_enum:"0A050080000000":"80000000":0
330+
331+
ENUMERATED 0xffffffff
332+
get_enum:"0A0500ffffffff":"ffffffff":0
333+
334+
ENUMERATED 0x100000000
335+
get_enum:"0A050100000000":"0100000000":0
336+
337+
ENUMERATED -1
338+
get_enum:"0A01ff":"-1":0
339+
340+
ENUMERATED -1, extra leading ff
341+
get_enum:"0A02ffff":"-1":0
342+
343+
ENUMERATED -0x7f
344+
get_enum:"0A0181":"-7f":0
345+
346+
ENUMERATED -0x80
347+
get_enum:"0A0180":"-80":0
348+
349+
ENUMERATED -0x81
350+
get_enum:"0A02ff7f":"-81":0
351+
352+
ENUMERATED -0xff
353+
get_enum:"0A02ff01":"-ff":0
354+
355+
ENUMERATED -0x100
356+
get_enum:"0A02ff00":"-100":0
357+
358+
ENUMERATED -0x7fffffff
359+
get_enum:"0A0480000001":"-7fffffff":0
360+
361+
ENUMERATED -0x80000000
362+
get_enum:"0A0480000000":"-80000000":0
363+
364+
ENUMERATED -0x80000001
365+
get_enum:"0A05ff7fffffff":"-80000001":0
366+
367+
ENUMERATED -0xffffffff
368+
get_enum:"0A05ff00000001":"-ffffffff":0
369+
370+
ENUMERATED -0x100000000
371+
get_enum:"0A05ff00000000":"-100000000":0
372+
289373
BIT STRING: empty
290374
get_bitstring:"0300":0:0:MBEDTLS_ERR_ASN1_OUT_OF_DATA:MBEDTLS_ERR_ASN1_INVALID_DATA
291375

tests/suites/test_suite_asn1parse.function

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,49 @@ exit:
393393
}
394394
/* END_CASE */
395395

396+
/* BEGIN_CASE */
397+
void get_enum( const data_t *input,
398+
const char *expected_hex, int expected_result )
399+
{
400+
unsigned char *p;
401+
long expected_value;
402+
int expected_result_for_enum = expected_result;
403+
int val;
404+
int ret;
405+
406+
errno = 0;
407+
expected_value = strtol( expected_hex, NULL, 16 );
408+
if( expected_result == 0 &&
409+
( errno == ERANGE
410+
#if LONG_MAX > INT_MAX
411+
|| expected_value > INT_MAX || expected_value < INT_MIN
412+
#endif
413+
) )
414+
{
415+
/* The library returns the dubious error code INVALID_LENGTH
416+
* for integers that are out of range. */
417+
expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
418+
}
419+
if( expected_result == 0 && expected_value < 0 )
420+
{
421+
/* The library does not support negative INTEGERs and
422+
* returns the dubious error code INVALID_LENGTH.
423+
* Test that we preserve the historical behavior. If we
424+
* decide to change the behavior, we'll also change this test. */
425+
expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
426+
}
427+
428+
p = input->x;
429+
ret = mbedtls_asn1_get_enum( &p, input->x + input->len, &val );
430+
TEST_EQUAL( ret, expected_result_for_enum );
431+
if( ret == 0 )
432+
{
433+
TEST_EQUAL( val, expected_value );
434+
TEST_ASSERT( p == input->x + input->len );
435+
}
436+
}
437+
/* END_CASE */
438+
396439
/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
397440
void get_mpi_too_large( )
398441
{

tests/suites/test_suite_asn1write.data

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,48 @@ mbedtls_asn1_write_int:0x12345678:"020412345678"
4949
ASN.1 Write int 2147483647
5050
mbedtls_asn1_write_int:0x7fffffff:"02047fffffff"
5151

52+
ASN.1 Write enum 0
53+
mbedtls_asn1_write_enum:0:"0A0100"
54+
55+
ASN.1 Write enum 1
56+
mbedtls_asn1_write_enum:1:"0A0101"
57+
58+
ASN.1 Write enum 127
59+
mbedtls_asn1_write_enum:0x7f:"0A017f"
60+
61+
ASN.1 Write enum 128
62+
mbedtls_asn1_write_enum:0x80:"0A020080"
63+
64+
ASN.1 Write enum 255
65+
mbedtls_asn1_write_enum:0xff:"0A0200ff"
66+
67+
ASN.1 Write enum 256
68+
mbedtls_asn1_write_enum:0x100:"0A020100"
69+
70+
ASN.1 Write enum 32767
71+
mbedtls_asn1_write_enum:0x7fff:"0A027fff"
72+
73+
ASN.1 Write enum 32768
74+
mbedtls_asn1_write_enum:0x8000:"0A03008000"
75+
76+
ASN.1 Write enum 65535
77+
mbedtls_asn1_write_enum:0xffff:"0A0300ffff"
78+
79+
ASN.1 Write enum 65536
80+
mbedtls_asn1_write_enum:0x10000:"0A03010000"
81+
82+
ASN.1 Write enum 8388607
83+
mbedtls_asn1_write_enum:0x7fffff:"0A037fffff"
84+
85+
ASN.1 Write enum 8388608
86+
mbedtls_asn1_write_enum:0x800000:"0A0400800000"
87+
88+
ASN.1 Write enum 0x12345678
89+
mbedtls_asn1_write_enum:0x12345678:"0A0412345678"
90+
91+
ASN.1 Write enum 2147483647
92+
mbedtls_asn1_write_enum:0x7fffffff:"0A047fffffff"
93+
5294
#ASN.1 Write mpi 0
5395
#mbedtls_asn1_write_mpi:"00":"020100"
5496

tests/suites/test_suite_asn1write.function

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,27 @@ exit:
117117
}
118118
/* END_CASE */
119119

120+
121+
/* BEGIN_CASE */
122+
void mbedtls_asn1_write_enum( int val, data_t *expected )
123+
{
124+
generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
125+
int ret;
126+
127+
for( data.size = 0; data.size < expected->len + 1; data.size++ )
128+
{
129+
if( ! generic_write_start_step( &data ) )
130+
goto exit;
131+
ret = mbedtls_asn1_write_enum( &data.p, data.start, val );
132+
if( ! generic_write_finish_step( &data, expected, ret ) )
133+
goto exit;
134+
}
135+
136+
exit:
137+
mbedtls_free( data.output );
138+
}
139+
/* END_CASE */
140+
120141
/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
121142
void mbedtls_asn1_write_mpi( data_t *val, data_t *expected )
122143
{

0 commit comments

Comments
 (0)