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
)
242 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
247 if( val
> 0 && **p
& 0x80 )
250 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
256 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
257 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_INTEGER
) );
262 int mbedtls_asn1_write_printable_string( unsigned char **p
, unsigned char *start
,
263 const char *text
, size_t text_len
)
268 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_raw_buffer( p
, start
,
269 (const unsigned char *) text
, text_len
) );
271 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
272 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_PRINTABLE_STRING
) );
277 int mbedtls_asn1_write_ia5_string( unsigned char **p
, unsigned char *start
,
278 const char *text
, size_t text_len
)
283 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_raw_buffer( p
, start
,
284 (const unsigned char *) text
, text_len
) );
286 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
287 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_IA5_STRING
) );
292 int mbedtls_asn1_write_bitstring( unsigned char **p
, unsigned char *start
,
293 const unsigned char *buf
, size_t bits
)
296 size_t len
= 0, size
;
298 size
= ( bits
/ 8 ) + ( ( bits
% 8 ) ? 1 : 0 );
300 // Calculate byte length
302 if( *p
< start
|| (size_t)( *p
- start
) < size
+ 1 )
303 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
307 memcpy( *p
, buf
, size
);
311 *--(*p
) = (unsigned char) (size
* 8 - bits
);
313 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
314 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_BIT_STRING
) );
319 int mbedtls_asn1_write_octet_string( unsigned char **p
, unsigned char *start
,
320 const unsigned char *buf
, size_t size
)
325 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_raw_buffer( p
, start
, buf
, size
) );
327 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
328 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_OCTET_STRING
) );
333 mbedtls_asn1_named_data
*mbedtls_asn1_store_named_data( mbedtls_asn1_named_data
**head
,
334 const char *oid
, size_t oid_len
,
335 const unsigned char *val
,
338 mbedtls_asn1_named_data
*cur
;
340 if( ( cur
= mbedtls_asn1_find_named_data( *head
, oid
, oid_len
) ) == NULL
)
342 // Add new entry if not present yet based on OID
344 cur
= (mbedtls_asn1_named_data
*)mbedtls_calloc( 1,
345 sizeof(mbedtls_asn1_named_data
) );
349 cur
->oid
.len
= oid_len
;
350 cur
->oid
.p
= mbedtls_calloc( 1, oid_len
);
351 if( cur
->oid
.p
== NULL
)
357 memcpy( cur
->oid
.p
, oid
, oid_len
);
359 cur
->val
.len
= val_len
;
360 cur
->val
.p
= mbedtls_calloc( 1, val_len
);
361 if( cur
->val
.p
== NULL
)
363 mbedtls_free( cur
->oid
.p
);
371 else if( cur
->val
.len
< val_len
)
374 * Enlarge existing value buffer if needed
375 * Preserve old data until the allocation succeeded, to leave list in
376 * a consistent state in case allocation fails.
378 void *p
= mbedtls_calloc( 1, val_len
);
382 mbedtls_free( cur
->val
.p
);
384 cur
->val
.len
= val_len
;
388 memcpy( cur
->val
.p
, val
, val_len
);
392 #endif /* MBEDTLS_ASN1_WRITE_C */