- Extracted ASN.1 parsing code from the X.509 parsing code. Added new module.

diff --git a/ChangeLog b/ChangeLog
index 0ae3e35..245cbf2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,6 +16,8 @@
    * Inceased maximum size of ASN1 length reads to 32-bits.
    * Added an EXPLICIT tag number parameter to x509_get_ext()
    * Added a separate CRL entry extension parsing function
+   * Separated the ASN.1 parsing code from the X.509 specific parsing code.
+     So now there is a module that is controlled with POLARSSL_ASN1_PARSE_C.
 
 Bugfix
    * Fixed faulty HMAC-MD2 implementation. Found by dibac. (Closes
diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h
new file mode 100644
index 0000000..fc86fc8
--- /dev/null
+++ b/include/polarssl/asn1.h
@@ -0,0 +1,242 @@
+/**
+ * \file asn1.h
+ *
+ * \brief 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 <polarssl_maintainer at polarssl.org>
+ *
+ *  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.
+ */
+#ifndef POLARSSL_ASN1_H
+#define POLARSSL_ASN1_H
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#include <string.h>
+
+/** 
+ * \addtogroup asn1_module
+ * \{ 
+ */
+ 
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity. 
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define POLARSSL_ERR_ASN1_OUT_OF_DATA                      -0x0014  /**< Out of data when parsing an ASN1 data structure. */
+#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG                   -0x0016  /**< ASN1 tag was of an unexpected value. */
+#define POLARSSL_ERR_ASN1_INVALID_LENGTH                   -0x0018  /**< Error when trying to determine the length or invalid length. */
+#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH                  -0x001A  /**< Actual length differs from expected length. */
+#define POLARSSL_ERR_ASN1_INVALID_DATA                     -0x001C  /**< Data is invalid. (not used) */
+/* \} name */
+
+/**
+ * \name DER constants
+ * These constants comply with DER encoded the ANS1 type tags.
+ * DER encoding uses hexadecimal representation.
+ * An example DER sequence is:\n
+ * - 0x02 -- tag indicating INTEGER
+ * - 0x01 -- length in octets
+ * - 0x05 -- value
+ * Such sequences are typically read into \c ::x509_buf.
+ * \{
+ */
+#define ASN1_BOOLEAN                 0x01
+#define ASN1_INTEGER                 0x02
+#define ASN1_BIT_STRING              0x03
+#define ASN1_OCTET_STRING            0x04
+#define ASN1_NULL                    0x05
+#define ASN1_OID                     0x06
+#define ASN1_UTF8_STRING             0x0C
+#define ASN1_SEQUENCE                0x10
+#define ASN1_SET                     0x11
+#define ASN1_PRINTABLE_STRING        0x13
+#define ASN1_T61_STRING              0x14
+#define ASN1_IA5_STRING              0x16
+#define ASN1_UTC_TIME                0x17
+#define ASN1_GENERALIZED_TIME        0x18
+#define ASN1_UNIVERSAL_STRING        0x1C
+#define ASN1_BMP_STRING              0x1E
+#define ASN1_PRIMITIVE               0x00
+#define ASN1_CONSTRUCTED             0x20
+#define ASN1_CONTEXT_SPECIFIC        0x80
+/* \} name */
+/* \} addtogroup asn1_module */
+
+/** Returns the size of the binary string, without the trailing \\0 */
+#define OID_SIZE(x) (sizeof(x) - 1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Functions to parse ASN.1 data structures
+ * \{
+ */
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef struct _asn1_buf
+{
+    int tag;                /**< ASN1 type, e.g. ASN1_UTF8_STRING. */
+    size_t len;             /**< ASN1 length, e.g. in octets. */
+    unsigned char *p;       /**< ASN1 data, e.g. in ASCII. */
+}
+asn1_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef struct _asn1_bitstring
+{
+    size_t len;                 /**< ASN1 length, e.g. in octets. */
+    unsigned char unused_bits;  /**< Number of unused bits at the end of the string */
+    unsigned char *p;           /**< Raw ASN1 data for the bit string */
+}
+asn1_bitstring;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef struct _asn1_sequence
+{
+    asn1_buf buf;                   /**< Buffer containing the given ASN.1 item. */
+    struct _asn1_sequence *next;    /**< The next entry in the sequence. */
+}
+asn1_sequence;
+
+/**
+ * Get the length of an ASN.1 element.
+ * Updates the pointer to immediately behind the length.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   The variable that will receive the value
+ *
+ * \return      0 if successful, POLARSSL_ERR_ASN1_OUT_OF_DATA on reaching
+ *              end of data, POLARSSL_ERR_ASN1_INVALID_LENGTH if length is
+ *              unparseable.
+ */
+int asn1_get_len( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len );
+
+/**
+ * Get the tag and length of the tag. Check for the requested tag.
+ * Updates the pointer to immediately behind the tag and length.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   The variable that will receive the length
+ * \param tag   The expected tag
+ *
+ * \return      0 if successful, POLARSSL_ERR_ASN1_UNEXPECTED_TAG if tag did
+ *              not match requested tag, or another specific ASN.1 error code.
+ */
+int asn1_get_tag( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len, int tag );
+
+/**
+ * Retrieve a boolean ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param val   The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_bool( unsigned char **p,
+                   const unsigned char *end,
+                   int *val );
+
+/**
+ * Retrieve an integer ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param val   The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_int( unsigned char **p,
+                  const unsigned char *end,
+                  int *val );
+
+/**
+ * Retrieve a bitstring ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param bs    The variable that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+                        asn1_bitstring *bs);
+
+/**
+ * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ * Updated the pointer to immediately behind the full sequence tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param cur   First variable in the chain to fill
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_sequence_of( unsigned char **p,
+                          const unsigned char *end,
+                          asn1_sequence *cur,
+                          int tag);
+
+#if defined(POLARSSL_BIGNUM_C)
+/**
+ * Retrieve a MPI value from an integer ASN.1 tag.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param X     The MPI that will receive the value
+ *
+ * \return      0 if successful or a specific ASN.1 or MPI error code.
+ */
+int asn1_get_mpi( unsigned char **p,
+                  const unsigned char *end,
+                  mpi *X );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* asn1.h */
diff --git a/include/polarssl/config.h b/include/polarssl/config.h
index 61500a7..06ee291 100644
--- a/include/polarssl/config.h
+++ b/include/polarssl/config.h
@@ -3,7 +3,7 @@
  *
  * \brief Configuration options (set of defines)
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2011, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -231,6 +231,16 @@
 #define POLARSSL_ARC4_C
 
 /**
+ * \def POLARSSL_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module:  library/asn1.c
+ * Caller:  library/x509parse.c
+ */
+#define POLARSSL_ASN1_PARSE_C
+
+/**
  * \def POLARSSL_BASE64_C
  *
  * Enable the Base64 module.
@@ -605,7 +615,7 @@
  *          library/ssl_srv.c
  *          library/ssl_tls.c
  *
- * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C
  *
  * This module is required for X.509 certificate parsing.
  */
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index a2d5440..93ef265 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -3,7 +3,7 @@
  *
  * \brief X.509 certificate and private key decoding
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2011, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -27,6 +27,7 @@
 #ifndef POLARSSL_X509_H
 #define POLARSSL_X509_H
 
+#include "asn1.h"
 #include "rsa.h"
 #include "dhm.h"
 
@@ -35,20 +36,6 @@
  * \{ 
  */
  
-/**
- * \name ASN1 Error codes
- * These error codes are OR'ed to X509 error codes for
- * higher error granularity. 
- * ASN1 is a standard to specify data structures.
- * \{
- */
-#define POLARSSL_ERR_ASN1_OUT_OF_DATA                      -0x0014  /**< Out of data when parsing an ASN1 data structure. */
-#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG                   -0x0016  /**< ASN1 tag was of an unexpected value. */
-#define POLARSSL_ERR_ASN1_INVALID_LENGTH                   -0x0018  /**< Error when trying to determine the length or invalid length. */
-#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH                  -0x001A  /**< Actual length differs from expected length. */
-#define POLARSSL_ERR_ASN1_INVALID_DATA                     -0x001C  /**< Data is invalid. (not used) */
-/* \} name */
-
 /** 
  * \name X509 Error codes
  * \{
@@ -89,39 +76,6 @@
 #define BADCERT_MISSING             0x40  /**< Certificate was missing. */
 #define BADCERT_SKIP_VERIFY         0x80  /**< Certificate verification was skipped. */
 /* \} name */
-
-
-/**
- * \name DER constants
- * These constants comply with DER encoded the ANS1 type tags.
- * DER encoding uses hexadecimal representation.
- * An example DER sequence is:\n
- * - 0x02 -- tag indicating INTEGER
- * - 0x01 -- length in octets
- * - 0x05 -- value
- * Such sequences are typically read into \c ::x509_buf.
- * \{
- */
-#define ASN1_BOOLEAN                 0x01
-#define ASN1_INTEGER                 0x02
-#define ASN1_BIT_STRING              0x03
-#define ASN1_OCTET_STRING            0x04
-#define ASN1_NULL                    0x05
-#define ASN1_OID                     0x06
-#define ASN1_UTF8_STRING             0x0C
-#define ASN1_SEQUENCE                0x10
-#define ASN1_SET                     0x11
-#define ASN1_PRINTABLE_STRING        0x13
-#define ASN1_T61_STRING              0x14
-#define ASN1_IA5_STRING              0x16
-#define ASN1_UTC_TIME                0x17
-#define ASN1_GENERALIZED_TIME        0x18
-#define ASN1_UNIVERSAL_STRING        0x1C
-#define ASN1_BMP_STRING              0x1E
-#define ASN1_PRIMITIVE               0x00
-#define ASN1_CONSTRUCTED             0x20
-#define ASN1_CONTEXT_SPECIFIC        0x80
-/* \} name */
 /* \} addtogroup x509_module */
 
 /*
@@ -141,9 +95,6 @@
 #define X509_ISSUER                  0x01
 #define X509_SUBJECT                 0x02
 
-/** Returns the size of the binary string, without the trailing \\0 */
-#define OID_SIZE(x) (sizeof(x) - 1)
-
 #define OID_X520                "\x55\x04"
 #define OID_CN                  OID_X520 "\x03"
 
@@ -281,24 +232,12 @@
 /** 
  * Type-length-value structure that allows for ASN1 using DER.
  */
-typedef struct _x509_buf
-{
-    int tag;                /**< ASN1 type, e.g. ASN1_UTF8_STRING. */
-    size_t len;             /**< ASN1 length, e.g. in octets. */
-    unsigned char *p;       /**< ASN1 data, e.g. in ASCII. */
-}
-x509_buf;
+typedef asn1_buf x509_buf;
 
 /**
  * Container for ASN1 bit strings.
  */
-typedef struct _x509_bitstring
-{
-    size_t len;                 /**< ASN1 length, e.g. in octets. */
-    unsigned char unused_bits;  /**< Number of unused bits at the end of the string */
-    unsigned char *p;           /**< Raw ASN1 data for the bit string */
-}
-x509_bitstring;
+typedef asn1_bitstring x509_bitstring;
 
 /**
  * Container for ASN1 named information objects. 
@@ -315,12 +254,7 @@
 /**
  * Container for a sequence of ASN.1 items
  */
-typedef struct _x509_sequence
-{
-    x509_buf buf;                   /**< Buffer containing the given ASN.1 item. */
-    struct _x509_sequence *next;    /**< The next entry in the sequence. */
-}
-x509_sequence;
+typedef asn1_sequence x509_sequence;
 
 /** Container for date and time (precision in seconds). */
 typedef struct _x509_time
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 3050856..a7f978a 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -3,6 +3,7 @@
 set(src
      aes.c
      arc4.c
+     asn1parse.c
      base64.c
      bignum.c
      camellia.c
diff --git a/library/Makefile b/library/Makefile
index 1ecd2ff..960da37 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -22,7 +22,8 @@
 # Windows shared library extension:
 # DLEXT=dll
 
-OBJS=	aes.o		arc4.o		base64.o	\
+OBJS=	aes.o		arc4.o		asn1parse.o	\
+		base64.o	\
 		bignum.o	camellia.o	certs.o		\
 		cipher.o	cipher_wrap.o	debug.o	\
 		des.o		dhm.o		havege.o	\
diff --git a/library/asn1parse.c b/library/asn1parse.c
new file mode 100644
index 0000000..09f67fa
--- /dev/null
+++ b/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 <polarssl_maintainer at polarssl.org>
+ *
+ *  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 <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+/*
+ * 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 <tag>"
+ */
+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( 1 );
+
+            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
diff --git a/library/x509parse.c b/library/x509parse.c
index d97efff..9fc8831 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -1,7 +1,7 @@
 /*
  *  X.509 certificate and private key decoding
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2011, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -39,6 +39,7 @@
 #if defined(POLARSSL_X509_PARSE_C)
 
 #include "polarssl/x509.h"
+#include "polarssl/asn1.h"
 #include "polarssl/pem.h"
 #include "polarssl/des.h"
 #include "polarssl/md2.h"
@@ -58,224 +59,6 @@
 #endif
 
 /*
- * ASN.1 DER decoding routines
- */
-static 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 );
-}
-
-static 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 ) );
-}
-
-static 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 );
-}
-
-static 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 );
-}
-
-static 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 );
-}
-
-static int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
-        x509_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 <tag>"
- */
-static int asn1_get_sequence_of( unsigned char **p,
-                          const unsigned char *end,
-                          x509_sequence *cur,
-                          int tag)
-{
-    int ret;
-    size_t len;
-    x509_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 = (x509_sequence *) malloc(
-                 sizeof( x509_sequence ) );
-
-            if( cur->next == NULL )
-                return( 1 );
-
-            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 );
-}
-
-/*
  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
  */
 static int x509_get_version( unsigned char **p,