PolarSSL v1.1.4
asn1parse.c
Go to the documentation of this file.
00001 /*
00002  *  Generic ASN.1 parsing
00003  *
00004  *  Copyright (C) 2006-2011, Brainspark B.V.
00005  *
00006  *  This file is part of PolarSSL (http://www.polarssl.org)
00007  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
00008  *
00009  *  All rights reserved.
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License along
00022  *  with this program; if not, write to the Free Software Foundation, Inc.,
00023  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00024  */
00025 
00026 #include "polarssl/config.h"
00027 
00028 #if defined(POLARSSL_ASN1_PARSE_C)
00029 
00030 #include "polarssl/asn1.h"
00031 
00032 #if defined(POLARSSL_BIGNUM_C)
00033 #include "polarssl/bignum.h"
00034 #endif
00035 
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <time.h>
00039 
00040 /*
00041  * ASN.1 DER decoding routines
00042  */
00043 int asn1_get_len( unsigned char **p,
00044                   const unsigned char *end,
00045                   size_t *len )
00046 {
00047     if( ( end - *p ) < 1 )
00048         return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
00049 
00050     if( ( **p & 0x80 ) == 0 )
00051         *len = *(*p)++;
00052     else
00053     {
00054         switch( **p & 0x7F )
00055         {
00056         case 1:
00057             if( ( end - *p ) < 2 )
00058                 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
00059 
00060             *len = (*p)[1];
00061             (*p) += 2;
00062             break;
00063 
00064         case 2:
00065             if( ( end - *p ) < 3 )
00066                 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
00067 
00068             *len = ( (*p)[1] << 8 ) | (*p)[2];
00069             (*p) += 3;
00070             break;
00071 
00072         case 3:
00073             if( ( end - *p ) < 4 )
00074                 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
00075 
00076             *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
00077             (*p) += 4;
00078             break;
00079 
00080         case 4:
00081             if( ( end - *p ) < 5 )
00082                 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
00083 
00084             *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4];
00085             (*p) += 5;
00086             break;
00087 
00088         default:
00089             return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
00090         }
00091     }
00092 
00093     if( *len > (size_t) ( end - *p ) )
00094         return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
00095 
00096     return( 0 );
00097 }
00098 
00099 int asn1_get_tag( unsigned char **p,
00100                   const unsigned char *end,
00101                   size_t *len, int tag )
00102 {
00103     if( ( end - *p ) < 1 )
00104         return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
00105 
00106     if( **p != tag )
00107         return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
00108 
00109     (*p)++;
00110 
00111     return( asn1_get_len( p, end, len ) );
00112 }
00113 
00114 int asn1_get_bool( unsigned char **p,
00115                    const unsigned char *end,
00116                    int *val )
00117 {
00118     int ret;
00119     size_t len;
00120 
00121     if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
00122         return( ret );
00123 
00124     if( len != 1 )
00125         return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
00126 
00127     *val = ( **p != 0 ) ? 1 : 0;
00128     (*p)++;
00129 
00130     return( 0 );
00131 }
00132 
00133 int asn1_get_int( unsigned char **p,
00134                   const unsigned char *end,
00135                   int *val )
00136 {
00137     int ret;
00138     size_t len;
00139 
00140     if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
00141         return( ret );
00142 
00143     if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
00144         return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
00145 
00146     *val = 0;
00147 
00148     while( len-- > 0 )
00149     {
00150         *val = ( *val << 8 ) | **p;
00151         (*p)++;
00152     }
00153 
00154     return( 0 );
00155 }
00156 
00157 #if defined(POLARSSL_BIGNUM_C)
00158 int asn1_get_mpi( unsigned char **p,
00159                   const unsigned char *end,
00160                   mpi *X )
00161 {
00162     int ret;
00163     size_t len;
00164 
00165     if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
00166         return( ret );
00167 
00168     ret = mpi_read_binary( X, *p, len );
00169 
00170     *p += len;
00171 
00172     return( ret );
00173 }
00174 #endif /* POLARSSL_BIGNUM_C */
00175 
00176 int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
00177                         asn1_bitstring *bs)
00178 {
00179     int ret;
00180 
00181     /* Certificate type is a single byte bitstring */
00182     if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
00183         return( ret );
00184 
00185     /* Check length, subtract one for actual bit string length */
00186     if ( bs->len < 1 )
00187         return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
00188     bs->len -= 1;
00189 
00190     /* Get number of unused bits, ensure unused bits <= 7 */
00191     bs->unused_bits = **p;
00192     if( bs->unused_bits > 7 )
00193         return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
00194     (*p)++;
00195 
00196     /* Get actual bitstring */
00197     bs->p = *p;
00198     *p += bs->len;
00199 
00200     if( *p != end )
00201         return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
00202 
00203     return 0;
00204 }
00205 
00206 
00207 /*
00208  *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
00209  */
00210 int asn1_get_sequence_of( unsigned char **p,
00211                           const unsigned char *end,
00212                           asn1_sequence *cur,
00213                           int tag)
00214 {
00215     int ret;
00216     size_t len;
00217     asn1_buf *buf;
00218 
00219     /* Get main sequence tag */
00220     if( ( ret = asn1_get_tag( p, end, &len,
00221             ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00222         return( ret );
00223 
00224     if( *p + len != end )
00225         return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
00226 
00227     while( *p < end )
00228     {
00229         buf = &(cur->buf);
00230         buf->tag = **p;
00231 
00232         if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
00233             return( ret );
00234 
00235         buf->p = *p;
00236         *p += buf->len;
00237 
00238         /* Allocate and assign next pointer */
00239         if (*p < end)
00240         {
00241             cur->next = (asn1_sequence *) malloc(
00242                  sizeof( asn1_sequence ) );
00243 
00244             if( cur->next == NULL )
00245                 return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
00246 
00247             cur = cur->next;
00248         }
00249     }
00250 
00251     /* Set final sequence entry's next pointer to NULL */
00252     cur->next = NULL;
00253 
00254     if( *p != end )
00255         return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
00256 
00257     return( 0 );
00258 }
00259 
00260 #endif