From 81db488ebe397ddba4e51e04c0719023ef18cf70 Mon Sep 17 00:00:00 2001 From: Michał Cichoń Date: Sun, 6 May 2012 01:46:56 +0200 Subject: Replace axTLS with PolarSSL as it does not handle secure connections well enough. --- polarssl/src/library/asn1parse.c | 260 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 polarssl/src/library/asn1parse.c (limited to 'polarssl/src/library/asn1parse.c') diff --git a/polarssl/src/library/asn1parse.c b/polarssl/src/library/asn1parse.c new file mode 100644 index 0000000..2584774 --- /dev/null +++ b/polarssl/src/library/asn1parse.c @@ -0,0 +1,260 @@ +/* + * Generic ASN.1 parsing + * + * Copyright (C) 2006-2011, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_ASN1_PARSE_C) + +#include "polarssl/asn1.h" + +#if defined(POLARSSL_BIGNUM_C) +#include "polarssl/bignum.h" +#endif + +#include +#include +#include + +/* + * ASN.1 DER decoding routines + */ +int asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( asn1_get_len( p, end, len ) ); +} + +int asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +int asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) + return( ret ); + + if( len > sizeof( int ) || ( **p & 0x80 ) != 0 ) + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +#if defined(POLARSSL_BIGNUM_C) +int asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mpi *X ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* POLARSSL_BIGNUM_C */ + +int asn1_get_bitstring( unsigned char **p, const unsigned char *end, + asn1_bitstring *bs) +{ + int ret; + + /* Certificate type is a single byte bitstring */ + if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if ( bs->len < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return 0; +} + + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + asn1_sequence *cur, + int tag) +{ + int ret; + size_t len; + asn1_buf *buf; + + /* Get main sequence tag */ + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + buf = &(cur->buf); + buf->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) + return( ret ); + + buf->p = *p; + *p += buf->len; + + /* Allocate and assign next pointer */ + if (*p < end) + { + cur->next = (asn1_sequence *) malloc( + sizeof( asn1_sequence ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_ASN1_MALLOC_FAILED ); + + cur = cur->next; + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#endif -- cgit v1.2.3