1 /* 2 * ASN.1 buffer writing functionality 3 * 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5 * SPDX-License-Identifier: GPL-2.0 6 * 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. 11 * 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. 16 * 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. 20 * 21 * This file is part of mbed TLS (https://tls.mbed.org) 22 */ 23 24 #if !defined(MBEDTLS_CONFIG_FILE) 25 #include "mbedtls/config.h" 26 #else 27 #include MBEDTLS_CONFIG_FILE 28 #endif 29 30 #if defined(MBEDTLS_ASN1_WRITE_C) 31 32 #include "mbedtls/asn1write.h" 33 34 #include <string.h> 35 36 #if defined(MBEDTLS_PLATFORM_C) 37 #include "mbedtls/platform.h" 38 #else 39 #include <stdlib.h> 40 #define mbedtls_calloc calloc 41 #define mbedtls_free free 42 #endif 43 44 int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) 45 { 46 if( len < 0x80 ) 47 { 48 if( *p - start < 1 ) 49 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 50 51 *--(*p) = (unsigned char) len; 52 return( 1 ); 53 } 54 55 if( len <= 0xFF ) 56 { 57 if( *p - start < 2 ) 58 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 59 60 *--(*p) = (unsigned char) len; 61 *--(*p) = 0x81; 62 return( 2 ); 63 } 64 65 if( len <= 0xFFFF ) 66 { 67 if( *p - start < 3 ) 68 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 69 70 *--(*p) = ( len ) & 0xFF; 71 *--(*p) = ( len >> 8 ) & 0xFF; 72 *--(*p) = 0x82; 73 return( 3 ); 74 } 75 76 if( len <= 0xFFFFFF ) 77 { 78 if( *p - start < 4 ) 79 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 80 81 *--(*p) = ( len ) & 0xFF; 82 *--(*p) = ( len >> 8 ) & 0xFF; 83 *--(*p) = ( len >> 16 ) & 0xFF; 84 *--(*p) = 0x83; 85 return( 4 ); 86 } 87 88 if( len <= 0xFFFFFFFF ) 89 { 90 if( *p - start < 5 ) 91 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 92 93 *--(*p) = ( len ) & 0xFF; 94 *--(*p) = ( len >> 8 ) & 0xFF; 95 *--(*p) = ( len >> 16 ) & 0xFF; 96 *--(*p) = ( len >> 24 ) & 0xFF; 97 *--(*p) = 0x84; 98 return( 5 ); 99 } 100 101 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); 102 } 103 104 int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) 105 { 106 if( *p - start < 1 ) 107 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 108 109 *--(*p) = tag; 110 111 return( 1 ); 112 } 113 114 int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, 115 const unsigned char *buf, size_t size ) 116 { 117 size_t len = 0; 118 119 if( *p < start || (size_t)( *p - start ) < size ) 120 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 121 122 len = size; 123 (*p) -= len; 124 memcpy( *p, buf, len ); 125 126 return( (int) len ); 127 } 128 129 #if defined(MBEDTLS_BIGNUM_C) 130 int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) 131 { 132 int ret; 133 size_t len = 0; 134 135 // Write the MPI 136 // 137 len = mbedtls_mpi_size( X ); 138 139 if( *p < start || (size_t)( *p - start ) < len ) 140 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 141 142 (*p) -= len; 143 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); 144 145 // DER format assumes 2s complement for numbers, so the leftmost bit 146 // should be 0 for positive numbers and 1 for negative numbers. 147 // 148 if( X->s ==1 && **p & 0x80 ) 149 { 150 if( *p - start < 1 ) 151 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 152 153 *--(*p) = 0x00; 154 len += 1; 155 } 156 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 ) ); 159 160 ret = (int) len; 161 162 cleanup: 163 return( ret ); 164 } 165 #endif /* MBEDTLS_BIGNUM_C */ 166 167 int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) 168 { 169 int ret; 170 size_t len = 0; 171 172 // Write NULL 173 // 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 ) ); 176 177 return( (int) len ); 178 } 179 180 int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, 181 const char *oid, size_t oid_len ) 182 { 183 int ret; 184 size_t len = 0; 185 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 ) ); 190 191 return( (int) len ); 192 } 193 194 int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, 195 const char *oid, size_t oid_len, 196 size_t par_len ) 197 { 198 int ret; 199 size_t len = 0; 200 201 if( par_len == 0 ) 202 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); 203 else 204 len += par_len; 205 206 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); 207 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 ) ); 211 212 return( (int) len ); 213 } 214 215 int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) 216 { 217 int ret; 218 size_t len = 0; 219 220 if( *p - start < 1 ) 221 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 222 223 *--(*p) = (boolean) ? 255 : 0; 224 len++; 225 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 ) ); 228 229 return( (int) len ); 230 } 231 232 int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) 233 { 234 int ret; 235 size_t len = 0; 236 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. 240 // 241 if( *p - start < 1 ) 242 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 243 244 len += 1; 245 *--(*p) = val; 246 247 if( val > 0 && **p & 0x80 ) 248 { 249 if( *p - start < 1 ) 250 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 251 252 *--(*p) = 0x00; 253 len += 1; 254 } 255 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 ) ); 258 259 return( (int) len ); 260 } 261 262 int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, 263 const char *text, size_t text_len ) 264 { 265 int ret; 266 size_t len = 0; 267 268 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 269 (const unsigned char *) text, text_len ) ); 270 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 ) ); 273 274 return( (int) len ); 275 } 276 277 int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, 278 const char *text, size_t text_len ) 279 { 280 int ret; 281 size_t len = 0; 282 283 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 284 (const unsigned char *) text, text_len ) ); 285 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 ) ); 288 289 return( (int) len ); 290 } 291 292 int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, 293 const unsigned char *buf, size_t bits ) 294 { 295 int ret; 296 size_t len = 0, size; 297 298 size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); 299 300 // Calculate byte length 301 // 302 if( *p < start || (size_t)( *p - start ) < size + 1 ) 303 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 304 305 len = size + 1; 306 (*p) -= size; 307 memcpy( *p, buf, size ); 308 309 // Write unused bits 310 // 311 *--(*p) = (unsigned char) (size * 8 - bits); 312 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 ) ); 315 316 return( (int) len ); 317 } 318 319 int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, 320 const unsigned char *buf, size_t size ) 321 { 322 int ret; 323 size_t len = 0; 324 325 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); 326 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 ) ); 329 330 return( (int) len ); 331 } 332 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, 336 size_t val_len ) 337 { 338 mbedtls_asn1_named_data *cur; 339 340 if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) 341 { 342 // Add new entry if not present yet based on OID 343 // 344 cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, 345 sizeof(mbedtls_asn1_named_data) ); 346 if( cur == NULL ) 347 return( NULL ); 348 349 cur->oid.len = oid_len; 350 cur->oid.p = mbedtls_calloc( 1, oid_len ); 351 if( cur->oid.p == NULL ) 352 { 353 mbedtls_free( cur ); 354 return( NULL ); 355 } 356 357 memcpy( cur->oid.p, oid, oid_len ); 358 359 cur->val.len = val_len; 360 cur->val.p = mbedtls_calloc( 1, val_len ); 361 if( cur->val.p == NULL ) 362 { 363 mbedtls_free( cur->oid.p ); 364 mbedtls_free( cur ); 365 return( NULL ); 366 } 367 368 cur->next = *head; 369 *head = cur; 370 } 371 else if( cur->val.len < val_len ) 372 { 373 /* 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. 377 */ 378 void *p = mbedtls_calloc( 1, val_len ); 379 if( p == NULL ) 380 return( NULL ); 381 382 mbedtls_free( cur->val.p ); 383 cur->val.p = p; 384 cur->val.len = val_len; 385 } 386 387 if( val != NULL ) 388 memcpy( cur->val.p, val, val_len ); 389 390 return( cur ); 391 } 392 #endif /* MBEDTLS_ASN1_WRITE_C */ 393