CSR Parsing (without attributes / extensions) implemented
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index e68789c..0c30296 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -151,7 +151,7 @@
  * \{ */
 
 /**
- * \name Structures for parsing X.509 certificates and CRLs
+ * \name Structures for parsing X.509 certificates, CRLs and CSRs
  * \{
  */
 
@@ -227,12 +227,12 @@
     md_type_t sig_md;           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
     pk_type_t sig_pk            /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
 
-    struct _x509_cert *next;    /**< Next certificate in the CA-chain. */ 
+    struct _x509_cert *next;    /**< Next certificate in the CA-chain. */
 }
 x509_cert;
 
-/** 
- * Certificate revocation list entry. 
+/**
+ * Certificate revocation list entry.
  * Contains the CA-specific serial numbers and revocation dates.
  */
 typedef struct _x509_crl_entry
@@ -249,8 +249,8 @@
 }
 x509_crl_entry;
 
-/** 
- * Certificate revocation list structure. 
+/**
+ * Certificate revocation list structure.
  * Every CRL may have multiple entries.
  */
 typedef struct _x509_crl
@@ -265,7 +265,7 @@
 
     x509_name issuer;       /**< The parsed issuer data (named information object). */
 
-    x509_time this_update;  
+    x509_time this_update;
     x509_time next_update;
 
     x509_crl_entry entry;   /**< The CRL entries containing the certificate revocation times for this CA. */
@@ -277,10 +277,32 @@
     md_type_t sig_md;           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
     pk_type_t sig_pk            /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
 
-    struct _x509_crl *next; 
+    struct _x509_crl *next;
 }
 x509_crl;
-/** \} name Structures for parsing X.509 certificates and CRLs */
+
+/**
+ * Certificate Signing Request (CSR) structure.
+ */
+typedef struct _x509_csr
+{
+    x509_buf raw;           /**< The raw CSR data (DER). */
+    x509_buf cri;           /**< The raw CertificateRequestInfo body (DER). */
+
+    int version;
+
+    x509_buf  subject_raw;  /**< The raw subject data (DER). */
+    x509_name subject;      /**< The parsed subject data (named information object). */
+
+    pk_context pk;          /**< Container for the public key context. */
+
+    x509_buf sig_oid;
+    x509_buf sig;
+    md_type_t sig_md;       /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
+    pk_type_t sig_pk        /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
+}
+x509_csr;
+/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */
 /** \} addtogroup x509_module */
 
 /**
@@ -364,6 +386,18 @@
 
 /** \ingroup x509_module */
 /**
+ * \brief          Load a Certificate Signing Request (CSR)
+ *
+ * \param csr      CSR context to fill
+ * \param buf      buffer holding the CRL data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen );
+
+/** \ingroup x509_module */
+/**
  * \brief          Load one or more CRLs and add them
  *                 to the chained list
  *
@@ -374,6 +408,17 @@
  */
 int x509parse_crlfile( x509_crl *chain, const char *path );
 
+/** \ingroup x509_module */
+/**
+ * \brief          Load a Certificate Signing Request (CSR)
+ *
+ * \param csr      CSR context to fill
+ * \param path     filename to read the CSR from
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_csrfile( x509_csr *csr, const char *path );
+
 #if defined(POLARSSL_RSA_C)
 /** \ingroup x509_module */
 /**
@@ -564,6 +609,21 @@
                         const x509_crl *crl );
 
 /**
+ * \brief          Returns an informational string about the
+ *                 CSR.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param csr      The X509 CSR to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509parse_csr_info( char *buf, size_t size, const char *prefix,
+                        const x509_csr *csr );
+
+/**
  * \brief          Give an known OID, return its descriptive string.
  *
  * \param oid      buffer containing the oid
@@ -680,6 +740,13 @@
  */
 void x509_crl_free( x509_crl *crl );
 
+/**
+ * \brief          Unallocate all CSR data
+ *
+ * \param csr      CSR to free
+ */
+void x509_csr_free( x509_csr *csr );
+
 /** \} name Functions to clear a certificate, CRL or private RSA key */
 
 
diff --git a/library/x509parse.c b/library/x509parse.c
index c175df4..2290b7b 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -132,6 +132,29 @@
 }
 
 /*
+ *  Version  ::=  INTEGER  {  v1(0)  }
+ */
+static int x509_csr_get_version( unsigned char **p,
+                             const unsigned char *end,
+                             int *ver )
+{
+    int ret;
+
+    if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        {
+            *ver = 0;
+            return( 0 );
+        }
+
+        return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
+    }
+
+    return( 0 );
+}
+
+/*
  *  CertificateSerialNumber  ::=  INTEGER
  */
 static int x509_get_serial( unsigned char **p,
@@ -1625,6 +1648,214 @@
 }
 
 /*
+ * Parse a CSR
+ */
+int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+#if defined(POLARSSL_PEM_C)
+    size_t use_len;
+    pem_context pem;
+#endif
+
+    /*
+     * Check for valid input
+     */
+    if( csr == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_INVALID_INPUT );
+
+    memset( csr, 0, sizeof( x509_csr ) );
+
+#if defined(POLARSSL_PEM_C)
+    pem_init( &pem );
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN CERTIFICATE REQUEST-----",
+                           "-----END CERTIFICATE REQUEST-----",
+                           buf, NULL, 0, &use_len );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded
+         */
+        buflen -= use_len;
+        buf += use_len;
+
+        /*
+         * Steal PEM buffer
+         */
+        p = pem.buf;
+        pem.buf = NULL;
+        len = pem.buflen;
+        pem_free( &pem );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    {
+        pem_free( &pem );
+        return( ret );
+    }
+    else
+    {
+        /*
+         * nope, copy the raw DER data
+         */
+        p = (unsigned char *) polarssl_malloc( len = buflen );
+
+        if( p == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        memcpy( p, buf, buflen );
+
+        buflen = 0;
+    }
+#else
+    p = (unsigned char *) polarssl_malloc( len = buflen );
+
+    if( p == NULL )
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+    memcpy( p, buf, buflen );
+
+    buflen = 0;
+#endif
+
+    csr->raw.p = p;
+    csr->raw.len = len;
+    end = p + len;
+
+    /*
+     *  CertificationRequest ::= SEQUENCE {
+     *       certificationRequestInfo CertificationRequestInfo,
+     *       signatureAlgorithm AlgorithmIdentifier,
+     *       signature          BIT STRING
+     *  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
+    }
+
+    if( len != (size_t) ( end - p ) )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    /*
+     *  CertificationRequestInfo ::= SEQUENCE {
+     */
+    csr->cri.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+    csr->cri.len = end - csr->cri.p;
+
+    /*
+     *  Version  ::=  INTEGER {  v1(0) }
+     */
+    if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    csr->version++;
+
+    if( csr->version != 1 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
+    }
+
+    /*
+     *  subject               Name
+     */
+    csr->subject_raw.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    csr->subject_raw.len = p - csr->subject_raw.p;
+
+    /*
+     *  subjectPKInfo SubjectPublicKeyInfo
+     */
+    if( ( ret = x509_get_pubkey( &p, end, &csr->pk ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    /*
+     *  attributes    [0] Attributes
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+    }
+    // TODO Parse Attributes / extension requests
+
+    p += len;
+
+    end = csr->raw.p + csr->raw.len;
+
+    /*
+     *  signatureAlgorithm   AlgorithmIdentifier,
+     *  signature            BIT STRING
+     */
+    if( ( ret = x509_get_alg_null( &p, end, &csr->sig_oid ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    if( ( ret = x509_get_sig_alg( &csr->sig_oid, &csr->sig_md,
+                                  &csr->sig_pk ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
+    }
+
+    if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 )
+    {
+        x509_csr_free( csr );
+        return( ret );
+    }
+
+    if( p != end )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    return( 0 );
+}
+
+/*
  * Parse one or more CRLs and add them to the chained list
  */
 int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen )
@@ -2073,6 +2304,26 @@
 }
 
 /*
+ * Load a CSR into the structure
+ */
+int x509parse_csrfile( x509_csr *csr, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509parse_csr( csr, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+
+/*
  * Load one or more CRLs and add them to the chained list
  */
 int x509parse_crlfile( x509_crl *chain, const char *path )
@@ -3285,6 +3536,53 @@
 }
 
 /*
+ * Return an informational string about the CSR.
+ */
+int x509parse_csr_info( char *buf, size_t size, const char *prefix,
+                        const x509_csr *csr )
+{
+    int ret;
+    size_t n;
+    char *p;
+    const char *desc;
+    char key_size_str[BEFORE_COLON];
+
+    p = buf;
+    n = size;
+
+    ret = snprintf( p, n, "%sCSR version   : %d",
+                               prefix, csr->version );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%ssubject name  : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509parse_dn_gets( p, n, &csr->subject );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = oid_get_sig_alg_desc( &csr->sig_oid, &desc );
+    if( ret != 0 )
+        ret = snprintf( p, n, "???"  );
+    else
+        ret = snprintf( p, n, "%s", desc );
+    SAFE_SNPRINTF();
+
+    if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
+                                      pk_get_name( &csr->pk ) ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
+                          (int) pk_get_size( &csr->pk ) );
+    SAFE_SNPRINTF();
+
+    return( (int) ( size - n ) );
+}
+
+/*
  * Return 0 if the x509_time is still valid, or 1 otherwise.
  */
 #if defined(POLARSSL_HAVE_TIME)
@@ -3921,6 +4219,37 @@
     while( crl_cur != NULL );
 }
 
+/*
+ * Unallocate all CSR data
+ */
+void x509_csr_free( x509_csr *csr )
+{
+    x509_name *name_cur;
+    x509_name *name_prv;
+
+    if( csr == NULL )
+        return;
+
+    pk_free( &csr->pk );
+
+    name_cur = csr->subject.next;
+    while( name_cur != NULL )
+    {
+        name_prv = name_cur;
+        name_cur = name_cur->next;
+        memset( name_prv, 0, sizeof( x509_name ) );
+        polarssl_free( name_prv );
+    }
+
+    if( csr->raw.p != NULL )
+    {
+        memset( csr->raw.p, 0, csr->raw.len );
+        polarssl_free( csr->raw.p );
+    }
+
+    memset( csr, 0, sizeof( x509_csr ) );
+}
+
 #if defined(POLARSSL_SELF_TEST)
 
 #include "polarssl/certs.h"
diff --git a/programs/.gitignore b/programs/.gitignore
index b349cd4..32ca900 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -41,3 +41,4 @@
 x509/cert_req
 x509/crl_app
 x509/cert_write
+x509/req_app
diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt
index 8aaa4ac..fe46da5 100644
--- a/programs/x509/CMakeLists.txt
+++ b/programs/x509/CMakeLists.txt
@@ -16,12 +16,15 @@
 add_executable(crl_app crl_app.c)
 target_link_libraries(crl_app ${libs})
 
+add_executable(req_app req_app.c)
+target_link_libraries(req_app ${libs})
+
 add_executable(cert_req cert_req.c)
 target_link_libraries(cert_req ${libs})
 
 add_executable(cert_write cert_write.c)
 target_link_libraries(cert_write ${libs})
 
-install(TARGETS cert_app crl_app cert_req cert_write
+install(TARGETS cert_app crl_app req_app cert_req cert_write
         DESTINATION "bin"
         PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/programs/x509/req_app.c b/programs/x509/req_app.c
new file mode 100644
index 0000000..8c0e3fe
--- /dev/null
+++ b/programs/x509/req_app.c
@@ -0,0 +1,152 @@
+/*
+ *  Certificate request reading application
+ *
+ *  Copyright (C) 2006-2013, 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 _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "polarssl/config.h"
+
+#include "polarssl/x509.h"
+
+#define DFL_FILENAME            "cert.req"
+#define DFL_DEBUG_LEVEL         0
+
+/*
+ * global options
+ */
+struct options
+{
+    const char *filename;       /* filename of the certificate request  */
+} opt;
+
+#define USAGE \
+    "\n usage: req_app param=<>...\n"                   \
+    "\n acceptable parameters:\n"                       \
+    "    filename=%%s         default: cert.req\n"      \
+    "\n"
+
+#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) ||  \
+    !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO)
+int main( int argc, char *argv[] )
+{
+    ((void) argc);
+    ((void) argv);
+
+    printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or "
+           "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n");
+    return( 0 );
+}
+#else
+int main( int argc, char *argv[] )
+{
+    int ret = 0;
+    unsigned char buf[100000];
+    x509_csr csr;
+    int i, j, n;
+    char *p, *q;
+
+    /*
+     * Set to sane values
+     */
+    memset( &csr, 0, sizeof( x509_csr ) );
+
+    if( argc == 0 )
+    {
+    usage:
+        printf( USAGE );
+        goto exit;
+    }
+
+    opt.filename            = DFL_FILENAME;
+
+    for( i = 1; i < argc; i++ )
+    {
+        n = strlen( argv[i] );
+
+        for( j = 0; j < n; j++ )
+        {
+            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
+                argv[i][j] |= 0x20;
+        }
+
+        p = argv[i];
+        if( ( q = strchr( p, '=' ) ) == NULL )
+            goto usage;
+        *q++ = '\0';
+
+        if( strcmp( p, "filename" ) == 0 )
+            opt.filename = q;
+        else
+            goto usage;
+    }
+
+    /*
+     * 1.1. Load the CSR
+     */
+    printf( "\n  . Loading the CSR ..." );
+    fflush( stdout );
+
+    ret = x509parse_csrfile( &csr, opt.filename );
+
+    if( ret != 0 )
+    {
+        printf( " failed\n  !  x509parse_csr returned %d\n\n", ret );
+        x509_csr_free( &csr );
+        goto exit;
+    }
+
+    printf( " ok\n" );
+
+    /*
+     * 1.2 Print the CSR
+     */
+    printf( "  . CSR information    ...\n" );
+    ret = x509parse_csr_info( (char *) buf, sizeof( buf ) - 1, "      ", &csr );
+    if( ret == -1 )
+    {
+        printf( " failed\n  !  x509parse_csr_info returned %d\n\n", ret );
+        x509_csr_free( &csr );
+        goto exit;
+    }
+
+    printf( "%s\n", buf );
+
+exit:
+    x509_csr_free( &csr );
+
+#if defined(_WIN32)
+    printf( "  + Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( ret );
+}
+#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_X509_PARSE_C &&
+          POLARSSL_FS_IO */