Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers asn1write.c Source File

asn1write.c

00001 /*
00002  * ASN.1 buffer writing functionality
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 
00022 #if !defined(MBEDTLS_CONFIG_FILE)
00023 #include "mbedtls/config.h"
00024 #else
00025 #include MBEDTLS_CONFIG_FILE
00026 #endif
00027 
00028 #if defined(MBEDTLS_ASN1_WRITE_C)
00029 
00030 #include "mbedtls/asn1write.h"
00031 
00032 #include <string.h>
00033 
00034 #if defined(MBEDTLS_PLATFORM_C)
00035 #include "mbedtls/platform.h"
00036 #else
00037 #include <stdlib.h>
00038 #define mbedtls_calloc    calloc
00039 #define mbedtls_free       free
00040 #endif
00041 
00042 int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
00043 {
00044     if( len < 0x80 )
00045     {
00046         if( *p - start < 1 )
00047             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00048 
00049         *--(*p) = (unsigned char) len;
00050         return( 1 );
00051     }
00052 
00053     if( len <= 0xFF )
00054     {
00055         if( *p - start < 2 )
00056             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00057 
00058         *--(*p) = (unsigned char) len;
00059         *--(*p) = 0x81;
00060         return( 2 );
00061     }
00062 
00063     if( len <= 0xFFFF )
00064     {
00065         if( *p - start < 3 )
00066             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00067 
00068         *--(*p) = ( len       ) & 0xFF;
00069         *--(*p) = ( len >>  8 ) & 0xFF;
00070         *--(*p) = 0x82;
00071         return( 3 );
00072     }
00073 
00074     if( len <= 0xFFFFFF )
00075     {
00076         if( *p - start < 4 )
00077             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00078 
00079         *--(*p) = ( len       ) & 0xFF;
00080         *--(*p) = ( len >>  8 ) & 0xFF;
00081         *--(*p) = ( len >> 16 ) & 0xFF;
00082         *--(*p) = 0x83;
00083         return( 4 );
00084     }
00085 
00086 #if SIZE_MAX > 0xFFFFFFFF
00087     if( len <= 0xFFFFFFFF )
00088 #endif
00089     {
00090         if( *p - start < 5 )
00091             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00092 
00093         *--(*p) = ( len       ) & 0xFF;
00094         *--(*p) = ( len >>  8 ) & 0xFF;
00095         *--(*p) = ( len >> 16 ) & 0xFF;
00096         *--(*p) = ( len >> 24 ) & 0xFF;
00097         *--(*p) = 0x84;
00098         return( 5 );
00099     }
00100 
00101 #if SIZE_MAX > 0xFFFFFFFF
00102     return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
00103 #endif
00104 }
00105 
00106 int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
00107 {
00108     if( *p - start < 1 )
00109         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00110 
00111     *--(*p) = tag;
00112 
00113     return( 1 );
00114 }
00115 
00116 int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
00117                            const unsigned char *buf, size_t size )
00118 {
00119     size_t len = 0;
00120 
00121     if( *p < start || (size_t)( *p - start ) < size )
00122         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00123 
00124     len = size;
00125     (*p) -= len;
00126     memcpy( *p, buf, len );
00127 
00128     return( (int) len );
00129 }
00130 
00131 #if defined(MBEDTLS_BIGNUM_C)
00132 int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X )
00133 {
00134     int ret;
00135     size_t len = 0;
00136 
00137     // Write the MPI
00138     //
00139     len = mbedtls_mpi_size( X );
00140 
00141     if( *p < start || (size_t)( *p - start ) < len )
00142         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00143 
00144     (*p) -= len;
00145     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) );
00146 
00147     // DER format assumes 2s complement for numbers, so the leftmost bit
00148     // should be 0 for positive numbers and 1 for negative numbers.
00149     //
00150     if( X->s  ==1 && **p & 0x80 )
00151     {
00152         if( *p - start < 1 )
00153             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00154 
00155         *--(*p) = 0x00;
00156         len += 1;
00157     }
00158 
00159     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00160     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
00161 
00162     ret = (int) len;
00163 
00164 cleanup:
00165     return( ret );
00166 }
00167 #endif /* MBEDTLS_BIGNUM_C */
00168 
00169 int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
00170 {
00171     int ret;
00172     size_t len = 0;
00173 
00174     // Write NULL
00175     //
00176     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) );
00177     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) );
00178 
00179     return( (int) len );
00180 }
00181 
00182 int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
00183                     const char *oid, size_t oid_len )
00184 {
00185     int ret;
00186     size_t len = 0;
00187 
00188     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
00189                                   (const unsigned char *) oid, oid_len ) );
00190     MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) );
00191     MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
00192 
00193     return( (int) len );
00194 }
00195 
00196 int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
00197                                      const char *oid, size_t oid_len,
00198                                      size_t par_len )
00199 {
00200     int ret;
00201     size_t len = 0;
00202 
00203     if( par_len == 0 )
00204         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) );
00205     else
00206         len += par_len;
00207 
00208     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
00209 
00210     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00211     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
00212                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
00213 
00214     return( (int) len );
00215 }
00216 
00217 int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
00218 {
00219     int ret;
00220     size_t len = 0;
00221 
00222     if( *p - start < 1 )
00223         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00224 
00225     *--(*p) = (boolean) ? 255 : 0;
00226     len++;
00227 
00228     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00229     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) );
00230 
00231     return( (int) len );
00232 }
00233 
00234 int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
00235 {
00236     int ret;
00237     size_t len = 0;
00238 
00239     do
00240     {
00241         if( *p - start < 1 )
00242             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00243         len += 1;
00244         *--(*p) = val & 0xff;
00245         val >>= 8;
00246     }
00247     while( val > 0 );
00248 
00249     if( **p & 0x80 )
00250     {
00251         if( *p - start < 1 )
00252             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00253         *--(*p) = 0x00;
00254         len += 1;
00255     }
00256 
00257     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00258     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
00259 
00260     return( (int) len );
00261 }
00262 
00263 int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
00264     const char *text, size_t text_len )
00265 {
00266     int ret;
00267     size_t len = 0;
00268 
00269     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
00270         (const unsigned char *) text, text_len ) );
00271 
00272     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00273     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
00274 
00275     return( (int) len );
00276 }
00277 
00278 int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
00279     const char *text, size_t text_len )
00280 {
00281     return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) );
00282 }
00283 
00284 int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
00285                                  const char *text, size_t text_len )
00286 {
00287     return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) );
00288 }
00289 
00290 int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
00291                            const char *text, size_t text_len )
00292 {
00293     return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
00294 }
00295 
00296 int mbedtls_asn1_write_named_bitstring( unsigned char **p,
00297                                         unsigned char *start,
00298                                         const unsigned char *buf,
00299                                         size_t bits )
00300 {
00301     size_t unused_bits, byte_len;
00302     const unsigned char *cur_byte;
00303     unsigned char cur_byte_shifted;
00304     unsigned char bit;
00305 
00306     byte_len = ( bits + 7 ) / 8;
00307     unused_bits = ( byte_len * 8 ) - bits;
00308 
00309     /*
00310      * Named bitstrings require that trailing 0s are excluded in the encoding
00311      * of the bitstring. Trailing 0s are considered part of the 'unused' bits
00312      * when encoding this value in the first content octet
00313      */
00314     if( bits != 0 )
00315     {
00316         cur_byte = buf + byte_len - 1;
00317         cur_byte_shifted = *cur_byte >> unused_bits;
00318 
00319         for( ; ; )
00320         {
00321             bit = cur_byte_shifted & 0x1;
00322             cur_byte_shifted >>= 1;
00323 
00324             if( bit != 0 )
00325                 break;
00326 
00327             bits--;
00328             if( bits == 0 )
00329                 break;
00330 
00331             if( bits % 8 == 0 )
00332                 cur_byte_shifted = *--cur_byte;
00333         }
00334     }
00335 
00336     return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) );
00337 }
00338 
00339 int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
00340                           const unsigned char *buf, size_t bits )
00341 {
00342     int ret;
00343     size_t len = 0;
00344     size_t unused_bits, byte_len;
00345 
00346     byte_len = ( bits + 7 ) / 8;
00347     unused_bits = ( byte_len * 8 ) - bits;
00348 
00349     if( *p < start || (size_t)( *p - start ) < byte_len + 1 )
00350         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00351 
00352     len = byte_len + 1;
00353 
00354     /* Write the bitstring. Ensure the unused bits are zeroed */
00355     if( byte_len > 0 )
00356     {
00357         byte_len--;
00358         *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 );
00359         ( *p ) -= byte_len;
00360         memcpy( *p, buf, byte_len );
00361     }
00362 
00363     /* Write unused bits */
00364     *--( *p ) = (unsigned char)unused_bits;
00365 
00366     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00367     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
00368 
00369     return( (int) len );
00370 }
00371 
00372 int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
00373                              const unsigned char *buf, size_t size )
00374 {
00375     int ret;
00376     size_t len = 0;
00377 
00378     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
00379 
00380     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00381     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
00382 
00383     return( (int) len );
00384 }
00385 
00386 
00387 /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
00388  * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
00389 static mbedtls_asn1_named_data *asn1_find_named_data(
00390                                                mbedtls_asn1_named_data *list,
00391                                                const char *oid, size_t len )
00392 {
00393     while( list != NULL )
00394     {
00395         if( list->oid.len == len &&
00396             memcmp( list->oid.p, oid, len ) == 0 )
00397         {
00398             break;
00399         }
00400 
00401         list = list->next;
00402     }
00403 
00404     return( list );
00405 }
00406 
00407 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
00408                                         mbedtls_asn1_named_data **head,
00409                                         const char *oid, size_t oid_len,
00410                                         const unsigned char *val,
00411                                         size_t val_len )
00412 {
00413     mbedtls_asn1_named_data *cur;
00414 
00415     if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
00416     {
00417         // Add new entry if not present yet based on OID
00418         //
00419         cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1,
00420                                             sizeof(mbedtls_asn1_named_data) );
00421         if( cur == NULL )
00422             return( NULL );
00423 
00424         cur->oid.len = oid_len;
00425         cur->oid.p = mbedtls_calloc( 1, oid_len );
00426         if( cur->oid.p == NULL )
00427         {
00428             mbedtls_free( cur );
00429             return( NULL );
00430         }
00431 
00432         memcpy( cur->oid.p, oid, oid_len );
00433 
00434         cur->val.len = val_len;
00435         if( val_len != 0 )
00436         {
00437             cur->val.p = mbedtls_calloc( 1, val_len );
00438             if( cur->val.p == NULL )
00439             {
00440                 mbedtls_free( cur->oid.p );
00441                 mbedtls_free( cur );
00442                 return( NULL );
00443             }
00444         }
00445 
00446         cur->next = *head;
00447         *head = cur;
00448     }
00449     else if( val_len == 0 )
00450     {
00451         mbedtls_free( cur->val.p );
00452         cur->val.p = NULL;
00453     }
00454     else if( cur->val.len != val_len )
00455     {
00456         /*
00457          * Enlarge existing value buffer if needed
00458          * Preserve old data until the allocation succeeded, to leave list in
00459          * a consistent state in case allocation fails.
00460          */
00461         void *p = mbedtls_calloc( 1, val_len );
00462         if( p == NULL )
00463             return( NULL );
00464 
00465         mbedtls_free( cur->val.p );
00466         cur->val.p = p;
00467         cur->val.len = val_len;
00468     }
00469 
00470     if( val != NULL )
00471         memcpy( cur->val.p, val, val_len );
00472 
00473     return( cur );
00474 }
00475 #endif /* MBEDTLS_ASN1_WRITE_C */