2 * ASN.1 buffer writing functionality
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * This file is part of mbed TLS (https://tls.mbed.org)
24 #if !defined(MBEDTLS_CONFIG_FILE)
25 #include "mbedtls/config.h"
27 #include MBEDTLS_CONFIG_FILE
30 #if defined(MBEDTLS_ASN1_WRITE_C)
32 #include "mbedtls/asn1write.h"
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
40 #define mbedtls_calloc calloc
41 #define mbedtls_free free
44 int mbedtls_asn1_write_len( unsigned char **p
, unsigned char *start
, size_t len
)
49 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
51 *--(*p
) = (unsigned char) len
;
58 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
60 *--(*p
) = (unsigned char) len
;
68 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
70 *--(*p
) = ( len
) & 0xFF;
71 *--(*p
) = ( len
>> 8 ) & 0xFF;
79 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
81 *--(*p
) = ( len
) & 0xFF;
82 *--(*p
) = ( len
>> 8 ) & 0xFF;
83 *--(*p
) = ( len
>> 16 ) & 0xFF;
88 #if SIZE_MAX > 0xFFFFFFFF
89 if( len
<= 0xFFFFFFFF )
93 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
95 *--(*p
) = ( len
) & 0xFF;
96 *--(*p
) = ( len
>> 8 ) & 0xFF;
97 *--(*p
) = ( len
>> 16 ) & 0xFF;
98 *--(*p
) = ( len
>> 24 ) & 0xFF;
103 #if SIZE_MAX > 0xFFFFFFFF
104 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH
);
108 int mbedtls_asn1_write_tag( unsigned char **p
, unsigned char *start
, unsigned char tag
)
111 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
118 int mbedtls_asn1_write_raw_buffer( unsigned char **p
, unsigned char *start
,
119 const unsigned char *buf
, size_t size
)
123 if( *p
< start
|| (size_t)( *p
- start
) < size
)
124 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
128 memcpy( *p
, buf
, len
);
133 #if defined(MBEDTLS_BIGNUM_C)
134 int mbedtls_asn1_write_mpi( unsigned char **p
, unsigned char *start
, const mbedtls_mpi
*X
)
141 len
= mbedtls_mpi_size( X
);
143 if( *p
< start
|| (size_t)( *p
- start
) < len
)
144 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
147 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X
, *p
, len
) );
149 // DER format assumes 2s complement for numbers, so the leftmost bit
150 // should be 0 for positive numbers and 1 for negative numbers.
152 if( X
->s
==1 && **p
& 0x80 )
155 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
161 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
162 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_INTEGER
) );
169 #endif /* MBEDTLS_BIGNUM_C */
171 int mbedtls_asn1_write_null( unsigned char **p
, unsigned char *start
)
178 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, 0) );
179 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_NULL
) );
184 int mbedtls_asn1_write_oid( unsigned char **p
, unsigned char *start
,
185 const char *oid
, size_t oid_len
)
190 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_raw_buffer( p
, start
,
191 (const unsigned char *) oid
, oid_len
) );
192 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
193 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_OID
) );
198 int mbedtls_asn1_write_algorithm_identifier( unsigned char **p
, unsigned char *start
,
199 const char *oid
, size_t oid_len
,
206 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_null( p
, start
) );
210 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_oid( p
, start
, oid
, oid_len
) );
212 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
213 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
,
214 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) );
219 int mbedtls_asn1_write_bool( unsigned char **p
, unsigned char *start
, int boolean
)
225 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
227 *--(*p
) = (boolean
) ? 255 : 0;
230 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
231 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_BOOLEAN
) );
236 int mbedtls_asn1_write_int( unsigned char **p
, unsigned char *start
, int val
)
241 // DER format assumes 2s complement for numbers, so the leftmost bit
242 // should be 0 for positive numbers and 1 for negative numbers.
245 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
250 if( val
> 0 && **p
& 0x80 )
253 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
259 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
260 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_INTEGER
) );
265 int mbedtls_asn1_write_printable_string( unsigned char **p
, unsigned char *start
,
266 const char *text
, size_t text_len
)
271 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_raw_buffer( p
, start
,
272 (const unsigned char *) text
, text_len
) );
274 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
275 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_PRINTABLE_STRING
) );
280 int mbedtls_asn1_write_ia5_string( unsigned char **p
, unsigned char *start
,
281 const char *text
, size_t text_len
)
286 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_raw_buffer( p
, start
,
287 (const unsigned char *) text
, text_len
) );
289 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
290 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_IA5_STRING
) );
295 int mbedtls_asn1_write_bitstring( unsigned char **p
, unsigned char *start
,
296 const unsigned char *buf
, size_t bits
)
300 size_t unused_bits
, byte_len
;
302 byte_len
= ( bits
+ 7 ) / 8;
303 unused_bits
= ( byte_len
* 8 ) - bits
;
305 if( *p
< start
|| (size_t)( *p
- start
) < byte_len
+ 1 )
306 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
310 /* Write the bitstring. Ensure the unused bits are zeroed */
314 *--( *p
) = buf
[byte_len
] & ~( ( 0x1 << unused_bits
) - 1 );
316 memcpy( *p
, buf
, byte_len
);
319 /* Write unused bits */
320 *--( *p
) = (unsigned char)unused_bits
;
322 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
323 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_BIT_STRING
) );
328 int mbedtls_asn1_write_octet_string( unsigned char **p
, unsigned char *start
,
329 const unsigned char *buf
, size_t size
)
334 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_raw_buffer( p
, start
, buf
, size
) );
336 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
337 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_OCTET_STRING
) );
343 /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
344 * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
345 static mbedtls_asn1_named_data
*asn1_find_named_data(
346 mbedtls_asn1_named_data
*list
,
347 const char *oid
, size_t len
)
349 while( list
!= NULL
)
351 if( list
->oid
.len
== len
&&
352 memcmp( list
->oid
.p
, oid
, len
) == 0 )
363 mbedtls_asn1_named_data
*mbedtls_asn1_store_named_data(
364 mbedtls_asn1_named_data
**head
,
365 const char *oid
, size_t oid_len
,
366 const unsigned char *val
,
369 mbedtls_asn1_named_data
*cur
;
371 if( ( cur
= asn1_find_named_data( *head
, oid
, oid_len
) ) == NULL
)
373 // Add new entry if not present yet based on OID
375 cur
= (mbedtls_asn1_named_data
*)mbedtls_calloc( 1,
376 sizeof(mbedtls_asn1_named_data
) );
380 cur
->oid
.len
= oid_len
;
381 cur
->oid
.p
= mbedtls_calloc( 1, oid_len
);
382 if( cur
->oid
.p
== NULL
)
388 memcpy( cur
->oid
.p
, oid
, oid_len
);
390 cur
->val
.len
= val_len
;
391 cur
->val
.p
= mbedtls_calloc( 1, val_len
);
392 if( cur
->val
.p
== NULL
)
394 mbedtls_free( cur
->oid
.p
);
402 else if( cur
->val
.len
< val_len
)
405 * Enlarge existing value buffer if needed
406 * Preserve old data until the allocation succeeded, to leave list in
407 * a consistent state in case allocation fails.
409 void *p
= mbedtls_calloc( 1, val_len
);
413 mbedtls_free( cur
->val
.p
);
415 cur
->val
.len
= val_len
;
419 memcpy( cur
->val
.p
, val
, val_len
);
423 #endif /* MBEDTLS_ASN1_WRITE_C */