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( len
<= 0xFFFFFFFF )
91 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
93 *--(*p
) = ( len
) & 0xFF;
94 *--(*p
) = ( len
>> 8 ) & 0xFF;
95 *--(*p
) = ( len
>> 16 ) & 0xFF;
96 *--(*p
) = ( len
>> 24 ) & 0xFF;
101 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH
);
104 int mbedtls_asn1_write_tag( unsigned char **p
, unsigned char *start
, unsigned char tag
)
107 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
114 int mbedtls_asn1_write_raw_buffer( unsigned char **p
, unsigned char *start
,
115 const unsigned char *buf
, size_t size
)
119 if( *p
< start
|| (size_t)( *p
- start
) < size
)
120 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
124 memcpy( *p
, buf
, len
);
129 #if defined(MBEDTLS_BIGNUM_C)
130 int mbedtls_asn1_write_mpi( unsigned char **p
, unsigned char *start
, const mbedtls_mpi
*X
)
137 len
= mbedtls_mpi_size( X
);
139 if( *p
< start
|| (size_t)( *p
- start
) < len
)
140 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
143 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X
, *p
, len
) );
145 // DER format assumes 2s complement for numbers, so the leftmost bit
146 // should be 0 for positive numbers and 1 for negative numbers.
148 if( X
->s
==1 && **p
& 0x80 )
151 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
157 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
158 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_INTEGER
) );
165 #endif /* MBEDTLS_BIGNUM_C */
167 int mbedtls_asn1_write_null( unsigned char **p
, unsigned char *start
)
174 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, 0) );
175 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_NULL
) );
180 int mbedtls_asn1_write_oid( unsigned char **p
, unsigned char *start
,
181 const char *oid
, size_t oid_len
)
186 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_raw_buffer( p
, start
,
187 (const unsigned char *) oid
, oid_len
) );
188 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
189 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_OID
) );
194 int mbedtls_asn1_write_algorithm_identifier( unsigned char **p
, unsigned char *start
,
195 const char *oid
, size_t oid_len
,
202 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_null( p
, start
) );
206 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_oid( p
, start
, oid
, oid_len
) );
208 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
209 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
,
210 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) );
215 int mbedtls_asn1_write_bool( unsigned char **p
, unsigned char *start
, int boolean
)
221 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
223 *--(*p
) = (boolean
) ? 255 : 0;
226 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_len( p
, start
, len
) );
227 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_tag( p
, start
, MBEDTLS_ASN1_BOOLEAN
) );
232 int mbedtls_asn1_write_int( unsigned char **p
, unsigned char *start
, int val
)
237 // TODO negative values and values larger than 128
238 // DER format assumes 2s complement for numbers, so the leftmost bit
239 // should be 0 for positive numbers and 1 for negative numbers.
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 */