mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * ASN.1 buffer writing functionality
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22
ansond 0:137634ff4186 23 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 24 #include "polarssl/config.h"
ansond 0:137634ff4186 25 #else
ansond 0:137634ff4186 26 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 27 #endif
ansond 0:137634ff4186 28
ansond 0:137634ff4186 29 #if defined(POLARSSL_ASN1_WRITE_C)
ansond 0:137634ff4186 30
ansond 0:137634ff4186 31 #include "polarssl/asn1write.h"
ansond 0:137634ff4186 32
ansond 0:137634ff4186 33 #include <string.h>
ansond 0:137634ff4186 34
ansond 0:137634ff4186 35 #if defined(POLARSSL_PLATFORM_C)
ansond 0:137634ff4186 36 #include "polarssl/platform.h"
ansond 0:137634ff4186 37 #else
ansond 0:137634ff4186 38 #include <stdlib.h>
ansond 0:137634ff4186 39 #define polarssl_malloc malloc
ansond 0:137634ff4186 40 #define polarssl_free free
ansond 0:137634ff4186 41 #endif
ansond 0:137634ff4186 42
ansond 0:137634ff4186 43 int asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
ansond 0:137634ff4186 44 {
ansond 0:137634ff4186 45 if( len < 0x80 )
ansond 0:137634ff4186 46 {
ansond 0:137634ff4186 47 if( *p - start < 1 )
ansond 0:137634ff4186 48 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 49
ansond 0:137634ff4186 50 *--(*p) = (unsigned char) len;
ansond 0:137634ff4186 51 return( 1 );
ansond 0:137634ff4186 52 }
ansond 0:137634ff4186 53
ansond 0:137634ff4186 54 if( len <= 0xFF )
ansond 0:137634ff4186 55 {
ansond 0:137634ff4186 56 if( *p - start < 2 )
ansond 0:137634ff4186 57 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 58
ansond 0:137634ff4186 59 *--(*p) = (unsigned char) len;
ansond 0:137634ff4186 60 *--(*p) = 0x81;
ansond 0:137634ff4186 61 return( 2 );
ansond 0:137634ff4186 62 }
ansond 0:137634ff4186 63
ansond 0:137634ff4186 64 if( *p - start < 3 )
ansond 0:137634ff4186 65 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 66
ansond 0:137634ff4186 67 // We assume we never have lengths larger than 65535 bytes
ansond 0:137634ff4186 68 //
ansond 0:137634ff4186 69 *--(*p) = len % 256;
ansond 0:137634ff4186 70 *--(*p) = ( len / 256 ) % 256;
ansond 0:137634ff4186 71 *--(*p) = 0x82;
ansond 0:137634ff4186 72
ansond 0:137634ff4186 73 return( 3 );
ansond 0:137634ff4186 74 }
ansond 0:137634ff4186 75
ansond 0:137634ff4186 76 int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
ansond 0:137634ff4186 77 {
ansond 0:137634ff4186 78 if( *p - start < 1 )
ansond 0:137634ff4186 79 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 80
ansond 0:137634ff4186 81 *--(*p) = tag;
ansond 0:137634ff4186 82
ansond 0:137634ff4186 83 return( 1 );
ansond 0:137634ff4186 84 }
ansond 0:137634ff4186 85
ansond 0:137634ff4186 86 int asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
ansond 0:137634ff4186 87 const unsigned char *buf, size_t size )
ansond 0:137634ff4186 88 {
ansond 0:137634ff4186 89 size_t len = 0;
ansond 0:137634ff4186 90
ansond 0:137634ff4186 91 if( *p - start < (int) size )
ansond 0:137634ff4186 92 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 93
ansond 0:137634ff4186 94 len = size;
ansond 0:137634ff4186 95 (*p) -= len;
ansond 0:137634ff4186 96 memcpy( *p, buf, len );
ansond 0:137634ff4186 97
ansond 0:137634ff4186 98 return( (int) len );
ansond 0:137634ff4186 99 }
ansond 0:137634ff4186 100
ansond 0:137634ff4186 101 #if defined(POLARSSL_BIGNUM_C)
ansond 0:137634ff4186 102 int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X )
ansond 0:137634ff4186 103 {
ansond 0:137634ff4186 104 int ret;
ansond 0:137634ff4186 105 size_t len = 0;
ansond 0:137634ff4186 106
ansond 0:137634ff4186 107 // Write the MPI
ansond 0:137634ff4186 108 //
ansond 0:137634ff4186 109 len = mpi_size( X );
ansond 0:137634ff4186 110
ansond 0:137634ff4186 111 if( *p - start < (int) len )
ansond 0:137634ff4186 112 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 113
ansond 0:137634ff4186 114 (*p) -= len;
ansond 0:137634ff4186 115 MPI_CHK( mpi_write_binary( X, *p, len ) );
ansond 0:137634ff4186 116
ansond 0:137634ff4186 117 // DER format assumes 2s complement for numbers, so the leftmost bit
ansond 0:137634ff4186 118 // should be 0 for positive numbers and 1 for negative numbers.
ansond 0:137634ff4186 119 //
ansond 0:137634ff4186 120 if( X->s ==1 && **p & 0x80 )
ansond 0:137634ff4186 121 {
ansond 0:137634ff4186 122 if( *p - start < 1 )
ansond 0:137634ff4186 123 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 124
ansond 0:137634ff4186 125 *--(*p) = 0x00;
ansond 0:137634ff4186 126 len += 1;
ansond 0:137634ff4186 127 }
ansond 0:137634ff4186 128
ansond 0:137634ff4186 129 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 130 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
ansond 0:137634ff4186 131
ansond 0:137634ff4186 132 ret = (int) len;
ansond 0:137634ff4186 133
ansond 0:137634ff4186 134 cleanup:
ansond 0:137634ff4186 135 return( ret );
ansond 0:137634ff4186 136 }
ansond 0:137634ff4186 137 #endif /* POLARSSL_BIGNUM_C */
ansond 0:137634ff4186 138
ansond 0:137634ff4186 139 int asn1_write_null( unsigned char **p, unsigned char *start )
ansond 0:137634ff4186 140 {
ansond 0:137634ff4186 141 int ret;
ansond 0:137634ff4186 142 size_t len = 0;
ansond 0:137634ff4186 143
ansond 0:137634ff4186 144 // Write NULL
ansond 0:137634ff4186 145 //
ansond 0:137634ff4186 146 ASN1_CHK_ADD( len, asn1_write_len( p, start, 0) );
ansond 0:137634ff4186 147 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_NULL ) );
ansond 0:137634ff4186 148
ansond 0:137634ff4186 149 return( (int) len );
ansond 0:137634ff4186 150 }
ansond 0:137634ff4186 151
ansond 0:137634ff4186 152 int asn1_write_oid( unsigned char **p, unsigned char *start,
ansond 0:137634ff4186 153 const char *oid, size_t oid_len )
ansond 0:137634ff4186 154 {
ansond 0:137634ff4186 155 int ret;
ansond 0:137634ff4186 156 size_t len = 0;
ansond 0:137634ff4186 157
ansond 0:137634ff4186 158 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
ansond 0:137634ff4186 159 (const unsigned char *) oid, oid_len ) );
ansond 0:137634ff4186 160 ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 161 ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) );
ansond 0:137634ff4186 162
ansond 0:137634ff4186 163 return( (int) len );
ansond 0:137634ff4186 164 }
ansond 0:137634ff4186 165
ansond 0:137634ff4186 166 int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
ansond 0:137634ff4186 167 const char *oid, size_t oid_len,
ansond 0:137634ff4186 168 size_t par_len )
ansond 0:137634ff4186 169 {
ansond 0:137634ff4186 170 int ret;
ansond 0:137634ff4186 171 size_t len = 0;
ansond 0:137634ff4186 172
ansond 0:137634ff4186 173 if( par_len == 0 )
ansond 0:137634ff4186 174 ASN1_CHK_ADD( len, asn1_write_null( p, start ) );
ansond 0:137634ff4186 175 else
ansond 0:137634ff4186 176 len += par_len;
ansond 0:137634ff4186 177
ansond 0:137634ff4186 178 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
ansond 0:137634ff4186 179
ansond 0:137634ff4186 180 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 181 ASN1_CHK_ADD( len, asn1_write_tag( p, start,
ansond 0:137634ff4186 182 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
ansond 0:137634ff4186 183
ansond 0:137634ff4186 184 return( (int) len );
ansond 0:137634ff4186 185 }
ansond 0:137634ff4186 186
ansond 0:137634ff4186 187 int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
ansond 0:137634ff4186 188 {
ansond 0:137634ff4186 189 int ret;
ansond 0:137634ff4186 190 size_t len = 0;
ansond 0:137634ff4186 191
ansond 0:137634ff4186 192 if( *p - start < 1 )
ansond 0:137634ff4186 193 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 194
ansond 0:137634ff4186 195 *--(*p) = (boolean) ? 1 : 0;
ansond 0:137634ff4186 196 len++;
ansond 0:137634ff4186 197
ansond 0:137634ff4186 198 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 199 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BOOLEAN ) );
ansond 0:137634ff4186 200
ansond 0:137634ff4186 201 return( (int) len );
ansond 0:137634ff4186 202 }
ansond 0:137634ff4186 203
ansond 0:137634ff4186 204 int asn1_write_int( unsigned char **p, unsigned char *start, int val )
ansond 0:137634ff4186 205 {
ansond 0:137634ff4186 206 int ret;
ansond 0:137634ff4186 207 size_t len = 0;
ansond 0:137634ff4186 208
ansond 0:137634ff4186 209 // TODO negative values and values larger than 128
ansond 0:137634ff4186 210 // DER format assumes 2s complement for numbers, so the leftmost bit
ansond 0:137634ff4186 211 // should be 0 for positive numbers and 1 for negative numbers.
ansond 0:137634ff4186 212 //
ansond 0:137634ff4186 213 if( *p - start < 1 )
ansond 0:137634ff4186 214 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 215
ansond 0:137634ff4186 216 len += 1;
ansond 0:137634ff4186 217 *--(*p) = val;
ansond 0:137634ff4186 218
ansond 0:137634ff4186 219 if( val > 0 && **p & 0x80 )
ansond 0:137634ff4186 220 {
ansond 0:137634ff4186 221 if( *p - start < 1 )
ansond 0:137634ff4186 222 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 223
ansond 0:137634ff4186 224 *--(*p) = 0x00;
ansond 0:137634ff4186 225 len += 1;
ansond 0:137634ff4186 226 }
ansond 0:137634ff4186 227
ansond 0:137634ff4186 228 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 229 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
ansond 0:137634ff4186 230
ansond 0:137634ff4186 231 return( (int) len );
ansond 0:137634ff4186 232 }
ansond 0:137634ff4186 233
ansond 0:137634ff4186 234 int asn1_write_printable_string( unsigned char **p, unsigned char *start,
ansond 0:137634ff4186 235 const char *text, size_t text_len )
ansond 0:137634ff4186 236 {
ansond 0:137634ff4186 237 int ret;
ansond 0:137634ff4186 238 size_t len = 0;
ansond 0:137634ff4186 239
ansond 0:137634ff4186 240 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
ansond 0:137634ff4186 241 (const unsigned char *) text, text_len ) );
ansond 0:137634ff4186 242
ansond 0:137634ff4186 243 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 244 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) );
ansond 0:137634ff4186 245
ansond 0:137634ff4186 246 return( (int) len );
ansond 0:137634ff4186 247 }
ansond 0:137634ff4186 248
ansond 0:137634ff4186 249 int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
ansond 0:137634ff4186 250 const char *text, size_t text_len )
ansond 0:137634ff4186 251 {
ansond 0:137634ff4186 252 int ret;
ansond 0:137634ff4186 253 size_t len = 0;
ansond 0:137634ff4186 254
ansond 0:137634ff4186 255 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
ansond 0:137634ff4186 256 (const unsigned char *) text, text_len ) );
ansond 0:137634ff4186 257
ansond 0:137634ff4186 258 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 259 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) );
ansond 0:137634ff4186 260
ansond 0:137634ff4186 261 return( (int) len );
ansond 0:137634ff4186 262 }
ansond 0:137634ff4186 263
ansond 0:137634ff4186 264 int asn1_write_bitstring( unsigned char **p, unsigned char *start,
ansond 0:137634ff4186 265 const unsigned char *buf, size_t bits )
ansond 0:137634ff4186 266 {
ansond 0:137634ff4186 267 int ret;
ansond 0:137634ff4186 268 size_t len = 0, size;
ansond 0:137634ff4186 269
ansond 0:137634ff4186 270 size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
ansond 0:137634ff4186 271
ansond 0:137634ff4186 272 // Calculate byte length
ansond 0:137634ff4186 273 //
ansond 0:137634ff4186 274 if( *p - start < (int) size + 1 )
ansond 0:137634ff4186 275 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
ansond 0:137634ff4186 276
ansond 0:137634ff4186 277 len = size + 1;
ansond 0:137634ff4186 278 (*p) -= size;
ansond 0:137634ff4186 279 memcpy( *p, buf, size );
ansond 0:137634ff4186 280
ansond 0:137634ff4186 281 // Write unused bits
ansond 0:137634ff4186 282 //
ansond 0:137634ff4186 283 *--(*p) = (unsigned char) (size * 8 - bits);
ansond 0:137634ff4186 284
ansond 0:137634ff4186 285 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 286 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
ansond 0:137634ff4186 287
ansond 0:137634ff4186 288 return( (int) len );
ansond 0:137634ff4186 289 }
ansond 0:137634ff4186 290
ansond 0:137634ff4186 291 int asn1_write_octet_string( unsigned char **p, unsigned char *start,
ansond 0:137634ff4186 292 const unsigned char *buf, size_t size )
ansond 0:137634ff4186 293 {
ansond 0:137634ff4186 294 int ret;
ansond 0:137634ff4186 295 size_t len = 0;
ansond 0:137634ff4186 296
ansond 0:137634ff4186 297 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, buf, size ) );
ansond 0:137634ff4186 298
ansond 0:137634ff4186 299 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
ansond 0:137634ff4186 300 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
ansond 0:137634ff4186 301
ansond 0:137634ff4186 302 return( (int) len );
ansond 0:137634ff4186 303 }
ansond 0:137634ff4186 304
ansond 0:137634ff4186 305 asn1_named_data *asn1_store_named_data( asn1_named_data **head,
ansond 0:137634ff4186 306 const char *oid, size_t oid_len,
ansond 0:137634ff4186 307 const unsigned char *val,
ansond 0:137634ff4186 308 size_t val_len )
ansond 0:137634ff4186 309 {
ansond 0:137634ff4186 310 asn1_named_data *cur;
ansond 0:137634ff4186 311
ansond 0:137634ff4186 312 if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
ansond 0:137634ff4186 313 {
ansond 0:137634ff4186 314 // Add new entry if not present yet based on OID
ansond 0:137634ff4186 315 //
ansond 0:137634ff4186 316 if( ( cur = polarssl_malloc( sizeof(asn1_named_data) ) ) == NULL )
ansond 0:137634ff4186 317 return( NULL );
ansond 0:137634ff4186 318
ansond 0:137634ff4186 319 memset( cur, 0, sizeof(asn1_named_data) );
ansond 0:137634ff4186 320
ansond 0:137634ff4186 321 cur->oid.len = oid_len;
ansond 0:137634ff4186 322 cur->oid.p = polarssl_malloc( oid_len );
ansond 0:137634ff4186 323 if( cur->oid.p == NULL )
ansond 0:137634ff4186 324 {
ansond 0:137634ff4186 325 polarssl_free( cur );
ansond 0:137634ff4186 326 return( NULL );
ansond 0:137634ff4186 327 }
ansond 0:137634ff4186 328
ansond 0:137634ff4186 329 memcpy( cur->oid.p, oid, oid_len );
ansond 0:137634ff4186 330
ansond 0:137634ff4186 331 cur->val.len = val_len;
ansond 0:137634ff4186 332 cur->val.p = polarssl_malloc( val_len );
ansond 0:137634ff4186 333 if( cur->val.p == NULL )
ansond 0:137634ff4186 334 {
ansond 0:137634ff4186 335 polarssl_free( cur->oid.p );
ansond 0:137634ff4186 336 polarssl_free( cur );
ansond 0:137634ff4186 337 return( NULL );
ansond 0:137634ff4186 338 }
ansond 0:137634ff4186 339
ansond 0:137634ff4186 340 cur->next = *head;
ansond 0:137634ff4186 341 *head = cur;
ansond 0:137634ff4186 342 }
ansond 0:137634ff4186 343 else if( cur->val.len < val_len )
ansond 0:137634ff4186 344 {
ansond 0:137634ff4186 345 // Enlarge existing value buffer if needed
ansond 0:137634ff4186 346 //
ansond 0:137634ff4186 347 polarssl_free( cur->val.p );
ansond 0:137634ff4186 348 cur->val.p = NULL;
ansond 0:137634ff4186 349
ansond 0:137634ff4186 350 cur->val.len = val_len;
ansond 0:137634ff4186 351 cur->val.p = polarssl_malloc( val_len );
ansond 0:137634ff4186 352 if( cur->val.p == NULL )
ansond 0:137634ff4186 353 {
ansond 0:137634ff4186 354 polarssl_free( cur->oid.p );
ansond 0:137634ff4186 355 polarssl_free( cur );
ansond 0:137634ff4186 356 return( NULL );
ansond 0:137634ff4186 357 }
ansond 0:137634ff4186 358 }
ansond 0:137634ff4186 359
ansond 0:137634ff4186 360 if( val != NULL )
ansond 0:137634ff4186 361 memcpy( cur->val.p, val, val_len );
ansond 0:137634ff4186 362
ansond 0:137634ff4186 363 return( cur );
ansond 0:137634ff4186 364 }
ansond 0:137634ff4186 365 #endif /* POLARSSL_ASN1_WRITE_C */
ansond 0:137634ff4186 366