1 // SPDX-License-Identifier: Apache-2.0 2 /* 3 * ASN.1 buffer writing functionality 4 * 5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may 8 * not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 * This file is part of mbed TLS (https://tls.mbed.org) 20 */ 21 22 #if !defined(MBEDTLS_CONFIG_FILE) 23 #include "mbedtls/config.h" 24 #else 25 #include MBEDTLS_CONFIG_FILE 26 #endif 27 28 #if defined(MBEDTLS_ASN1_WRITE_C) 29 30 #include "mbedtls/asn1write.h" 31 32 #include <string.h> 33 34 #if defined(MBEDTLS_PLATFORM_C) 35 #include "mbedtls/platform.h" 36 #else 37 #include <stdlib.h> 38 #define mbedtls_calloc calloc 39 #define mbedtls_free free 40 #endif 41 42 int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) 43 { 44 if( len < 0x80 ) 45 { 46 if( *p - start < 1 ) 47 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 48 49 *--(*p) = (unsigned char) len; 50 return( 1 ); 51 } 52 53 if( len <= 0xFF ) 54 { 55 if( *p - start < 2 ) 56 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 57 58 *--(*p) = (unsigned char) len; 59 *--(*p) = 0x81; 60 return( 2 ); 61 } 62 63 if( len <= 0xFFFF ) 64 { 65 if( *p - start < 3 ) 66 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 67 68 *--(*p) = ( len ) & 0xFF; 69 *--(*p) = ( len >> 8 ) & 0xFF; 70 *--(*p) = 0x82; 71 return( 3 ); 72 } 73 74 if( len <= 0xFFFFFF ) 75 { 76 if( *p - start < 4 ) 77 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 78 79 *--(*p) = ( len ) & 0xFF; 80 *--(*p) = ( len >> 8 ) & 0xFF; 81 *--(*p) = ( len >> 16 ) & 0xFF; 82 *--(*p) = 0x83; 83 return( 4 ); 84 } 85 86 if( len <= 0xFFFFFFFF ) 87 { 88 if( *p - start < 5 ) 89 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 90 91 *--(*p) = ( len ) & 0xFF; 92 *--(*p) = ( len >> 8 ) & 0xFF; 93 *--(*p) = ( len >> 16 ) & 0xFF; 94 *--(*p) = ( len >> 24 ) & 0xFF; 95 *--(*p) = 0x84; 96 return( 5 ); 97 } 98 99 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); 100 } 101 102 int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) 103 { 104 if( *p - start < 1 ) 105 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 106 107 *--(*p) = tag; 108 109 return( 1 ); 110 } 111 112 int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, 113 const unsigned char *buf, size_t size ) 114 { 115 size_t len = 0; 116 117 if( *p < start || (size_t)( *p - start ) < size ) 118 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 119 120 len = size; 121 (*p) -= len; 122 memcpy( *p, buf, len ); 123 124 return( (int) len ); 125 } 126 127 #if defined(MBEDTLS_BIGNUM_C) 128 int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) 129 { 130 int ret; 131 size_t len = 0; 132 133 // Write the MPI 134 // 135 len = mbedtls_mpi_size( X ); 136 137 if( *p < start || (size_t)( *p - start ) < len ) 138 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 139 140 (*p) -= len; 141 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); 142 143 // DER format assumes 2s complement for numbers, so the leftmost bit 144 // should be 0 for positive numbers and 1 for negative numbers. 145 // 146 if( X->s ==1 && **p & 0x80 ) 147 { 148 if( *p - start < 1 ) 149 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 150 151 *--(*p) = 0x00; 152 len += 1; 153 } 154 155 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 156 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); 157 158 ret = (int) len; 159 160 cleanup: 161 return( ret ); 162 } 163 #endif /* MBEDTLS_BIGNUM_C */ 164 165 int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) 166 { 167 int ret; 168 size_t len = 0; 169 170 // Write NULL 171 // 172 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); 173 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); 174 175 return( (int) len ); 176 } 177 178 int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, 179 const char *oid, size_t oid_len ) 180 { 181 int ret; 182 size_t len = 0; 183 184 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 185 (const unsigned char *) oid, oid_len ) ); 186 MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); 187 MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); 188 189 return( (int) len ); 190 } 191 192 int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, 193 const char *oid, size_t oid_len, 194 size_t par_len ) 195 { 196 int ret; 197 size_t len = 0; 198 199 if( par_len == 0 ) 200 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); 201 else 202 len += par_len; 203 204 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); 205 206 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 207 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, 208 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); 209 210 return( (int) len ); 211 } 212 213 int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) 214 { 215 int ret; 216 size_t len = 0; 217 218 if( *p - start < 1 ) 219 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 220 221 *--(*p) = (boolean) ? 255 : 0; 222 len++; 223 224 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 225 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); 226 227 return( (int) len ); 228 } 229 230 int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) 231 { 232 int ret; 233 size_t len = 0; 234 235 // TODO negative values and values larger than 128 236 // DER format assumes 2s complement for numbers, so the leftmost bit 237 // should be 0 for positive numbers and 1 for negative numbers. 238 // 239 if( *p - start < 1 ) 240 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 241 242 len += 1; 243 *--(*p) = val; 244 245 if( val > 0 && **p & 0x80 ) 246 { 247 if( *p - start < 1 ) 248 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 249 250 *--(*p) = 0x00; 251 len += 1; 252 } 253 254 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 255 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); 256 257 return( (int) len ); 258 } 259 260 int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, 261 const char *text, size_t text_len ) 262 { 263 int ret; 264 size_t len = 0; 265 266 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 267 (const unsigned char *) text, text_len ) ); 268 269 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 270 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); 271 272 return( (int) len ); 273 } 274 275 int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, 276 const char *text, size_t text_len ) 277 { 278 int ret; 279 size_t len = 0; 280 281 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 282 (const unsigned char *) text, text_len ) ); 283 284 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 285 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) ); 286 287 return( (int) len ); 288 } 289 290 int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, 291 const unsigned char *buf, size_t bits ) 292 { 293 int ret; 294 size_t len = 0, size; 295 296 size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); 297 298 // Calculate byte length 299 // 300 if( *p < start || (size_t)( *p - start ) < size + 1 ) 301 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 302 303 len = size + 1; 304 (*p) -= size; 305 memcpy( *p, buf, size ); 306 307 // Write unused bits 308 // 309 *--(*p) = (unsigned char) (size * 8 - bits); 310 311 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 312 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); 313 314 return( (int) len ); 315 } 316 317 int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, 318 const unsigned char *buf, size_t size ) 319 { 320 int ret; 321 size_t len = 0; 322 323 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); 324 325 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 326 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); 327 328 return( (int) len ); 329 } 330 331 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, 332 const char *oid, size_t oid_len, 333 const unsigned char *val, 334 size_t val_len ) 335 { 336 mbedtls_asn1_named_data *cur; 337 338 if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) 339 { 340 // Add new entry if not present yet based on OID 341 // 342 cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, 343 sizeof(mbedtls_asn1_named_data) ); 344 if( cur == NULL ) 345 return( NULL ); 346 347 cur->oid.len = oid_len; 348 cur->oid.p = mbedtls_calloc( 1, oid_len ); 349 if( cur->oid.p == NULL ) 350 { 351 mbedtls_free( cur ); 352 return( NULL ); 353 } 354 355 memcpy( cur->oid.p, oid, oid_len ); 356 357 cur->val.len = val_len; 358 cur->val.p = mbedtls_calloc( 1, val_len ); 359 if( cur->val.p == NULL ) 360 { 361 mbedtls_free( cur->oid.p ); 362 mbedtls_free( cur ); 363 return( NULL ); 364 } 365 366 cur->next = *head; 367 *head = cur; 368 } 369 else if( cur->val.len < val_len ) 370 { 371 /* 372 * Enlarge existing value buffer if needed 373 * Preserve old data until the allocation succeeded, to leave list in 374 * a consistent state in case allocation fails. 375 */ 376 void *p = mbedtls_calloc( 1, val_len ); 377 if( p == NULL ) 378 return( NULL ); 379 380 mbedtls_free( cur->val.p ); 381 cur->val.p = p; 382 cur->val.len = val_len; 383 } 384 385 if( val != NULL ) 386 memcpy( cur->val.p, val, val_len ); 387 388 return( cur ); 389 } 390 #endif /* MBEDTLS_ASN1_WRITE_C */ 391