Merged X509 refactoring into development
diff --git a/include/polarssl/compat-1.2.h b/include/polarssl/compat-1.2.h
new file mode 100644
index 0000000..b60c932
--- /dev/null
+++ b/include/polarssl/compat-1.2.h
@@ -0,0 +1,372 @@
+/**
+ * \file compat-1.2.h
+ *
+ * \brief Backwards compatibility header for PolarSSL-1.2 from PolarSSL-1.3
+ *
+ *  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 POLARSSL_COMPAT_1_2_H
+#define POLARSSL_COMPAT_1_2_H
+
+#include "config.h"
+
+// Comment out to disable prototype change warnings
+#define SHOW_PROTOTYPE_CHANGE_WARNINGS
+
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "You can disable these warnings by commenting SHOW_PROTOTYPE_CHANGE_WARNINGS in compat-1.2.h"
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+#define POLARSSL_SHA2_C
+#include "sha256.h"
+
+/*
+ * SHA-2 -> SHA-256
+ */
+typedef sha256_context sha2_context;
+
+inline void sha2_starts( sha256_context *ctx, int is224 ) {
+    sha256_starts( ctx, is224 );
+}
+inline void sha2_update( sha256_context *ctx, const unsigned char *input,
+                         size_t ilen ) {
+    sha256_update( ctx, input, ilen );
+}
+inline void sha2_finish( sha256_context *ctx, unsigned char output[32] ) {
+    return sha256_finish( ctx, output );
+}
+inline int sha2_file( const char *path, unsigned char output[32], int is224 ) {
+    return sha256_file( path, output, is224 );
+}
+inline void sha2( const unsigned char *input, size_t ilen,
+                  unsigned char output[32], int is224 ) {
+    return sha256( input, ilen, output, is224 );
+}
+inline void sha2_hmac_starts( sha256_context *ctx, const unsigned char *key,
+                              size_t keylen, int is224 ) {
+    sha256_hmac_starts( ctx, key, keylen, is224 );
+}
+inline void sha2_hmac_update( sha256_context *ctx, const unsigned char *input, size_t ilen ) {
+    sha256_hmac_update( ctx, input, ilen );
+}
+inline void sha2_hmac_finish( sha256_context *ctx, unsigned char output[32] ) {
+    sha256_hmac_finish( ctx, output );
+}
+inline void sha2_hmac_reset( sha256_context *ctx ) {
+    sha256_hmac_reset( ctx );
+}
+inline void sha2_hmac( const unsigned char *key, size_t keylen,
+                       const unsigned char *input, size_t ilen,
+                       unsigned char output[32], int is224 ) {
+    sha256_hmac( key, keylen, input, ilen, output, is224 );
+}
+inline int sha2_self_test( int verbose ) {
+    return sha256_self_test( verbose );
+}
+#endif /* POLARSSL_SHA256_C */
+
+#if defined(POLARSSL_SHA512_C)
+#define POLARSSL_SHA4_C
+#include "sha512.h"
+
+/*
+ * SHA-4 -> SHA-512
+ */
+typedef sha512_context sha4_context;
+
+inline void sha4_starts( sha512_context *ctx, int is384 ) {
+    sha512_starts( ctx, is384 );
+}
+inline void sha4_update( sha512_context *ctx, const unsigned char *input,
+                         size_t ilen ) {
+    sha512_update( ctx, input, ilen );
+}
+inline void sha4_finish( sha512_context *ctx, unsigned char output[64] ) {
+    return sha512_finish( ctx, output );
+}
+inline int sha4_file( const char *path, unsigned char output[64], int is384 ) {
+    return sha512_file( path, output, is384 );
+}
+inline void sha4( const unsigned char *input, size_t ilen,
+                  unsigned char output[32], int is384 ) {
+    return sha512( input, ilen, output, is384 );
+}
+inline void sha4_hmac_starts( sha512_context *ctx, const unsigned char *key,
+                              size_t keylen, int is384 ) {
+    sha512_hmac_starts( ctx, key, keylen, is384 );
+}
+inline void sha4_hmac_update( sha512_context *ctx, const unsigned char *input, size_t ilen ) {
+    sha512_hmac_update( ctx, input, ilen );
+}
+inline void sha4_hmac_finish( sha512_context *ctx, unsigned char output[64] ) {
+    sha512_hmac_finish( ctx, output );
+}
+inline void sha4_hmac_reset( sha512_context *ctx ) {
+    sha512_hmac_reset( ctx );
+}
+inline void sha4_hmac( const unsigned char *key, size_t keylen,
+                       const unsigned char *input, size_t ilen,
+                       unsigned char output[64], int is384 ) {
+    sha512_hmac( key, keylen, input, ilen, output, is384 );
+}
+inline int sha4_self_test( int verbose ) {
+    return sha512_self_test( verbose );
+}
+#endif /* POLARSSL_SHA512_C */
+
+#if defined(POLARSSL_CIPHER_C)
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "cipher_reset() prototype changed. Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_RSA_C)
+#define SIG_RSA_RAW     POLARSSL_MD_NONE
+#define SIG_RSA_MD2     POLARSSL_MD_MD2
+#define SIG_RSA_MD4     POLARSSL_MD_MD4
+#define SIG_RSA_MD5     POLARSSL_MD_MD5
+#define SIG_RSA_SHA1    POLARSSL_MD_SHA1
+#define SIG_RSA_SHA224  POLARSSL_MD_SHA224
+#define SIG_RSA_SHA256  POLARSSL_MD_SHA256
+#define SIG_RSA_SHA384  POLARSSL_MD_SHA384
+#define SIG_RSA_SHA512  POLARSSL_MD_SHA512
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "rsa_pkcs1_verify() prototype changed. Manual change required if used"
+#warning "rsa_pkcs1_decrypt() prototype changed. Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_DHM_C)
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "dhm_calc_secret() prototype changed. Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_GCM_C)
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "gcm_init() prototype changed. Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_SSL_CLI_C)
+#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
+#warning "ssl_set_own_cert() prototype changed. Change to ssl_set_own_cert_rsa(). Manual change required if used"
+#endif
+#endif
+
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+#include "x509.h"
+
+#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT POLARSSL_ERR_X509_INVALID_FORMAT
+#define POLARSSL_ERR_X509_CERT_INVALID_VERSION POLARSSL_ERR_X509_INVALID_VERSION
+#define POLARSSL_ERR_X509_CERT_INVALID_ALG POLARSSL_ERR_X509_INVALID_ALG
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG POLARSSL_ERR_X509_UNKNOWN_SIG_ALG
+#define POLARSSL_ERR_X509_CERT_INVALID_NAME POLARSSL_ERR_X509_INVALID_NAME
+#define POLARSSL_ERR_X509_CERT_INVALID_DATE POLARSSL_ERR_X509_INVALID_DATE
+#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS POLARSSL_ERR_X509_INVALID_EXTENSIONS
+#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH POLARSSL_ERR_X509_SIG_MISMATCH
+#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE POLARSSL_ERR_X509_INVALID_SIGNATURE
+#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL POLARSSL_ERR_X509_INVALID_SERIAL
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION POLARSSL_ERR_X509_UNKNOWN_VERSION
+
+inline int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial ) {
+    return x509_serial_gets( buf, size, serial );
+}
+inline int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn ) {
+    return x509_dn_gets( buf, size, dn );
+}
+inline int x509parse_time_expired( const x509_time *time ) {
+    return x509_time_expired( time );
+}
+#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+#define POLARSSL_X509_PARSE_C
+#include "x509_crt.h"
+typedef x509_crt x509_cert;
+
+inline int x509parse_crt_der( x509_cert *chain, const unsigned char *buf,
+                              size_t buflen ) {
+    return x509_crt_parse_der( chain, buf, buflen );
+}
+inline int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ) {
+    return x509_crt_parse( chain, buf, buflen );
+}
+inline int x509parse_crtfile( x509_cert *chain, const char *path ) {
+    return x509_crt_parse_file( chain, path );
+}
+inline int x509parse_crtpath( x509_cert *chain, const char *path ) {
+    return x509_crt_parse_path( chain, path );
+}
+inline int x509parse_cert_info( char *buf, size_t size, const char *prefix,
+                                const x509_cert *crt ) {
+    return x509_crt_info( buf, size, prefix, crt );
+}
+inline int x509parse_verify( x509_cert *crt, x509_cert *trust_ca,
+                             x509_crl *ca_crl, const char *cn, int *flags,
+                             int (*f_vrfy)(void *, x509_cert *, int, int *),
+                             void *p_vrfy ) {
+    return x509_crt_verify( crt, trust_ca, ca_crl, cn, flags, f_vrfy, p_vrfy );
+}
+inline int x509parse_revoked( const x509_cert *crt, const x509_crl *crl ) {
+    return x509_crt_revoked( crt, crl );
+}
+inline void x509_free( x509_cert *crt ) {
+    return x509_crt_free( crt );
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+#define POLARSSL_X509_PARSE_C
+#include "x509_crl.h"
+inline int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) {
+    return x509_crl_parse( chain, buf, buflen );
+}
+inline int x509parse_crlfile( x509_crl *chain, const char *path ) {
+    return x509_crl_parse_file( chain, path );
+}
+inline int x509parse_crl_info( char *buf, size_t size, const char *prefix,
+                               const x509_crl *crl ) {
+    return x509_crl_info( buf, size, prefix, crl );
+}
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+#define POLARSSL_X509_PARSE_C
+#include "x509_csr.h"
+inline int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) {
+    return x509_csr_parse( csr, buf, buflen );
+}
+inline int x509parse_csrfile( x509_csr *csr, const char *path ) {
+    return x509_csr_parse_file( csr, path );
+}
+inline int x509parse_csr_info( char *buf, size_t size, const char *prefix,
+                               const x509_csr *csr ) {
+    return x509_csr_info( buf, size, prefix, csr );
+}
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+
+#if defined(POLARSSL_SSL_TLS_C)
+#include "ssl_ciphersuites.h"
+
+#define ssl_default_ciphersuites ssl_list_ciphersuites()
+#endif
+
+#if defined(POLARSSL_PK_PARSE_C) && defined(POLARSSL_RSA_C)
+#include "rsa.h"
+#include "pk.h"
+
+#define POLARSSL_ERR_X509_PASSWORD_MISMATCH POLARSSL_ERR_PK_PASSWORD_MISMATCH
+#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG POLARSSL_ERR_PK_UNKNOWN_PK_ALG
+#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY POLARSSL_ERR_PK_INVALID_PUBKEY
+
+#if defined(POLARSSL_FS_IO)
+inline int x509parse_keyfile( rsa_context *rsa, const char *path,
+                              const char *pwd ) {
+    int ret;
+    pk_context pk;
+    pk_init( &pk );
+    ret = pk_parse_keyfile( &pk, path, pwd );
+    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+    if( ret == 0 )
+        rsa_copy( rsa, pk_rsa( pk ) );
+    else
+        rsa_free( rsa );
+    pk_free( &pk );
+    return( ret );
+}
+inline int x509parse_public_keyfile( rsa_context *rsa, const char *path ) {
+    int ret;
+    pk_context pk;
+    pk_init( &pk );
+    ret = pk_parse_public_keyfile( &pk, path );
+    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+    if( ret == 0 )
+        rsa_copy( rsa, pk_rsa( pk ) );
+    else
+        rsa_free( rsa );
+    pk_free( &pk );
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+inline int x509parse_key( rsa_context *rsa, const unsigned char *key,
+                          size_t keylen,
+                          const unsigned char *pwd, size_t pwdlen ) {
+    int ret;
+    pk_context pk;
+    pk_init( &pk );
+    ret = pk_parse_key( &pk, key, keylen, pwd, pwdlen );
+    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+    if( ret == 0 )
+        rsa_copy( rsa, pk_rsa( pk ) );
+    else
+        rsa_free( rsa );
+    pk_free( &pk );
+    return( ret );
+}
+
+inline int x509parse_public_key( rsa_context *rsa,
+                                 const unsigned char *key, size_t keylen )
+{
+    int ret;
+    pk_context pk;
+    pk_init( &pk );
+    ret = pk_parse_public_key( &pk, key, keylen );
+    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+    if( ret == 0 )
+        rsa_copy( rsa, pk_rsa( pk ) );
+    else
+        rsa_free( rsa );
+    pk_free( &pk );
+    return( ret );
+}
+#endif /* POLARSSL_PK_PARSE_C && POLARSSL_RSA_C */
+
+#if defined(POLARSSL_PK_WRITE_C) && defined(POLARSSL_RSA_C)
+#include "pk.h"
+inline int x509_write_pubkey_der( unsigned char *buf, size_t len, rsa_context *rsa ) {
+    int ret;
+    pk_context ctx;
+    if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret );
+    if( ( ret = rsa_copy( ctx.pk_ctx, rsa ) ) != 0 ) return( ret );
+    ret = pk_write_pubkey_der( &ctx, buf, len );
+    pk_free( &ctx );
+    return( ret );
+}
+inline int x509_write_key_der( unsigned char *buf, size_t len, rsa_context *rsa ) {
+    int ret;
+    pk_context ctx;
+    if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret );
+    if( ( ret = rsa_copy( ctx.pk_ctx, rsa ) ) != 0 ) return( ret );
+    ret = pk_write_key_der( &ctx, buf, len );
+    pk_free( &ctx );
+    return( ret );
+}
+#endif /* POLARSSL_PK_WRITE_C && POLARSSL_RSA_C */
+#endif /* compat-1.2.h */
diff --git a/include/polarssl/config.h b/include/polarssl/config.h
index f75d94d..8c92faf 100644
--- a/include/polarssl/config.h
+++ b/include/polarssl/config.h
@@ -287,7 +287,7 @@
  *
  * Enable the RSA-PSK based ciphersuite modes in SSL / TLS
  * (NOT YET IMPLEMENTED)
- * Requires: POLARSSL_RSA_C, POLARSSL_X509_PARSE_C, POLARSSL_PKCS1_V15
+ * Requires: POLARSSL_RSA_C, POLARSSL_X509_CRT_PARSE_C, POLARSSL_PKCS1_V15
  *
  * This enables the following ciphersuites (if other requisites are
  * enabled as well):
@@ -307,7 +307,7 @@
  *
  * Enable the RSA-only based ciphersuite modes in SSL / TLS
  *
- * Requires: POLARSSL_RSA_C, POLARSSL_X509_PARSE_C, POLARSSL_PKCS1_V15
+ * Requires: POLARSSL_RSA_C, POLARSSL_X509_CRT_PARSE_C, POLARSSL_PKCS1_V15
  *
  * This enables the following ciphersuites (if other requisites are
  * enabled as well):
@@ -332,7 +332,7 @@
  *
  * Enable the DHE-RSA based ciphersuite modes in SSL / TLS
  *
- * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_X509_PARSE_C,
+ * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_X509_CRT_PARSE_C,
  *           POLARSSL_PKCS1_V15
  *
  * This enables the following ciphersuites (if other requisites are
@@ -354,7 +354,7 @@
  *
  * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS
  *
- * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_X509_PARSE_C,
+ * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_X509_CRT_PARSE_C,
  *           POLARSSL_PKCS1_V15
  *
  * This enables the following ciphersuites (if other requisites are
@@ -377,7 +377,7 @@
  *
  * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS
  *
- * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_PARSE_C
+ * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C
  *
  * This enables the following ciphersuites (if other requisites are
  * enabled as well):
@@ -719,7 +719,7 @@
  *      TLS_PSK_WITH_AES_128_CBC_SHA
  *      TLS_PSK_WITH_AES_256_CBC_SHA
  *
- * PEM uses AES for decrypting encrypted keys.
+ * PEM_PARSE uses AES for decrypting encrypted keys.
  */
 #define POLARSSL_AES_C
 
@@ -884,7 +884,7 @@
  *      TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
  *      TLS_PSK_WITH_3DES_EDE_CBC_SHA
  *
- * PEM uses DES/3DES for decrypting encrypted keys.
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
  */
 #define POLARSSL_DES_C
 
@@ -1074,7 +1074,7 @@
  *          library/x509parse.c
  *
  * This module is required for SSL/TLS and X.509.
- * PEM uses MD5 for decrypting encrypted keys.
+ * PEM_PARSE uses MD5 for decrypting encrypted keys.
  */
 #define POLARSSL_MD5_C
 
@@ -1156,18 +1156,34 @@
 #define POLARSSL_PBKDF2_C
 
 /**
- * \def POLARSSL_PEM_C
+ * \def POLARSSL_PEM_PARSE_C
  *
- * Enable PEM decoding
+ * Enable PEM decoding / parsing
  *
  * Module:  library/pem.c
  * Caller:  library/x509parse.c
+ *          library/pkparse.c
  *
  * Requires: POLARSSL_BASE64_C
  *
- * This modules adds support for decoding PEM files.
+ * This modules adds support for decoding / parsing PEM files.
  */
-#define POLARSSL_PEM_C
+#define POLARSSL_PEM_PARSE_C
+
+/**
+ * \def POLARSSL_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing
+ *
+ * Module:  library/pem.c
+ * Caller:  library/x509write.c
+ *          library/pkwrite.c
+ *
+ * Requires: POLARSSL_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+#define POLARSSL_PEM_WRITE_C
 
 /**
  * \def POLARSSL_PK_C
@@ -1185,6 +1201,34 @@
 #define POLARSSL_PK_C
 
 /**
+ * \def POLARSSL_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module:  library/pkparse.c
+ * Caller:  library/x509parse.c
+ *
+ * Requires: POLARSSL_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define POLARSSL_PK_PARSE_C
+
+/**
+ * \def POLARSSL_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module:  library/pkwrite.c
+ * Caller:  library/x509write.c
+ *
+ * Requires: POLARSSL_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define POLARSSL_PK_WRITE_C
+
+/**
  * \def POLARSSL_PKCS5_C
  *
  * Enable PKCS#5 functions
@@ -1369,34 +1413,104 @@
 #define POLARSSL_VERSION_C
 
 /**
- * \def POLARSSL_X509_PARSE_C
+ * \def POLARSSL_X509_USE_C
+ *
+ * Enable X.509 core for using certificates
+ *
+ * Module:  library/x509.c
+ * Caller:  library/x509_crl.c
+ *          library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C,
+ *           POLARSSL_PK_PARSE_C
+ *
+ * This module is required for the X.509 parsing modules.
+ */
+#define POLARSSL_X509_USE_C
+
+/**
+ * \def POLARSSL_X509_CRT_PARSE_C
  *
  * Enable X.509 certificate parsing.
  *
- * Module:  library/x509parse.c
+ * Module:  library/x509_crt.c
  * Caller:  library/ssl_cli.c
  *          library/ssl_srv.c
  *          library/ssl_tls.c
  *
- * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C,
- *           POLARSSL_PK_C
+ * Requires: POLARSSL_X509_USE_C
  *
  * This module is required for X.509 certificate parsing.
  */
-#define POLARSSL_X509_PARSE_C
+#define POLARSSL_X509_CRT_PARSE_C
 
 /**
- * \def POLARSSL_X509_WRITE_C
+ * \def POLARSSL_X509_CRL_PARSE_C
  *
- * Enable X.509 buffer writing.
+ * Enable X.509 CRL parsing.
  *
- * Module:  library/x509write.c
+ * Module:  library/x509_crl.c
+ * Caller:  library/x509_crt.c
  *
- * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_C
+ * Requires: POLARSSL_X509_USE_C
+ *
+ * This module is required for X.509 CRL parsing.
+ */
+#define POLARSSL_X509_CRL_PARSE_C
+
+/**
+ * \def POLARSSL_X509_CSR_PARSE_C
+ *
+ * Enable X.509 Certificate Signing Request (CSR) parsing.
+ *
+ * Module:  library/x509_csr.c
+ * Caller:  library/x509_crt_write.c
+ *
+ * Requires: POLARSSL_X509_USE_C
+ *
+ * This module is used for reading X.509 certificate request.
+ */
+#define POLARSSL_X509_CSR_PARSE_C
+
+/**
+ * \def POLARSSL_X509_CREATE_C
+ *
+ * Enable X.509 core for creating certificates
+ *
+ * Module:  library/x509_create.c
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C
+ *
+ * This module is the basis for creating X.509 certificates and CSRs.
+ */
+#define POLARSSL_X509_CREATE_C
+
+/**
+ * \def POLARSSL_X509_CRT_WRITE_C
+ *
+ * Enable creating X.509 certificates.
+ *
+ * Module:  library/x509_crt_write.c
+ *
+ * Requires: POLARSSL_CREATE_C
+ *
+ * This module is required for X.509 certificate creation.
+ */
+#define POLARSSL_X509_CRT_WRITE_C
+
+/**
+ * \def POLARSSL_X509_CSR_WRITE_C
+ *
+ * Enable creating X.509 Certificate Signing Requests (CSR)
+ *
+ * Module:  library/x509_csr_write.c
+ *
+ * Requires: POLARSSL_CREATE_C
  *
  * This module is required for X.509 certificate request writing.
  */
-#define POLARSSL_X509_WRITE_C
+#define POLARSSL_X509_CSR_WRITE_C
 
 /**
  * \def POLARSSL_XTEA_C
@@ -1522,30 +1636,30 @@
 
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) &&                   \
     ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) ||           \
-      !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
+      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
 #error "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
 #endif
 
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) &&                 \
     ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_RSA_C) ||          \
-      !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
+      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
 #error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
 #endif
 
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                 \
     ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) ||          \
-      !defined(POLARSSL_X509_PARSE_C) )
+      !defined(POLARSSL_X509_CRT_PARSE_C) )
 #error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
 #endif
 
 #if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) &&                   \
-    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_PARSE_C) ||    \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
       !defined(POLARSSL_PKCS1_V15) )
 #error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
 #endif
 
 #if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) &&                       \
-    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_PARSE_C) ||    \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
       !defined(POLARSSL_PKCS1_V15) )
 #error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
 #endif
@@ -1558,8 +1672,20 @@
 #error "POLARSSL_PBKDF2_C defined, but not all prerequisites"
 #endif
 
-#if defined(POLARSSL_PEM_C) && !defined(POLARSSL_PEM_C)
-#error "POLARSSL_PEM_C defined, but not all prerequisites"
+#if defined(POLARSSL_PEM_PARSE_C) && !defined(POLARSSL_BASE64_C)
+#error "POLARSSL_PEM_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PEM_WRITE_C) && !defined(POLARSSL_BASE64_C)
+#error "POLARSSL_PEM_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PK_PARSE_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PK_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PK_WRITE_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PK_WRITE_C defined, but not all prerequisites"
 #endif
 
 #if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C)
@@ -1612,16 +1738,36 @@
 #error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites"
 #endif
 
-#if defined(POLARSSL_X509_PARSE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
+#if defined(POLARSSL_X509_USE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
     !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) ||      \
-    !defined(POLARSSL_PK_C) )
-#error "POLARSSL_X509_PARSE_C defined, but not all prerequisites"
+    !defined(POLARSSL_PK_PARSE_C) )
+#error "POLARSSL_X509_USE_C defined, but not all prerequisites"
 #endif
 
-#if defined(POLARSSL_X509_WRITE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
-    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) ||      \
-    !defined(POLARSSL_RSA_C) )
-#error "POLARSSL_X509_WRITE_C defined, but not all prerequisites"
+#if defined(POLARSSL_X509_CREATE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
+    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) ||       \
+    !defined(POLARSSL_PK_WRITE_C) )
+#error "POLARSSL_X509_CREATE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CRT_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRL_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CRL_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CSR_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CSR_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRT_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
+#error "POLARSSL_X509_CRT_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CSR_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
+#error "POLARSSL_X509_CSR_WRITE_C defined, but not all prerequisites"
 #endif
 
 #endif /* config.h */
diff --git a/include/polarssl/debug.h b/include/polarssl/debug.h
index fdd3627..7335ad3 100644
--- a/include/polarssl/debug.h
+++ b/include/polarssl/debug.h
@@ -54,7 +54,7 @@
     debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X );
 #endif
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 #define SSL_DEBUG_CRT( level, text, crt )                \
     debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt );
 #endif
@@ -99,10 +99,10 @@
                       const char *text, const ecp_point *X );
 #endif
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 void debug_print_crt( const ssl_context *ssl, int level,
                       const char *file, int line,
-                      const char *text, const x509_cert *crt );
+                      const char *text, const x509_crt *crt );
 #endif
 
 #ifdef __cplusplus
diff --git a/include/polarssl/dhm.h b/include/polarssl/dhm.h
index 09de70b..0152dc9 100644
--- a/include/polarssl/dhm.h
+++ b/include/polarssl/dhm.h
@@ -38,6 +38,9 @@
 #define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED                -0x3200  /**< Reading of the public values failed. */
 #define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED                -0x3280  /**< Making of the public value failed. */
 #define POLARSSL_ERR_DHM_CALC_SECRET_FAILED                -0x3300  /**< Calculation of the DHM secret failed. */
+#define POLARSSL_ERR_DHM_INVALID_FORMAT                    -0x3380  /**< The ASN.1 data is not formatted correctly. */
+#define POLARSSL_ERR_DHM_MALLOC_FAILED                     -0x3400  /**< Allocation of memory failed. */
+#define POLARSSL_ERR_DHM_FILE_IO_ERROR                     -0x3480  /**< Read/write of file failed. */
 
 /**
  * RFC 3526 defines a number of standardized Diffie-Hellman groups
@@ -245,6 +248,34 @@
  */
 void dhm_free( dhm_context *ctx );
 
+#if defined(POLARSSL_ASN1_PARSE_C)
+/** \ingroup x509_module */
+/**
+ * \brief          Parse DHM parameters
+ *
+ * \param dhm      DHM context to be initialized
+ * \param dhmin    input buffer
+ * \param dhminlen size of the buffer
+ *
+ * \return         0 if successful, or a specific DHM or PEM error code
+ */
+int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin,
+                   size_t dhminlen );
+
+#if defined(POLARSSL_FS_IO)
+/** \ingroup x509_module */
+/**
+ * \brief          Load and parse DHM parameters
+ *
+ * \param dhm      DHM context to be initialized
+ * \param path     filename to read the DHM Parameters from
+ *
+ * \return         0 if successful, or a specific DHM or PEM error code
+ */
+int dhm_parse_dhmfile( dhm_context *dhm, const char *path );
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_ASN1_PARSE_C */
+
 /**
  * \brief          Checkup routine
  *
diff --git a/include/polarssl/error.h b/include/polarssl/error.h
index 4c9ef7c..0c9e451 100644
--- a/include/polarssl/error.h
+++ b/include/polarssl/error.h
@@ -76,14 +76,13 @@
  * Name      ID  Nr of Errors
  * PEM       1   9
  * PKCS#12   1   4 (Started from top)
- * X509      2   25
- * PK        2   3 (Started from top)
- * DHM       3   6
+ * X509      2   18
+ * PK        2   13 (Started from top)
+ * DHM       3   9
  * PKCS5     3   4 (Started from top)
  * RSA       4   9
  * ECP       4   4 (Started from top)
  * MD        5   4
- * X509WRITE 5   3 (Started from top)
  * CIPHER    6   5
  * SSL       6   6 (Started from top)
  * SSL       7   31
diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h
index ba0ce7d..20bacae 100644
--- a/include/polarssl/oid.h
+++ b/include/polarssl/oid.h
@@ -39,7 +39,7 @@
 #include "md.h"
 #endif
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
 #include "x509.h"
 #endif
 
@@ -337,7 +337,7 @@
  */
 int oid_get_numeric_string( char *buf, size_t size, const asn1_buf *oid );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
 /**
  * \brief          Translate an X.509 extension OID into local values
  *
diff --git a/include/polarssl/pem.h b/include/polarssl/pem.h
index cc6cba1..e606cf0 100644
--- a/include/polarssl/pem.h
+++ b/include/polarssl/pem.h
@@ -50,6 +50,7 @@
 extern "C" {
 #endif
 
+#if defined(POLARSSL_PEM_PARSE_C)
 /**
  * \brief       PEM context structure
  */
@@ -88,7 +89,7 @@
  *                  the decrypted text starts with an ASN.1 sequence of
  *                  appropriate length
  *
- * \return          0 on success, ior a specific PEM error code
+ * \return          0 on success, or a specific PEM error code
  */
 int pem_read_buffer( pem_context *ctx, const char *header, const char *footer,
                      const unsigned char *data,
@@ -101,6 +102,29 @@
  * \param ctx   context to be freed
  */
 void pem_free( pem_context *ctx );
+#endif /* POLARSSL_PEM_PARSE_C */
+
+#if defined(POLARSSL_PEM_WRITE_C)
+/**
+ * \brief           Write a buffer of PEM information from a DER encoded
+ *                  buffer.
+ *
+ * \param header    header string to write
+ * \param footer    footer string to write
+ * \param der_data  DER data to write
+ * \param der_len   length of the DER data
+ * \param buf       buffer to write to
+ * \param buf_len   length of output buffer
+ * \param olen      total length written / required (if buf_len is not enough)
+ *
+ * \return          0 on success, or a specific PEM or BASE64 error code. On
+ *                  POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL olen is the required
+ *                  size.
+ */
+int pem_write_buffer( const char *header, const char *footer,
+                      const unsigned char *der_data, size_t der_len,
+                      unsigned char *buf, size_t buf_len, size_t *olen );
+#endif /* POLARSSL_PEM_WRITE_C */
 
 #ifdef __cplusplus
 }
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index f8c6cc8..c14c149 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -47,6 +47,17 @@
 #define POLARSSL_ERR_PK_MALLOC_FAILED       -0x2F80  /**< Memory alloation failed. */
 #define POLARSSL_ERR_PK_TYPE_MISMATCH       -0x2F00  /**< Type mismatch, eg attempt to encrypt with an ECDSA key */
 #define POLARSSL_ERR_PK_BAD_INPUT_DATA      -0x2E80  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_PK_FILE_IO_ERROR       -0x2E00  /**< Read/write of file failed. */
+#define POLARSSL_ERR_PK_KEY_INVALID_VERSION -0x2D80  /**< Unsupported key version */
+#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT  -0x2D00  /**< Invalid key tag or value. */
+#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG      -0x2C80  /**< Key algorithm is unsupported (only RSA and EC are supported). */
+#define POLARSSL_ERR_PK_PASSWORD_REQUIRED   -0x2C00  /**< Private key password can't be empty. */
+#define POLARSSL_ERR_PK_PASSWORD_MISMATCH   -0x2B80  /**< Given private key password does not allow for correct decryption. */
+#define POLARSSL_ERR_PK_INVALID_PUBKEY      -0x2B00  /**< The pubkey tag or value is invalid (only RSA and EC are supported). */
+#define POLARSSL_ERR_PK_INVALID_ALG         -0x2A80  /**< The algorithm tag or value is invalid. */
+#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE -0x2A00  /**< Elliptic curve is unsupported (only NIST curves are supported). */
+#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE -0x2980  /**< Unavailable feature, e.g. RSA disabled for RSA key. */
+
 
 #if defined(POLARSSL_RSA_C)
 /**
@@ -378,6 +389,153 @@
  */
 pk_type_t pk_get_type( const pk_context *ctx );
 
+#if defined(POLARSSL_PK_PARSE_C)
+/** \ingroup pk_module */
+/**
+ * \brief           Parse a private key
+ *
+ * \param ctx       key to be initialized
+ * \param key       input buffer
+ * \param keylen    size of the buffer
+ * \param pwd       password for decryption (optional)
+ * \param pwdlen    size of the password
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int pk_parse_key( pk_context *ctx,
+                  const unsigned char *key, size_t keylen,
+                  const unsigned char *pwd, size_t pwdlen );
+
+/** \ingroup pk_module */
+/**
+ * \brief           Parse a public key
+ *
+ * \param ctx       key to be initialized
+ * \param key       input buffer
+ * \param keylen    size of the buffer
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int pk_parse_public_key( pk_context *ctx,
+                         const unsigned char *key, size_t keylen );
+
+#if defined(POLARSSL_FS_IO)
+/** \ingroup pk_module */
+/**
+ * \brief           Load and parse a private key
+ *
+ * \param ctx       key to be initialized
+ * \param path      filename to read the private key from
+ * \param password  password to decrypt the file (can be NULL)
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int pk_parse_keyfile( pk_context *ctx,
+                      const char *path, const char *password );
+
+/** \ingroup pk_module */
+/**
+ * \brief           Load and parse a public key
+ *
+ * \param ctx       key to be initialized
+ * \param path      filename to read the private key from
+ *
+ * \return          0 if successful, or a specific PK or PEM error code
+ */
+int pk_parse_public_keyfile( pk_context *ctx, const char *path );
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_PK_PARSE_C */
+
+#if defined(POLARSSL_PK_WRITE_C)
+/**
+ * \brief           Write a private key to a PKCS#1 or SEC1 DER structure
+ *                  Note: data is written at the end of the buffer! Use the
+ *                        return value to determine where you should start
+ *                        using the buffer
+ *
+ * \param key       private to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ *
+ * \return          length of data written if successful, or a specific
+ *                  error code
+ */
+int pk_write_key_der( pk_context *pk, unsigned char *buf, size_t size );
+
+/**
+ * \brief           Write a public key to a SubjectPublicKeyInfo DER structure
+ *                  Note: data is written at the end of the buffer! Use the
+ *                        return value to determine where you should start
+ *                        using the buffer
+ *
+ * \param key       public key to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ *
+ * \return          length of data written if successful, or a specific
+ *                  error code
+ */
+int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size );
+
+#if defined(POLARSSL_PEM_WRITE_C)
+/**
+ * \brief           Write a public key to a PEM string
+ *
+ * \param key       public key to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ *
+ * \return          0 successful, or a specific error code
+ */
+int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size );
+
+/**
+ * \brief           Write a private key to a PKCS#1 or SEC1 PEM string
+ *
+ * \param key       private to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ *
+ * \return          0 successful, or a specific error code
+ */
+int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size );
+#endif /* POLARSSL_PEM_WRITE_C */
+#endif /* POLARSSL_PK_WRITE_C */
+
+/*
+ * WARNING: Low-level functions. You probably do not want to use these unless
+ *          you are certain you do ;)
+ */
+
+#if defined(POLARSSL_PK_PARSE_C)
+/**
+ * \brief           Parse a SubjectPublicKeyInfo DER structure
+ *
+ * \param p         the position in the ASN.1 data
+ * \param end       end of the buffer
+ * \param pk        the key to fill
+ *
+ * \return          0 if successful, or a specific PK error code
+ */
+int pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
+                        pk_context *pk );
+#endif /* POLARSSL_PK_PARSE_C */
+
+#if defined(POLARSSL_PK_WRITE_C)
+/**
+ * \brief           Write a subjectPublicKey to ASN.1 data
+ *                  Note: function works backwards in data buffer
+ *
+ * \param p         reference to current position pointer
+ * \param start     start of the buffer (for bounds-checking)
+ * \param key       public key to write away
+ *
+ * \return          the length written or a negative error code
+ */
+int pk_write_pubkey( unsigned char **p, unsigned char *start,
+                     const pk_context *key );
+#endif /* POLARSSL_PK_WRITE_C */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/polarssl/pkcs11.h b/include/polarssl/pkcs11.h
index 270eb6d..c0515e6 100644
--- a/include/polarssl/pkcs11.h
+++ b/include/polarssl/pkcs11.h
@@ -33,7 +33,7 @@
 
 #if defined(POLARSSL_PKCS11_C)
 
-#include "x509.h"
+#include "x509_crt.h"
 
 #include <pkcs11-helper-1.0/pkcs11h-certificate.h>
 
@@ -65,7 +65,7 @@
  *
  * \return              0 on success.
  */
-int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11h_cert );
+int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert );
 
 /**
  * Initialise a pkcs11_context, storing the given certificate. Note that the
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index cc60a4e..7c90987 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -54,8 +54,12 @@
 #include "aes.h"
 #endif
 
-#if defined(POLARSSL_X509_PARSE_C)
-#include "x509.h"
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+#include "x509_crt.h"
+#endif
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+#include "x509_crl.h"
 #endif
 
 #if defined(POLARSSL_DHM_C)
@@ -406,9 +410,9 @@
     unsigned char id[32];       /*!< session identifier */
     unsigned char master[48];   /*!< the master secret  */
 
-#if defined(POLARSSL_X509_PARSE_C)
-    x509_cert *peer_cert;       /*!< peer X.509 cert chain */
-#endif /* POLARSSL_X509_PARSE_C */
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt *peer_cert;        /*!< peer X.509 cert chain */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
     int verify_result;          /*!<  verification result     */
 
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
@@ -579,8 +583,8 @@
     void *p_sni;                /*!< context for SNI extension        */
 #endif
 
-#if defined(POLARSSL_X509_PARSE_C)
-    int (*f_vrfy)(void *, x509_cert *, int, int *);
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    int (*f_vrfy)(void *, x509_crt *, int, int *);
     void *p_vrfy;               /*!< context for verification         */
 #endif
 
@@ -642,12 +646,14 @@
     pk_context *pk_key;                 /*!<  own private key         */
     int pk_key_own_alloc;               /*!<  did we allocate pk_key? */
 
-#if defined(POLARSSL_X509_PARSE_C)
-    x509_cert *own_cert;                /*!<  own X.509 certificate   */
-    x509_cert *ca_chain;                /*!<  own trusted CA chain    */
-    x509_crl *ca_crl;                   /*!<  trusted CA CRLs         */
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt *own_cert;                 /*!<  own X.509 certificate   */
+    x509_crt *ca_chain;                 /*!<  own trusted CA chain    */
     const char *peer_cn;                /*!<  expected peer CN        */
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+    x509_crl *ca_crl;                   /*!<  trusted CA CRLs         */
+#endif /* POLARSSL_X509_CRL_PARSE_C */
 
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
     /*
@@ -806,7 +812,7 @@
  */
 void ssl_set_authmode( ssl_context *ssl, int authmode );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 /**
  * \brief          Set the verification callback (Optional).
  *
@@ -819,9 +825,9 @@
  * \param p_vrfy   verification parameter
  */
 void ssl_set_verify( ssl_context *ssl,
-                     int (*f_vrfy)(void *, x509_cert *, int, int *),
+                     int (*f_vrfy)(void *, x509_crt *, int, int *),
                      void *p_vrfy );
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 /**
  * \brief          Set the random number generator callback
@@ -941,7 +947,7 @@
                                        const int *ciphersuites,
                                        int major, int minor );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 /**
  * \brief          Set the data required to verify peer certificate
  *
@@ -950,7 +956,7 @@
  * \param ca_crl   trusted CA CRLs
  * \param peer_cn  expected peer CommonName (or NULL)
  */
-void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
+void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain,
                        x509_crl *ca_crl, const char *peer_cn );
 
 /**
@@ -964,7 +970,7 @@
  * \param own_cert own public certificate chain
  * \param pk_key   own private key
  */
-void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
+void ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert,
                        pk_context *pk_key );
 
 #if defined(POLARSSL_RSA_C)
@@ -981,7 +987,7 @@
  *
  * \return          0 on success, or a specific error code.
  */
-int ssl_set_own_cert_rsa( ssl_context *ssl, x509_cert *own_cert,
+int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert,
                           rsa_context *rsa_key );
 #endif /* POLARSSL_RSA_C */
 
@@ -1006,12 +1012,12 @@
  *
  * \return          0 on success, or a specific error code.
  */
-int ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
+int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert,
                           void *rsa_key,
                           rsa_decrypt_func rsa_decrypt,
                           rsa_sign_func rsa_sign,
                           rsa_key_len_func rsa_key_len );
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
 /**
@@ -1272,7 +1278,7 @@
  */
 const char *ssl_get_version( const ssl_context *ssl );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 /**
  * \brief          Return the peer certificate from the current connection
  *
@@ -1287,8 +1293,8 @@
  *
  * \return         the current peer certificate
  */
-const x509_cert *ssl_get_peer_cert( const ssl_context *ssl );
-#endif /* POLARSSL_X509_PARSE_C */
+const x509_crt *ssl_get_peer_cert( const ssl_context *ssl );
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 /**
  * \brief          Save session in order to resume it later (client-side only)
diff --git a/include/polarssl/ssl_cache.h b/include/polarssl/ssl_cache.h
index 979dc14..3c5ef8b 100644
--- a/include/polarssl/ssl_cache.h
+++ b/include/polarssl/ssl_cache.h
@@ -50,7 +50,7 @@
     time_t timestamp;           /*!< entry timestamp    */
 #endif
     ssl_session session;        /*!< entry session      */
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     x509_buf peer_cert;         /*!< entry peer_cert    */
 #endif
     ssl_cache_entry *next;      /*!< chain pointer      */
diff --git a/include/polarssl/ssl_ciphersuites.h b/include/polarssl/ssl_ciphersuites.h
index 85392c1..cfc0474 100644
--- a/include/polarssl/ssl_ciphersuites.h
+++ b/include/polarssl/ssl_ciphersuites.h
@@ -193,7 +193,7 @@
     unsigned char flags;
 };
 
-const int *ssl_ciphersuites_list( void );
+const int *ssl_list_ciphersuites( void );
 
 const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name );
 const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite_id );
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index 00e9b0b..285e69c 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -1,7 +1,7 @@
 /**
  * \file x509.h
  *
- * \brief X.509 certificate and private key decoding
+ * \brief X.509 generic defines and structures
  *
  *  Copyright (C) 2006-2013, Brainspark B.V.
  *
@@ -29,46 +29,40 @@
 
 #include "config.h"
 
-#if defined(POLARSSL_X509_PARSE_C) || defined(POLARSSL_X509_WRITE_C)
 #include "asn1.h"
-#include "dhm.h"
-#include "md.h"
 #include "pk.h"
 
-/** 
+#if defined(POLARSSL_RSA_C)
+#include "rsa.h"
+#endif
+
+/**
  * \addtogroup x509_module
- * \{ 
+ * \{
  */
- 
-/** 
+
+/**
  * \name X509 Error codes
  * \{
  */
 #define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE              -0x2080  /**< Unavailable feature, e.g. RSA hashing/encryption combination. */
-#define POLARSSL_ERR_X509_CERT_INVALID_PEM                 -0x2100  /**< The PEM-encoded certificate contains invalid elements, e.g. invalid character. */ 
-#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT              -0x2180  /**< The certificate format is invalid, e.g. different type expected. */
-#define POLARSSL_ERR_X509_CERT_INVALID_VERSION             -0x2200  /**< The certificate version element is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL              -0x2280  /**< The serial tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_ALG                 -0x2300  /**< The algorithm tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_NAME                -0x2380  /**< The name tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_DATE                -0x2400  /**< The date tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY              -0x2480  /**< The pubkey tag or value is invalid (only RSA and EC are supported). */
-#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE           -0x2500  /**< The signature tag or value invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS          -0x2580  /**< The extension tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION             -0x2600  /**< Certificate or CRL has an unsupported version number. */
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG             -0x2680  /**< Signature algorithm (oid) is unsupported. */
-#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG                   -0x2700  /**< Key algorithm is unsupported (only RSA and EC are supported). */
-#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH                -0x2780  /**< Certificate signature algorithms do not match. (see \c ::x509_cert sig_oid) */
-#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED               -0x2800  /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */
-#define POLARSSL_ERR_X509_KEY_INVALID_VERSION              -0x2880  /**< Unsupported RSA key version */
-#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT               -0x2900  /**< Invalid RSA key tag or value. */
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT              -0x2980  /**< Format not recognized as DER or PEM. */
-#define POLARSSL_ERR_X509_INVALID_INPUT                    -0x2A00  /**< Input invalid. */
-#define POLARSSL_ERR_X509_MALLOC_FAILED                    -0x2A80  /**< Allocation of memory failed. */
-#define POLARSSL_ERR_X509_FILE_IO_ERROR                    -0x2B00  /**< Read/write of file failed. */
-#define POLARSSL_ERR_X509_PASSWORD_REQUIRED                -0x2B80  /**< Private key password can't be empty. */
-#define POLARSSL_ERR_X509_PASSWORD_MISMATCH                -0x2C00  /**< Given private key password does not allow for correct decryption. */
-#define POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE              -0x2C80  /**< Elliptic curve is unsupported (only NIST curves are supported). */
+#define POLARSSL_ERR_X509_UNKNOWN_OID                      -0x2100  /**< Requested OID is unknown. */
+#define POLARSSL_ERR_X509_INVALID_FORMAT                   -0x2180  /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */
+#define POLARSSL_ERR_X509_INVALID_VERSION                  -0x2200  /**< The CRT/CRL/CSR version element is invalid. */
+#define POLARSSL_ERR_X509_INVALID_SERIAL                   -0x2280  /**< The serial tag or value is invalid. */
+#define POLARSSL_ERR_X509_INVALID_ALG                      -0x2300  /**< The algorithm tag or value is invalid. */
+#define POLARSSL_ERR_X509_INVALID_NAME                     -0x2380  /**< The name tag or value is invalid. */
+#define POLARSSL_ERR_X509_INVALID_DATE                     -0x2400  /**< The date tag or value is invalid. */
+#define POLARSSL_ERR_X509_INVALID_SIGNATURE                -0x2480  /**< The signature tag or value invalid. */
+#define POLARSSL_ERR_X509_INVALID_EXTENSIONS               -0x2500  /**< The extension tag or value is invalid. */
+#define POLARSSL_ERR_X509_UNKNOWN_VERSION                  -0x2580  /**< CRT/CRL/CSR has an unsupported version number. */
+#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG                  -0x2600  /**< Signature algorithm (oid) is unsupported. */
+#define POLARSSL_ERR_X509_SIG_MISMATCH                     -0x2680  /**< Signature algorithms do not match. (see \c ::x509_crt sig_oid) */
+#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED               -0x2700  /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT              -0x2780  /**< Format not recognized as DER or PEM. */
+#define POLARSSL_ERR_X509_BAD_INPUT_DATA                   -0x2800  /**< Input invalid. */
+#define POLARSSL_ERR_X509_MALLOC_FAILED                    -0x2880  /**< Allocation of memory failed. */
+#define POLARSSL_ERR_X509_FILE_IO_ERROR                    -0x2900  /**< Read/write of file failed. */
 /* \} name */
 
 /**
@@ -182,389 +176,10 @@
 }
 x509_time;
 
-/**
- * Container for an X.509 certificate. The certificate may be chained.
- */
-typedef struct _x509_cert
-{
-    x509_buf raw;               /**< The raw certificate data (DER). */
-    x509_buf tbs;               /**< The raw certificate body (DER). The part that is To Be Signed. */
-
-    int version;                /**< The X.509 version. (0=v1, 1=v2, 2=v3) */
-    x509_buf serial;            /**< Unique id for certificate issued by a specific CA. */
-    x509_buf sig_oid1;          /**< Signature algorithm, e.g. sha1RSA */
-
-    x509_buf issuer_raw;        /**< The raw issuer data (DER). Used for quick comparison. */
-    x509_buf subject_raw;       /**< The raw subject data (DER). Used for quick comparison. */
-
-    x509_name issuer;           /**< The parsed issuer data (named information object). */
-    x509_name subject;          /**< The parsed subject data (named information object). */
-
-    x509_time valid_from;       /**< Start time of certificate validity. */
-    x509_time valid_to;         /**< End time of certificate validity. */
-
-    pk_context pk;              /**< Container for the public key context. */
-
-    x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
-    x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
-    x509_buf v3_ext;            /**< Optional X.509 v3 extensions. Only Basic Contraints are supported at this time. */
-    x509_sequence subject_alt_names;    /**< Optional list of Subject Alternative Names (Only dNSName supported). */
-
-    int ext_types;              /**< Bit string containing detected and parsed extensions */
-    int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
-    int max_pathlen;            /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */
-
-    unsigned char key_usage;    /**< Optional key usage extension value: See the values below */
-
-    x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
-
-    unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values below */
-
-    x509_buf sig_oid2;          /**< Signature algorithm. Must match sig_oid1. */
-    x509_buf sig;               /**< Signature: hash of the tbs part signed with the private key. */
-    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. */
-}
-x509_cert;
-
-/**
- * Certificate revocation list entry.
- * Contains the CA-specific serial numbers and revocation dates.
- */
-typedef struct _x509_crl_entry
-{
-    x509_buf raw;
-
-    x509_buf serial;
-
-    x509_time revocation_date;
-
-    x509_buf entry_ext;
-
-    struct _x509_crl_entry *next;
-}
-x509_crl_entry;
-
-/**
- * Certificate revocation list structure.
- * Every CRL may have multiple entries.
- */
-typedef struct _x509_crl
-{
-    x509_buf raw;           /**< The raw certificate data (DER). */
-    x509_buf tbs;           /**< The raw certificate body (DER). The part that is To Be Signed. */
-
-    int version;
-    x509_buf sig_oid1;
-
-    x509_buf issuer_raw;    /**< The raw issuer data (DER). */
-
-    x509_name issuer;       /**< The parsed issuer data (named information object). */
-
-    x509_time this_update;
-    x509_time next_update;
-
-    x509_crl_entry entry;   /**< The CRL entries containing the certificate revocation times for this CA. */
-
-    x509_buf crl_ext;
-
-    x509_buf sig_oid2;
-    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 */;
-
-    struct _x509_crl *next;
-}
-x509_crl;
-
-/**
- * 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 */
 
 /**
- * \name Functions to read in DHM parameters, a certificate, CRL or private RSA key
- * \{
- */
-
-/** \ingroup x509_module */
-/**
- * \brief          Parse a single DER formatted certificate and add it
- *                 to the chained list.
- *
- * \param chain    points to the start of the chain
- * \param buf      buffer holding the certificate DER data
- * \param buflen   size of the buffer
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_crt_der( x509_cert *chain, const unsigned char *buf, size_t buflen );
-
-/**
- * \brief          Parse one or more certificates and add them
- *                 to the chained list. Parses permissively. If some
- *                 certificates can be parsed, the result is the number
- *                 of failed certificates it encountered. If none complete
- *                 correctly, the first error is returned.
- *
- * \param chain    points to the start of the chain
- * \param buf      buffer holding the certificate data
- * \param buflen   size of the buffer
- *
- * \return         0 if all certificates parsed successfully, a positive number
- *                 if partly successful or a specific X509 or PEM error code
- */
-int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen );
-
-#if defined(POLARSSL_FS_IO)
-/** \ingroup x509_module */
-/**
- * \brief          Load one or more certificates and add them
- *                 to the chained list. Parses permissively. If some
- *                 certificates can be parsed, the result is the number
- *                 of failed certificates it encountered. If none complete
- *                 correctly, the first error is returned.
- *
- * \param chain    points to the start of the chain
- * \param path     filename to read the certificates from
- *
- * \return         0 if all certificates parsed successfully, a positive number
- *                 if partly successful or a specific X509 or PEM error code
- */
-int x509parse_crtfile( x509_cert *chain, const char *path );
-
-/** \ingroup x509_module */
-/**
- * \brief          Load one or more certificate files from a path and add them
- *                 to the chained list. Parses permissively. If some
- *                 certificates can be parsed, the result is the number
- *                 of failed certificates it encountered. If none complete
- *                 correctly, the first error is returned.
- *
- * \param chain    points to the start of the chain
- * \param path     directory / folder to read the certificate files from
- *
- * \return         0 if all certificates parsed successfully, a positive number
- *                 if partly successful or a specific X509 or PEM error code
- */
-int x509parse_crtpath( x509_cert *chain, const char *path );
-#endif /* POLARSSL_FS_IO */
-
-/** \ingroup x509_module */
-/**
- * \brief          Parse one or more CRLs and add them
- *                 to the chained list
- *
- * \param chain    points to the start of the chain
- * \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_crl( x509_crl *chain, const unsigned char *buf, size_t buflen );
-
-/** \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 );
-
-#if defined(POLARSSL_FS_IO)
-/** \ingroup x509_module */
-/**
- * \brief          Load one or more CRLs and add them
- *                 to the chained list
- *
- * \param chain    points to the start of the chain
- * \param path     filename to read the CRLs from
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-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 );
-#endif /* POLARSSL_FS_IO */
-
-#if defined(POLARSSL_RSA_C)
-/** \ingroup x509_module */
-/**
- * \brief          Parse a private RSA key
- *
- * \param rsa      RSA context to be initialized
- * \param key      input buffer
- * \param keylen   size of the buffer
- * \param pwd      password for decryption (optional)
- * \param pwdlen   size of the password
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_key_rsa( rsa_context *rsa,
-                       const unsigned char *key, size_t keylen,
-                       const unsigned char *pwd, size_t pwdlen );
-
-#if defined(POLARSSL_FS_IO)
-/** \ingroup x509_module */
-/**
- * \brief          Load and parse a private RSA key
- *
- * \param rsa      RSA context to be initialized
- * \param path     filename to read the private key from
- * \param password password to decrypt the file (can be NULL)
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_keyfile_rsa( rsa_context *rsa, const char *path,
-                           const char *password );
-#endif /* POLARSSL_FS_IO */
-
-/** \ingroup x509_module */
-/**
- * \brief          Parse a public RSA key
- *
- * \param rsa      RSA context to be initialized
- * \param key      input buffer
- * \param keylen   size of the buffer
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_public_key_rsa( rsa_context *rsa,
-                       const unsigned char *key, size_t keylen );
-
-#if defined(POLARSSL_FS_IO)
-/** \ingroup x509_module */
-/**
- * \brief          Load and parse a public RSA key
- *
- * \param rsa      RSA context to be initialized
- * \param path     filename to read the private key from
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path );
-#endif /* POLARSSL_FS_IO */
-#endif /* POLARSSL_RSA_C */
-
-/** \ingroup x509_module */
-/**
- * \brief          Parse a private key
- *
- * \param ctx      key to be initialized
- * \param key      input buffer
- * \param keylen   size of the buffer
- * \param pwd      password for decryption (optional)
- * \param pwdlen   size of the password
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_key( pk_context *ctx,
-                   const unsigned char *key, size_t keylen,
-                   const unsigned char *pwd, size_t pwdlen );
-
-#if defined(POLARSSL_FS_IO)
-/** \ingroup x509_module */
-/**
- * \brief          Load and parse a private key
- *
- * \param ctx      key to be initialized
- * \param path     filename to read the private key from
- * \param password password to decrypt the file (can be NULL)
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_keyfile( pk_context *ctx,
-                       const char *path, const char *password );
-#endif /* POLARSSL_FS_IO */
-
-/** \ingroup x509_module */
-/**
- * \brief          Parse a public key
- *
- * \param ctx      key to be initialized
- * \param key      input buffer
- * \param keylen   size of the buffer
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_public_key( pk_context *ctx,
-                          const unsigned char *key, size_t keylen );
-
-#if defined(POLARSSL_FS_IO)
-/** \ingroup x509_module */
-/**
- * \brief          Load and parse a public key
- *
- * \param ctx      key to be initialized
- * \param path     filename to read the private key from
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_public_keyfile( pk_context *ctx, const char *path );
-#endif /* POLARSSL_FS_IO */
-
-/** \ingroup x509_module */
-/**
- * \brief          Parse DHM parameters
- *
- * \param dhm      DHM context to be initialized
- * \param dhmin    input buffer
- * \param dhminlen size of the buffer
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen );
-
-#if defined(POLARSSL_FS_IO)
-/** \ingroup x509_module */
-/**
- * \brief          Load and parse DHM parameters
- *
- * \param dhm      DHM context to be initialized
- * \param path     filename to read the DHM Parameters from
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_dhmfile( dhm_context *dhm, const char *path );
-#endif /* POLARSSL_FS_IO */
-
-/** \} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */
-
-/**
  * \brief          Store the certificate DN in printable form into buf;
  *                 no more than size characters will be written.
  *
@@ -575,7 +190,7 @@
  * \return         The amount of data written to the buffer, or -1 in
  *                 case of an error.
  */
-int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn );
+int x509_dn_gets( char *buf, size_t size, const x509_name *dn );
 
 /**
  * \brief          Store the certificate serial in printable form into buf;
@@ -588,52 +203,7 @@
  * \return         The amount of data written to the buffer, or -1 in
  *                 case of an error.
  */
-int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial );
-
-/**
- * \brief          Returns an informational string about the
- *                 certificate.
- *
- * \param buf      Buffer to write to
- * \param size     Maximum size of buffer
- * \param prefix   A line prefix
- * \param crt      The X509 certificate to represent
- *
- * \return         The amount of data written to the buffer, or -1 in
- *                 case of an error.
- */
-int x509parse_cert_info( char *buf, size_t size, const char *prefix,
-                         const x509_cert *crt );
-
-/**
- * \brief          Returns an informational string about the
- *                 CRL.
- *
- * \param buf      Buffer to write to
- * \param size     Maximum size of buffer
- * \param prefix   A line prefix
- * \param crl      The X509 CRL to represent
- *
- * \return         The amount of data written to the buffer, or -1 in
- *                 case of an error.
- */
-int x509parse_crl_info( char *buf, size_t size, const char *prefix,
-                        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 );
+int x509_serial_gets( char *buf, size_t size, const x509_buf *serial );
 
 /**
  * \brief          Give an known OID, return its descriptive string.
@@ -667,100 +237,7 @@
  * \return         Return 0 if the x509_time is still valid,
  *                 or 1 otherwise.
  */
-int x509parse_time_expired( const x509_time *time );
-
-/**
- * \name Functions to verify a certificate
- * \{
- */
-/** \ingroup x509_module */
-/**
- * \brief          Verify the certificate signature
- *
- *                 The verify callback is a user-supplied callback that
- *                 can clear / modify / add flags for a certificate. If set,
- *                 the verification callback is called for each
- *                 certificate in the chain (from the trust-ca down to the
- *                 presented crt). The parameters for the callback are:
- *                 (void *parameter, x509_cert *crt, int certificate_depth,
- *                 int *flags). With the flags representing current flags for
- *                 that specific certificate and the certificate depth from
- *                 the bottom (Peer cert depth = 0).
- *
- *                 All flags left after returning from the callback
- *                 are also returned to the application. The function should
- *                 return 0 for anything but a fatal error.
- *
- * \param crt      a certificate to be verified
- * \param trust_ca the trusted CA chain
- * \param ca_crl   the CRL chain for trusted CA's
- * \param cn       expected Common Name (can be set to
- *                 NULL if the CN must not be verified)
- * \param flags    result of the verification
- * \param f_vrfy   verification function
- * \param p_vrfy   verification parameter
- *
- * \return         0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED,
- *                 in which case *flags will have one or more of
- *                 the following values set:
- *                      BADCERT_EXPIRED --
- *                      BADCERT_REVOKED --
- *                      BADCERT_CN_MISMATCH --
- *                      BADCERT_NOT_TRUSTED
- *                 or another error in case of a fatal error encountered
- *                 during the verification process.
- */
-int x509parse_verify( x509_cert *crt,
-                      x509_cert *trust_ca,
-                      x509_crl *ca_crl,
-                      const char *cn, int *flags,
-                      int (*f_vrfy)(void *, x509_cert *, int, int *),
-                      void *p_vrfy );
-
-/**
- * \brief          Verify the certificate signature
- *
- * \param crt      a certificate to be verified
- * \param crl      the CRL to verify against
- *
- * \return         1 if the certificate is revoked, 0 otherwise
- *
- */
-int x509parse_revoked( const x509_cert *crt, const x509_crl *crl );
-
-/** \} name Functions to verify a certificate */
-
-
-
-/**
- * \name Functions to clear a certificate, CRL or private RSA key 
- * \{
- */
-/** \ingroup x509_module */
-/**
- * \brief          Unallocate all certificate data
- *
- * \param crt      Certificate chain to free
- */
-void x509_free( x509_cert *crt );
-
-/** \ingroup x509_module */
-/**
- * \brief          Unallocate all CRL data
- *
- * \param crl      CRL chain to free
- */
-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 */
-
+int x509_time_expired( const x509_time *time );
 
 /**
  * \brief          Checkup routine
@@ -769,9 +246,32 @@
  */
 int x509_self_test( int verbose );
 
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* POLARSSL_X509_PARSE_C || POLARSSL_X509_WRITE_C */
+/*
+ * Internal module functions. You probably do not want to use these unless you
+ * know you do.
+ */
+int x509_get_name( unsigned char **p, const unsigned char *end,
+                   x509_name *cur );
+int x509_get_alg_null( unsigned char **p, const unsigned char *end,
+                       x509_buf *alg );
+int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig );
+int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
+                      pk_type_t *pk_alg );
+int x509_get_time( unsigned char **p, const unsigned char *end,
+                   x509_time *time );
+int x509_get_serial( unsigned char **p, const unsigned char *end,
+                     x509_buf *serial );
+int x509_get_ext( unsigned char **p, const unsigned char *end,
+                  x509_buf *ext, int tag );
+int x509_load_file( const char *path, unsigned char **buf, size_t *n );
+int x509_key_size_helper( char *buf, size_t size, const char *name );
+int x509_string_to_names( asn1_named_data **head, char *name );
+int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,                       int critical, const unsigned char *val, size_t val_len );
+int x509_write_extensions( unsigned char **p, unsigned char *start,
+                           asn1_named_data *first );
+int x509_write_names( unsigned char **p, unsigned char *start,
+                      asn1_named_data *first );
+int x509_write_sig( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len,
+                    unsigned char *sig, size_t size );
 #endif /* x509.h */
diff --git a/include/polarssl/x509_crl.h b/include/polarssl/x509_crl.h
new file mode 100644
index 0000000..0c79916
--- /dev/null
+++ b/include/polarssl/x509_crl.h
@@ -0,0 +1,157 @@
+/**
+ * \file x509_crl.h
+ *
+ * \brief X.509 certificate revocation list parsing
+ *
+ *  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 POLARSSL_X509_CRL_H
+#define POLARSSL_X509_CRL_H
+
+#include "config.h"
+
+#include "x509.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup x509_module
+ * \{ */
+
+/**
+ * \name Structures and functions for parsing CRLs
+ * \{
+ */
+
+/**
+ * Certificate revocation list entry.
+ * Contains the CA-specific serial numbers and revocation dates.
+ */
+typedef struct _x509_crl_entry
+{
+    x509_buf raw;
+
+    x509_buf serial;
+
+    x509_time revocation_date;
+
+    x509_buf entry_ext;
+
+    struct _x509_crl_entry *next;
+}
+x509_crl_entry;
+
+/**
+ * Certificate revocation list structure.
+ * Every CRL may have multiple entries.
+ */
+typedef struct _x509_crl
+{
+    x509_buf raw;           /**< The raw certificate data (DER). */
+    x509_buf tbs;           /**< The raw certificate body (DER). The part that is To Be Signed. */
+
+    int version;
+    x509_buf sig_oid1;
+
+    x509_buf issuer_raw;    /**< The raw issuer data (DER). */
+
+    x509_name issuer;       /**< The parsed issuer data (named information object). */
+
+    x509_time this_update;
+    x509_time next_update;
+
+    x509_crl_entry entry;   /**< The CRL entries containing the certificate revocation times for this CA. */
+
+    x509_buf crl_ext;
+
+    x509_buf sig_oid2;
+    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 */;
+
+    struct _x509_crl *next;
+}
+x509_crl;
+
+/**
+ * \brief          Parse one or more CRLs and add them
+ *                 to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \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 x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief          Load one or more CRLs and add them
+ *                 to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \param path     filename to read the CRLs from
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509_crl_parse_file( x509_crl *chain, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief          Returns an informational string about the CRL.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param crl      The X509 CRL to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_crl_info( char *buf, size_t size, const char *prefix,
+                   const x509_crl *crl );
+
+/**
+ * \brief          Initialize a CRL (chain)
+ *
+ * \param crl      CRL chain to initialize
+ */
+void x509_crl_init( x509_crl *crl );
+
+/**
+ * \brief          Unallocate all CRL data
+ *
+ * \param crl      CRL chain to free
+ */
+void x509_crl_free( x509_crl *crl );
+
+/* \} name */
+/* \} addtogroup x509_module */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509_crl.h */
diff --git a/include/polarssl/x509_crt.h b/include/polarssl/x509_crt.h
new file mode 100644
index 0000000..f5703be
--- /dev/null
+++ b/include/polarssl/x509_crt.h
@@ -0,0 +1,508 @@
+/**
+ * \file x509_crt.h
+ *
+ * \brief X.509 certificate parsing and writing
+ *
+ *  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 POLARSSL_X509_CRT_H
+#define POLARSSL_X509_CRT_H
+
+#include "config.h"
+
+#include "x509.h"
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+#include "x509_crl.h"
+#endif
+
+/**
+ * \addtogroup x509_module
+ * \{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Structures and functions for parsing and writing X.509 certificates
+ * \{
+ */
+
+/**
+ * Container for an X.509 certificate. The certificate may be chained.
+ */
+typedef struct _x509_crt
+{
+    x509_buf raw;               /**< The raw certificate data (DER). */
+    x509_buf tbs;               /**< The raw certificate body (DER). The part that is To Be Signed. */
+
+    int version;                /**< The X.509 version. (0=v1, 1=v2, 2=v3) */
+    x509_buf serial;            /**< Unique id for certificate issued by a specific CA. */
+    x509_buf sig_oid1;          /**< Signature algorithm, e.g. sha1RSA */
+
+    x509_buf issuer_raw;        /**< The raw issuer data (DER). Used for quick comparison. */
+    x509_buf subject_raw;       /**< The raw subject data (DER). Used for quick comparison. */
+
+    x509_name issuer;           /**< The parsed issuer data (named information object). */
+    x509_name subject;          /**< The parsed subject data (named information object). */
+
+    x509_time valid_from;       /**< Start time of certificate validity. */
+    x509_time valid_to;         /**< End time of certificate validity. */
+
+    pk_context pk;              /**< Container for the public key context. */
+
+    x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
+    x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
+    x509_buf v3_ext;            /**< Optional X.509 v3 extensions. Only Basic Contraints are supported at this time. */
+    x509_sequence subject_alt_names;    /**< Optional list of Subject Alternative Names (Only dNSName supported). */
+
+    int ext_types;              /**< Bit string containing detected and parsed extensions */
+    int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
+    int max_pathlen;            /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */
+
+    unsigned char key_usage;    /**< Optional key usage extension value: See the values below */
+
+    x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
+
+    unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values below */
+
+    x509_buf sig_oid2;          /**< Signature algorithm. Must match sig_oid1. */
+    x509_buf sig;               /**< Signature: hash of the tbs part signed with the private key. */
+    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_crt *next;     /**< Next certificate in the CA-chain. */
+}
+x509_crt;
+
+#define X509_CRT_VERSION_1              0
+#define X509_CRT_VERSION_2              1
+#define X509_CRT_VERSION_3              2
+
+#define X509_RFC5280_MAX_SERIAL_LEN 32
+#define X509_RFC5280_UTC_TIME_LEN   15
+
+/**
+ * Container for writing a certificate (CRT)
+ */
+typedef struct _x509write_cert
+{
+    int version;
+    mpi serial;
+    pk_context *subject_key;
+    pk_context *issuer_key;
+    asn1_named_data *subject;
+    asn1_named_data *issuer;
+    md_type_t md_alg;
+    char not_before[X509_RFC5280_UTC_TIME_LEN + 1];
+    char not_after[X509_RFC5280_UTC_TIME_LEN + 1];
+    asn1_named_data *extensions;
+}
+x509write_cert;
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/**
+ * \brief          Parse a single DER formatted certificate and add it
+ *                 to the chained list.
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the certificate DER data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf,
+                        size_t buflen );
+
+/**
+ * \brief          Parse one or more certificates and add them
+ *                 to the chained list. Parses permissively. If some
+ *                 certificates can be parsed, the result is the number
+ *                 of failed certificates it encountered. If none complete
+ *                 correctly, the first error is returned.
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the certificate data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if all certificates parsed successfully, a positive number
+ *                 if partly successful or a specific X509 or PEM error code
+ */
+int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief          Load one or more certificates and add them
+ *                 to the chained list. Parses permissively. If some
+ *                 certificates can be parsed, the result is the number
+ *                 of failed certificates it encountered. If none complete
+ *                 correctly, the first error is returned.
+ *
+ * \param chain    points to the start of the chain
+ * \param path     filename to read the certificates from
+ *
+ * \return         0 if all certificates parsed successfully, a positive number
+ *                 if partly successful or a specific X509 or PEM error code
+ */
+int x509_crt_parse_file( x509_crt *chain, const char *path );
+
+/**
+ * \brief          Load one or more certificate files from a path and add them
+ *                 to the chained list. Parses permissively. If some
+ *                 certificates can be parsed, the result is the number
+ *                 of failed certificates it encountered. If none complete
+ *                 correctly, the first error is returned.
+ *
+ * \param chain    points to the start of the chain
+ * \param path     directory / folder to read the certificate files from
+ *
+ * \return         0 if all certificates parsed successfully, a positive number
+ *                 if partly successful or a specific X509 or PEM error code
+ */
+int x509_crt_parse_path( x509_crt *chain, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief          Returns an informational string about the
+ *                 certificate.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param crt      The X509 certificate to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_crt_info( char *buf, size_t size, const char *prefix,
+                   const x509_crt *crt );
+
+/**
+ * \brief          Verify the certificate signature
+ *
+ *                 The verify callback is a user-supplied callback that
+ *                 can clear / modify / add flags for a certificate. If set,
+ *                 the verification callback is called for each
+ *                 certificate in the chain (from the trust-ca down to the
+ *                 presented crt). The parameters for the callback are:
+ *                 (void *parameter, x509_crt *crt, int certificate_depth,
+ *                 int *flags). With the flags representing current flags for
+ *                 that specific certificate and the certificate depth from
+ *                 the bottom (Peer cert depth = 0).
+ *
+ *                 All flags left after returning from the callback
+ *                 are also returned to the application. The function should
+ *                 return 0 for anything but a fatal error.
+ *
+ * \param crt      a certificate to be verified
+ * \param trust_ca the trusted CA chain
+ * \param ca_crl   the CRL chain for trusted CA's
+ * \param cn       expected Common Name (can be set to
+ *                 NULL if the CN must not be verified)
+ * \param flags    result of the verification
+ * \param f_vrfy   verification function
+ * \param p_vrfy   verification parameter
+ *
+ * \return         0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED,
+ *                 in which case *flags will have one or more of
+ *                 the following values set:
+ *                      BADCERT_EXPIRED --
+ *                      BADCERT_REVOKED --
+ *                      BADCERT_CN_MISMATCH --
+ *                      BADCERT_NOT_TRUSTED
+ *                 or another error in case of a fatal error encountered
+ *                 during the verification process.
+ */
+int x509_crt_verify( x509_crt *crt,
+                     x509_crt *trust_ca,
+                     x509_crl *ca_crl,
+                     const char *cn, int *flags,
+                     int (*f_vrfy)(void *, x509_crt *, int, int *),
+                     void *p_vrfy );
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+/**
+ * \brief          Verify the certificate signature
+ *
+ * \param crt      a certificate to be verified
+ * \param crl      the CRL to verify against
+ *
+ * \return         1 if the certificate is revoked, 0 otherwise
+ *
+ */
+int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl );
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+
+/**
+ * \brief          Initialize a certificate (chain)
+ *
+ * \param crt      Certificate chain to initialize
+ */
+void x509_crt_init( x509_crt *crt );
+
+/**
+ * \brief          Unallocate all certificate data
+ *
+ * \param crt      Certificate chain to free
+ */
+void x509_crt_free( x509_crt *crt );
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+/* \} name */
+/* \} addtogroup x509_module */
+
+#if defined(POLARSSL_X509_CRT_WRITE_C)
+/**
+ * \brief           Initialize a CRT writing context
+ *
+ * \param ctx       CRT context to initialize
+ */
+void x509write_crt_init( x509write_cert *ctx );
+
+/**
+ * \brief           Set the verion for a Certificate
+ *                  Default: X509_CRT_VERSION_3
+ *
+ * \param ctx       CRT context to use
+ * \param version   version to set (X509_CRT_VERSION_1, X509_CRT_VERSION_2 or
+ *                                  X509_CRT_VERSION_3)
+ */
+void x509write_crt_set_version( x509write_cert *ctx, int version );
+
+/**
+ * \brief           Set the serial number for a Certificate.
+ *
+ * \param ctx       CRT context to use
+ * \param serial    serial number to set
+ *
+ * \return          0 if successful
+ */
+int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial );
+
+/**
+ * \brief           Set the validity period for a Certificate
+ *                  Timestamps should be in string format for UTC timezone
+ *                  i.e. "YYYYMMDDhhmmss"
+ *                  e.g. "20131231235959" for December 31st 2013
+ *                       at 23:59:59
+ *
+ * \param ctx       CRT context to use
+ * \param not_before    not_before timestamp
+ * \param not_after     not_after timestamp
+ *
+ * \return          0 if timestamp was parsed successfully, or
+ *                  a specific error code
+ */
+int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
+                                char *not_after );
+
+/**
+ * \brief           Set the issuer name for a Certificate
+ *                  Issuer names should contain a comma-separated list
+ *                  of OID types and values:
+ *                  e.g. "C=NL,O=Offspark,CN=PolarSSL CA"
+ *
+ * \param ctx           CRT context to use
+ * \param issuer_name   issuer name to set
+ *
+ * \return          0 if issuer name was parsed successfully, or
+ *                  a specific error code
+ */
+int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name );
+
+/**
+ * \brief           Set the subject name for a Certificate
+ *                  Subject names should contain a comma-separated list
+ *                  of OID types and values:
+ *                  e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1"
+ *
+ * \param ctx           CRT context to use
+ * \param subject_name  subject name to set
+ *
+ * \return          0 if subject name was parsed successfully, or
+ *                  a specific error code
+ */
+int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name );
+
+/**
+ * \brief           Set the subject public key for the certificate
+ *
+ * \param ctx       CRT context to use
+ * \param key       public key to include
+ */
+void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key );
+
+/**
+ * \brief           Set the issuer key used for signing the certificate
+ *
+ * \param ctx       CRT context to use
+ * \param key       private key to sign with
+ */
+void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key );
+
+/**
+ * \brief           Set the MD algorithm to use for the signature
+ *                  (e.g. POLARSSL_MD_SHA1)
+ *
+ * \param ctx       CRT context to use
+ * \param md_ald    MD algorithm to use
+ */
+void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg );
+
+/**
+ * \brief           Generic function to add to or replace an extension in the
+ *                  CRT
+ *
+ * \param ctx       CRT context to use
+ * \param oid       OID of the extension
+ * \param oid_len   length of the OID
+ * \param critical  if the extension is critical (per the RFC's definition)
+ * \param val       value of the extension OCTET STRING
+ * \param val_len   length of the value data
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_extension( x509write_cert *ctx,
+                                 const char *oid, size_t oid_len,
+                                 int critical,
+                                 const unsigned char *val, size_t val_len );
+
+/**
+ * \brief           Set the basicConstraints extension for a CRT
+ *
+ * \param ctx       CRT context to use
+ * \param is_ca     is this a CA certificate
+ * \param max_pathlen   maximum length of certificate chains below this
+ *                      certificate (only for CA certificates, -1 is
+ *                      inlimited)
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_basic_constraints( x509write_cert *ctx,
+                                         int is_ca, int max_pathlen );
+
+/**
+ * \brief           Set the subjectKeyIdentifier extension for a CRT
+ *                  Requires that x509write_crt_set_subject_key() has been
+ *                  called before
+ *
+ * \param ctx       CRT context to use
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_subject_key_identifier( x509write_cert *ctx );
+
+/**
+ * \brief           Set the authorityKeyIdentifier extension for a CRT
+ *                  Requires that x509write_crt_set_issuer_key() has been
+ *                  called before
+ *
+ * \param ctx       CRT context to use
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_authority_key_identifier( x509write_cert *ctx );
+
+/**
+ * \brief           Set the Key Usage Extension flags
+ *                  (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN)
+ *
+ * \param ctx       CRT context to use
+ * \param key_usage key usage flags to set
+ *
+ * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage );
+
+/**
+ * \brief           Set the Netscape Cert Type flags
+ *                  (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL)
+ *
+ * \param ctx           CRT context to use
+ * \param ns_cert_type  Netscape Cert Type flags to set
+ *
+ * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
+                                    unsigned char ns_cert_type );
+
+/**
+ * \brief           Free the contents of a CRT write context
+ *
+ * \param ctx       CRT context to free
+ */
+void x509write_crt_free( x509write_cert *ctx );
+
+/**
+ * \brief           Write a built up certificate to a X509 DER structure
+ *                  Note: data is written at the end of the buffer! Use the
+ *                        return value to determine where you should start
+ *                        using the buffer
+ *
+ * \param crt       certificate to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ * \param f_rng     RNG function (for signature, see note)
+ * \param p_rng     RNG parameter
+ *
+ * \return          length of data written if successful, or a specific
+ *                  error code
+ *
+ * \note            f_rng may be NULL if RSA is used for signature and the
+ *                  signature is made offline (otherwise f_rng is desirable
+ *                  for countermeasures against timing attacks).
+ *                  ECDSA signatures always require a non-NULL f_rng.
+ */
+int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng );
+
+#if defined(POLARSSL_PEM_WRITE_C)
+/**
+ * \brief           Write a built up certificate to a X509 PEM string
+ *
+ * \param crt       certificate to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ * \param f_rng     RNG function (for signature, see note)
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 successful, or a specific error code
+ *
+ * \note            f_rng may be NULL if RSA is used for signature and the
+ *                  signature is made offline (otherwise f_rng is desirable
+ *                  for countermeasures against timing attacks).
+ *                  ECDSA signatures always require a non-NULL f_rng.
+ */
+int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng );
+#endif /* POLARSSL_PEM_WRITE_C */
+#endif /* POLARSSL_X509_CRT_WRITE_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509_crt.h */
diff --git a/include/polarssl/x509_csr.h b/include/polarssl/x509_csr.h
new file mode 100644
index 0000000..30ef7c5
--- /dev/null
+++ b/include/polarssl/x509_csr.h
@@ -0,0 +1,276 @@
+/**
+ * \file x509_csr.h
+ *
+ * \brief X.509 certificate signing request parsing and writing
+ *
+ *  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 POLARSSL_X509_CSR_H
+#define POLARSSL_X509_CSR_H
+
+#include "config.h"
+
+#include "x509.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup x509_module
+ * \{ */
+
+/**
+ * \name Structures and functions for X.509 Certificate Signing Requests (CSR)
+ * \{
+ */
+
+/**
+ * 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;
+
+/**
+ * Container for writing a CSR
+ */
+typedef struct _x509write_csr
+{
+    pk_context *key;
+    asn1_named_data *subject;
+    md_type_t md_alg;
+    asn1_named_data *extensions;
+}
+x509write_csr;
+
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+/**
+ * \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 x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \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 x509_csr_parse_file( x509_csr *csr, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \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 x509_csr_info( char *buf, size_t size, const char *prefix,
+                   const x509_csr *csr );
+
+/**
+ * \brief          Initialize a CSR
+ *
+ * \param csr      CSR to initialize
+ */
+void x509_csr_init( x509_csr *csr );
+
+/**
+ * \brief          Unallocate all CSR data
+ *
+ * \param csr      CSR to free
+ */
+void x509_csr_free( x509_csr *csr );
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+
+/* \} name */
+/* \} addtogroup x509_module */
+
+#if defined(POLARSSL_X509_CSR_WRITE_C)
+/**
+ * \brief           Initialize a CSR context
+ *
+ * \param ctx       CSR context to initialize
+ */
+void x509write_csr_init( x509write_csr *ctx );
+
+/**
+ * \brief           Set the subject name for a CSR
+ *                  Subject names should contain a comma-separated list
+ *                  of OID types and values:
+ *                  e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1"
+ *
+ * \param ctx           CSR context to use
+ * \param subject_name  subject name to set
+ *
+ * \return          0 if subject name was parsed successfully, or
+ *                  a specific error code
+ */
+int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name );
+
+/**
+ * \brief           Set the key for a CSR (public key will be included,
+ *                  private key used to sign the CSR when writing it)
+ *
+ * \param ctx       CSR context to use
+ * \param key       Asymetric key to include
+ */
+void x509write_csr_set_key( x509write_csr *ctx, pk_context *key );
+
+/**
+ * \brief           Set the MD algorithm to use for the signature
+ *                  (e.g. POLARSSL_MD_SHA1)
+ *
+ * \param ctx       CSR context to use
+ * \param md_alg    MD algorithm to use
+ */
+void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg );
+
+/**
+ * \brief           Set the Key Usage Extension flags
+ *                  (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN)
+ *
+ * \param ctx       CSR context to use
+ * \param key_usage key usage flags to set
+ *
+ * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage );
+
+/**
+ * \brief           Set the Netscape Cert Type flags
+ *                  (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL)
+ *
+ * \param ctx           CSR context to use
+ * \param ns_cert_type  Netscape Cert Type flags to set
+ *
+ * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
+                                    unsigned char ns_cert_type );
+
+/**
+ * \brief           Generic function to add to or replace an extension in the CSR
+ *
+ * \param ctx       CSR context to use
+ * \param oid       OID of the extension
+ * \param oid_len   length of the OID
+ * \param val       value of the extension OCTET STRING
+ * \param val_len   length of the value data
+ *
+ * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
+ */
+int x509write_csr_set_extension( x509write_csr *ctx,
+                                 const char *oid, size_t oid_len,
+                                 const unsigned char *val, size_t val_len );
+
+/**
+ * \brief           Free the contents of a CSR context
+ *
+ * \param ctx       CSR context to free
+ */
+void x509write_csr_free( x509write_csr *ctx );
+
+/**
+ * \brief           Write a CSR (Certificate Signing Request) to a
+ *                  DER structure
+ *                  Note: data is written at the end of the buffer! Use the
+ *                        return value to determine where you should start
+ *                        using the buffer
+ *
+ * \param ctx       CSR to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ * \param f_rng     RNG function (for signature, see note)
+ * \param p_rng     RNG parameter
+ *
+ * \return          length of data written if successful, or a specific
+ *                  error code
+ *
+ * \note            f_rng may be NULL if RSA is used for signature and the
+ *                  signature is made offline (otherwise f_rng is desirable
+ *                  for countermeasures against timing attacks).
+ *                  ECDSA signatures always require a non-NULL f_rng.
+ */
+int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng );
+
+#if defined(POLARSSL_PEM_WRITE_C)
+/**
+ * \brief           Write a CSR (Certificate Signing Request) to a
+ *                  PEM string
+ *
+ * \param ctx       CSR to write away
+ * \param buf       buffer to write to
+ * \param size      size of the buffer
+ * \param f_rng     RNG function (for signature, see note)
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 successful, or a specific error code
+ *
+ * \note            f_rng may be NULL if RSA is used for signature and the
+ *                  signature is made offline (otherwise f_rng is desirable
+ *                  for couermeasures against timing attacks).
+ *                  ECDSA signatures always require a non-NULL f_rng.
+ */
+int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng );
+#endif /* POLARSSL_PEM_WRITE_C */
+#endif /* POLARSSL_X509_CSR_WRITE_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509_csr.h */
diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h
deleted file mode 100644
index 552d453..0000000
--- a/include/polarssl/x509write.h
+++ /dev/null
@@ -1,516 +0,0 @@
-/**
- * \file x509write.h
- *
- * \brief X509 buffer writing functionality
- *
- *  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 POLARSSL_X509_WRITE_H
-#define POLARSSL_X509_WRITE_H
-
-#include "config.h"
-
-#include "x509.h"
-
-/**
- * \addtogroup x509_module
- * \{
- */
-
-/**
- * \name X509 Write Error codes
- * \{
- */
-#define POLARSSL_ERR_X509WRITE_UNKNOWN_OID                -0x5F80  /**< Requested OID is unknown. */
-#define POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA             -0x5F00  /**< Failed to allocate memory. */
-#define POLARSSL_ERR_X509WRITE_MALLOC_FAILED              -0x5E80  /**< Failed to allocate memory. */
-/* \} name */
-/* \} addtogroup x509_module */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \addtogroup x509_module
- * \{
- */
-
-/**
- * \name Structures for writing X.509 CSRs (Certificate Signing Request) 
- * \{
- */
-
-/**
- * Container for a CSR
- */
-typedef struct _x509write_csr
-{
-    pk_context *key;
-    asn1_named_data *subject;
-    md_type_t md_alg;
-    asn1_named_data *extensions;
-}
-x509write_csr;
-
-#define X509_CRT_VERSION_1              0
-#define X509_CRT_VERSION_2              1
-#define X509_CRT_VERSION_3              2
-
-#define X509_RFC5280_MAX_SERIAL_LEN 32
-#define X509_RFC5280_UTC_TIME_LEN   15
-
-/**
- * Container for writing a certificate (CRT)
- */
-typedef struct _x509write_cert
-{
-    int version;
-    mpi serial;
-    pk_context *subject_key;
-    pk_context *issuer_key;
-    asn1_named_data *subject;
-    asn1_named_data *issuer;
-    md_type_t md_alg;
-    char not_before[X509_RFC5280_UTC_TIME_LEN + 1];
-    char not_after[X509_RFC5280_UTC_TIME_LEN + 1];
-    asn1_named_data *extensions;
-}
-x509write_cert;
-
-/* \} name */
-/* \} addtogroup x509_module */
-
-/**
- * \brief           Initialize a CSR context
- *
- * \param ctx       CSR context to initialize
- */
-void x509write_csr_init( x509write_csr *ctx );
-
-/**
- * \brief           Set the subject name for a CSR
- *                  Subject names should contain a comma-separated list
- *                  of OID types and values:
- *                  e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1"
- *
- * \param ctx           CSR context to use
- * \param subject_name  subject name to set
- *
- * \return          0 if subject name was parsed successfully, or
- *                  a specific error code
- */
-int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name );
-
-/**
- * \brief           Set the key for a CSR (public key will be included,
- *                  private key used to sign the CSR when writing it)
- *
- * \param ctx       CSR context to use
- * \param key       Asymetric key to include
- */
-void x509write_csr_set_key( x509write_csr *ctx, pk_context *key );
-
-/**
- * \brief           Set the MD algorithm to use for the signature
- *                  (e.g. POLARSSL_MD_SHA1)
- *
- * \param ctx       CSR context to use
- * \param md_alg    MD algorithm to use
- */
-void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg );
-
-/**
- * \brief           Set the Key Usage Extension flags
- *                  (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN)
- *
- * \param ctx       CSR context to use
- * \param key_usage key usage flags to set
- *
- * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage );
-
-/**
- * \brief           Set the Netscape Cert Type flags
- *                  (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL)
- *
- * \param ctx           CSR context to use
- * \param ns_cert_type  Netscape Cert Type flags to set
- *
- * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
-                                    unsigned char ns_cert_type );
-
-/**
- * \brief           Generic function to add to or replace an extension in the CSR
- *
- * \param ctx       CSR context to use
- * \param oid       OID of the extension
- * \param oid_len   length of the OID
- * \param val       value of the extension OCTET STRING
- * \param val_len   length of the value data
- *
- * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_csr_set_extension( x509write_csr *ctx,
-                                 const char *oid, size_t oid_len,
-                                 const unsigned char *val, size_t val_len );
-
-/**
- * \brief           Free the contents of a CSR context
- *
- * \param ctx       CSR context to free
- */
-void x509write_csr_free( x509write_csr *ctx );
-
-/**
- * \brief           Initialize a CRT writing context
- *
- * \param ctx       CRT context to initialize
- */
-void x509write_crt_init( x509write_cert *ctx );
-
-/**
- * \brief           Set the verion for a Certificate
- *                  Default: X509_CRT_VERSION_3
- *
- * \param ctx       CRT context to use
- * \param version   version to set (X509_CRT_VERSION_1, X509_CRT_VERSION_2 or
- *                                  X509_CRT_VERSION_3)
- */
-void x509write_crt_set_version( x509write_cert *ctx, int version );
-
-/**
- * \brief           Set the serial number for a Certificate.
- *
- * \param ctx       CRT context to use
- * \param serial    serial number to set
- *
- * \return          0 if successful
- */
-int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial );
-
-/**
- * \brief           Set the validity period for a Certificate
- *                  Timestamps should be in string format for UTC timezone
- *                  i.e. "YYYYMMDDhhmmss"
- *                  e.g. "20131231235959" for December 31st 2013
- *                       at 23:59:59
- *
- * \param ctx       CRT context to use
- * \param not_before    not_before timestamp
- * \param not_after     not_after timestamp
- *
- * \return          0 if timestamp was parsed successfully, or
- *                  a specific error code
- */
-int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
-                                char *not_after );
-
-/**
- * \brief           Set the issuer name for a Certificate
- *                  Issuer names should contain a comma-separated list
- *                  of OID types and values:
- *                  e.g. "C=NL,O=Offspark,CN=PolarSSL CA"
- *
- * \param ctx           CRT context to use
- * \param issuer_name   issuer name to set
- *
- * \return          0 if issuer name was parsed successfully, or
- *                  a specific error code
- */
-int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name );
-
-/**
- * \brief           Set the subject name for a Certificate
- *                  Subject names should contain a comma-separated list
- *                  of OID types and values:
- *                  e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1"
- *
- * \param ctx           CRT context to use
- * \param subject_name  subject name to set
- *
- * \return          0 if subject name was parsed successfully, or
- *                  a specific error code
- */
-int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name );
-
-/**
- * \brief           Set the subject public key for the certificate
- *
- * \param ctx       CRT context to use
- * \param key       public key to include
- */
-void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key );
-
-/**
- * \brief           Set the issuer key used for signing the certificate
- *
- * \param ctx       CRT context to use
- * \param key       private key to sign with
- */
-void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key );
-
-/**
- * \brief           Set the MD algorithm to use for the signature
- *                  (e.g. POLARSSL_MD_SHA1)
- *
- * \param ctx       CRT context to use
- * \param md_ald    MD algorithm to use
- */
-void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg );
-
-/**
- * \brief           Generic function to add to or replace an extension in the
- *                  CRT
- *
- * \param ctx       CRT context to use
- * \param oid       OID of the extension
- * \param oid_len   length of the OID
- * \param critical  if the extension is critical (per the RFC's definition)
- * \param val       value of the extension OCTET STRING
- * \param val_len   length of the value data
- *
- * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_crt_set_extension( x509write_cert *ctx,
-                                 const char *oid, size_t oid_len,
-                                 int critical,
-                                 const unsigned char *val, size_t val_len );
-
-/**
- * \brief           Set the basicConstraints extension for a CRT
- *
- * \param ctx       CRT context to use
- * \param is_ca     is this a CA certificate
- * \param max_pathlen   maximum length of certificate chains below this
- *                      certificate (only for CA certificates, -1 is
- *                      inlimited)
- *
- * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_crt_set_basic_constraints( x509write_cert *ctx,
-                                         int is_ca, int max_pathlen );
-
-/**
- * \brief           Set the subjectKeyIdentifier extension for a CRT
- *                  Requires that x509write_crt_set_subject_key() has been
- *                  called before
- *
- * \param ctx       CRT context to use
- *
- * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_crt_set_subject_key_identifier( x509write_cert *ctx );
-
-/**
- * \brief           Set the authorityKeyIdentifier extension for a CRT
- *                  Requires that x509write_crt_set_issuer_key() has been
- *                  called before
- *
- * \param ctx       CRT context to use
- *
- * \return          0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_crt_set_authority_key_identifier( x509write_cert *ctx );
-
-/**
- * \brief           Set the Key Usage Extension flags
- *                  (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN)
- *
- * \param ctx       CRT context to use
- * \param key_usage key usage flags to set
- *
- * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage );
-
-/**
- * \brief           Set the Netscape Cert Type flags
- *                  (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL)
- *
- * \param ctx           CRT context to use
- * \param ns_cert_type  Netscape Cert Type flags to set
- *
- * \return          0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
- */
-int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
-                                    unsigned char ns_cert_type );
-
-/**
- * \brief           Free the contents of a CRT write context
- *
- * \param ctx       CRT context to free
- */
-void x509write_crt_free( x509write_cert *ctx );
-
-/**
- * \brief           Write a built up certificate to a X509 DER structure
- *                  Note: data is written at the end of the buffer! Use the
- *                        return value to determine where you should start
- *                        using the buffer
- *
- * \param crt       certificate to write away
- * \param buf       buffer to write to
- * \param size      size of the buffer
- * \param f_rng     RNG function (for signature, see note)
- * \param p_rng     RNG parameter
- *
- * \return          length of data written if successful, or a specific
- *                  error code
- *
- * \note            f_rng may be NULL if RSA is used for signature and the
- *                  signature is made offline (otherwise f_rng is desirable
- *                  for countermeasures against timing attacks).
- *                  ECDSA signatures always require a non-NULL f_rng.
- */
-int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng );
-
-/**
- * \brief           Write a public key to a DER structure
- *                  Note: data is written at the end of the buffer! Use the
- *                        return value to determine where you should start
- *                        using the buffer
- *
- * \param key       public key to write away
- * \param buf       buffer to write to
- * \param size      size of the buffer
- *
- * \return          length of data written if successful, or a specific
- *                  error code
- */
-int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size );
-
-/**
- * \brief           Write a private key to a PKCS#1 or SEC1 DER structure
- *                  Note: data is written at the end of the buffer! Use the
- *                        return value to determine where you should start
- *                        using the buffer
- *
- * \param key       private to write away
- * \param buf       buffer to write to
- * \param size      size of the buffer
- *
- * \return          length of data written if successful, or a specific
- *                  error code
- */
-int x509write_key_der( pk_context *pk, unsigned char *buf, size_t size );
-
-/**
- * \brief           Write a CSR (Certificate Signing Request) to a
- *                  DER structure
- *                  Note: data is written at the end of the buffer! Use the
- *                        return value to determine where you should start
- *                        using the buffer
- *
- * \param ctx       CSR to write away
- * \param buf       buffer to write to
- * \param size      size of the buffer
- * \param f_rng     RNG function (for signature, see note)
- * \param p_rng     RNG parameter
- *
- * \return          length of data written if successful, or a specific
- *                  error code
- *
- * \note            f_rng may be NULL if RSA is used for signature and the
- *                  signature is made offline (otherwise f_rng is desirable
- *                  for countermeasures against timing attacks).
- *                  ECDSA signatures always require a non-NULL f_rng.
- */
-int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng );
-
-#if defined(POLARSSL_BASE64_C)
-/**
- * \brief           Write a built up certificate to a X509 PEM string
- *
- * \param crt       certificate to write away
- * \param buf       buffer to write to
- * \param size      size of the buffer
- * \param f_rng     RNG function (for signature, see note)
- * \param p_rng     RNG parameter
- *
- * \return          0 successful, or a specific error code
- *
- * \note            f_rng may be NULL if RSA is used for signature and the
- *                  signature is made offline (otherwise f_rng is desirable
- *                  for countermeasures against timing attacks).
- *                  ECDSA signatures always require a non-NULL f_rng.
- */
-int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng );
-
-/**
- * \brief           Write a public key to a PEM string
- *
- * \param key       public key to write away
- * \param buf       buffer to write to
- * \param size      size of the buffer
- *
- * \return          0 successful, or a specific error code
- */
-int x509write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size );
-
-/**
- * \brief           Write a private key to a PKCS#1 or SEC1 PEM string
- *
- * \param key       private to write away
- * \param buf       buffer to write to
- * \param size      size of the buffer
- *
- * \return          0 successful, or a specific error code
- */
-int x509write_key_pem( pk_context *key, unsigned char *buf, size_t size );
-
-/**
- * \brief           Write a CSR (Certificate Signing Request) to a
- *                  PEM string
- *
- * \param ctx       CSR to write away
- * \param buf       buffer to write to
- * \param size      size of the buffer
- * \param f_rng     RNG function (for signature, see note)
- * \param p_rng     RNG parameter
- *
- * \return          0 successful, or a specific error code
- *
- * \note            f_rng may be NULL if RSA is used for signature and the
- *                  signature is made offline (otherwise f_rng is desirable
- *                  for couermeasures against timing attacks).
- *                  ECDSA signatures always require a non-NULL f_rng.
- */
-int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng );
-#endif /* POLARSSL_BASE64_C */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* POLARSSL_X509_WRITE_H */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 9eea7dc..0550189 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -41,19 +41,26 @@
      pkcs12.c
      pk.c
      pk_wrap.c
+     pkparse.c
+     pkwrite.c
      rsa.c
      sha1.c
      sha256.c
      sha512.c
      ssl_cache.c
      ssl_ciphersuites.c
-     ssl_cli.c 
-     ssl_srv.c 
+     ssl_cli.c
+     ssl_srv.c
      ssl_tls.c
      timing.c
      version.c
-     x509parse.c
-     x509write.c
+     x509.c
+     x509_crt.c
+     x509_crl.c
+     x509_csr.c
+     x509_create.c
+     x509write_crt.c
+     x509write_csr.c
      xtea.c
 )
 
diff --git a/library/Makefile b/library/Makefile
index 044e2b7..003b933 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -49,12 +49,16 @@
 		oid.o									\
 		padlock.o	pbkdf2.o	pem.o			\
 		pkcs5.o		pkcs11.o	pkcs12.o		\
-		pk.o		pk_wrap.o					\
+		pk.o		pk_wrap.o	pkparse.o		\
+		pkwrite.o								\
 		rsa.o		sha1.o		sha256.o		\
 		sha512.o	ssl_cache.o	ssl_cli.o		\
 		ssl_srv.o   ssl_ciphersuites.o			\
 		ssl_tls.o	timing.o	version.o		\
-		x509parse.o	x509write.o	xtea.o
+		x509.o		x509_create.o				\
+		x509_crl.o	x509_crt.o	x509_csr.o		\
+		x509write_crt.o			x509write_csr.o	\
+		xtea.o
 
 .SILENT:
 
diff --git a/library/debug.c b/library/debug.c
index 5522fb6..d640bff 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -224,7 +224,7 @@
 }
 #endif /* POLARSSL_BIGNUM_C */
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 static void debug_print_pk( const ssl_context *ssl, int level,
                             const char *file, int line,
                             const char *text, const pk_context *pk )
@@ -260,7 +260,7 @@
 
 void debug_print_crt( const ssl_context *ssl, int level,
                       const char *file, int line,
-                      const char *text, const x509_cert *crt )
+                      const char *text, const x509_crt *crt )
 {
     char str[1024], prefix[64];
     int i = 0, maxlen = sizeof( prefix ) - 1;
@@ -275,7 +275,7 @@
     while( crt != NULL )
     {
         char buf[1024];
-        x509parse_cert_info( buf, sizeof( buf ) - 1, prefix, crt );
+        x509_crt_info( buf, sizeof( buf ) - 1, prefix, crt );
 
         snprintf( str, maxlen, "%s(%04d): %s #%d:\n%s",
                   file, line, text, ++i, buf );
@@ -288,6 +288,6 @@
         crt = crt->next;
     }
 }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 #endif
diff --git a/library/dhm.c b/library/dhm.c
index f43b047..625837e 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -34,6 +34,22 @@
 
 #include "polarssl/dhm.h"
 
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+#include "polarssl/asn1.h"
+#endif
+
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
 /*
  * helper to validate the mpi size and import it
  */
@@ -372,14 +388,183 @@
     memset( ctx, 0, sizeof( dhm_context ) );
 }
 
+#if defined(POLARSSL_ASN1_PARSE_C)
+/*
+ * Parse DHM parameters
+ */
+int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_context pem;
+
+    pem_init( &pem );
+    memset( dhm, 0, sizeof( dhm_context ) );
+
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN DH PARAMETERS-----",
+                           "-----END DH PARAMETERS-----",
+                           dhmin, NULL, 0, &dhminlen );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded
+         */
+        dhminlen = pem.buflen;
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        goto exit;
+
+    p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
+#else
+    p = (unsigned char *) dhmin;
+#endif
+    end = p + dhminlen;
+
+    /*
+     *  DHParams ::= SEQUENCE {
+     *      prime            INTEGER,  -- P
+     *      generator        INTEGER,  -- g
+     *  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret;
+        goto exit;
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_mpi( &p, end, &dhm->P  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret;
+        goto exit;
+    }
+
+    if( p != end )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT +
+              POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+        goto exit;
+    }
+
+    ret = 0;
+
+exit:
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_free( &pem );
+#endif
+    if( ret != 0 )
+        dhm_free( dhm );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ */
+static int load_file( const char *path, unsigned char **buf, size_t *n )
+{
+    FILE *f;
+    long size;
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    if( ( size = ftell( f ) ) == -1 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+    }
+    fseek( f, 0, SEEK_SET );
+
+    *n = (size_t) size;
+
+    if( *n + 1 == 0 ||
+        ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_DHM_MALLOC_FAILED );
+    }
+
+    if( fread( *buf, 1, *n, f ) != *n )
+    {
+        fclose( f );
+        polarssl_free( *buf );
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    (*buf)[*n] = '\0';
+
+    return( 0 );
+}
+
+/*
+ * Load and parse DHM parameters
+ */
+int dhm_parse_dhmfile( dhm_context *dhm, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = dhm_parse_dhm( dhm, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_ASN1_PARSE_C */
+
 #if defined(POLARSSL_SELF_TEST)
 
+#include "polarssl/certs.h"
+
 /*
  * Checkup routine
  */
 int dhm_self_test( int verbose )
 {
-    return( verbose++ );
+#if defined(POLARSSL_CERTS_C)
+    int ret;
+    dhm_context dhm;
+
+    if( verbose != 0 )
+        printf( "  DHM parameter load: " );
+
+    if( ( ret = dhm_parse_dhm( &dhm, (const unsigned char *) test_dhm_params,
+                               strlen( test_dhm_params ) ) ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( ret );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n\n" );
+
+    dhm_free( &dhm );
+
+    return( 0 );
+#else
+    ((void) verbose);
+    return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+#endif
 }
 
 #endif
diff --git a/library/error.c b/library/error.c
index 86586dd..4323e72 100644
--- a/library/error.c
+++ b/library/error.c
@@ -109,7 +109,7 @@
 #include "polarssl/pbkdf2.h"
 #endif
 
-#if defined(POLARSSL_PEM_C)
+#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
 #include "polarssl/pem.h"
 #endif
 
@@ -145,14 +145,10 @@
 #include "polarssl/ssl.h"
 #endif
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
 #include "polarssl/x509.h"
 #endif
 
-#if defined(POLARSSL_X509_WRITE_C)
-#include "polarssl/x509write.h"
-#endif
-
 #if defined(POLARSSL_XTEA_C)
 #include "polarssl/xtea.h"
 #endif
@@ -206,6 +202,12 @@
             snprintf( buf, buflen, "DHM - Making of the public value failed" );
         if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) )
             snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_INVALID_FORMAT) )
+            snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MALLOC_FAILED) )
+            snprintf( buf, buflen, "DHM - Allocation of memory failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_FILE_IO_ERROR) )
+            snprintf( buf, buflen, "DHM - Read/write of file failed" );
 #endif /* POLARSSL_DHM_C */
 
 #if defined(POLARSSL_ECP_C)
@@ -214,9 +216,11 @@
         if( use_ret == -(POLARSSL_ERR_ECP_BUFFER_TOO_SMALL) )
             snprintf( buf, buflen, "ECP - The buffer is too small to write to" );
         if( use_ret == -(POLARSSL_ERR_ECP_GENERIC) )
-            snprintf( buf, buflen, "ECP -  Generic ECP error" );
+            snprintf( buf, buflen, "ECP - Generic ECP error" );
         if( use_ret == -(POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE) )
             snprintf( buf, buflen, "ECP - Requested curve not available" );
+        if( use_ret == -(POLARSSL_ERR_ECP_VERIFY_FAILED) )
+            snprintf( buf, buflen, "ECP - The signature is not valid" );
 #endif /* POLARSSL_ECP_C */
 
 #if defined(POLARSSL_MD_C)
@@ -230,7 +234,7 @@
             snprintf( buf, buflen, "MD - Opening or reading of file failed" );
 #endif /* POLARSSL_MD_C */
 
-#if defined(POLARSSL_PEM_C)
+#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
         if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT) )
             snprintf( buf, buflen, "PEM - No PEM header or footer found" );
         if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) )
@@ -249,7 +253,7 @@
             snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" );
         if( use_ret == -(POLARSSL_ERR_PEM_BAD_INPUT_DATA) )
             snprintf( buf, buflen, "PEM - Bad input parameters to function" );
-#endif /* POLARSSL_PEM_C */
+#endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */
 
 #if defined(POLARSSL_PK_C)
         if( use_ret == -(POLARSSL_ERR_PK_MALLOC_FAILED) )
@@ -258,6 +262,26 @@
             snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" );
         if( use_ret == -(POLARSSL_ERR_PK_BAD_INPUT_DATA) )
             snprintf( buf, buflen, "PK - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_PK_FILE_IO_ERROR) )
+            snprintf( buf, buflen, "PK - Read/write of file failed" );
+        if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_VERSION) )
+            snprintf( buf, buflen, "PK - Unsupported key version" );
+        if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_FORMAT) )
+            snprintf( buf, buflen, "PK - Invalid key tag or value" );
+        if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_PK_ALG) )
+            snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" );
+        if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_REQUIRED) )
+            snprintf( buf, buflen, "PK - Private key password can't be empty" );
+        if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_MISMATCH) )
+            snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" );
+        if( use_ret == -(POLARSSL_ERR_PK_INVALID_PUBKEY) )
+            snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" );
+        if( use_ret == -(POLARSSL_ERR_PK_INVALID_ALG) )
+            snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE) )
+            snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" );
+        if( use_ret == -(POLARSSL_ERR_PK_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" );
 #endif /* POLARSSL_PK_C */
 
 #if defined(POLARSSL_PKCS12_C)
@@ -383,67 +407,44 @@
             snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" );
 #endif /* POLARSSL_SSL_TLS_C */
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
         if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) )
             snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PEM) )
-            snprintf( buf, buflen, "X509 - The PEM-encoded certificate contains invalid elements, e.g. invalid character" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_FORMAT) )
-            snprintf( buf, buflen, "X509 - The certificate format is invalid, e.g. different type expected" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_VERSION) )
-            snprintf( buf, buflen, "X509 - The certificate version element is invalid" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SERIAL) )
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_OID) )
+            snprintf( buf, buflen, "X509 - Requested OID is unknown" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_FORMAT) )
+            snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_VERSION) )
+            snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_SERIAL) )
             snprintf( buf, buflen, "X509 - The serial tag or value is invalid" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_ALG) )
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_ALG) )
             snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_NAME) )
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_NAME) )
             snprintf( buf, buflen, "X509 - The name tag or value is invalid" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_DATE) )
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_DATE) )
             snprintf( buf, buflen, "X509 - The date tag or value is invalid" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PUBKEY) )
-            snprintf( buf, buflen, "X509 - The pubkey tag or value is invalid (only RSA is supported)" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE) )
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_SIGNATURE) )
             snprintf( buf, buflen, "X509 - The signature tag or value invalid" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS) )
+        if( use_ret == -(POLARSSL_ERR_X509_INVALID_EXTENSIONS) )
             snprintf( buf, buflen, "X509 - The extension tag or value is invalid" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION) )
-            snprintf( buf, buflen, "X509 - Certificate or CRL has an unsupported version number" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG) )
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_VERSION) )
+            snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" );
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_SIG_ALG) )
             snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" );
-        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_PK_ALG) )
-            snprintf( buf, buflen, "X509 - Key algorithm is unsupported (only RSA and EC are supported)" );
-        if( use_ret == -(POLARSSL_ERR_X509_CERT_SIG_MISMATCH) )
-            snprintf( buf, buflen, "X509 - Certificate signature algorithms do not match. (see \\c ::x509_cert sig_oid)" );
+        if( use_ret == -(POLARSSL_ERR_X509_SIG_MISMATCH) )
+            snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::x509_cert sig_oid)" );
         if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) )
             snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" );
-        if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_VERSION) )
-            snprintf( buf, buflen, "X509 - Unsupported RSA key version" );
-        if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_FORMAT) )
-            snprintf( buf, buflen, "X509 - Invalid RSA key tag or value" );
         if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) )
             snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" );
-        if( use_ret == -(POLARSSL_ERR_X509_INVALID_INPUT) )
+        if( use_ret == -(POLARSSL_ERR_X509_BAD_INPUT_DATA) )
             snprintf( buf, buflen, "X509 - Input invalid" );
         if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) )
             snprintf( buf, buflen, "X509 - Allocation of memory failed" );
         if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) )
             snprintf( buf, buflen, "X509 - Read/write of file failed" );
-        if( use_ret == -(POLARSSL_ERR_X509_PASSWORD_REQUIRED) )
-            snprintf( buf, buflen, "X509 - Private key password can't be empty" );
-        if( use_ret == -(POLARSSL_ERR_X509_PASSWORD_MISMATCH) )
-            snprintf( buf, buflen, "X509 - Given private key password does not allow for correct decryption" );
-        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE) )
-            snprintf( buf, buflen, "X509 - Elliptic curve is unsupported (only NIST curves are supported)" );
-#endif /* POLARSSL_X509_PARSE_C */
-
-#if defined(POLARSSL_X509_WRITE_C)
-        if( use_ret == -(POLARSSL_ERR_X509WRITE_UNKNOWN_OID) )
-            snprintf( buf, buflen, "X509WRITE - Requested OID is unknown" );
-        if( use_ret == -(POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA) )
-            snprintf( buf, buflen, "X509WRITE - Failed to allocate memory" );
-        if( use_ret == -(POLARSSL_ERR_X509WRITE_MALLOC_FAILED) )
-            snprintf( buf, buflen, "X509WRITE - Failed to allocate memory" );
-#endif /* POLARSSL_X509_WRITE_C */
+#endif /* POLARSSL_X509_USE,X509_CREATE_C */
 
         if( strlen( buf ) == 0 )
             snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
diff --git a/library/oid.c b/library/oid.c
index 81b313e..485fd4c 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -32,6 +32,10 @@
 #include "polarssl/oid.h"
 #include "polarssl/rsa.h"
 
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
+#include "polarssl/x509.h"
+#endif
+
 #include <stdio.h>
 
 /*
@@ -203,7 +207,7 @@
 FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type);
 FN_OID_GET_ATTR1(oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name);
 
-#if defined(POLARSSL_X509_PARSE_C) || defined(POLARSSL_X509_WRITE_C)
+#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
 /*
  * For X509 extensions
  */
@@ -256,7 +260,7 @@
 
 FN_OID_TYPED_FROM_ASN1(oid_descriptor_t, ext_key_usage, oid_ext_key_usage);
 FN_OID_GET_ATTR1(oid_get_extended_key_usage, oid_descriptor_t, ext_key_usage, const char *, description);
-#endif /* POLARSSL_X509_PARSE_C || POLARSSL_X509_WRITE_C */
+#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */
 
 #if defined(POLARSSL_MD_C)
 /*
diff --git a/library/pem.c b/library/pem.c
index 8a6de3a..d602d8a 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -25,8 +25,7 @@
 
 #include "polarssl/config.h"
 
-#if defined(POLARSSL_PEM_C)
-
+#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
 #include "polarssl/pem.h"
 #include "polarssl/base64.h"
 #include "polarssl/des.h"
@@ -43,6 +42,7 @@
 
 #include <stdlib.h>
 
+#if defined(POLARSSL_PEM_PARSE_C)
 void pem_init( pem_context *ctx )
 {
     memset( ctx, 0, sizeof( pem_context ) );
@@ -285,7 +285,7 @@
             s1 += 32;
         }
 #endif /* POLARSSL_AES_C */
-        
+
         if( enc_alg == POLARSSL_CIPHER_NONE )
             return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
 
@@ -312,7 +312,7 @@
         polarssl_free( buf );
         return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
     }
-    
+
     if( enc != 0 )
     {
 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
@@ -373,5 +373,57 @@
 
     memset( ctx, 0, sizeof( pem_context ) );
 }
+#endif /* POLARSSL_PEM_PARSE_C */
 
-#endif
+#if defined(POLARSSL_PEM_WRITE_C)
+int pem_write_buffer( const char *header, const char *footer,
+                      const unsigned char *der_data, size_t der_len,
+                      unsigned char *buf, size_t buf_len, size_t *olen )
+{
+    int ret;
+    unsigned char *encode_buf, *c, *p = buf;
+    size_t len = 0, use_len = 0;
+    size_t add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
+
+    base64_encode( NULL, &use_len, der_data, der_len );
+    if( use_len + add_len > buf_len )
+    {
+        *olen = use_len + add_len;
+        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+    if( ( encode_buf = polarssl_malloc( use_len ) ) == NULL )
+        return( POLARSSL_ERR_PEM_MALLOC_FAILED );
+
+    if( ( ret = base64_encode( encode_buf, &use_len, der_data,
+                               der_len ) ) != 0 )
+    {
+        polarssl_free( encode_buf );
+        return( ret );
+    }
+
+    memcpy( p, header, strlen( header ) );
+    p += strlen( header );
+    c = encode_buf;
+
+    while( use_len )
+    {
+        len = ( use_len > 64 ) ? 64 : use_len;
+        memcpy( p, c, len );
+        use_len -= len;
+        p += len;
+        c += len;
+        *p++ = '\n';
+    }
+
+    memcpy( p, footer, strlen( footer ) );
+    p += strlen( footer );
+
+    *p++ = '\0';
+    *olen = p - buf;
+
+    polarssl_free( encode_buf );
+    return( 0 );
+}
+#endif /* POLARSSL_PEM_WRITE_C */
+#endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */
diff --git a/library/pkcs11.c b/library/pkcs11.c
index 5343659..9f68d78 100644
--- a/library/pkcs11.c
+++ b/library/pkcs11.c
@@ -40,7 +40,7 @@
 
 #include <stdlib.h>
 
-int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11_cert )
+int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11_cert )
 {
     int ret = 1;
     unsigned char *cert_blob = NULL;
@@ -71,7 +71,7 @@
         goto cleanup;
     }
 
-    if( 0 != x509parse_crt(cert, cert_blob, cert_blob_size ) )
+    if( 0 != x509_crt_parse(cert, cert_blob, cert_blob_size ) )
     {
         ret = 6;
         goto cleanup;
@@ -91,9 +91,9 @@
         pkcs11h_certificate_t pkcs11_cert )
 {
     int ret = 1;
-    x509_cert cert;
+    x509_crt cert;
 
-    memset( &cert, 0, sizeof( cert ) );
+    x509_crt_init( &cert );
 
     if( priv_key == NULL )
         goto cleanup;
@@ -107,7 +107,7 @@
     ret = 0;
 
 cleanup:
-    x509_free( &cert );
+    x509_crt_free( &cert );
 
     return ret;
 }
diff --git a/library/pkparse.c b/library/pkparse.c
new file mode 100644
index 0000000..f123b6c
--- /dev/null
+++ b/library/pkparse.c
@@ -0,0 +1,957 @@
+/*
+ *  Public Key layer for parsing key files and structures
+ *
+ *  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.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PK_PARSE_C)
+
+#include "polarssl/pk.h"
+#include "polarssl/asn1.h"
+#include "polarssl/oid.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+#if defined(POLARSSL_ECDSA_C)
+#include "polarssl/ecdsa.h"
+#endif
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+#if defined(POLARSSL_PKCS5_C)
+#include "polarssl/pkcs5.h"
+#endif
+#if defined(POLARSSL_PKCS12_C)
+#include "polarssl/pkcs12.h"
+#endif
+
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ */
+static int load_file( const char *path, unsigned char **buf, size_t *n )
+{
+    FILE *f;
+    long size;
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_PK_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    if( ( size = ftell( f ) ) == -1 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_PK_FILE_IO_ERROR );
+    }
+    fseek( f, 0, SEEK_SET );
+
+    *n = (size_t) size;
+
+    if( *n + 1 == 0 ||
+        ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_PK_MALLOC_FAILED );
+    }
+
+    if( fread( *buf, 1, *n, f ) != *n )
+    {
+        fclose( f );
+        polarssl_free( *buf );
+        return( POLARSSL_ERR_PK_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    (*buf)[*n] = '\0';
+
+    return( 0 );
+}
+
+/*
+ * Load and parse a private key
+ */
+int pk_parse_keyfile( pk_context *ctx,
+                      const char *path, const char *pwd )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    if( pwd == NULL )
+        ret = pk_parse_key( ctx, buf, n, NULL, 0 );
+    else
+        ret = pk_parse_key( ctx, buf, n,
+                (const unsigned char *) pwd, strlen( pwd ) );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+
+/*
+ * Load and parse a public key
+ */
+int pk_parse_public_keyfile( pk_context *ctx, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = pk_parse_public_key( ctx, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(POLARSSL_ECP_C)
+/* Get an EC group id from an ECParameters buffer
+ *
+ * ECParameters ::= CHOICE {
+ *   namedCurve         OBJECT IDENTIFIER
+ *   -- implicitCurve   NULL
+ *   -- specifiedCurve  SpecifiedECDomain
+ * }
+ */
+static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
+                            asn1_buf *params )
+{
+    int ret;
+
+    params->tag = **p;
+
+    if( ( ret = asn1_get_tag( p, end, &params->len, ASN1_OID ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    params->p = *p;
+    *p += params->len;
+
+    if( *p != end )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * Use EC parameters to initialise an EC group
+ */
+static int pk_use_ecparams( const asn1_buf *params, ecp_group *grp )
+{
+    int ret;
+    ecp_group_id grp_id;
+
+    if( oid_get_ec_grp( params, &grp_id ) != 0 )
+        return( POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE );
+
+    /*
+     * grp may already be initilialized; if so, make sure IDs match
+     */
+    if( grp->id != POLARSSL_ECP_DP_NONE && grp->id != grp_id )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+
+    if( ( ret = ecp_use_known_dp( grp, grp_id ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+/*
+ * EC public key is an EC point
+ */
+static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
+                            ecp_keypair *key )
+{
+    int ret;
+
+    if( ( ret = ecp_point_read_binary( &key->grp, &key->Q,
+                    (const unsigned char *) *p, end - *p ) ) != 0 ||
+        ( ret = ecp_check_pubkey( &key->grp, &key->Q ) ) != 0 )
+    {
+        ecp_keypair_free( key );
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY );
+    }
+
+    /*
+     * We know ecp_point_read_binary consumed all bytes
+     */
+    *p = (unsigned char *) end;
+
+    return( 0 );
+}
+#endif /* POLARSSL_ECP_C */
+
+#if defined(POLARSSL_RSA_C)
+/*
+ *  RSAPublicKey ::= SEQUENCE {
+ *      modulus           INTEGER,  -- n
+ *      publicExponent    INTEGER   -- e
+ *  }
+ */
+static int pk_get_rsapubkey( unsigned char **p,
+                             const unsigned char *end,
+                             rsa_context *rsa )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret );
+
+    if( *p + len != end )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    if( ( ret = asn1_get_mpi( p, end, &rsa->N ) ) != 0 ||
+        ( ret = asn1_get_mpi( p, end, &rsa->E ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
+        return( ret );
+
+    rsa->len = mpi_size( &rsa->N );
+
+    return( 0 );
+}
+#endif /* POLARSSL_RSA_C */
+
+/* Get a PK algorithm identifier
+ *
+ *  AlgorithmIdentifier  ::=  SEQUENCE  {
+ *       algorithm               OBJECT IDENTIFIER,
+ *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
+ */
+static int pk_get_pk_alg( unsigned char **p,
+                          const unsigned char *end,
+                          pk_type_t *pk_alg, asn1_buf *params )
+{
+    int ret;
+    asn1_buf alg_oid;
+
+    memset( params, 0, sizeof(asn1_buf) );
+
+    if( ( ret = asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_ALG + ret );
+
+    if( oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    /*
+     * No parameters with RSA (only for EC)
+     */
+    if( *pk_alg == POLARSSL_PK_RSA &&
+            ( ( params->tag != ASN1_NULL && params->tag != 0 ) ||
+                params->len != 0 ) )
+    {
+        return( POLARSSL_ERR_PK_INVALID_ALG );
+    }
+
+    return( 0 );
+}
+
+/*
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
+ *       algorithm            AlgorithmIdentifier,
+ *       subjectPublicKey     BIT STRING }
+ */
+int pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
+                        pk_context *pk )
+{
+    int ret;
+    size_t len;
+    asn1_buf alg_params;
+    pk_type_t pk_alg = POLARSSL_PK_NONE;
+    const pk_info_t *pk_info;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+                    ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = *p + len;
+
+    if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
+        return( ret );
+
+    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret );
+
+    if( *p + len != end )
+        return( POLARSSL_ERR_PK_INVALID_PUBKEY +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 )
+        return( ret );
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_alg == POLARSSL_PK_RSA )
+    {
+        ret = pk_get_rsapubkey( p, end, pk_rsa( *pk ) );
+    } else
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+    if( pk_alg == POLARSSL_PK_ECKEY_DH || pk_alg == POLARSSL_PK_ECKEY )
+    {
+        ret = pk_use_ecparams( &alg_params, &pk_ec( *pk )->grp );
+        if( ret == 0 )
+            ret = pk_get_ecpubkey( p, end, pk_ec( *pk ) );
+    } else
+#endif /* POLARSSL_ECP_C */
+        ret = POLARSSL_ERR_PK_UNKNOWN_PK_ALG;
+
+    if( ret == 0 && *p != end )
+        ret = POLARSSL_ERR_PK_INVALID_PUBKEY
+              POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+    if( ret != 0 )
+        pk_free( pk );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_RSA_C)
+/*
+ * Parse a PKCS#1 encoded private RSA key
+ */
+static int pk_parse_key_pkcs1_der( rsa_context *rsa,
+                                   const unsigned char *key,
+                                   size_t keylen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+
+    p = (unsigned char *) key;
+    end = p + keylen;
+
+    /*
+     * This function parses the RSAPrivateKey (PKCS#1)
+     *
+     *  RSAPrivateKey ::= SEQUENCE {
+     *      version           Version,
+     *      modulus           INTEGER,  -- n
+     *      publicExponent    INTEGER,  -- e
+     *      privateExponent   INTEGER,  -- d
+     *      prime1            INTEGER,  -- p
+     *      prime2            INTEGER,  -- q
+     *      exponent1         INTEGER,  -- d mod (p-1)
+     *      exponent2         INTEGER,  -- d mod (q-1)
+     *      coefficient       INTEGER,  -- (inverse of q) mod p
+     *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
+     *  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    if( rsa->ver != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_VERSION );
+    }
+
+    if( ( ret = asn1_get_mpi( &p, end, &rsa->N  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->E  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->D  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->P  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->Q  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
+    {
+        rsa_free( rsa );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    rsa->len = mpi_size( &rsa->N );
+
+    if( p != end )
+    {
+        rsa_free( rsa );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
+    {
+        rsa_free( rsa );
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+/*
+ * Parse a SEC1 encoded private EC key
+ */
+static int pk_parse_key_sec1_der( ecp_keypair *eck,
+                                  const unsigned char *key,
+                                  size_t keylen )
+{
+    int ret;
+    int version;
+    size_t len;
+    asn1_buf params;
+    unsigned char *p = (unsigned char *) key;
+    unsigned char *end = p + keylen;
+    unsigned char *end2;
+
+    /*
+     * RFC 5915, or SEC1 Appendix C.4
+     *
+     * ECPrivateKey ::= SEQUENCE {
+     *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+     *      privateKey     OCTET STRING,
+     *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+     *      publicKey  [1] BIT STRING OPTIONAL
+     *    }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( version != 1 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_VERSION );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    p += len;
+
+    /*
+     * Is 'parameters' present?
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
+    {
+        if( ( ret = pk_get_ecparams( &p, p + len, &params) ) != 0 ||
+            ( ret = pk_use_ecparams( &params, &eck->grp )  ) != 0 )
+        {
+            ecp_keypair_free( eck );
+            return( ret );
+        }
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    /*
+     * Is 'publickey' present?
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        if( ( ret = asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
+            return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+        if( p + len != end2 )
+            return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+        if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) != 0 )
+            return( ret );
+    }
+    else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
+    {
+        ecp_keypair_free( eck );
+        return( ret );
+    }
+
+    return 0;
+}
+#endif /* POLARSSL_ECP_C */
+
+/*
+ * Parse an unencrypted PKCS#8 encoded private key
+ */
+static int pk_parse_key_pkcs8_unencrypted_der(
+                                    pk_context *pk,
+                                    const unsigned char* key,
+                                    size_t keylen )
+{
+    int ret, version;
+    size_t len;
+    asn1_buf params;
+    unsigned char *p = (unsigned char *) key;
+    unsigned char *end = p + keylen;
+    pk_type_t pk_alg = POLARSSL_PK_NONE;
+    const pk_info_t *pk_info;
+
+    /*
+     * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208)
+     *
+     *    PrivateKeyInfo ::= SEQUENCE {
+     *      version                   Version,
+     *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
+     *      privateKey                PrivateKey,
+     *      attributes           [0]  IMPLICIT Attributes OPTIONAL }
+     *
+     *    Version ::= INTEGER
+     *    PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+     *    PrivateKey ::= OCTET STRING
+     *
+     *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
+     */
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( version != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_VERSION + ret );
+
+    if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( len < 1 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 )
+        return( ret );
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_alg == POLARSSL_PK_RSA )
+    {
+        if( ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), p, len ) ) != 0 )
+        {
+            pk_free( pk );
+            return( ret );
+        }
+    } else
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+    if( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH )
+    {
+        if( ( ret = pk_use_ecparams( &params, &pk_ec( *pk )->grp ) ) != 0 ||
+            ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), p, len )  ) != 0 )
+        {
+            pk_free( pk );
+            return( ret );
+        }
+    } else
+#endif /* POLARSSL_ECP_C */
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    return 0;
+}
+
+/*
+ * Parse an encrypted PKCS#8 encoded private key
+ */
+static int pk_parse_key_pkcs8_encrypted_der(
+                                    pk_context *pk,
+                                    const unsigned char *key, size_t keylen,
+                                    const unsigned char *pwd, size_t pwdlen )
+{
+    int ret;
+    size_t len;
+    unsigned char buf[2048];
+    unsigned char *p, *end;
+    asn1_buf pbe_alg_oid, pbe_params;
+#if defined(POLARSSL_PKCS12_C)
+    cipher_type_t cipher_alg;
+    md_type_t md_alg;
+#endif
+
+    memset( buf, 0, sizeof( buf ) );
+
+    p = (unsigned char *) key;
+    end = p + keylen;
+
+    if( pwdlen == 0 )
+        return( POLARSSL_ERR_PK_PASSWORD_REQUIRED );
+
+    /*
+     * This function parses the EncryptedPrivatKeyInfo object (PKCS#8)
+     *
+     *  EncryptedPrivateKeyInfo ::= SEQUENCE {
+     *    encryptionAlgorithm  EncryptionAlgorithmIdentifier,
+     *    encryptedData        EncryptedData
+     *  }
+     *
+     *  EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+     *
+     *  EncryptedData ::= OCTET STRING
+     *
+     *  The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( len > sizeof( buf ) )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    /*
+     * Decrypt EncryptedData with appropriate PDE
+     */
+#if defined(POLARSSL_PKCS12_C)
+    if( oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
+    {
+        if( ( ret = pkcs12_pbe( &pbe_params, PKCS12_PBE_DECRYPT,
+                                cipher_alg, md_alg,
+                                pwd, pwdlen, p, len, buf ) ) != 0 )
+        {
+            if( ret == POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH )
+                return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+
+            return( ret );
+        }
+    }
+    else if( OID_CMP( OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) )
+    {
+        if( ( ret = pkcs12_pbe_sha1_rc4_128( &pbe_params,
+                                             PKCS12_PBE_DECRYPT,
+                                             pwd, pwdlen,
+                                             p, len, buf ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        // Best guess for password mismatch when using RC4. If first tag is
+        // not ASN1_CONSTRUCTED | ASN1_SEQUENCE
+        //
+        if( *buf != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+            return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+    }
+    else
+#endif /* POLARSSL_PKCS12_C */
+#if defined(POLARSSL_PKCS5_C)
+    if( OID_CMP( OID_PKCS5_PBES2, &pbe_alg_oid ) )
+    {
+        if( ( ret = pkcs5_pbes2( &pbe_params, PKCS5_DECRYPT, pwd, pwdlen,
+                                  p, len, buf ) ) != 0 )
+        {
+            if( ret == POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH )
+                return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+
+            return( ret );
+        }
+    }
+    else
+#endif /* POLARSSL_PKCS5_C */
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
+    return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
+}
+
+/*
+ * Parse a private key
+ */
+int pk_parse_key( pk_context *pk,
+                  const unsigned char *key, size_t keylen,
+                  const unsigned char *pwd, size_t pwdlen )
+{
+    int ret;
+    const pk_info_t *pk_info;
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t len;
+    pem_context pem;
+
+    pem_init( &pem );
+
+#if defined(POLARSSL_RSA_C)
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN RSA PRIVATE KEY-----",
+                           "-----END RSA PRIVATE KEY-----",
+                           key, pwd, pwdlen, &len );
+    if( ret == 0 )
+    {
+        if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL )
+            return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+        if( ( ret = pk_init_ctx( pk, pk_info                    ) ) != 0 ||
+            ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ),
+                                            pem.buf, pem.buflen ) ) != 0 )
+        {
+            pk_free( pk );
+        }
+
+        pem_free( &pem );
+        return( ret );
+    }
+    else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH )
+        return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+    else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED )
+        return( POLARSSL_ERR_PK_PASSWORD_REQUIRED );
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        return( ret );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN EC PRIVATE KEY-----",
+                           "-----END EC PRIVATE KEY-----",
+                           key, pwd, pwdlen, &len );
+    if( ret == 0 )
+    {
+        if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL )
+            return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+        if( ( ret = pk_init_ctx( pk, pk_info                   ) ) != 0 ||
+            ( ret = pk_parse_key_sec1_der( pk_ec( *pk ),
+                                           pem.buf, pem.buflen ) ) != 0 )
+        {
+            pk_free( pk );
+        }
+
+        pem_free( &pem );
+        return( ret );
+    }
+    else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH )
+        return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+    else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED )
+        return( POLARSSL_ERR_PK_PASSWORD_REQUIRED );
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        return( ret );
+#endif /* POLARSSL_ECP_C */
+
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN PRIVATE KEY-----",
+                           "-----END PRIVATE KEY-----",
+                           key, NULL, 0, &len );
+    if( ret == 0 )
+    {
+        if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk,
+                                                pem.buf, pem.buflen ) ) != 0 )
+        {
+            pk_free( pk );
+        }
+
+        pem_free( &pem );
+        return( ret );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        return( ret );
+
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN ENCRYPTED PRIVATE KEY-----",
+                           "-----END ENCRYPTED PRIVATE KEY-----",
+                           key, NULL, 0, &len );
+    if( ret == 0 )
+    {
+        if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk,
+                                                      pem.buf, pem.buflen,
+                                                      pwd, pwdlen ) ) != 0 )
+        {
+            pk_free( pk );
+        }
+
+        pem_free( &pem );
+        return( ret );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        return( ret );
+#else
+    ((void) pwd);
+    ((void) pwdlen);
+#endif /* POLARSSL_PEM_PARSE_C */
+
+    /*
+    * At this point we only know it's not a PEM formatted key. Could be any
+    * of the known DER encoded private key formats
+    *
+    * We try the different DER format parsers to see if one passes without
+    * error
+    */
+    if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen,
+                                                  pwd, pwdlen ) ) == 0 )
+    {
+        return( 0 );
+    }
+
+    pk_free( pk );
+
+    if( ret == POLARSSL_ERR_PK_PASSWORD_MISMATCH )
+    {
+        return( ret );
+    }
+
+    if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
+        return( 0 );
+
+    pk_free( pk );
+
+#if defined(POLARSSL_RSA_C)
+    if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    if( ( ret = pk_init_ctx( pk, pk_info                           ) ) != 0 ||
+        ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 )
+    {
+        return( 0 );
+    }
+
+    pk_free( pk );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+    if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL )
+        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
+
+    if( ( ret = pk_init_ctx( pk, pk_info                         ) ) != 0 ||
+        ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 )
+    {
+        return( 0 );
+    }
+
+    pk_free( pk );
+#endif /* POLARSSL_ECP_C */
+
+    return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+}
+
+/*
+ * Parse a public key
+ */
+int pk_parse_public_key( pk_context *ctx,
+                         const unsigned char *key, size_t keylen )
+{
+    int ret;
+    unsigned char *p;
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t len;
+    pem_context pem;
+
+    pem_init( &pem );
+    ret = pem_read_buffer( &pem,
+            "-----BEGIN PUBLIC KEY-----",
+            "-----END PUBLIC KEY-----",
+            key, NULL, 0, &len );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded
+         */
+        key = pem.buf;
+        keylen = pem.buflen;
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    {
+        pem_free( &pem );
+        return( ret );
+    }
+#endif
+    p = (unsigned char *) key;
+
+    ret = pk_parse_subpubkey( &p, p + keylen, ctx );
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_free( &pem );
+#endif
+
+    return( ret );
+}
+
+#endif /* POLARSSL_PK_PARSE_C */
diff --git a/library/pkwrite.c b/library/pkwrite.c
new file mode 100644
index 0000000..a3e9c57
--- /dev/null
+++ b/library/pkwrite.c
@@ -0,0 +1,350 @@
+/*
+ *  Public Key layer for writing key files and structures
+ *
+ *  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.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PK_WRITE_C)
+
+#include "polarssl/pk.h"
+#include "polarssl/asn1write.h"
+#include "polarssl/oid.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+#if defined(POLARSSL_ECP_C)
+#include "polarssl/ecp.h"
+#endif
+#if defined(POLARSSL_ECDSA_C)
+#include "polarssl/ecdsa.h"
+#endif
+#if defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#if defined(POLARSSL_RSA_C)
+/*
+ *  RSAPublicKey ::= SEQUENCE {
+ *      modulus           INTEGER,  -- n
+ *      publicExponent    INTEGER   -- e
+ *  }
+ */
+static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
+                                  rsa_context *rsa )
+{
+    int ret;
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
+    ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return( len );
+}
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+/*
+ * EC public key is an EC point
+ */
+static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
+                                 ecp_keypair *ec )
+{
+    int ret;
+    size_t len = 0;
+    unsigned char buf[POLARSSL_ECP_MAX_PT_LEN];
+
+    if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q,
+                                        POLARSSL_ECP_PF_UNCOMPRESSED,
+                                        &len, buf, sizeof( buf ) ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( *p - start < (int) len )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    *p -= len;
+    memcpy( *p, buf, len );
+
+    return( len );
+}
+
+/*
+ * ECParameters ::= CHOICE {
+ *   namedCurve         OBJECT IDENTIFIER
+ * }
+ */
+static int pk_write_ec_param( unsigned char **p, unsigned char *start,
+                                ecp_keypair *ec )
+{
+    int ret;
+    size_t len = 0;
+    const char *oid;
+    size_t oid_len;
+
+    if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
+        return( ret );
+
+    ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
+
+    return( len );
+}
+#endif /* POLARSSL_ECP_C */
+
+int pk_write_pubkey( unsigned char **p, unsigned char *start,
+                     const pk_context *key )
+{
+    int ret;
+    size_t len = 0;
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_get_type( key ) == POLARSSL_PK_RSA )
+        ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, pk_rsa( *key ) ) );
+    else
+#endif
+#if defined(POLARSSL_ECP_C)
+    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
+        ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, pk_ec( *key ) ) );
+    else
+#endif
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
+    return( len );
+}
+
+int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char *c;
+    size_t len = 0, par_len = 0, oid_len;
+    const char *oid;
+
+    c = buf + size;
+
+    ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, key ) );
+
+    if( c - buf < 1 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    /*
+     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
+     *       algorithm            AlgorithmIdentifier,
+     *       subjectPublicKey     BIT STRING }
+     */
+    *--c = 0;
+    len += 1;
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
+
+    if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ),
+                                       &oid, &oid_len ) ) != 0 )
+    {
+        return( ret );
+    }
+
+#if defined(POLARSSL_ECP_C)
+    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
+    {
+        ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, pk_ec( *key ) ) );
+    }
+#endif
+
+    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
+                                                        par_len ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return( len );
+}
+
+int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char *c = buf + size;
+    size_t len = 0;
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_get_type( key ) == POLARSSL_PK_RSA )
+    {
+        rsa_context *rsa = pk_rsa( *key );
+
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
+        ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
+
+        ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    }
+    else
+#endif
+#if defined(POLARSSL_ECP_C)
+    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
+    {
+        ecp_keypair *ec = pk_ec( *key );
+        size_t pub_len = 0, par_len = 0;
+
+        /*
+         * RFC 5915, or SEC1 Appendix C.4
+         *
+         * ECPrivateKey ::= SEQUENCE {
+         *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+         *      privateKey     OCTET STRING,
+         *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+         *      publicKey  [1] BIT STRING OPTIONAL
+         *    }
+         */
+
+        /* publicKey */
+        ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
+
+        if( c - buf < 1 )
+            return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+        *--c = 0;
+        pub_len += 1;
+
+        ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
+        ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
+
+        ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
+        ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf,
+                            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) );
+        len += pub_len;
+
+        /* parameters */
+        ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
+
+        ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) );
+        ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf,
+                            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
+        len += par_len;
+
+        /* privateKey: write as MPI then fix tag */
+        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) );
+        *c = ASN1_OCTET_STRING;
+
+        /* version */
+        ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) );
+
+        ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    }
+    else
+#endif
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
+    return( len );
+}
+
+#if defined(POLARSSL_PEM_WRITE_C)
+
+#define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
+#define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
+
+#define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
+#define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
+#define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
+#define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
+
+int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char output_buf[4096];
+    size_t olen = 0;
+
+    if( ( ret = pk_write_pubkey_der( key, output_buf,
+                                     sizeof(output_buf) ) ) < 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
+                                  output_buf + sizeof(output_buf) - ret,
+                                  ret, buf, size, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size )
+{
+    int ret;
+    unsigned char output_buf[4096];
+    char *begin, *end;
+    size_t olen = 0;
+
+    if( ( ret = pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
+        return( ret );
+
+#if defined(POLARSSL_RSA_C)
+    if( pk_get_type( key ) == POLARSSL_PK_RSA )
+    {
+        begin = PEM_BEGIN_PRIVATE_KEY_RSA;
+        end = PEM_END_PRIVATE_KEY_RSA;
+    }
+    else
+#endif
+#if defined(POLARSSL_ECP_C)
+    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
+    {
+        begin = PEM_BEGIN_PRIVATE_KEY_EC;
+        end = PEM_END_PRIVATE_KEY_EC;
+    }
+    else
+#endif
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
+    if( ( ret = pem_write_buffer( begin, end,
+                                  output_buf + sizeof(output_buf) - ret,
+                                  ret, buf, size, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_PEM_WRITE_C */
+
+#endif /* POLARSSL_PK_WRITE_C */
diff --git a/library/rsa.c b/library/rsa.c
index 4929275..42fea41 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -1512,8 +1512,7 @@
 
     rsa_free( &rsa );
 #else /* POLARSSL_PKCS1_V15 */
-    if( verbose != 0 )
-        printf( "skipper\n\n" );
+    ((void) verbose);
 #endif /* POLARSSL_PKCS1_V15 */
     return( 0 );
 }
diff --git a/library/ssl_cache.c b/library/ssl_cache.c
index 7c7da4b..113f724 100644
--- a/library/ssl_cache.c
+++ b/library/ssl_cache.c
@@ -85,26 +85,26 @@
 
         session->verify_result = entry->session.verify_result;
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
         /*
          * Restore peer certificate (without rest of the original chain)
          */
         if( entry->peer_cert.p != NULL )
         {
-            session->peer_cert = (x509_cert *) polarssl_malloc( sizeof(x509_cert) );
+            session->peer_cert = (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
             if( session->peer_cert == NULL )
                 return( 1 );
 
-            memset( session->peer_cert, 0, sizeof(x509_cert) );
-            if( x509parse_crt( session->peer_cert, entry->peer_cert.p,
-                               entry->peer_cert.len ) != 0 )
+            x509_crt_init( session->peer_cert );
+            if( x509_crt_parse( session->peer_cert, entry->peer_cert.p,
+                                entry->peer_cert.len ) != 0 )
             {
                 polarssl_free( session->peer_cert );
                 session->peer_cert = NULL;
                 return( 1 );
             }
         }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
         return( 0 );
     }
@@ -163,13 +163,13 @@
         {
             cur = old;
             memset( &cur->session, 0, sizeof(ssl_session) );
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
             if( cur->peer_cert.p != NULL )
             {
                 polarssl_free( cur->peer_cert.p );
                 memset( &cur->peer_cert, 0, sizeof(x509_buf) );
             }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
         }
 #else /* POLARSSL_HAVE_TIME */
         /*
@@ -184,13 +184,13 @@
             cur = cache->chain;
             cache->chain = cur->next;
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
             if( cur->peer_cert.p != NULL )
             {
                 polarssl_free( cur->peer_cert.p );
                 memset( &cur->peer_cert, 0, sizeof(x509_buf) );
             }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
             memset( cur, 0, sizeof(ssl_cache_entry) );
             prv->next = cur;
@@ -217,7 +217,7 @@
 
     memcpy( &cur->session, session, sizeof( ssl_session ) );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     /*
      * Store peer certificate
      */
@@ -233,7 +233,7 @@
 
         cur->session.peer_cert = NULL;
     }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     return( 0 );
 }
@@ -267,10 +267,10 @@
 
         ssl_session_free( &prv->session );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
         if( prv->peer_cert.p != NULL )
             polarssl_free( prv->peer_cert.p );
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
         polarssl_free( prv );
     }
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 8edc57f..bce3d4e 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -62,9 +62,9 @@
 {
     unsigned char *p = buf;
     size_t left = buf_len;
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     size_t cert_len;
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     if( left < sizeof( ssl_session ) )
         return( -1 );
@@ -73,7 +73,7 @@
     p += sizeof( ssl_session );
     left -= sizeof( ssl_session );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     ((ssl_session *) buf)->peer_cert = NULL;
 
     if( session->peer_cert == NULL )
@@ -92,7 +92,7 @@
         memcpy( p, session->peer_cert->raw.p, cert_len );
 
     p += cert_len;
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     *olen = p - buf;
 
@@ -105,12 +105,11 @@
 static int ssl_load_session( ssl_session *session,
                              const unsigned char *buf, size_t len )
 {
-    int ret;
     const unsigned char *p = buf;
     const unsigned char * const end = buf + len;
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     size_t cert_len;
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     if( p + sizeof( ssl_session ) > end )
         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
@@ -118,7 +117,7 @@
     memcpy( session, p, sizeof( ssl_session ) );
     p += sizeof( ssl_session );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     if( p + 3 > end )
         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
 
@@ -131,19 +130,21 @@
     }
     else
     {
+        int ret;
+
         if( p + cert_len > end )
             return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
 
-        session->peer_cert = polarssl_malloc( sizeof( x509_cert ) );
+        session->peer_cert = polarssl_malloc( sizeof( x509_crt ) );
 
         if( session->peer_cert == NULL )
             return( POLARSSL_ERR_SSL_MALLOC_FAILED );
 
-        memset( session->peer_cert, 0, sizeof( x509_cert ) );
+        x509_crt_init( session->peer_cert );
 
-        if( ( ret = x509parse_crt( session->peer_cert, p, cert_len ) ) != 0 )
+        if( ( ret = x509_crt_parse( session->peer_cert, p, cert_len ) ) != 0 )
         {
-            x509_free( session->peer_cert );
+            x509_crt_free( session->peer_cert );
             polarssl_free( session->peer_cert );
             session->peer_cert = NULL;
             return( ret );
@@ -151,7 +152,7 @@
 
         p += cert_len;
     }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     if( p != end )
         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
@@ -1694,7 +1695,7 @@
     size_t dn_size, total_dn_size; /* excluding length bytes */
     size_t ct_len, sa_len; /* including length bytes */
     unsigned char *buf, *p;
-    const x509_cert *crt;
+    const x509_crt *crt;
 
     SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
 
@@ -1834,14 +1835,19 @@
 {
     int ret;
     size_t n = 0, len;
-    unsigned char hash[64];
-    md_type_t md_alg = POLARSSL_MD_NONE;
-    unsigned int hashlen = 0;
     unsigned char *p = ssl->out_msg + 4;
+    const ssl_ciphersuite_t *ciphersuite_info;
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
     unsigned char *dig_signed = p;
     size_t dig_signed_len = 0;
+    ((void) dig_signed);
+    ((void) dig_signed_len);
+#endif
 
-    const ssl_ciphersuite_t *ciphersuite_info;
     ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
@@ -1959,6 +1965,9 @@
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
     {
         size_t signature_len = 0;
+        unsigned int hashlen = 0;
+        unsigned char hash[64];
+        md_type_t md_alg = POLARSSL_MD_NONE;
 
         /*
          * Choose hash algorithm. NONE means MD5 + SHA1 here.
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 208e69b..c19536b 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -72,28 +72,28 @@
 
 static int ssl_session_copy( ssl_session *dst, const ssl_session *src )
 {
-    int ret;
-
     ssl_session_free( dst );
     memcpy( dst, src, sizeof( ssl_session ) );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     if( src->peer_cert != NULL )
     {
-        if( ( dst->peer_cert = polarssl_malloc( sizeof(x509_cert) ) ) == NULL )
+        int ret;
+
+        if( ( dst->peer_cert = polarssl_malloc( sizeof(x509_crt) ) ) == NULL )
             return( POLARSSL_ERR_SSL_MALLOC_FAILED );
 
-        memset( dst->peer_cert, 0, sizeof(x509_cert) );
+        x509_crt_init( dst->peer_cert );
 
-        if( ( ret = x509parse_crt( dst->peer_cert, src->peer_cert->raw.p,
-                                   src->peer_cert->raw.len ) != 0 ) )
+        if( ( ret = x509_crt_parse( dst->peer_cert, src->peer_cert->raw.p,
+                                    src->peer_cert->raw.len ) != 0 ) )
         {
             polarssl_free( dst->peer_cert );
             dst->peer_cert = NULL;
             return( ret );
         }
     }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
     if( src->ticket != NULL )
@@ -2272,7 +2272,7 @@
 {
     int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
     size_t i, n;
-    const x509_cert *crt;
+    const x509_crt *crt;
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
@@ -2482,19 +2482,19 @@
     /* In case we tried to reuse a session but it failed */
     if( ssl->session_negotiate->peer_cert != NULL )
     {
-        x509_free( ssl->session_negotiate->peer_cert );
+        x509_crt_free( ssl->session_negotiate->peer_cert );
         polarssl_free( ssl->session_negotiate->peer_cert );
     }
 
-    if( ( ssl->session_negotiate->peer_cert = (x509_cert *) polarssl_malloc(
-                    sizeof( x509_cert ) ) ) == NULL )
+    if( ( ssl->session_negotiate->peer_cert = (x509_crt *) polarssl_malloc(
+                    sizeof( x509_crt ) ) ) == NULL )
     {
         SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed",
-                       sizeof( x509_cert ) ) );
+                       sizeof( x509_crt ) ) );
         return( POLARSSL_ERR_SSL_MALLOC_FAILED );
     }
 
-    memset( ssl->session_negotiate->peer_cert, 0, sizeof( x509_cert ) );
+    x509_crt_init( ssl->session_negotiate->peer_cert );
 
     i = 7;
 
@@ -2516,11 +2516,11 @@
             return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
         }
 
-        ret = x509parse_crt_der( ssl->session_negotiate->peer_cert,
-                                 ssl->in_msg + i, n );
+        ret = x509_crt_parse_der( ssl->session_negotiate->peer_cert,
+                                  ssl->in_msg + i, n );
         if( ret != 0 )
         {
-            SSL_DEBUG_RET( 1, " x509parse_crt", ret );
+            SSL_DEBUG_RET( 1, " x509_crt_parse_der", ret );
             return( ret );
         }
 
@@ -2537,10 +2537,10 @@
             return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED );
         }
 
-        ret = x509parse_verify( ssl->session_negotiate->peer_cert,
-                                ssl->ca_chain, ssl->ca_crl, ssl->peer_cn,
-                               &ssl->session_negotiate->verify_result,
-                                ssl->f_vrfy, ssl->p_vrfy );
+        ret = x509_crt_verify( ssl->session_negotiate->peer_cert,
+                               ssl->ca_chain, ssl->ca_crl, ssl->peer_cn,
+                              &ssl->session_negotiate->verify_result,
+                               ssl->f_vrfy, ssl->p_vrfy );
 
         if( ret != 0 )
             SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
@@ -3377,15 +3377,15 @@
     ssl->authmode   = authmode;
 }
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 void ssl_set_verify( ssl_context *ssl,
-                     int (*f_vrfy)(void *, x509_cert *, int, int *),
+                     int (*f_vrfy)(void *, x509_crt *, int, int *),
                      void *p_vrfy )
 {
     ssl->f_vrfy      = f_vrfy;
     ssl->p_vrfy      = p_vrfy;
 }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 void ssl_set_rng( ssl_context *ssl,
                   int (*f_rng)(void *, unsigned char *, size_t),
@@ -3463,8 +3463,8 @@
     ssl->ciphersuite_list[minor] = ciphersuites;
 }
 
-#if defined(POLARSSL_X509_PARSE_C)
-void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain,
                        x509_crl *ca_crl, const char *peer_cn )
 {
     ssl->ca_chain   = ca_chain;
@@ -3472,7 +3472,7 @@
     ssl->peer_cn    = peer_cn;
 }
 
-void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
+void ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert,
                        pk_context *pk_key )
 {
     ssl->own_cert   = own_cert;
@@ -3480,7 +3480,7 @@
 }
 
 #if defined(POLARSSL_RSA_C)
-int ssl_set_own_cert_rsa( ssl_context *ssl, x509_cert *own_cert,
+int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert,
                            rsa_context *rsa_key )
 {
     int ret;
@@ -3505,7 +3505,7 @@
 }
 #endif /* POLARSSL_RSA_C */
 
-int ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
+int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert,
                           void *rsa_key,
                           rsa_decrypt_func rsa_decrypt,
                           rsa_sign_func rsa_sign,
@@ -3523,7 +3523,7 @@
     return( pk_init_ctx_rsa_alt( ssl->pk_key, rsa_key,
                                  rsa_decrypt, rsa_sign, rsa_key_len ) );
 }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
 void ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
@@ -3730,15 +3730,15 @@
     return( "unknown" );
 }
 
-#if defined(POLARSSL_X509_PARSE_C)
-const x509_cert *ssl_get_peer_cert( const ssl_context *ssl )
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+const x509_crt *ssl_get_peer_cert( const ssl_context *ssl )
 {
     if( ssl == NULL || ssl->session == NULL )
         return NULL;
 
     return ssl->session->peer_cert;
 }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 int ssl_get_session( const ssl_context *ssl, ssl_session *dst )
 {
@@ -4076,10 +4076,10 @@
 
 void ssl_session_free( ssl_session *session )
 {
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     if( session->peer_cert != NULL )
     {
-        x509_free( session->peer_cert );
+        x509_crt_free( session->peer_cert );
         polarssl_free( session->peer_cert );
     }
 #endif
diff --git a/library/x509.c b/library/x509.c
new file mode 100644
index 0000000..677760e
--- /dev/null
+++ b/library/x509.c
@@ -0,0 +1,764 @@
+/*
+ *  X.509 certificate and private key decoding
+ *
+ *  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.
+ */
+/*
+ *  The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ *  http://www.ietf.org/rfc/rfc3279.txt
+ *  http://www.ietf.org/rfc/rfc3280.txt
+ *
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_USE_C)
+
+#include "polarssl/x509.h"
+#include "polarssl/asn1.h"
+#include "polarssl/oid.h"
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32)
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#if !defined(_WIN32)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#endif
+#endif
+
+/*
+ *  CertificateSerialNumber  ::=  INTEGER
+ */
+int x509_get_serial( unsigned char **p, const unsigned char *end,
+                     x509_buf *serial )
+{
+    int ret;
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_SERIAL +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
+        **p !=   ASN1_INTEGER )
+        return( POLARSSL_ERR_X509_INVALID_SERIAL +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    serial->tag = *(*p)++;
+
+    if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_SERIAL + ret );
+
+    serial->p = *p;
+    *p += serial->len;
+
+    return( 0 );
+}
+
+/* Get an algorithm identifier without parameters (eg for signatures)
+ *
+ *  AlgorithmIdentifier  ::=  SEQUENCE  {
+ *       algorithm               OBJECT IDENTIFIER,
+ *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
+ */
+int x509_get_alg_null( unsigned char **p, const unsigned char *end,
+                       x509_buf *alg )
+{
+    int ret;
+
+    if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    return( 0 );
+}
+
+/*
+ *  AttributeTypeAndValue ::= SEQUENCE {
+ *    type     AttributeType,
+ *    value    AttributeValue }
+ *
+ *  AttributeType ::= OBJECT IDENTIFIER
+ *
+ *  AttributeValue ::= ANY DEFINED BY AttributeType
+ */
+static int x509_get_attr_type_value( unsigned char **p,
+                                     const unsigned char *end,
+                                     x509_name *cur )
+{
+    int ret;
+    size_t len;
+    x509_buf *oid;
+    x509_buf *val;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_NAME +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    oid = &cur->oid;
+    oid->tag = **p;
+
+    if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+    oid->p = *p;
+    *p += oid->len;
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_NAME +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING      &&
+        **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
+        **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
+        return( POLARSSL_ERR_X509_INVALID_NAME +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    val = &cur->val;
+    val->tag = *(*p)++;
+
+    if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+    val->p = *p;
+    *p += val->len;
+
+    cur->next = NULL;
+
+    return( 0 );
+}
+
+/*
+ *  RelativeDistinguishedName ::=
+ *    SET OF AttributeTypeAndValue
+ *
+ *  AttributeTypeAndValue ::= SEQUENCE {
+ *    type     AttributeType,
+ *    value    AttributeValue }
+ *
+ *  AttributeType ::= OBJECT IDENTIFIER
+ *
+ *  AttributeValue ::= ANY DEFINED BY AttributeType
+ */
+int x509_get_name( unsigned char **p, const unsigned char *end,
+                   x509_name *cur )
+{
+    int ret;
+    size_t len;
+    const unsigned char *end2;
+    x509_name *use;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+
+    end2 = end;
+    end  = *p + len;
+    use = cur;
+
+    do
+    {
+        if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
+            return( ret );
+
+        if( *p != end )
+        {
+            use->next = (x509_name *) polarssl_malloc(
+                    sizeof( x509_name ) );
+
+            if( use->next == NULL )
+                return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+            memset( use->next, 0, sizeof( x509_name ) );
+
+            use = use->next;
+        }
+    }
+    while( *p != end );
+
+    /*
+     * recurse until end of SEQUENCE is reached
+     */
+    if( *p == end2 )
+        return( 0 );
+
+    cur->next = (x509_name *) polarssl_malloc(
+         sizeof( x509_name ) );
+
+    if( cur->next == NULL )
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+    memset( cur->next, 0, sizeof( x509_name ) );
+
+    return( x509_get_name( p, end2, cur->next ) );
+}
+
+/*
+ *  Time ::= CHOICE {
+ *       utcTime        UTCTime,
+ *       generalTime    GeneralizedTime }
+ */
+int x509_get_time( unsigned char **p, const unsigned char *end,
+                   x509_time *time )
+{
+    int ret;
+    size_t len;
+    char date[64];
+    unsigned char tag;
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_DATE +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    tag = **p;
+
+    if ( tag == ASN1_UTC_TIME )
+    {
+        (*p)++;
+        ret = asn1_get_len( p, end, &len );
+
+        if( ret != 0 )
+            return( POLARSSL_ERR_X509_INVALID_DATE + ret );
+
+        memset( date,  0, sizeof( date ) );
+        memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
+                len : sizeof( date ) - 1 );
+
+        if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
+                    &time->year, &time->mon, &time->day,
+                    &time->hour, &time->min, &time->sec ) < 5 )
+            return( POLARSSL_ERR_X509_INVALID_DATE );
+
+        time->year +=  100 * ( time->year < 50 );
+        time->year += 1900;
+
+        *p += len;
+
+        return( 0 );
+    }
+    else if ( tag == ASN1_GENERALIZED_TIME )
+    {
+        (*p)++;
+        ret = asn1_get_len( p, end, &len );
+
+        if( ret != 0 )
+            return( POLARSSL_ERR_X509_INVALID_DATE + ret );
+
+        memset( date,  0, sizeof( date ) );
+        memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
+                len : sizeof( date ) - 1 );
+
+        if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
+                    &time->year, &time->mon, &time->day,
+                    &time->hour, &time->min, &time->sec ) < 5 )
+            return( POLARSSL_ERR_X509_INVALID_DATE );
+
+        *p += len;
+
+        return( 0 );
+    }
+    else
+        return( POLARSSL_ERR_X509_INVALID_DATE +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+}
+
+int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
+{
+    int ret;
+    size_t len;
+
+    if( ( end - *p ) < 1 )
+        return( POLARSSL_ERR_X509_INVALID_SIGNATURE +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    sig->tag = **p;
+
+    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret );
+
+    sig->len = len;
+    sig->p = *p;
+
+    *p += len;
+
+    return( 0 );
+}
+
+int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
+                      pk_type_t *pk_alg )
+{
+    int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
+
+    return( 0 );
+}
+
+/*
+ * X.509 Extensions (No parsing of extensions, pointer should
+ * be either manually updated or extensions should be parsed!
+ */
+int x509_get_ext( unsigned char **p, const unsigned char *end,
+                  x509_buf *ext, int tag )
+{
+    int ret;
+    size_t len;
+
+    if( *p == end )
+        return( 0 );
+
+    ext->tag = **p;
+
+    if( ( ret = asn1_get_tag( p, end, &ext->len,
+            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
+        return( ret );
+
+    ext->p = *p;
+    end = *p + ext->len;
+
+    /*
+     * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
+     *
+     * Extension  ::=  SEQUENCE  {
+     *      extnID      OBJECT IDENTIFIER,
+     *      critical    BOOLEAN DEFAULT FALSE,
+     *      extnValue   OCTET STRING  }
+     */
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( end != *p + len )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ */
+int x509_load_file( const char *path, unsigned char **buf, size_t *n )
+{
+    FILE *f;
+    long size;
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    if( ( size = ftell( f ) ) == -1 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+    }
+    fseek( f, 0, SEEK_SET );
+
+    *n = (size_t) size;
+
+    if( *n + 1 == 0 ||
+        ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+    }
+
+    if( fread( *buf, 1, *n, f ) != *n )
+    {
+        fclose( f );
+        polarssl_free( *buf );
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    (*buf)[*n] = '\0';
+
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined _MSC_VER && !defined snprintf
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return( -1 );                           \
+                                                \
+    if ( (unsigned int) ret > n ) {             \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+/*
+ * Store the name in printable form into buf; no more
+ * than size characters will be written
+ */
+int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
+{
+    int ret;
+    size_t i, n;
+    unsigned char c;
+    const x509_name *name;
+    const char *short_name = NULL;
+    char s[128], *p;
+
+    memset( s, 0, sizeof( s ) );
+
+    name = dn;
+    p = buf;
+    n = size;
+
+    while( name != NULL )
+    {
+        if( !name->oid.p )
+        {
+            name = name->next;
+            continue;
+        }
+
+        if( name != dn )
+        {
+            ret = snprintf( p, n, ", " );
+            SAFE_SNPRINTF();
+        }
+
+        ret = oid_get_attr_short_name( &name->oid, &short_name );
+
+        if( ret == 0 )
+            ret = snprintf( p, n, "%s=", short_name );
+        else
+            ret = snprintf( p, n, "\?\?=" );
+        SAFE_SNPRINTF();
+
+        for( i = 0; i < name->val.len; i++ )
+        {
+            if( i >= sizeof( s ) - 1 )
+                break;
+
+            c = name->val.p[i];
+            if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
+                 s[i] = '?';
+            else s[i] = c;
+        }
+        s[i] = '\0';
+        ret = snprintf( p, n, "%s", s );
+        SAFE_SNPRINTF();
+        name = name->next;
+    }
+
+    return( (int) ( size - n ) );
+}
+
+/*
+ * Store the serial in printable form into buf; no more
+ * than size characters will be written
+ */
+int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
+{
+    int ret;
+    size_t i, n, nr;
+    char *p;
+
+    p = buf;
+    n = size;
+
+    nr = ( serial->len <= 32 )
+        ? serial->len  : 28;
+
+    for( i = 0; i < nr; i++ )
+    {
+        if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
+            continue;
+
+        ret = snprintf( p, n, "%02X%s",
+                serial->p[i], ( i < nr - 1 ) ? ":" : "" );
+        SAFE_SNPRINTF();
+    }
+
+    if( nr != serial->len )
+    {
+        ret = snprintf( p, n, "...." );
+        SAFE_SNPRINTF();
+    }
+
+    return( (int) ( size - n ) );
+}
+
+/*
+ * Helper for writing "RSA key size", "EC key size", etc
+ */
+int x509_key_size_helper( char *buf, size_t size, const char *name )
+{
+    char *p = buf;
+    size_t n = size;
+    int ret;
+
+    if( strlen( name ) + sizeof( " key size" ) > size )
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
+
+    ret = snprintf( p, n, "%s key size", name );
+    SAFE_SNPRINTF();
+
+    return( 0 );
+}
+
+/*
+ * Return an informational string describing the given OID
+ */
+const char *x509_oid_get_description( x509_buf *oid )
+{
+    const char *desc = NULL;
+    int ret;
+
+    ret = oid_get_extended_key_usage( oid, &desc );
+
+    if( ret != 0 )
+        return( NULL );
+
+    return( desc );
+}
+
+/* Return the x.y.z.... style numeric string for the given OID */
+int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
+{
+    return oid_get_numeric_string( buf, size, oid );
+}
+
+/*
+ * Return 0 if the x509_time is still valid, or 1 otherwise.
+ */
+#if defined(POLARSSL_HAVE_TIME)
+int x509_time_expired( const x509_time *to )
+{
+    int year, mon, day;
+    int hour, min, sec;
+
+#if defined(_WIN32)
+    SYSTEMTIME st;
+
+    GetLocalTime(&st);
+
+    year = st.wYear;
+    mon = st.wMonth;
+    day = st.wDay;
+    hour = st.wHour;
+    min = st.wMinute;
+    sec = st.wSecond;
+#else
+    struct tm *lt;
+    time_t tt;
+
+    tt = time( NULL );
+    lt = localtime( &tt );
+
+    year = lt->tm_year + 1900;
+    mon = lt->tm_mon + 1;
+    day = lt->tm_mday;
+    hour = lt->tm_hour;
+    min = lt->tm_min;
+    sec = lt->tm_sec;
+#endif
+
+    if( year  > to->year )
+        return( 1 );
+
+    if( year == to->year &&
+        mon   > to->mon )
+        return( 1 );
+
+    if( year == to->year &&
+        mon  == to->mon  &&
+        day   > to->day )
+        return( 1 );
+
+    if( year == to->year &&
+        mon  == to->mon  &&
+        day  == to->day  &&
+        hour  > to->hour )
+        return( 1 );
+
+    if( year == to->year &&
+        mon  == to->mon  &&
+        day  == to->day  &&
+        hour == to->hour &&
+        min   > to->min  )
+        return( 1 );
+
+    if( year == to->year &&
+        mon  == to->mon  &&
+        day  == to->day  &&
+        hour == to->hour &&
+        min  == to->min  &&
+        sec   > to->sec  )
+        return( 1 );
+
+    return( 0 );
+}
+#else  /* POLARSSL_HAVE_TIME */
+int x509_time_expired( const x509_time *to )
+{
+    ((void) to);
+    return( 0 );
+}
+#endif /* POLARSSL_HAVE_TIME */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/x509_crt.h"
+#include "polarssl/certs.h"
+
+/*
+ * Checkup routine
+ */
+int x509_self_test( int verbose )
+{
+#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
+    int ret;
+    int flags;
+    x509_crt cacert;
+    x509_crt clicert;
+
+    if( verbose != 0 )
+        printf( "  X.509 certificate load: " );
+
+    x509_crt_init( &clicert );
+
+    ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
+                          strlen( test_cli_crt ) );
+    if( ret != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( ret );
+    }
+
+    x509_crt_init( &cacert );
+
+    ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
+                          strlen( test_ca_crt ) );
+    if( ret != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( ret );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n  X.509 signature verify: ");
+
+    ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
+    if( ret != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        printf("ret = %d, &flags = %04x\n", ret, flags);
+
+        return( ret );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n\n");
+
+    x509_crt_free( &cacert  );
+    x509_crt_free( &clicert );
+
+    return( 0 );
+#else
+    ((void) verbose);
+    return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+#endif
+}
+
+#endif
+
+#endif /* POLARSSL_X509_USE_C */
diff --git a/library/x509_create.c b/library/x509_create.c
new file mode 100644
index 0000000..d7a1fee
--- /dev/null
+++ b/library/x509_create.c
@@ -0,0 +1,267 @@
+/*
+ *  X.509 base functions for creating certificates / CSRs
+ *
+ *  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.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_CREATE_C)
+
+#include "polarssl/x509.h"
+#include "polarssl/asn1write.h"
+#include "polarssl/oid.h"
+
+int x509_string_to_names( asn1_named_data **head, char *name )
+{
+    int ret = 0;
+    char *s = name, *c = s;
+    char *end = s + strlen( s );
+    char *oid = NULL;
+    int in_tag = 1;
+    asn1_named_data *cur;
+
+    /* Clear existing chain if present */
+    asn1_free_named_data_list( head );
+
+    while( c <= end )
+    {
+        if( in_tag && *c == '=' )
+        {
+            if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
+                oid = OID_AT_CN;
+            else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
+                oid = OID_AT_COUNTRY;
+            else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
+                oid = OID_AT_ORGANIZATION;
+            else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
+                oid = OID_AT_LOCALITY;
+            else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
+                oid = OID_PKCS9_EMAIL;
+            else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
+                oid = OID_AT_ORG_UNIT;
+            else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
+                oid = OID_AT_STATE;
+            else
+            {
+                ret = POLARSSL_ERR_X509_UNKNOWN_OID;
+                goto exit;
+            }
+
+            s = c + 1;
+            in_tag = 0;
+        }
+
+        if( !in_tag && ( *c == ',' || c == end ) )
+        {
+            if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
+                                               (unsigned char *) s,
+                                               c - s ) ) == NULL )
+            {
+                return( POLARSSL_ERR_X509_MALLOC_FAILED );
+            }
+
+            while( c < end && *(c + 1) == ' ' )
+                c++;
+
+            s = c + 1;
+            in_tag = 1;
+        }
+        c++;
+    }
+
+exit:
+
+    return( ret );
+}
+
+/* The first byte of the value in the asn1_named_data structure is reserved
+ * to store the critical boolean for us
+ */
+int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,
+                        int critical, const unsigned char *val, size_t val_len )
+{
+    asn1_named_data *cur;
+
+    if( ( cur = asn1_store_named_data( head, oid, oid_len,
+                                       NULL, val_len + 1 ) ) == NULL )
+    {
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+    }
+
+    cur->val.p[0] = critical;
+    memcpy( cur->val.p + 1, val, val_len );
+
+    return( 0 );
+}
+
+/*
+ *  RelativeDistinguishedName ::=
+ *    SET OF AttributeTypeAndValue
+ *
+ *  AttributeTypeAndValue ::= SEQUENCE {
+ *    type     AttributeType,
+ *    value    AttributeValue }
+ *
+ *  AttributeType ::= OBJECT IDENTIFIER
+ *
+ *  AttributeValue ::= ANY DEFINED BY AttributeType
+ */
+static int x509_write_name( unsigned char **p, unsigned char *start,
+                            const char *oid, size_t oid_len,
+                            const unsigned char *name, size_t name_len )
+{
+    int ret;
+    size_t len = 0;
+
+    // Write PrintableString for all except OID_PKCS9_EMAIL
+    //
+    if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
+        memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
+    {
+        ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
+                                                  (const char *) name,
+                                                  name_len ) );
+    }
+    else
+    {
+        ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
+                                                        (const char *) name,
+                                                        name_len ) );
+    }
+
+    // Write OID
+    //
+    ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
+
+    return( len );
+}
+
+int x509_write_names( unsigned char **p, unsigned char *start,
+                      asn1_named_data *first )
+{
+    int ret;
+    size_t len = 0;
+    asn1_named_data *cur = first;
+
+    while( cur != NULL )
+    {
+        ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
+                                            cur->oid.len,
+                                            cur->val.p, cur->val.len ) );
+        cur = cur->next;
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return( len );
+}
+
+int x509_write_sig( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len,
+                    unsigned char *sig, size_t size )
+{
+    int ret;
+    size_t len = 0;
+
+    if( *p - start < (int) size + 1 )
+        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+    len = size;
+    (*p) -= len;
+    memcpy( *p, sig, len );
+
+    *--(*p) = 0;
+    len += 1;
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
+
+    // Write OID
+    //
+    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
+                                                        oid_len, 0 ) );
+
+    return( len );
+}
+
+static int x509_write_extension( unsigned char **p, unsigned char *start,
+                                 asn1_named_data *ext )
+{
+    int ret;
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
+                                              ext->val.len - 1 ) );
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
+
+    if( ext->val.p[0] != 0 )
+    {
+        ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
+                                              ext->oid.len ) );
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return( len );
+}
+
+/*
+ * Extension  ::=  SEQUENCE  {
+ *     extnID      OBJECT IDENTIFIER,
+ *     critical    BOOLEAN DEFAULT FALSE,
+ *     extnValue   OCTET STRING
+ *                 -- contains the DER encoding of an ASN.1 value
+ *                 -- corresponding to the extension type identified
+ *                 -- by extnID
+ *     }
+ */
+int x509_write_extensions( unsigned char **p, unsigned char *start,
+                           asn1_named_data *first )
+{
+    int ret;
+    size_t len = 0;
+    asn1_named_data *cur_ext = first;
+
+    while( cur_ext != NULL )
+    {
+        ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
+        cur_ext = cur_ext->next;
+    }
+
+    return( len );
+}
+
+#endif /* POLARSSL_X509_CREATE_C */
diff --git a/library/x509_crl.c b/library/x509_crl.c
new file mode 100644
index 0000000..00d51bd
--- /dev/null
+++ b/library/x509_crl.c
@@ -0,0 +1,748 @@
+/*
+ *  X.509 certificate and private key decoding
+ *
+ *  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.
+ */
+/*
+ *  The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ *  http://www.ietf.org/rfc/rfc3279.txt
+ *  http://www.ietf.org/rfc/rfc3280.txt
+ *
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+
+#include "polarssl/x509_crl.h"
+#include "polarssl/oid.h"
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32)
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+/*
+ *  Version  ::=  INTEGER  {  v1(0), v2(1)  }
+ */
+static int x509_crl_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_INVALID_VERSION + ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * X.509 CRL v2 extensions (no extensions parsed yet.)
+ */
+static int x509_get_crl_ext( unsigned char **p,
+                             const unsigned char *end,
+                             x509_buf *ext )
+{
+    int ret;
+    size_t len = 0;
+
+    /* Get explicit tag */
+    if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( 0 );
+
+        return( ret );
+    }
+
+    while( *p < end )
+    {
+        if( ( ret = asn1_get_tag( p, end, &len,
+                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        *p += len;
+    }
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * X.509 CRL v2 entry extensions (no extensions parsed yet.)
+ */
+static int x509_get_crl_entry_ext( unsigned char **p,
+                             const unsigned char *end,
+                             x509_buf *ext )
+{
+    int ret;
+    size_t len = 0;
+
+    /* OPTIONAL */
+    if (end <= *p)
+        return( 0 );
+
+    ext->tag = **p;
+    ext->p = *p;
+
+    /*
+     * Get CRL-entry extension sequence header
+     * crlEntryExtensions      Extensions OPTIONAL  -- if present, MUST be v2
+     */
+    if( ( ret = asn1_get_tag( p, end, &ext->len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        {
+            ext->p = NULL;
+            return( 0 );
+        }
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+    }
+
+	end = *p + ext->len;
+
+    if( end != *p + ext->len )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    while( *p < end )
+    {
+        if( ( ret = asn1_get_tag( p, end, &len,
+                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        *p += len;
+    }
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * X.509 CRL Entries
+ */
+static int x509_get_entries( unsigned char **p,
+                             const unsigned char *end,
+                             x509_crl_entry *entry )
+{
+    int ret;
+    size_t entry_len;
+    x509_crl_entry *cur_entry = entry;
+
+    if( *p == end )
+        return( 0 );
+
+    if( ( ret = asn1_get_tag( p, end, &entry_len,
+            ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( 0 );
+
+        return( ret );
+    }
+
+    end = *p + entry_len;
+
+    while( *p < end )
+    {
+        size_t len2;
+        const unsigned char *end2;
+
+        if( ( ret = asn1_get_tag( p, end, &len2,
+                ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        cur_entry->raw.tag = **p;
+        cur_entry->raw.p = *p;
+        cur_entry->raw.len = len2;
+        end2 = *p + len2;
+
+        if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
+            return( ret );
+
+        if( ( ret = x509_get_time( p, end2, &cur_entry->revocation_date ) ) != 0 )
+            return( ret );
+
+        if( ( ret = x509_get_crl_entry_ext( p, end2, &cur_entry->entry_ext ) ) != 0 )
+            return( ret );
+
+        if ( *p < end )
+        {
+            cur_entry->next = polarssl_malloc( sizeof( x509_crl_entry ) );
+
+            if( cur_entry->next == NULL )
+                return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+            cur_entry = cur_entry->next;
+            memset( cur_entry, 0, sizeof( x509_crl_entry ) );
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse one or more CRLs and add them to the chained list
+ */
+int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+    x509_crl *crl;
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t use_len;
+    pem_context pem;
+#endif
+
+    crl = chain;
+
+    /*
+     * Check for valid input
+     */
+    if( crl == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    while( crl->version != 0 && crl->next != NULL )
+        crl = crl->next;
+
+    /*
+     * Add new CRL on the end of the chain if needed.
+     */
+    if ( crl->version != 0 && crl->next == NULL)
+    {
+        crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
+
+        if( crl->next == NULL )
+        {
+            x509_crl_free( crl );
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+        }
+
+        crl = crl->next;
+        x509_crl_init( crl );
+    }
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_init( &pem );
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN X509 CRL-----",
+                           "-----END X509 CRL-----",
+                           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
+#endif
+    {
+        /*
+         * 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;
+    }
+
+    crl->raw.p = p;
+    crl->raw.len = len;
+    end = p + len;
+
+    /*
+     * CertificateList  ::=  SEQUENCE  {
+     *      tbsCertList          TBSCertList,
+     *      signatureAlgorithm   AlgorithmIdentifier,
+     *      signatureValue       BIT STRING  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT );
+    }
+
+    if( len != (size_t) ( end - p ) )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    /*
+     * TBSCertList  ::=  SEQUENCE  {
+     */
+    crl->tbs.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+    crl->tbs.len = end - crl->tbs.p;
+
+    /*
+     * Version  ::=  INTEGER  OPTIONAL {  v1(0), v2(1)  }
+     *               -- if present, MUST be v2
+     *
+     * signature            AlgorithmIdentifier
+     */
+    if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
+        ( ret = x509_get_alg_null( &p, end, &crl->sig_oid1   ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    crl->version++;
+
+    if( crl->version > 2 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
+    }
+
+    if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_md,
+                                  &crl->sig_pk ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG );
+    }
+
+    /*
+     * issuer               Name
+     */
+    crl->issuer_raw.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    crl->issuer_raw.len = p - crl->issuer_raw.p;
+
+    /*
+     * thisUpdate          Time
+     * nextUpdate          Time OPTIONAL
+     */
+    if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
+    {
+        if ( ret != ( POLARSSL_ERR_X509_INVALID_DATE +
+                        POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
+             ret != ( POLARSSL_ERR_X509_INVALID_DATE +
+                        POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
+        {
+            x509_crl_free( crl );
+            return( ret );
+        }
+    }
+
+    /*
+     * revokedCertificates    SEQUENCE OF SEQUENCE   {
+     *      userCertificate        CertificateSerialNumber,
+     *      revocationDate         Time,
+     *      crlEntryExtensions     Extensions OPTIONAL
+     *                                   -- if present, MUST be v2
+     *                        } OPTIONAL
+     */
+    if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    /*
+     * crlExtensions          EXPLICIT Extensions OPTIONAL
+     *                              -- if present, MUST be v2
+     */
+    if( crl->version == 2 )
+    {
+        ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
+
+        if( ret != 0 )
+        {
+            x509_crl_free( crl );
+            return( ret );
+        }
+    }
+
+    if( p != end )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    end = crl->raw.p + crl->raw.len;
+
+    /*
+     *  signatureAlgorithm   AlgorithmIdentifier,
+     *  signatureValue       BIT STRING
+     */
+    if( ( ret = x509_get_alg_null( &p, end, &crl->sig_oid2 ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    if( crl->sig_oid1.len != crl->sig_oid2.len ||
+        memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_SIG_MISMATCH );
+    }
+
+    if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
+    {
+        x509_crl_free( crl );
+        return( ret );
+    }
+
+    if( p != end )
+    {
+        x509_crl_free( crl );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    if( buflen > 0 )
+    {
+        crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
+
+        if( crl->next == NULL )
+        {
+            x509_crl_free( crl );
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+        }
+
+        crl = crl->next;
+        x509_crl_init( crl );
+
+        return( x509_crl_parse( crl, buf, buflen ) );
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load one or more CRLs and add them to the chained list
+ */
+int x509_crl_parse_file( x509_crl *chain, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_crl_parse( chain, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined _MSC_VER && !defined snprintf
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return( -1 );                           \
+                                                \
+    if ( (unsigned int) ret > n ) {             \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+/*
+ * Return an informational string about the certificate.
+ */
+#define BEFORE_COLON    14
+#define BC              "14"
+/*
+ * Return an informational string about the CRL.
+ */
+int x509_crl_info( char *buf, size_t size, const char *prefix,
+                   const x509_crl *crl )
+{
+    int ret;
+    size_t n;
+    char *p;
+    const char *desc;
+    const x509_crl_entry *entry;
+
+    p = buf;
+    n = size;
+
+    ret = snprintf( p, n, "%sCRL version   : %d",
+                               prefix, crl->version );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sissuer name   : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crl->issuer );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sthis update   : " \
+                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                   crl->this_update.year, crl->this_update.mon,
+                   crl->this_update.day,  crl->this_update.hour,
+                   crl->this_update.min,  crl->this_update.sec );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%snext update   : " \
+                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                   crl->next_update.year, crl->next_update.mon,
+                   crl->next_update.day,  crl->next_update.hour,
+                   crl->next_update.min,  crl->next_update.sec );
+    SAFE_SNPRINTF();
+
+    entry = &crl->entry;
+
+    ret = snprintf( p, n, "\n%sRevoked certificates:",
+                               prefix );
+    SAFE_SNPRINTF();
+
+    while( entry != NULL && entry->raw.len != 0 )
+    {
+        ret = snprintf( p, n, "\n%sserial number: ",
+                               prefix );
+        SAFE_SNPRINTF();
+
+        ret = x509_serial_gets( p, n, &entry->serial);
+        SAFE_SNPRINTF();
+
+        ret = snprintf( p, n, " revocation date: " \
+                   "%04d-%02d-%02d %02d:%02d:%02d",
+                   entry->revocation_date.year, entry->revocation_date.mon,
+                   entry->revocation_date.day,  entry->revocation_date.hour,
+                   entry->revocation_date.min,  entry->revocation_date.sec );
+        SAFE_SNPRINTF();
+
+        entry = entry->next;
+    }
+
+    ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = oid_get_sig_alg_desc( &crl->sig_oid1, &desc );
+    if( ret != 0 )
+        ret = snprintf( p, n, "???"  );
+    else
+        ret = snprintf( p, n, "%s", desc );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n" );
+    SAFE_SNPRINTF();
+
+    return( (int) ( size - n ) );
+}
+
+/*
+ * Initialize a CRL chain
+ */
+void x509_crl_init( x509_crl *crl )
+{
+    memset( crl, 0, sizeof(x509_crl) );
+}
+
+/*
+ * Unallocate all CRL data
+ */
+void x509_crl_free( x509_crl *crl )
+{
+    x509_crl *crl_cur = crl;
+    x509_crl *crl_prv;
+    x509_name *name_cur;
+    x509_name *name_prv;
+    x509_crl_entry *entry_cur;
+    x509_crl_entry *entry_prv;
+
+    if( crl == NULL )
+        return;
+
+    do
+    {
+        name_cur = crl_cur->issuer.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 );
+        }
+
+        entry_cur = crl_cur->entry.next;
+        while( entry_cur != NULL )
+        {
+            entry_prv = entry_cur;
+            entry_cur = entry_cur->next;
+            memset( entry_prv, 0, sizeof( x509_crl_entry ) );
+            polarssl_free( entry_prv );
+        }
+
+        if( crl_cur->raw.p != NULL )
+        {
+            memset( crl_cur->raw.p, 0, crl_cur->raw.len );
+            polarssl_free( crl_cur->raw.p );
+        }
+
+        crl_cur = crl_cur->next;
+    }
+    while( crl_cur != NULL );
+
+    crl_cur = crl;
+    do
+    {
+        crl_prv = crl_cur;
+        crl_cur = crl_cur->next;
+
+        memset( crl_prv, 0, sizeof( x509_crl ) );
+        if( crl_prv != crl )
+            polarssl_free( crl_prv );
+    }
+    while( crl_cur != NULL );
+}
+
+#endif
diff --git a/library/x509_crt.c b/library/x509_crt.c
new file mode 100644
index 0000000..49cda66
--- /dev/null
+++ b/library/x509_crt.c
@@ -0,0 +1,1692 @@
+/*
+ *  X.509 certificate and private key decoding
+ *
+ *  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.
+ */
+/*
+ *  The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ *  http://www.ietf.org/rfc/rfc3279.txt
+ *  http://www.ietf.org/rfc/rfc3280.txt
+ *
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+
+#include "polarssl/x509_crt.h"
+#include "polarssl/oid.h"
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32)
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#if !defined(_WIN32)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#endif
+#endif
+
+/*
+ *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+ */
+static int x509_get_version( unsigned char **p,
+                             const unsigned char *end,
+                             int *ver )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        {
+            *ver = 0;
+            return( 0 );
+        }
+
+        return( ret );
+    }
+
+    end = *p + len;
+
+    if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_VERSION + ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_VERSION +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ *  Validity ::= SEQUENCE {
+ *       notBefore      Time,
+ *       notAfter       Time }
+ */
+static int x509_get_dates( unsigned char **p,
+                           const unsigned char *end,
+                           x509_time *from,
+                           x509_time *to )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_DATE + ret );
+
+    end = *p + len;
+
+    if( ( ret = x509_get_time( p, end, from ) ) != 0 )
+        return( ret );
+
+    if( ( ret = x509_get_time( p, end, to ) ) != 0 )
+        return( ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_DATE +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * X.509 v2/v3 unique identifier (not parsed)
+ */
+static int x509_get_uid( unsigned char **p,
+                         const unsigned char *end,
+                         x509_buf *uid, int n )
+{
+    int ret;
+
+    if( *p == end )
+        return( 0 );
+
+    uid->tag = **p;
+
+    if( ( ret = asn1_get_tag( p, end, &uid->len,
+            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( 0 );
+
+        return( ret );
+    }
+
+    uid->p = *p;
+    *p += uid->len;
+
+    return( 0 );
+}
+
+static int x509_get_basic_constraints( unsigned char **p,
+                                       const unsigned char *end,
+                                       int *ca_istrue,
+                                       int *max_pathlen )
+{
+    int ret;
+    size_t len;
+
+    /*
+     * BasicConstraints ::= SEQUENCE {
+     *      cA                      BOOLEAN DEFAULT FALSE,
+     *      pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
+     */
+    *ca_istrue = 0; /* DEFAULT FALSE */
+    *max_pathlen = 0; /* endless */
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( *p == end )
+        return 0;
+
+    if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            ret = asn1_get_int( p, end, ca_istrue );
+
+        if( ret != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        if( *ca_istrue != 0 )
+            *ca_istrue = 1;
+    }
+
+    if( *p == end )
+        return 0;
+
+    if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    (*max_pathlen)++;
+
+    return 0;
+}
+
+static int x509_get_ns_cert_type( unsigned char **p,
+                                       const unsigned char *end,
+                                       unsigned char *ns_cert_type)
+{
+    int ret;
+    x509_bitstring bs = { 0, 0, NULL };
+
+    if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( bs.len != 1 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+    /* Get actual bitstring */
+    *ns_cert_type = *bs.p;
+    return 0;
+}
+
+static int x509_get_key_usage( unsigned char **p,
+                               const unsigned char *end,
+                               unsigned char *key_usage)
+{
+    int ret;
+    x509_bitstring bs = { 0, 0, NULL };
+
+    if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( bs.len < 1 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+    /* Get actual bitstring */
+    *key_usage = *bs.p;
+    return 0;
+}
+
+/*
+ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ */
+static int x509_get_ext_key_usage( unsigned char **p,
+                               const unsigned char *end,
+                               x509_sequence *ext_key_usage)
+{
+    int ret;
+
+    if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    /* Sequence length must be >= 1 */
+    if( ext_key_usage->buf.p == NULL )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+    return 0;
+}
+
+/*
+ * SubjectAltName ::= GeneralNames
+ *
+ * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ *
+ * GeneralName ::= CHOICE {
+ *      otherName                       [0]     OtherName,
+ *      rfc822Name                      [1]     IA5String,
+ *      dNSName                         [2]     IA5String,
+ *      x400Address                     [3]     ORAddress,
+ *      directoryName                   [4]     Name,
+ *      ediPartyName                    [5]     EDIPartyName,
+ *      uniformResourceIdentifier       [6]     IA5String,
+ *      iPAddress                       [7]     OCTET STRING,
+ *      registeredID                    [8]     OBJECT IDENTIFIER }
+ *
+ * OtherName ::= SEQUENCE {
+ *      type-id    OBJECT IDENTIFIER,
+ *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= SEQUENCE {
+ *      nameAssigner            [0]     DirectoryString OPTIONAL,
+ *      partyName               [1]     DirectoryString }
+ *
+ * NOTE: PolarSSL only parses and uses dNSName at this point.
+ */
+static int x509_get_subject_alt_name( unsigned char **p,
+                                      const unsigned char *end,
+                                      x509_sequence *subject_alt_name )
+{
+    int ret;
+    size_t len, tag_len;
+    asn1_buf *buf;
+    unsigned char tag;
+    asn1_sequence *cur = subject_alt_name;
+
+    /* Get main sequence tag */
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( *p + len != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    while( *p < end )
+    {
+        if( ( end - *p ) < 1 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                    POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+        tag = **p;
+        (*p)++;
+        if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                    POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+        if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) )
+        {
+            *p += tag_len;
+            continue;
+        }
+
+        buf = &(cur->buf);
+        buf->tag = tag;
+        buf->p = *p;
+        buf->len = tag_len;
+        *p += buf->len;
+
+        /* Allocate and assign next pointer */
+        if (*p < end)
+        {
+            cur->next = (asn1_sequence *) polarssl_malloc(
+                 sizeof( asn1_sequence ) );
+
+            if( cur->next == NULL )
+                return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                        POLARSSL_ERR_ASN1_MALLOC_FAILED );
+
+            memset( cur->next, 0, sizeof( asn1_sequence ) );
+            cur = cur->next;
+        }
+    }
+
+    /* Set final sequence entry's next pointer to NULL */
+    cur->next = NULL;
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * X.509 v3 extensions
+ *
+ * TODO: Perform all of the basic constraints tests required by the RFC
+ * TODO: Set values for undetected extensions to a sane default?
+ *
+ */
+static int x509_get_crt_ext( unsigned char **p,
+                             const unsigned char *end,
+                             x509_crt *crt )
+{
+    int ret;
+    size_t len;
+    unsigned char *end_ext_data, *end_ext_octet;
+
+    if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
+    {
+        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+            return( 0 );
+
+        return( ret );
+    }
+
+    while( *p < end )
+    {
+        /*
+         * Extension  ::=  SEQUENCE  {
+         *      extnID      OBJECT IDENTIFIER,
+         *      critical    BOOLEAN DEFAULT FALSE,
+         *      extnValue   OCTET STRING  }
+         */
+        x509_buf extn_oid = {0, 0, NULL};
+        int is_critical = 0; /* DEFAULT FALSE */
+        int ext_type = 0;
+
+        if( ( ret = asn1_get_tag( p, end, &len,
+                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        end_ext_data = *p + len;
+
+        /* Get extension ID */
+        extn_oid.tag = **p;
+
+        if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        extn_oid.p = *p;
+        *p += extn_oid.len;
+
+        if( ( end - *p ) < 1 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                    POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+        /* Get optional critical */
+        if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
+            ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        /* Data should be octet string type */
+        if( ( ret = asn1_get_tag( p, end_ext_data, &len,
+                ASN1_OCTET_STRING ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        end_ext_octet = *p + len;
+
+        if( end_ext_octet != end_ext_data )
+            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+        /*
+         * Detect supported extensions
+         */
+        ret = oid_get_x509_ext_type( &extn_oid, &ext_type );
+
+        if( ret != 0 )
+        {
+            /* No parser found, skip extension */
+            *p = end_ext_octet;
+
+#if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+            if( is_critical )
+            {
+                /* Data is marked as critical: fail */
+                return ( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                        POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+            }
+#endif
+            continue;
+        }
+
+        crt->ext_types |= ext_type;
+
+        switch( ext_type )
+        {
+        case EXT_BASIC_CONSTRAINTS:
+            /* Parse basic constraints */
+            if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
+                    &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
+                return ( ret );
+            break;
+
+        case EXT_KEY_USAGE:
+            /* Parse key usage */
+            if( ( ret = x509_get_key_usage( p, end_ext_octet,
+                    &crt->key_usage ) ) != 0 )
+                return ( ret );
+            break;
+
+        case EXT_EXTENDED_KEY_USAGE:
+            /* Parse extended key usage */
+            if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
+                    &crt->ext_key_usage ) ) != 0 )
+                return ( ret );
+            break;
+
+        case EXT_SUBJECT_ALT_NAME:
+            /* Parse subject alt name */
+            if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
+                    &crt->subject_alt_names ) ) != 0 )
+                return ( ret );
+            break;
+
+        case EXT_NS_CERT_TYPE:
+            /* Parse netscape certificate type */
+            if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
+                    &crt->ns_cert_type ) ) != 0 )
+                return ( ret );
+            break;
+
+        default:
+            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+        }
+    }
+
+    if( *p != end )
+        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ * Parse and fill a single X.509 certificate in DER format
+ */
+static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
+                                    size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end, *crt_end;
+
+    /*
+     * Check for valid input
+     */
+    if( crt == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    p = (unsigned char *) polarssl_malloc( len = buflen );
+
+    if( p == NULL )
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+    memcpy( p, buf, buflen );
+
+    buflen = 0;
+
+    crt->raw.p = p;
+    crt->raw.len = len;
+    end = p + len;
+
+    /*
+     * Certificate  ::=  SEQUENCE  {
+     *      tbsCertificate       TBSCertificate,
+     *      signatureAlgorithm   AlgorithmIdentifier,
+     *      signatureValue       BIT STRING  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT );
+    }
+
+    if( len > (size_t) ( end - p ) )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    crt_end = p + len;
+
+    /*
+     * TBSCertificate  ::=  SEQUENCE  {
+     */
+    crt->tbs.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    end = p + len;
+    crt->tbs.len = end - crt->tbs.p;
+
+    /*
+     * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+     *
+     * CertificateSerialNumber  ::=  INTEGER
+     *
+     * signature            AlgorithmIdentifier
+     */
+    if( ( ret = x509_get_version(  &p, end, &crt->version  ) ) != 0 ||
+        ( ret = x509_get_serial(   &p, end, &crt->serial   ) ) != 0 ||
+        ( ret = x509_get_alg_null( &p, end, &crt->sig_oid1 ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    crt->version++;
+
+    if( crt->version > 3 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
+    }
+
+    if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_md,
+                                  &crt->sig_pk ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    /*
+     * issuer               Name
+     */
+    crt->issuer_raw.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    crt->issuer_raw.len = p - crt->issuer_raw.p;
+
+    /*
+     * Validity ::= SEQUENCE {
+     *      notBefore      Time,
+     *      notAfter       Time }
+     *
+     */
+    if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
+                                         &crt->valid_to ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    /*
+     * subject              Name
+     */
+    crt->subject_raw.p = p;
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
+    }
+
+    if( len && ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    crt->subject_raw.len = p - crt->subject_raw.p;
+
+    /*
+     * SubjectPublicKeyInfo
+     */
+    if( ( ret = pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    /*
+     *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+     *                       -- If present, version shall be v2 or v3
+     *  subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+     *                       -- If present, version shall be v2 or v3
+     *  extensions      [3]  EXPLICIT Extensions OPTIONAL
+     *                       -- If present, version shall be v3
+     */
+    if( crt->version == 2 || crt->version == 3 )
+    {
+        ret = x509_get_uid( &p, end, &crt->issuer_id,  1 );
+        if( ret != 0 )
+        {
+            x509_crt_free( crt );
+            return( ret );
+        }
+    }
+
+    if( crt->version == 2 || crt->version == 3 )
+    {
+        ret = x509_get_uid( &p, end, &crt->subject_id,  2 );
+        if( ret != 0 )
+        {
+            x509_crt_free( crt );
+            return( ret );
+        }
+    }
+
+    if( crt->version == 3 )
+    {
+        ret = x509_get_crt_ext( &p, end, crt);
+        if( ret != 0 )
+        {
+            x509_crt_free( crt );
+            return( ret );
+        }
+    }
+
+    if( p != end )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    end = crt_end;
+
+    /*
+     *  }
+     *  -- end of TBSCertificate
+     *
+     *  signatureAlgorithm   AlgorithmIdentifier,
+     *  signatureValue       BIT STRING
+     */
+    if( ( ret = x509_get_alg_null( &p, end, &crt->sig_oid2 ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    if( crt->sig_oid1.len != crt->sig_oid2.len ||
+        memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_SIG_MISMATCH );
+    }
+
+    if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
+    {
+        x509_crt_free( crt );
+        return( ret );
+    }
+
+    if( p != end )
+    {
+        x509_crt_free( crt );
+        return( POLARSSL_ERR_X509_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse one X.509 certificate in DER format from a buffer and add them to a
+ * chained list
+ */
+int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf,
+                        size_t buflen )
+{
+    int ret;
+    x509_crt *crt = chain, *prev = NULL;
+
+    /*
+     * Check for valid input
+     */
+    if( crt == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    while( crt->version != 0 && crt->next != NULL )
+    {
+        prev = crt;
+        crt = crt->next;
+    }
+
+    /*
+     * Add new certificate on the end of the chain if needed.
+     */
+    if ( crt->version != 0 && crt->next == NULL)
+    {
+        crt->next = (x509_crt *) polarssl_malloc( sizeof( x509_crt ) );
+
+        if( crt->next == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        prev = crt;
+        crt = crt->next;
+        x509_crt_init( crt );
+    }
+
+    if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 )
+    {
+        if( prev )
+            prev->next = NULL;
+
+        if( crt != chain )
+            polarssl_free( crt );
+
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse one or more PEM certificates from a buffer and add them to the chained list
+ */
+int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen )
+{
+    int success = 0, first_error = 0, total_failed = 0;
+    int buf_format = X509_FORMAT_DER;
+
+    /*
+     * Check for valid input
+     */
+    if( chain == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    /*
+     * Determine buffer content. Buffer contains either one DER certificate or
+     * one or more PEM certificates.
+     */
+#if defined(POLARSSL_PEM_PARSE_C)
+    if( strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
+        buf_format = X509_FORMAT_PEM;
+#endif
+
+    if( buf_format == X509_FORMAT_DER )
+        return x509_crt_parse_der( chain, buf, buflen );
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    if( buf_format == X509_FORMAT_PEM )
+    {
+        int ret;
+        pem_context pem;
+
+        while( buflen > 0 )
+        {
+            size_t use_len;
+            pem_init( &pem );
+
+            ret = pem_read_buffer( &pem,
+                           "-----BEGIN CERTIFICATE-----",
+                           "-----END CERTIFICATE-----",
+                           buf, NULL, 0, &use_len );
+
+            if( ret == 0 )
+            {
+                /*
+                 * Was PEM encoded
+                 */
+                buflen -= use_len;
+                buf += use_len;
+            }
+            else if( ret == POLARSSL_ERR_PEM_BAD_INPUT_DATA )
+            {
+                return( ret );
+            }
+            else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+            {
+                pem_free( &pem );
+
+                /*
+                 * PEM header and footer were found
+                 */
+                buflen -= use_len;
+                buf += use_len;
+
+                if( first_error == 0 )
+                    first_error = ret;
+
+                continue;
+            }
+            else
+                break;
+
+            ret = x509_crt_parse_der( chain, pem.buf, pem.buflen );
+
+            pem_free( &pem );
+
+            if( ret != 0 )
+            {
+                /*
+                 * Quit parsing on a memory error
+                 */
+                if( ret == POLARSSL_ERR_X509_MALLOC_FAILED )
+                    return( ret );
+
+                if( first_error == 0 )
+                    first_error = ret;
+
+                total_failed++;
+                continue;
+            }
+
+            success = 1;
+        }
+    }
+#endif
+
+    if( success )
+        return( total_failed );
+    else if( first_error )
+        return( first_error );
+    else
+        return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load one or more certificates and add them to the chained list
+ */
+int x509_crt_parse_file( x509_crt *chain, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_crt_parse( chain, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+
+int x509_crt_parse_path( x509_crt *chain, const char *path )
+{
+    int ret = 0;
+#if defined(_WIN32)
+    int w_ret;
+    WCHAR szDir[MAX_PATH];
+    char filename[MAX_PATH];
+	char *p;
+    int len = strlen( path );
+
+	WIN32_FIND_DATAW file_data;
+    HANDLE hFind;
+
+    if( len > MAX_PATH - 3 )
+        return( POLARSSL_ERR_X509_INVALID_INPUT );
+
+	memset( szDir, 0, sizeof(szDir) );
+	memset( filename, 0, MAX_PATH );
+	memcpy( filename, path, len );
+	filename[len++] = '\\';
+	p = filename + len;
+    filename[len++] = '*';
+
+	w_ret = MultiByteToWideChar( CP_ACP, 0, path, len, szDir, MAX_PATH - 3 );
+
+    hFind = FindFirstFileW( szDir, &file_data );
+    if (hFind == INVALID_HANDLE_VALUE) 
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+    len = MAX_PATH - len;
+    do
+    {
+		memset( p, 0, len );
+
+        if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+            continue;
+
+		w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
+									 lstrlenW(file_data.cFileName),
+									 p, len - 1,
+									 NULL, NULL );
+
+        w_ret = x509_crt_parse_file( chain, filename );
+        if( w_ret < 0 )
+            ret++;
+        else
+            ret += w_ret;
+    }
+    while( FindNextFileW( hFind, &file_data ) != 0 );
+
+    if (GetLastError() != ERROR_NO_MORE_FILES) 
+        ret = POLARSSL_ERR_X509_FILE_IO_ERROR;
+
+cleanup:
+    FindClose( hFind );
+#else
+    int t_ret, i;
+    struct stat sb;
+    struct dirent entry, *result = NULL;
+    char entry_name[255];
+    DIR *dir = opendir( path );
+
+    if( dir == NULL)
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+    while( ( t_ret = readdir_r( dir, &entry, &result ) ) == 0 )
+    {
+        if( result == NULL )
+            break;
+
+        snprintf( entry_name, sizeof(entry_name), "%s/%s", path, entry.d_name );
+
+        i = stat( entry_name, &sb );
+
+        if( i == -1 )
+        {
+            closedir( dir );
+            return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+        }
+
+        if( !S_ISREG( sb.st_mode ) )
+            continue;
+
+        // Ignore parse errors
+        //
+        t_ret = x509_crt_parse_file( chain, entry_name );
+        if( t_ret < 0 )
+            ret++;
+        else
+            ret += t_ret;
+    }
+    closedir( dir );
+#endif
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined _MSC_VER && !defined snprintf
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return( -1 );                           \
+                                                \
+    if ( (unsigned int) ret > n ) {             \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+/*
+ * Return an informational string about the certificate.
+ */
+#define BEFORE_COLON    14
+#define BC              "14"
+int x509_crt_info( char *buf, size_t size, const char *prefix,
+                   const x509_crt *crt )
+{
+    int ret;
+    size_t n;
+    char *p;
+    const char *desc = NULL;
+    char key_size_str[BEFORE_COLON];
+
+    p = buf;
+    n = size;
+
+    ret = snprintf( p, n, "%scert. version : %d\n",
+                               prefix, crt->version );
+    SAFE_SNPRINTF();
+    ret = snprintf( p, n, "%sserial number : ",
+                               prefix );
+    SAFE_SNPRINTF();
+
+    ret = x509_serial_gets( p, n, &crt->serial);
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sissuer name   : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crt->issuer  );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%ssubject name  : ", prefix );
+    SAFE_SNPRINTF();
+    ret = x509_dn_gets( p, n, &crt->subject );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sissued  on    : " \
+                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                   crt->valid_from.year, crt->valid_from.mon,
+                   crt->valid_from.day,  crt->valid_from.hour,
+                   crt->valid_from.min,  crt->valid_from.sec );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%sexpires on    : " \
+                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                   crt->valid_to.year, crt->valid_to.mon,
+                   crt->valid_to.day,  crt->valid_to.hour,
+                   crt->valid_to.min,  crt->valid_to.sec );
+    SAFE_SNPRINTF();
+
+    ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
+    SAFE_SNPRINTF();
+
+    ret = oid_get_sig_alg_desc( &crt->sig_oid1, &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( &crt->pk ) ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
+                          (int) pk_get_size( &crt->pk ) );
+    SAFE_SNPRINTF();
+
+    return( (int) ( size - n ) );
+}
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+/*
+ * Return 1 if the certificate is revoked, or 0 otherwise.
+ */
+int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl )
+{
+    const x509_crl_entry *cur = &crl->entry;
+
+    while( cur != NULL && cur->serial.len != 0 )
+    {
+        if( crt->serial.len == cur->serial.len &&
+            memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
+        {
+            if( x509_time_expired( &cur->revocation_date ) )
+                return( 1 );
+        }
+
+        cur = cur->next;
+    }
+
+    return( 0 );
+}
+
+/*
+ * Check that the given certificate is valid accoring to the CRL.
+ */
+static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca,
+                               x509_crl *crl_list)
+{
+    int flags = 0;
+    unsigned char hash[POLARSSL_MD_MAX_SIZE];
+    const md_info_t *md_info;
+
+    if( ca == NULL )
+        return( flags );
+
+    /*
+     * TODO: What happens if no CRL is present?
+     * Suggestion: Revocation state should be unknown if no CRL is present.
+     * For backwards compatibility this is not yet implemented.
+     */
+
+    while( crl_list != NULL )
+    {
+        if( crl_list->version == 0 ||
+            crl_list->issuer_raw.len != ca->subject_raw.len ||
+            memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
+                    crl_list->issuer_raw.len ) != 0 )
+        {
+            crl_list = crl_list->next;
+            continue;
+        }
+
+        /*
+         * Check if CRL is correctly signed by the trusted CA
+         */
+        md_info = md_info_from_type( crl_list->sig_md );
+        if( md_info == NULL )
+        {
+            /*
+             * Cannot check 'unknown' hash
+             */
+            flags |= BADCRL_NOT_TRUSTED;
+            break;
+        }
+
+        md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash );
+
+        if( pk_can_do( &ca->pk, crl_list->sig_pk ) == 0 ||
+            pk_verify( &ca->pk, crl_list->sig_md, hash, md_info->size,
+                       crl_list->sig.p, crl_list->sig.len ) != 0 )
+        {
+            flags |= BADCRL_NOT_TRUSTED;
+            break;
+        }
+
+        /*
+         * Check for validity of CRL (Do not drop out)
+         */
+        if( x509_time_expired( &crl_list->next_update ) )
+            flags |= BADCRL_EXPIRED;
+
+        /*
+         * Check if certificate is revoked
+         */
+        if( x509_crt_revoked(crt, crl_list) )
+        {
+            flags |= BADCERT_REVOKED;
+            break;
+        }
+
+        crl_list = crl_list->next;
+    }
+    return flags;
+}
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+
+// Equal == 0, inequal == 1
+static int x509_name_cmp( const void *s1, const void *s2, size_t len )
+{
+    size_t i;
+    unsigned char diff;
+    const unsigned char *n1 = s1, *n2 = s2;
+
+    for( i = 0; i < len; i++ )
+    {
+        diff = n1[i] ^ n2[i];
+
+        if( ( n1[i] >= 'a' || n1[i] <= 'z' ) && ( diff == 0 || diff == 32 ) )
+            continue;
+
+        if( ( n1[i] >= 'A' || n1[i] <= 'Z' ) && ( diff == 0 || diff == 32 ) )
+            continue;
+
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
+static int x509_wildcard_verify( const char *cn, x509_buf *name )
+{
+    size_t i;
+    size_t cn_idx = 0;
+
+    if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
+        return( 0 );
+
+    for( i = 0; i < strlen( cn ); ++i )
+    {
+        if( cn[i] == '.' )
+        {
+            cn_idx = i;
+            break;
+        }
+    }
+
+    if( cn_idx == 0 )
+        return( 0 );
+
+    if( strlen( cn ) - cn_idx == name->len - 1 &&
+        x509_name_cmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
+    {
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
+static int x509_crt_verify_top(
+                x509_crt *child, x509_crt *trust_ca,
+                x509_crl *ca_crl, int path_cnt, int *flags,
+                int (*f_vrfy)(void *, x509_crt *, int, int *),
+                void *p_vrfy )
+{
+    int ret;
+    int ca_flags = 0, check_path_cnt = path_cnt + 1;
+    unsigned char hash[POLARSSL_MD_MAX_SIZE];
+    const md_info_t *md_info;
+
+    if( x509_time_expired( &child->valid_to ) )
+        *flags |= BADCERT_EXPIRED;
+
+    /*
+     * Child is the top of the chain. Check against the trust_ca list.
+     */
+    *flags |= BADCERT_NOT_TRUSTED;
+
+    md_info = md_info_from_type( child->sig_md );
+    if( md_info == NULL )
+    {
+        /*
+         * Cannot check 'unknown', no need to try any CA
+         */
+        trust_ca = NULL;
+    }
+    else
+        md( md_info, child->tbs.p, child->tbs.len, hash );
+
+    while( trust_ca != NULL )
+    {
+        if( trust_ca->version == 0 ||
+            child->issuer_raw.len != trust_ca->subject_raw.len ||
+            memcmp( child->issuer_raw.p, trust_ca->subject_raw.p,
+                    child->issuer_raw.len ) != 0 )
+        {
+            trust_ca = trust_ca->next;
+            continue;
+        }
+
+        /*
+         * Reduce path_len to check against if top of the chain is
+         * the same as the trusted CA
+         */
+        if( child->subject_raw.len == trust_ca->subject_raw.len &&
+            memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
+                            child->issuer_raw.len ) == 0 )
+        {
+            check_path_cnt--;
+        }
+
+        if( trust_ca->max_pathlen > 0 &&
+            trust_ca->max_pathlen < check_path_cnt )
+        {
+            trust_ca = trust_ca->next;
+            continue;
+        }
+
+        if( pk_can_do( &trust_ca->pk, child->sig_pk ) == 0 ||
+            pk_verify( &trust_ca->pk, child->sig_md, hash, md_info->size,
+                       child->sig.p, child->sig.len ) != 0 )
+        {
+            trust_ca = trust_ca->next;
+            continue;
+        }
+
+        /*
+         * Top of chain is signed by a trusted CA
+         */
+        *flags &= ~BADCERT_NOT_TRUSTED;
+        break;
+    }
+
+    /*
+     * If top of chain is not the same as the trusted CA send a verify request
+     * to the callback for any issues with validity and CRL presence for the
+     * trusted CA certificate.
+     */
+    if( trust_ca != NULL &&
+        ( child->subject_raw.len != trust_ca->subject_raw.len ||
+          memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
+                            child->issuer_raw.len ) != 0 ) )
+    {
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+        /* Check trusted CA's CRL for the chain's top crt */
+        *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl );
+#endif
+
+        if( x509_time_expired( &trust_ca->valid_to ) )
+            ca_flags |= BADCERT_EXPIRED;
+
+        if( NULL != f_vrfy )
+        {
+            if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, &ca_flags ) ) != 0 )
+                return( ret );
+        }
+    }
+
+    /* Call callback on top cert */
+    if( NULL != f_vrfy )
+    {
+        if( ( ret = f_vrfy(p_vrfy, child, path_cnt, flags ) ) != 0 )
+            return( ret );
+    }
+
+    *flags |= ca_flags;
+
+    return( 0 );
+}
+
+static int x509_crt_verify_child(
+                x509_crt *child, x509_crt *parent, x509_crt *trust_ca,
+                x509_crl *ca_crl, int path_cnt, int *flags,
+                int (*f_vrfy)(void *, x509_crt *, int, int *),
+                void *p_vrfy )
+{
+    int ret;
+    int parent_flags = 0;
+    unsigned char hash[POLARSSL_MD_MAX_SIZE];
+    x509_crt *grandparent;
+    const md_info_t *md_info;
+
+    if( x509_time_expired( &child->valid_to ) )
+        *flags |= BADCERT_EXPIRED;
+
+    md_info = md_info_from_type( child->sig_md );
+    if( md_info == NULL )
+    {
+        /*
+         * Cannot check 'unknown' hash
+         */
+        *flags |= BADCERT_NOT_TRUSTED;
+    }
+    else
+    {
+        md( md_info, child->tbs.p, child->tbs.len, hash );
+
+        if( pk_can_do( &parent->pk, child->sig_pk ) == 0 ||
+            pk_verify( &parent->pk, child->sig_md, hash, md_info->size,
+                       child->sig.p, child->sig.len ) != 0 )
+        {
+            *flags |= BADCERT_NOT_TRUSTED;
+        }
+    }
+
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+    /* Check trusted CA's CRL for the given crt */
+    *flags |= x509_crt_verifycrl(child, parent, ca_crl);
+#endif
+
+    grandparent = parent->next;
+
+    while( grandparent != NULL )
+    {
+        if( grandparent->version == 0 ||
+            grandparent->ca_istrue == 0 ||
+            parent->issuer_raw.len != grandparent->subject_raw.len ||
+            memcmp( parent->issuer_raw.p, grandparent->subject_raw.p,
+                    parent->issuer_raw.len ) != 0 )
+        {
+            grandparent = grandparent->next;
+            continue;
+        }
+        break;
+    }
+
+    if( grandparent != NULL )
+    {
+        /*
+         * Part of the chain
+         */
+        ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
+        if( ret != 0 )
+            return( ret );
+    }
+    else
+    {
+        ret = x509_crt_verify_top( parent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    /* child is verified to be a child of the parent, call verify callback */
+    if( NULL != f_vrfy )
+        if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 )
+            return( ret );
+
+    *flags |= parent_flags;
+
+    return( 0 );
+}
+
+/*
+ * Verify the certificate validity
+ */
+int x509_crt_verify( x509_crt *crt,
+                     x509_crt *trust_ca,
+                     x509_crl *ca_crl,
+                     const char *cn, int *flags,
+                     int (*f_vrfy)(void *, x509_crt *, int, int *),
+                     void *p_vrfy )
+{
+    size_t cn_len;
+    int ret;
+    int pathlen = 0;
+    x509_crt *parent;
+    x509_name *name;
+    x509_sequence *cur = NULL;
+
+    *flags = 0;
+
+    if( cn != NULL )
+    {
+        name = &crt->subject;
+        cn_len = strlen( cn );
+
+        if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
+        {
+            cur = &crt->subject_alt_names;
+
+            while( cur != NULL )
+            {
+                if( cur->buf.len == cn_len &&
+                    x509_name_cmp( cn, cur->buf.p, cn_len ) == 0 )
+                    break;
+
+                if( cur->buf.len > 2 &&
+                    memcmp( cur->buf.p, "*.", 2 ) == 0 &&
+                            x509_wildcard_verify( cn, &cur->buf ) )
+                    break;
+
+                cur = cur->next;
+            }
+
+            if( cur == NULL )
+                *flags |= BADCERT_CN_MISMATCH;
+        }
+        else
+        {
+            while( name != NULL )
+            {
+                if( OID_CMP( OID_AT_CN, &name->oid ) )
+                {
+                    if( name->val.len == cn_len &&
+                        x509_name_cmp( name->val.p, cn, cn_len ) == 0 )
+                        break;
+
+                    if( name->val.len > 2 &&
+                        memcmp( name->val.p, "*.", 2 ) == 0 &&
+                                x509_wildcard_verify( cn, &name->val ) )
+                        break;
+                }
+
+                name = name->next;
+            }
+
+            if( name == NULL )
+                *flags |= BADCERT_CN_MISMATCH;
+        }
+    }
+
+    /*
+     * Iterate upwards in the given cert chain, to find our crt parent.
+     * Ignore any upper cert with CA != TRUE.
+     */
+    parent = crt->next;
+
+    while( parent != NULL && parent->version != 0 )
+    {
+        if( parent->ca_istrue == 0 ||
+            crt->issuer_raw.len != parent->subject_raw.len ||
+            memcmp( crt->issuer_raw.p, parent->subject_raw.p,
+                    crt->issuer_raw.len ) != 0 )
+        {
+            parent = parent->next;
+            continue;
+        }
+        break;
+    }
+
+    if( parent != NULL )
+    {
+        /*
+         * Part of the chain
+         */
+        ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy );
+        if( ret != 0 )
+            return( ret );
+    }
+    else
+    {
+        ret = x509_crt_verify_top( crt, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    if( *flags != 0 )
+        return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+
+    return( 0 );
+}
+
+/*
+ * Initialize a certificate chain
+ */
+void x509_crt_init( x509_crt *crt )
+{
+    memset( crt, 0, sizeof(x509_crt) );
+}
+
+/*
+ * Unallocate all certificate data
+ */
+void x509_crt_free( x509_crt *crt )
+{
+    x509_crt *cert_cur = crt;
+    x509_crt *cert_prv;
+    x509_name *name_cur;
+    x509_name *name_prv;
+    x509_sequence *seq_cur;
+    x509_sequence *seq_prv;
+
+    if( crt == NULL )
+        return;
+
+    do
+    {
+        pk_free( &cert_cur->pk );
+
+        name_cur = cert_cur->issuer.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 );
+        }
+
+        name_cur = cert_cur->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 );
+        }
+
+        seq_cur = cert_cur->ext_key_usage.next;
+        while( seq_cur != NULL )
+        {
+            seq_prv = seq_cur;
+            seq_cur = seq_cur->next;
+            memset( seq_prv, 0, sizeof( x509_sequence ) );
+            polarssl_free( seq_prv );
+        }
+
+        seq_cur = cert_cur->subject_alt_names.next;
+        while( seq_cur != NULL )
+        {
+            seq_prv = seq_cur;
+            seq_cur = seq_cur->next;
+            memset( seq_prv, 0, sizeof( x509_sequence ) );
+            polarssl_free( seq_prv );
+        }
+
+        if( cert_cur->raw.p != NULL )
+        {
+            memset( cert_cur->raw.p, 0, cert_cur->raw.len );
+            polarssl_free( cert_cur->raw.p );
+        }
+
+        cert_cur = cert_cur->next;
+    }
+    while( cert_cur != NULL );
+
+    cert_cur = crt;
+    do
+    {
+        cert_prv = cert_cur;
+        cert_cur = cert_cur->next;
+
+        memset( cert_prv, 0, sizeof( x509_crt ) );
+        if( cert_prv != crt )
+            polarssl_free( cert_prv );
+    }
+    while( cert_cur != NULL );
+}
+
+#endif
diff --git a/library/x509_csr.c b/library/x509_csr.c
new file mode 100644
index 0000000..91ddb1f
--- /dev/null
+++ b/library/x509_csr.c
@@ -0,0 +1,447 @@
+/*
+ *  X.509 Certificate Signing Request (CSR) parsing
+ *
+ *  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.
+ */
+/*
+ *  The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ *  http://www.ietf.org/rfc/rfc3279.txt
+ *  http://www.ietf.org/rfc/rfc3280.txt
+ *
+ *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+
+#include "polarssl/x509_csr.h"
+#include "polarssl/oid.h"
+#if defined(POLARSSL_PEM_PARSE_C)
+#include "polarssl/pem.h"
+#endif
+#if defined(POLARSSL_ASN1_WRITE_C)
+#include "polarssl/asn1write.h"
+#endif
+
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+/*
+ *  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_INVALID_VERSION + ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse a CSR
+ */
+int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t use_len;
+    pem_context pem;
+#endif
+
+    /*
+     * Check for valid input
+     */
+    if( csr == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    x509_csr_init( csr );
+
+#if defined(POLARSSL_PEM_PARSE_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
+#endif
+    {
+        /*
+         * 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;
+    }
+
+    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_INVALID_FORMAT );
+    }
+
+    if( len != (size_t) ( end - p ) )
+    {
+        x509_csr_free( csr );
+        return( POLARSSL_ERR_X509_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_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_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_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 = pk_parse_subpubkey( &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_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_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_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load a CSR into the structure
+ */
+int x509_csr_parse_file( x509_csr *csr, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = x509_csr_parse( csr, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined _MSC_VER && !defined snprintf
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+static int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int res = -1;
+
+    va_start( ap, format );
+
+    res = vsnprintf( str, size, format, ap );
+
+    va_end( ap );
+
+    // No quick fix possible
+    if ( res < 0 )
+        return( (int) size + 20 );
+
+    return res;
+}
+
+#define snprintf compat_snprintf
+#endif
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
+
+#define SAFE_SNPRINTF()                         \
+{                                               \
+    if( ret == -1 )                             \
+        return( -1 );                           \
+                                                \
+    if ( (unsigned int) ret > n ) {             \
+        p[n - 1] = '\0';                        \
+        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+    }                                           \
+                                                \
+    n -= (unsigned int) ret;                    \
+    p += (unsigned int) ret;                    \
+}
+
+#define BEFORE_COLON    14
+#define BC              "14"
+/*
+ * Return an informational string about the CSR.
+ */
+int x509_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 = x509_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 ) );
+}
+
+/*
+ * Initialize a CSR
+ */
+void x509_csr_init( x509_csr *csr )
+{
+    memset( csr, 0, sizeof(x509_csr) );
+}
+
+/*
+ * 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 ) );
+}
+
+#endif /* POLARSSL_X509_CSR_PARSE_C */
diff --git a/library/x509parse.c b/library/x509parse.c
deleted file mode 100644
index f5e8688..0000000
--- a/library/x509parse.c
+++ /dev/null
@@ -1,4374 +0,0 @@
-/*
- *  X.509 certificate and private key decoding
- *
- *  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.
- */
-/*
- *  The ITU-T X.509 standard defines a certificate format for PKI.
- *
- *  http://www.ietf.org/rfc/rfc3279.txt
- *  http://www.ietf.org/rfc/rfc3280.txt
- *
- *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
- *
- *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
- *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_X509_PARSE_C)
-
-#include "polarssl/x509.h"
-#include "polarssl/asn1.h"
-#include "polarssl/oid.h"
-#include "polarssl/pem.h"
-#include "polarssl/dhm.h"
-#if defined(POLARSSL_PKCS5_C)
-#include "polarssl/pkcs5.h"
-#endif
-#if defined(POLARSSL_PKCS12_C)
-#include "polarssl/pkcs12.h"
-#endif
-
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
-#else
-#define polarssl_malloc     malloc
-#define polarssl_free       free
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#if defined(_WIN32)
-#include <windows.h>
-#else
-#include <time.h>
-#endif
-
-#if defined(POLARSSL_FS_IO)
-#include <stdio.h>
-#if !defined(_WIN32)
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#endif
-#endif
-
-/*
- *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
- */
-static int x509_get_version( unsigned char **p,
-                             const unsigned char *end,
-                             int *ver )
-{
-    int ret;
-    size_t len;
-
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
-    {
-        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-        {
-            *ver = 0;
-            return( 0 );
-        }
-
-        return( ret );
-    }
-
-    end = *p + len;
-
-    if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_VERSION +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
-}
-
-/*
- *  Version  ::=  INTEGER  {  v1(0), v2(1)  }
- */
-static int x509_crl_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 );
-}
-
-/*
- *  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,
-                            const unsigned char *end,
-                            x509_buf *serial )
-{
-    int ret;
-
-    if( ( end - *p ) < 1 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
-                POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
-        **p !=   ASN1_INTEGER )
-        return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
-                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-
-    serial->tag = *(*p)++;
-
-    if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL + ret );
-
-    serial->p = *p;
-    *p += serial->len;
-
-    return( 0 );
-}
-
-/* Get a PK algorithm identifier
- *
- *  AlgorithmIdentifier  ::=  SEQUENCE  {
- *       algorithm               OBJECT IDENTIFIER,
- *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
- */
-static int x509_get_pk_alg( unsigned char **p,
-                            const unsigned char *end,
-                            pk_type_t *pk_alg, x509_buf *params )
-{
-    int ret;
-    x509_buf alg_oid;
-
-    memset( params, 0, sizeof(asn1_buf) );
-
-    if( ( ret = asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
-
-    if( oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-    /*
-     * No parameters with RSA (only for EC)
-     */
-    if( *pk_alg == POLARSSL_PK_RSA &&
-            ( ( params->tag != ASN1_NULL && params->tag != 0 ) ||
-                params->len != 0 ) )
-    {
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG );
-    }
-
-    return( 0 );
-}
-
-/* Get an algorithm identifier without parameters (eg for signatures)
- *
- *  AlgorithmIdentifier  ::=  SEQUENCE  {
- *       algorithm               OBJECT IDENTIFIER,
- *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
- */
-static int x509_get_alg_null( unsigned char **p, const unsigned char *end,
-                              x509_buf *alg )
-{
-    int ret;
-
-    if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
-
-    return( 0 );
-}
-
-
-#if defined(POLARSSL_ECP_C)
-/* Get an EC group id from an ECParameters buffer
- *
- * ECParameters ::= CHOICE {
- *   namedCurve         OBJECT IDENTIFIER
- *   -- implicitCurve   NULL
- *   -- specifiedCurve  SpecifiedECDomain
- * }
- */
-static int x509_get_ecparams( unsigned char **p, const unsigned char *end,
-                              x509_buf *params )
-{
-    int ret;
-
-    params->tag = **p;
-
-    if( ( ret = asn1_get_tag( p, end, &params->len, ASN1_OID ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    params->p = *p;
-    *p += params->len;
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
-}
-
-/*
- * Use EC parameters to initialise an EC group
- */
-static int x509_use_ecparams( const x509_buf *params, ecp_group *grp )
-{
-    int ret;
-    ecp_group_id grp_id;
-
-    if( oid_get_ec_grp( params, &grp_id ) != 0 )
-        return( POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE );
-
-    /*
-     * grp may already be initilialized; if so, make sure IDs match
-     */
-    if( grp->id != POLARSSL_ECP_DP_NONE && grp->id != grp_id )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
-
-    if( ( ret = ecp_use_known_dp( grp, grp_id ) ) != 0 )
-        return( ret );
-
-    return( 0 );
-}
-#endif /* POLARSSL_ECP_C */
-
-/*
- *  AttributeTypeAndValue ::= SEQUENCE {
- *    type     AttributeType,
- *    value    AttributeValue }
- *
- *  AttributeType ::= OBJECT IDENTIFIER
- *
- *  AttributeValue ::= ANY DEFINED BY AttributeType
- */
-static int x509_get_attr_type_value( unsigned char **p,
-                                     const unsigned char *end,
-                                     x509_name *cur )
-{
-    int ret;
-    size_t len;
-    x509_buf *oid;
-    x509_buf *val;
-
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
-
-    if( ( end - *p ) < 1 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
-                POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    oid = &cur->oid;
-    oid->tag = **p;
-
-    if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
-
-    oid->p = *p;
-    *p += oid->len;
-
-    if( ( end - *p ) < 1 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
-                POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING      &&
-        **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
-        **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
-        return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
-                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-
-    val = &cur->val;
-    val->tag = *(*p)++;
-
-    if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
-
-    val->p = *p;
-    *p += val->len;
-
-    cur->next = NULL;
-
-    return( 0 );
-}
-
-/*
- *  RelativeDistinguishedName ::=
- *    SET OF AttributeTypeAndValue
- *
- *  AttributeTypeAndValue ::= SEQUENCE {
- *    type     AttributeType,
- *    value    AttributeValue }
- *
- *  AttributeType ::= OBJECT IDENTIFIER
- *
- *  AttributeValue ::= ANY DEFINED BY AttributeType
- */
-static int x509_get_name( unsigned char **p,
-                          const unsigned char *end,
-                          x509_name *cur )
-{
-    int ret;
-    size_t len;
-    const unsigned char *end2;
-    x509_name *use; 
-    
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
-
-    end2 = end;
-    end  = *p + len;
-    use = cur;
-
-    do
-    {
-        if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
-            return( ret );
-        
-        if( *p != end )
-        {
-            use->next = (x509_name *) polarssl_malloc(
-                    sizeof( x509_name ) );
-
-            if( use->next == NULL )
-                return( POLARSSL_ERR_X509_MALLOC_FAILED );
-            
-            memset( use->next, 0, sizeof( x509_name ) );
-
-            use = use->next;
-        }
-    }
-    while( *p != end );
-
-    /*
-     * recurse until end of SEQUENCE is reached
-     */
-    if( *p == end2 )
-        return( 0 );
-
-    cur->next = (x509_name *) polarssl_malloc(
-         sizeof( x509_name ) );
-
-    if( cur->next == NULL )
-        return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
-    memset( cur->next, 0, sizeof( x509_name ) );
-
-    return( x509_get_name( p, end2, cur->next ) );
-}
-
-/*
- *  Time ::= CHOICE {
- *       utcTime        UTCTime,
- *       generalTime    GeneralizedTime }
- */
-static int x509_get_time( unsigned char **p,
-                          const unsigned char *end,
-                          x509_time *time )
-{
-    int ret;
-    size_t len;
-    char date[64];
-    unsigned char tag;
-
-    if( ( end - *p ) < 1 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
-                POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    tag = **p;
-
-    if ( tag == ASN1_UTC_TIME )
-    {
-        (*p)++;
-        ret = asn1_get_len( p, end, &len );
-        
-        if( ret != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
-
-        memset( date,  0, sizeof( date ) );
-        memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
-                len : sizeof( date ) - 1 );
-
-        if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
-                    &time->year, &time->mon, &time->day,
-                    &time->hour, &time->min, &time->sec ) < 5 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
-
-        time->year +=  100 * ( time->year < 50 );
-        time->year += 1900;
-
-        *p += len;
-
-        return( 0 );
-    }
-    else if ( tag == ASN1_GENERALIZED_TIME )
-    {
-        (*p)++;
-        ret = asn1_get_len( p, end, &len );
-        
-        if( ret != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
-
-        memset( date,  0, sizeof( date ) );
-        memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
-                len : sizeof( date ) - 1 );
-
-        if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
-                    &time->year, &time->mon, &time->day,
-                    &time->hour, &time->min, &time->sec ) < 5 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
-
-        *p += len;
-
-        return( 0 );
-    }
-    else
-        return( POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-}
-
-
-/*
- *  Validity ::= SEQUENCE {
- *       notBefore      Time,
- *       notAfter       Time }
- */
-static int x509_get_dates( unsigned char **p,
-                           const unsigned char *end,
-                           x509_time *from,
-                           x509_time *to )
-{
-    int ret;
-    size_t len;
-
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
-
-    end = *p + len;
-
-    if( ( ret = x509_get_time( p, end, from ) ) != 0 )
-        return( ret );
-
-    if( ( ret = x509_get_time( p, end, to ) ) != 0 )
-        return( ret );
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
-}
-
-#if defined(POLARSSL_RSA_C)
-/*
- *  RSAPublicKey ::= SEQUENCE {
- *      modulus           INTEGER,  -- n
- *      publicExponent    INTEGER   -- e
- *  }
- */
-static int x509_get_rsapubkey( unsigned char **p,
-                               const unsigned char *end,
-                               rsa_context *rsa )
-{
-    int ret;
-    size_t len;
-
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
-
-    if( *p + len != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    if( ( ret = asn1_get_mpi( p, end, &rsa->N ) ) != 0 ||
-        ( ret = asn1_get_mpi( p, end, &rsa->E ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
-        return( ret );
-
-    rsa->len = mpi_size( &rsa->N );
-
-    return( 0 );
-}
-#endif /* POLARSSL_RSA_C */
-
-#if defined(POLARSSL_ECP_C)
-/*
- * EC public key is an EC point
- */
-static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end,
-                              ecp_keypair *key )
-{
-    int ret;
-
-    if( ( ret = ecp_point_read_binary( &key->grp, &key->Q,
-                    (const unsigned char *) *p, end - *p ) ) != 0 ||
-        ( ret = ecp_check_pubkey( &key->grp, &key->Q ) ) != 0 )
-    {
-        ecp_keypair_free( key );
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
-    }
-
-    /*
-     * We know ecp_point_read_binary consumed all bytes
-     */
-    *p = (unsigned char *) end;
-
-    return( 0 );
-}
-#endif /* POLARSSL_ECP_C */
-
-/*
- *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
- *       algorithm            AlgorithmIdentifier,
- *       subjectPublicKey     BIT STRING }
- */
-static int x509_get_pubkey( unsigned char **p,
-                            const unsigned char *end,
-                            pk_context *pk )
-{
-    int ret;
-    size_t len;
-    x509_buf alg_params;
-    pk_type_t pk_alg = POLARSSL_PK_NONE;
-    const pk_info_t *pk_info;
-
-    if( ( ret = asn1_get_tag( p, end, &len,
-                    ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    end = *p + len;
-
-    if( ( ret = x509_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
-        return( ret );
-
-    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
-
-    if( *p + len != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL )
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-    if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 )
-        return( ret );
-
-#if defined(POLARSSL_RSA_C)
-    if( pk_alg == POLARSSL_PK_RSA )
-    {
-        ret = x509_get_rsapubkey( p, end, pk_rsa( *pk ) );
-    } else
-#endif /* POLARSSL_RSA_C */
-#if defined(POLARSSL_ECP_C)
-    if( pk_alg == POLARSSL_PK_ECKEY_DH || pk_alg == POLARSSL_PK_ECKEY )
-    {
-        ret = x509_use_ecparams( &alg_params, &pk_ec( *pk )->grp );
-        if( ret == 0 )
-            ret = x509_get_ecpubkey( p, end, pk_ec( *pk ) );
-    } else
-#endif /* POLARSSL_ECP_C */
-        ret = POLARSSL_ERR_X509_UNKNOWN_PK_ALG;
-
-    if( ret == 0 && *p != end )
-        ret = POLARSSL_ERR_X509_CERT_INVALID_PUBKEY
-              POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
-
-    if( ret != 0 )
-        pk_free( pk );
-
-    return( ret );
-}
-
-static int x509_get_sig( unsigned char **p,
-                         const unsigned char *end,
-                         x509_buf *sig )
-{
-    int ret;
-    size_t len;
-
-    if( ( end - *p ) < 1 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE +
-                POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    sig->tag = **p;
-
-    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + ret );
-
-    sig->len = len;
-    sig->p = *p;
-
-    *p += len;
-
-    return( 0 );
-}
-
-/*
- * X.509 v2/v3 unique identifier (not parsed)
- */
-static int x509_get_uid( unsigned char **p,
-                         const unsigned char *end,
-                         x509_buf *uid, int n )
-{
-    int ret;
-
-    if( *p == end )
-        return( 0 );
-
-    uid->tag = **p;
-
-    if( ( ret = asn1_get_tag( p, end, &uid->len,
-            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
-    {
-        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-            return( 0 );
-
-        return( ret );
-    }
-
-    uid->p = *p;
-    *p += uid->len;
-
-    return( 0 );
-}
-
-/*
- * X.509 Extensions (No parsing of extensions, pointer should
- * be either manually updated or extensions should be parsed!
- */
-static int x509_get_ext( unsigned char **p,
-                         const unsigned char *end,
-                         x509_buf *ext, int tag )
-{
-    int ret;
-    size_t len;
-
-    if( *p == end )
-        return( 0 );
-
-    ext->tag = **p;
-
-    if( ( ret = asn1_get_tag( p, end, &ext->len,
-            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
-        return( ret );
-
-    ext->p = *p;
-    end = *p + ext->len;
-
-    /*
-     * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
-     *
-     * Extension  ::=  SEQUENCE  {
-     *      extnID      OBJECT IDENTIFIER,
-     *      critical    BOOLEAN DEFAULT FALSE,
-     *      extnValue   OCTET STRING  }
-     */
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-    if( end != *p + len )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
-}
-
-/*
- * X.509 CRL v2 extensions (no extensions parsed yet.)
- */
-static int x509_get_crl_ext( unsigned char **p,
-                             const unsigned char *end,
-                             x509_buf *ext )
-{
-    int ret;
-    size_t len = 0;
-
-    /* Get explicit tag */
-    if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 )
-    {
-        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-            return( 0 );
-
-        return( ret );
-    }
-
-    while( *p < end )
-    {
-        if( ( ret = asn1_get_tag( p, end, &len,
-                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-        *p += len;
-    }
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
-}
-
-/*
- * X.509 CRL v2 entry extensions (no extensions parsed yet.)
- */
-static int x509_get_crl_entry_ext( unsigned char **p,
-                             const unsigned char *end,
-                             x509_buf *ext )
-{
-    int ret;
-    size_t len = 0;
-
-    /* OPTIONAL */
-    if (end <= *p)
-        return( 0 );
-
-    ext->tag = **p;
-    ext->p = *p;
-
-    /*
-     * Get CRL-entry extension sequence header
-     * crlEntryExtensions      Extensions OPTIONAL  -- if present, MUST be v2
-     */
-    if( ( ret = asn1_get_tag( p, end, &ext->len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-        {
-            ext->p = NULL;
-            return( 0 );
-        }
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-    }
-
-	end = *p + ext->len;
-
-    if( end != *p + ext->len )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    while( *p < end )
-    {
-        if( ( ret = asn1_get_tag( p, end, &len,
-                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-        *p += len;
-    }
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
-}
-
-static int x509_get_basic_constraints( unsigned char **p,
-                                       const unsigned char *end,
-                                       int *ca_istrue,
-                                       int *max_pathlen )
-{
-    int ret;
-    size_t len;
-
-    /*
-     * BasicConstraints ::= SEQUENCE {
-     *      cA                      BOOLEAN DEFAULT FALSE,
-     *      pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
-     */
-    *ca_istrue = 0; /* DEFAULT FALSE */
-    *max_pathlen = 0; /* endless */
-
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-    if( *p == end )
-        return 0;
-
-    if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
-    {
-        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-            ret = asn1_get_int( p, end, ca_istrue );
-
-        if( ret != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-        if( *ca_istrue != 0 )
-            *ca_istrue = 1;
-    }
-
-    if( *p == end )
-        return 0;
-
-    if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    (*max_pathlen)++;
-
-    return 0;
-}
-
-static int x509_get_ns_cert_type( unsigned char **p,
-                                       const unsigned char *end,
-                                       unsigned char *ns_cert_type)
-{
-    int ret;
-    x509_bitstring bs = { 0, 0, NULL };
-
-    if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-    if( bs.len != 1 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
-    /* Get actual bitstring */
-    *ns_cert_type = *bs.p;
-    return 0;
-}
-
-static int x509_get_key_usage( unsigned char **p,
-                               const unsigned char *end,
-                               unsigned char *key_usage)
-{
-    int ret;
-    x509_bitstring bs = { 0, 0, NULL };
-
-    if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-    if( bs.len < 1 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
-    /* Get actual bitstring */
-    *key_usage = *bs.p;
-    return 0;
-}
-
-/*
- * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
- *
- * KeyPurposeId ::= OBJECT IDENTIFIER
- */
-static int x509_get_ext_key_usage( unsigned char **p,
-                               const unsigned char *end,
-                               x509_sequence *ext_key_usage)
-{
-    int ret;
-
-    if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-    /* Sequence length must be >= 1 */
-    if( ext_key_usage->buf.p == NULL )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
-    return 0;
-}
-
-/*
- * SubjectAltName ::= GeneralNames
- *
- * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
- *
- * GeneralName ::= CHOICE {
- *      otherName                       [0]     OtherName,
- *      rfc822Name                      [1]     IA5String,
- *      dNSName                         [2]     IA5String,
- *      x400Address                     [3]     ORAddress,
- *      directoryName                   [4]     Name,
- *      ediPartyName                    [5]     EDIPartyName,
- *      uniformResourceIdentifier       [6]     IA5String,
- *      iPAddress                       [7]     OCTET STRING,
- *      registeredID                    [8]     OBJECT IDENTIFIER }
- *
- * OtherName ::= SEQUENCE {
- *      type-id    OBJECT IDENTIFIER,
- *      value      [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * EDIPartyName ::= SEQUENCE {
- *      nameAssigner            [0]     DirectoryString OPTIONAL,
- *      partyName               [1]     DirectoryString }
- *
- * NOTE: PolarSSL only parses and uses dNSName at this point.
- */
-static int x509_get_subject_alt_name( unsigned char **p,
-                                      const unsigned char *end,
-                                      x509_sequence *subject_alt_name )
-{
-    int ret;
-    size_t len, tag_len;
-    asn1_buf *buf;
-    unsigned char tag;
-    asn1_sequence *cur = subject_alt_name;
-
-    /* Get main sequence tag */
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-    if( *p + len != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    while( *p < end )
-    {
-        if( ( end - *p ) < 1 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                    POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-        tag = **p;
-        (*p)++;
-        if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-        if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                    POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-
-        if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) )
-        {
-            *p += tag_len;
-            continue;
-        }
-
-        buf = &(cur->buf);
-        buf->tag = tag;
-        buf->p = *p;
-        buf->len = tag_len;
-        *p += buf->len;
-
-        /* Allocate and assign next pointer */
-        if (*p < end)
-        {
-            cur->next = (asn1_sequence *) polarssl_malloc(
-                 sizeof( asn1_sequence ) );
-
-            if( cur->next == NULL )
-                return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                        POLARSSL_ERR_ASN1_MALLOC_FAILED );
-
-            memset( cur->next, 0, sizeof( asn1_sequence ) );
-            cur = cur->next;
-        }
-    }
-
-    /* Set final sequence entry's next pointer to NULL */
-    cur->next = NULL;
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
-}
-
-/*
- * X.509 v3 extensions
- *
- * TODO: Perform all of the basic constraints tests required by the RFC
- * TODO: Set values for undetected extensions to a sane default?
- *
- */
-static int x509_get_crt_ext( unsigned char **p,
-                             const unsigned char *end,
-                             x509_cert *crt )
-{
-    int ret;
-    size_t len;
-    unsigned char *end_ext_data, *end_ext_octet;
-
-    if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
-    {
-        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-            return( 0 );
-
-        return( ret );
-    }
-
-    while( *p < end )
-    {
-        /*
-         * Extension  ::=  SEQUENCE  {
-         *      extnID      OBJECT IDENTIFIER,
-         *      critical    BOOLEAN DEFAULT FALSE,
-         *      extnValue   OCTET STRING  }
-         */
-        x509_buf extn_oid = {0, 0, NULL};
-        int is_critical = 0; /* DEFAULT FALSE */
-        int ext_type = 0;
-
-        if( ( ret = asn1_get_tag( p, end, &len,
-                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-        end_ext_data = *p + len;
-
-        /* Get extension ID */
-        extn_oid.tag = **p;
-
-        if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-        extn_oid.p = *p;
-        *p += extn_oid.len;
-
-        if( ( end - *p ) < 1 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                    POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-        /* Get optional critical */
-        if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
-            ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-        /* Data should be octet string type */
-        if( ( ret = asn1_get_tag( p, end_ext_data, &len,
-                ASN1_OCTET_STRING ) ) != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
-        end_ext_octet = *p + len;
-
-        if( end_ext_octet != end_ext_data )
-            return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-        /*
-         * Detect supported extensions
-         */
-        ret = oid_get_x509_ext_type( &extn_oid, &ext_type );
-
-        if( ret != 0 )
-        {
-            /* No parser found, skip extension */
-            *p = end_ext_octet;
-
-#if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
-            if( is_critical )
-            {
-                /* Data is marked as critical: fail */
-                return ( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                        POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-            }
-#endif
-            continue;
-        }
-
-        crt->ext_types |= ext_type;
-
-        switch( ext_type )
-        {
-        case EXT_BASIC_CONSTRAINTS:
-            /* Parse basic constraints */
-            if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
-                    &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
-                return ( ret );
-            break;
-
-        case EXT_KEY_USAGE:
-            /* Parse key usage */
-            if( ( ret = x509_get_key_usage( p, end_ext_octet,
-                    &crt->key_usage ) ) != 0 )
-                return ( ret );
-            break;
-
-        case EXT_EXTENDED_KEY_USAGE:
-            /* Parse extended key usage */
-            if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
-                    &crt->ext_key_usage ) ) != 0 )
-                return ( ret );
-            break;
-
-        case EXT_SUBJECT_ALT_NAME:
-            /* Parse subject alt name */
-            if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
-                    &crt->subject_alt_names ) ) != 0 )
-                return ( ret );
-            break;
-
-        case EXT_NS_CERT_TYPE:
-            /* Parse netscape certificate type */
-            if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
-                    &crt->ns_cert_type ) ) != 0 )
-                return ( ret );
-            break;
-
-        default:
-            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-        }
-    }
-
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
-}
-
-/*
- * X.509 CRL Entries
- */
-static int x509_get_entries( unsigned char **p,
-                             const unsigned char *end,
-                             x509_crl_entry *entry )
-{
-    int ret;
-    size_t entry_len;
-    x509_crl_entry *cur_entry = entry;
-
-    if( *p == end )
-        return( 0 );
-
-    if( ( ret = asn1_get_tag( p, end, &entry_len,
-            ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
-    {
-        if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-            return( 0 );
-
-        return( ret );
-    }
-
-    end = *p + entry_len;
-
-    while( *p < end )
-    {
-        size_t len2;
-        const unsigned char *end2;
-
-        if( ( ret = asn1_get_tag( p, end, &len2,
-                ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
-        {
-            return( ret );
-        }
-
-        cur_entry->raw.tag = **p;
-        cur_entry->raw.p = *p;
-        cur_entry->raw.len = len2;
-        end2 = *p + len2;
-
-        if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
-            return( ret );
-
-        if( ( ret = x509_get_time( p, end2, &cur_entry->revocation_date ) ) != 0 )
-            return( ret );
-
-        if( ( ret = x509_get_crl_entry_ext( p, end2, &cur_entry->entry_ext ) ) != 0 )
-            return( ret );
-
-        if ( *p < end )
-        {
-            cur_entry->next = polarssl_malloc( sizeof( x509_crl_entry ) );
-
-            if( cur_entry->next == NULL )
-                return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
-            cur_entry = cur_entry->next;
-            memset( cur_entry, 0, sizeof( x509_crl_entry ) );
-        }
-    }
-
-    return( 0 );
-}
-
-static int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
-                             pk_type_t *pk_alg )
-{
-    int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
-
-    if( ret != 0 )
-        return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG + ret );
-
-    return( 0 );
-}
-
-/*
- * Parse and fill a single X.509 certificate in DER format
- */
-static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf,
-                                   size_t buflen )
-{
-    int ret;
-    size_t len;
-    unsigned char *p, *end, *crt_end;
-
-    /*
-     * Check for valid input
-     */
-    if( crt == NULL || buf == NULL )
-        return( POLARSSL_ERR_X509_INVALID_INPUT );
-
-    p = (unsigned char *) polarssl_malloc( len = buflen );
-
-    if( p == NULL )
-        return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
-    memcpy( p, buf, buflen );
-
-    buflen = 0;
-
-    crt->raw.p = p;
-    crt->raw.len = len;
-    end = p + len;
-
-    /*
-     * Certificate  ::=  SEQUENCE  {
-     *      tbsCertificate       TBSCertificate,
-     *      signatureAlgorithm   AlgorithmIdentifier,
-     *      signatureValue       BIT STRING  }
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
-    }
-
-    if( len > (size_t) ( end - p ) )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-    crt_end = p + len;
-
-    /*
-     * TBSCertificate  ::=  SEQUENCE  {
-     */
-    crt->tbs.p = p;
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-    crt->tbs.len = end - crt->tbs.p;
-
-    /*
-     * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
-     *
-     * CertificateSerialNumber  ::=  INTEGER
-     *
-     * signature            AlgorithmIdentifier
-     */
-    if( ( ret = x509_get_version(  &p, end, &crt->version  ) ) != 0 ||
-        ( ret = x509_get_serial(   &p, end, &crt->serial   ) ) != 0 ||
-        ( ret = x509_get_alg_null( &p, end, &crt->sig_oid1 ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    crt->version++;
-
-    if( crt->version > 3 )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
-    }
-
-    if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_md,
-                                  &crt->sig_pk ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    /*
-     * issuer               Name
-     */
-    crt->issuer_raw.p = p;
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    crt->issuer_raw.len = p - crt->issuer_raw.p;
-
-    /*
-     * Validity ::= SEQUENCE {
-     *      notBefore      Time,
-     *      notAfter       Time }
-     *
-     */
-    if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
-                                         &crt->valid_to ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    /*
-     * subject              Name
-     */
-    crt->subject_raw.p = p;
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    if( len && ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    crt->subject_raw.len = p - crt->subject_raw.p;
-
-    /*
-     * SubjectPublicKeyInfo
-     */
-    if( ( ret = x509_get_pubkey( &p, end, &crt->pk ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    /*
-     *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
-     *                       -- If present, version shall be v2 or v3
-     *  subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
-     *                       -- If present, version shall be v2 or v3
-     *  extensions      [3]  EXPLICIT Extensions OPTIONAL
-     *                       -- If present, version shall be v3
-     */
-    if( crt->version == 2 || crt->version == 3 )
-    {
-        ret = x509_get_uid( &p, end, &crt->issuer_id,  1 );
-        if( ret != 0 )
-        {
-            x509_free( crt );
-            return( ret );
-        }
-    }
-
-    if( crt->version == 2 || crt->version == 3 )
-    {
-        ret = x509_get_uid( &p, end, &crt->subject_id,  2 );
-        if( ret != 0 )
-        {
-            x509_free( crt );
-            return( ret );
-        }
-    }
-
-    if( crt->version == 3 )
-    {
-        ret = x509_get_crt_ext( &p, end, crt);
-        if( ret != 0 )
-        {
-            x509_free( crt );
-            return( ret );
-        }
-    }
-
-    if( p != end )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-    end = crt_end;
-
-    /*
-     *  }
-     *  -- end of TBSCertificate
-     *
-     *  signatureAlgorithm   AlgorithmIdentifier,
-     *  signatureValue       BIT STRING
-     */
-    if( ( ret = x509_get_alg_null( &p, end, &crt->sig_oid2 ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    if( crt->sig_oid1.len != crt->sig_oid2.len ||
-        memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
-    }
-
-    if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    if( p != end )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-    return( 0 );
-}
-
-/*
- * Parse one X.509 certificate in DER format from a buffer and add them to a
- * chained list
- */
-int x509parse_crt_der( x509_cert *chain, const unsigned char *buf, size_t buflen )
-{
-    int ret;
-    x509_cert *crt = chain, *prev = NULL;
-
-    /*
-     * Check for valid input
-     */
-    if( crt == NULL || buf == NULL )
-        return( POLARSSL_ERR_X509_INVALID_INPUT );
-
-    while( crt->version != 0 && crt->next != NULL )
-    {
-        prev = crt;
-        crt = crt->next;
-    }
-
-    /*
-     * Add new certificate on the end of the chain if needed.
-     */
-    if ( crt->version != 0 && crt->next == NULL)
-    {
-        crt->next = (x509_cert *) polarssl_malloc( sizeof( x509_cert ) );
-
-        if( crt->next == NULL )
-            return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
-        prev = crt;
-        crt = crt->next;
-        memset( crt, 0, sizeof( x509_cert ) );
-    }
-
-    if( ( ret = x509parse_crt_der_core( crt, buf, buflen ) ) != 0 )
-    {
-        if( prev )
-            prev->next = NULL;
-
-        if( crt != chain )
-            polarssl_free( crt );
-
-        return( ret );
-    }
-
-    return( 0 );
-}
-
-/*
- * Parse one or more PEM certificates from a buffer and add them to the chained list
- */
-int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen )
-{
-    int ret, success = 0, first_error = 0, total_failed = 0;
-    int buf_format = X509_FORMAT_DER;
-
-    /*
-     * Check for valid input
-     */
-    if( chain == NULL || buf == NULL )
-        return( POLARSSL_ERR_X509_INVALID_INPUT );
-
-    /*
-     * Determine buffer content. Buffer contains either one DER certificate or
-     * one or more PEM certificates.
-     */
-#if defined(POLARSSL_PEM_C)
-    if( strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
-        buf_format = X509_FORMAT_PEM;
-#endif
-
-    if( buf_format == X509_FORMAT_DER )
-        return x509parse_crt_der( chain, buf, buflen );
-
-#if defined(POLARSSL_PEM_C)
-    if( buf_format == X509_FORMAT_PEM )
-    {
-        pem_context pem;
-
-        while( buflen > 0 )
-        {
-            size_t use_len;
-            pem_init( &pem );
-
-            ret = pem_read_buffer( &pem,
-                           "-----BEGIN CERTIFICATE-----",
-                           "-----END CERTIFICATE-----",
-                           buf, NULL, 0, &use_len );
-
-            if( ret == 0 )
-            {
-                /*
-                 * Was PEM encoded
-                 */
-                buflen -= use_len;
-                buf += use_len;
-            }
-            else if( ret == POLARSSL_ERR_PEM_BAD_INPUT_DATA )
-            {
-                return( ret );
-            }
-            else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-            {
-                pem_free( &pem );
-
-                /*
-                 * PEM header and footer were found
-                 */
-                buflen -= use_len;
-                buf += use_len;
-
-                if( first_error == 0 )
-                    first_error = ret;
-
-                continue;
-            }
-            else
-                break;
-
-            ret = x509parse_crt_der( chain, pem.buf, pem.buflen );
-
-            pem_free( &pem );
-
-            if( ret != 0 )
-            {
-                /*
-                 * Quit parsing on a memory error
-                 */
-                if( ret == POLARSSL_ERR_X509_MALLOC_FAILED )
-                    return( ret );
-
-                if( first_error == 0 )
-                    first_error = ret;
-
-                total_failed++;
-                continue;
-            }
-
-            success = 1;
-        }
-    }
-#endif
-
-    if( success )
-        return( total_failed );
-    else if( first_error )
-        return( first_error );
-    else
-        return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
-}
-
-/*
- * 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
-#endif
-    {
-        /*
-         * 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;
-    }
-
-    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 )
-{
-    int ret;
-    size_t len;
-    unsigned char *p, *end;
-    x509_crl *crl;
-#if defined(POLARSSL_PEM_C)
-    size_t use_len;
-    pem_context pem;
-#endif
-
-    crl = chain;
-
-    /*
-     * Check for valid input
-     */
-    if( crl == NULL || buf == NULL )
-        return( POLARSSL_ERR_X509_INVALID_INPUT );
-
-    while( crl->version != 0 && crl->next != NULL )
-        crl = crl->next;
-
-    /*
-     * Add new CRL on the end of the chain if needed.
-     */
-    if ( crl->version != 0 && crl->next == NULL)
-    {
-        crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
-
-        if( crl->next == NULL )
-        {
-            x509_crl_free( crl );
-            return( POLARSSL_ERR_X509_MALLOC_FAILED );
-        }
-
-        crl = crl->next;
-        memset( crl, 0, sizeof( x509_crl ) );
-    }
-
-#if defined(POLARSSL_PEM_C)
-    pem_init( &pem );
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN X509 CRL-----",
-                           "-----END X509 CRL-----",
-                           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
-#endif
-    {
-        /*
-         * 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;
-    }
-
-    crl->raw.p = p;
-    crl->raw.len = len;
-    end = p + len;
-
-    /*
-     * CertificateList  ::=  SEQUENCE  {
-     *      tbsCertList          TBSCertList,
-     *      signatureAlgorithm   AlgorithmIdentifier,
-     *      signatureValue       BIT STRING  }
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
-    }
-
-    if( len != (size_t) ( end - p ) )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-    /*
-     * TBSCertList  ::=  SEQUENCE  {
-     */
-    crl->tbs.p = p;
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-    crl->tbs.len = end - crl->tbs.p;
-
-    /*
-     * Version  ::=  INTEGER  OPTIONAL {  v1(0), v2(1)  }
-     *               -- if present, MUST be v2
-     *
-     * signature            AlgorithmIdentifier
-     */
-    if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
-        ( ret = x509_get_alg_null( &p, end, &crl->sig_oid1   ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( ret );
-    }
-
-    crl->version++;
-
-    if( crl->version > 2 )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
-    }
-
-    if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_md,
-                                  &crl->sig_pk ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
-    }
-
-    /*
-     * issuer               Name
-     */
-    crl->issuer_raw.p = p;
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( ret );
-    }
-
-    crl->issuer_raw.len = p - crl->issuer_raw.p;
-
-    /*
-     * thisUpdate          Time
-     * nextUpdate          Time OPTIONAL
-     */
-    if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( ret );
-    }
-
-    if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
-    {
-        if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
-                        POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
-             ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
-                        POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
-        {
-            x509_crl_free( crl );
-            return( ret );
-        }
-    }
-
-    /*
-     * revokedCertificates    SEQUENCE OF SEQUENCE   {
-     *      userCertificate        CertificateSerialNumber,
-     *      revocationDate         Time,
-     *      crlEntryExtensions     Extensions OPTIONAL
-     *                                   -- if present, MUST be v2
-     *                        } OPTIONAL
-     */
-    if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( ret );
-    }
-
-    /*
-     * crlExtensions          EXPLICIT Extensions OPTIONAL
-     *                              -- if present, MUST be v2
-     */
-    if( crl->version == 2 )
-    {
-        ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
-                            
-        if( ret != 0 )
-        {
-            x509_crl_free( crl );
-            return( ret );
-        }
-    }
-
-    if( p != end )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-    end = crl->raw.p + crl->raw.len;
-
-    /*
-     *  signatureAlgorithm   AlgorithmIdentifier,
-     *  signatureValue       BIT STRING
-     */
-    if( ( ret = x509_get_alg_null( &p, end, &crl->sig_oid2 ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( ret );
-    }
-
-    if( crl->sig_oid1.len != crl->sig_oid2.len ||
-        memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
-    }
-
-    if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
-    {
-        x509_crl_free( crl );
-        return( ret );
-    }
-
-    if( p != end )
-    {
-        x509_crl_free( crl );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-    if( buflen > 0 )
-    {
-        crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
-
-        if( crl->next == NULL )
-        {
-            x509_crl_free( crl );
-            return( POLARSSL_ERR_X509_MALLOC_FAILED );
-        }
-
-        crl = crl->next;
-        memset( crl, 0, sizeof( x509_crl ) );
-
-        return( x509parse_crl( crl, buf, buflen ) );
-    }
-
-    return( 0 );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * Load all data from a file into a given buffer.
- */
-static int load_file( const char *path, unsigned char **buf, size_t *n )
-{
-    FILE *f;
-    long size;
-
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
-
-    fseek( f, 0, SEEK_END );
-    if( ( size = ftell( f ) ) == -1 )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
-    }
-    fseek( f, 0, SEEK_SET );
-
-    *n = (size_t) size;
-
-    if( *n + 1 == 0 ||
-        ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_X509_MALLOC_FAILED );
-    }
-
-    if( fread( *buf, 1, *n, f ) != *n )
-    {
-        fclose( f );
-        polarssl_free( *buf );
-        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
-    }
-
-    fclose( f );
-
-    (*buf)[*n] = '\0';
-
-    return( 0 );
-}
-
-/*
- * Load one or more certificates and add them to the chained list
- */
-int x509parse_crtfile( x509_cert *chain, const char *path )
-{
-    int ret;
-    size_t n;
-    unsigned char *buf;
-
-    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
-
-    ret = x509parse_crt( chain, buf, n );
-
-    memset( buf, 0, n + 1 );
-    polarssl_free( buf );
-
-    return( ret );
-}
-
-int x509parse_crtpath( x509_cert *chain, const char *path )
-{
-    int ret = 0;
-#if defined(_WIN32)
-    int w_ret;
-    WCHAR szDir[MAX_PATH];
-    char filename[MAX_PATH];
-	char *p;
-    int len = strlen( path );
-
-	WIN32_FIND_DATAW file_data;
-    HANDLE hFind;
-
-    if( len > MAX_PATH - 3 )
-        return( POLARSSL_ERR_X509_INVALID_INPUT );
-
-	memset( szDir, 0, sizeof(szDir) );
-	memset( filename, 0, MAX_PATH );
-	memcpy( filename, path, len );
-	filename[len++] = '\\';
-	p = filename + len;
-    filename[len++] = '*';
-
-	w_ret = MultiByteToWideChar( CP_ACP, 0, path, len, szDir, MAX_PATH - 3 );
-
-    hFind = FindFirstFileW( szDir, &file_data );
-    if (hFind == INVALID_HANDLE_VALUE) 
-        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
-
-    len = MAX_PATH - len;
-    do
-    {
-		memset( p, 0, len );
-
-        if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
-            continue;
-
-		w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
-									 lstrlenW(file_data.cFileName),
-									 p, len - 1,
-									 NULL, NULL );
-
-        w_ret = x509parse_crtfile( chain, filename );
-        if( w_ret < 0 )
-            ret++;
-        else
-            ret += w_ret;
-    }
-    while( FindNextFileW( hFind, &file_data ) != 0 );
-
-    if (GetLastError() != ERROR_NO_MORE_FILES) 
-        ret = POLARSSL_ERR_X509_FILE_IO_ERROR;
-
-cleanup:
-    FindClose( hFind );
-#else
-    int t_ret, i;
-    struct stat sb;
-    struct dirent entry, *result = NULL;
-    char entry_name[255];
-    DIR *dir = opendir( path );
-
-    if( dir == NULL)
-        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
-
-    while( ( t_ret = readdir_r( dir, &entry, &result ) ) == 0 )
-    {
-        if( result == NULL )
-            break;
-
-        snprintf( entry_name, sizeof(entry_name), "%s/%s", path, entry.d_name );
-
-        i = stat( entry_name, &sb );
-
-        if( i == -1 )
-        {
-            closedir( dir );
-            return( POLARSSL_ERR_X509_FILE_IO_ERROR );
-        }
-
-        if( !S_ISREG( sb.st_mode ) )
-            continue;
-
-        // Ignore parse errors
-        //
-        t_ret = x509parse_crtfile( chain, entry_name );
-        if( t_ret < 0 )
-            ret++;
-        else
-            ret += t_ret;
-    }
-    closedir( dir );
-#endif
-
-    return( ret );
-}
-
-/*
- * 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 )
-{
-    int ret;
-    size_t n;
-    unsigned char *buf;
-
-    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
-
-    ret = x509parse_crl( chain, buf, n );
-
-    memset( buf, 0, n + 1 );
-    polarssl_free( buf );
-
-    return( ret );
-}
-
-/*
- * Load and parse a private key
- */
-int x509parse_keyfile( pk_context *ctx,
-                       const char *path, const char *pwd )
-{
-    int ret;
-    size_t n;
-    unsigned char *buf;
-
-    if ( (ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
-
-    if( pwd == NULL )
-        ret = x509parse_key( ctx, buf, n, NULL, 0 );
-    else
-        ret = x509parse_key( ctx, buf, n,
-                (const unsigned char *) pwd, strlen( pwd ) );
-
-    memset( buf, 0, n + 1 );
-    polarssl_free( buf );
-
-    return( ret );
-}
-
-/*
- * Load and parse a public key
- */
-int x509parse_public_keyfile( pk_context *ctx, const char *path )
-{
-    int ret;
-    size_t n;
-    unsigned char *buf;
-
-    if ( (ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
-
-    ret = x509parse_public_key( ctx, buf, n );
-
-    memset( buf, 0, n + 1 );
-    polarssl_free( buf );
-
-    return( ret );
-}
-
-#if defined(POLARSSL_RSA_C)
-/*
- * Load and parse a private RSA key
- */
-int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *pwd )
-{
-    int ret;
-    pk_context pk;
-
-    pk_init( &pk );
-
-    ret = x509parse_keyfile( &pk, path, pwd );
-
-    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
-        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
-
-    if( ret == 0 )
-        rsa_copy( rsa, pk_rsa( pk ) );
-    else
-        rsa_free( rsa );
-
-    pk_free( &pk );
-
-    return( ret );
-}
-
-/*
- * Load and parse a public RSA key
- */
-int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path )
-{
-    int ret;
-    pk_context pk;
-
-    pk_init( &pk );
-
-    ret = x509parse_public_keyfile( &pk, path );
-
-    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
-        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
-
-    if( ret == 0 )
-        rsa_copy( rsa, pk_rsa( pk ) );
-    else
-        rsa_free( rsa );
-
-    pk_free( &pk );
-
-    return( ret );
-}
-#endif /* POLARSSL_RSA_C */
-#endif /* POLARSSL_FS_IO */
-
-#if defined(POLARSSL_RSA_C)
-/*
- * Parse a PKCS#1 encoded private RSA key
- */
-static int x509parse_key_pkcs1_der( rsa_context *rsa,
-                                    const unsigned char *key,
-                                    size_t keylen )
-{
-    int ret;
-    size_t len;
-    unsigned char *p, *end;
-
-    p = (unsigned char *) key;
-    end = p + keylen;
-
-    /*
-     * This function parses the RSAPrivateKey (PKCS#1)
-     *
-     *  RSAPrivateKey ::= SEQUENCE {
-     *      version           Version,
-     *      modulus           INTEGER,  -- n
-     *      publicExponent    INTEGER,  -- e
-     *      privateExponent   INTEGER,  -- d
-     *      prime1            INTEGER,  -- p
-     *      prime2            INTEGER,  -- q
-     *      exponent1         INTEGER,  -- d mod (p-1)
-     *      exponent2         INTEGER,  -- d mod (q-1)
-     *      coefficient       INTEGER,  -- (inverse of q) mod p
-     *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
-     *  }
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    if( rsa->ver != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_VERSION );
-    }
-
-    if( ( ret = asn1_get_mpi( &p, end, &rsa->N  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->E  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->D  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->P  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->Q  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
-    {
-        rsa_free( rsa );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    rsa->len = mpi_size( &rsa->N );
-
-    if( p != end )
-    {
-        rsa_free( rsa );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-    if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
-    {
-        rsa_free( rsa );
-        return( ret );
-    }
-
-    return( 0 );
-}
-#endif /* POLARSSL_RSA_C */
-
-#if defined(POLARSSL_ECP_C)
-/*
- * Parse a SEC1 encoded private EC key
- */
-static int x509parse_key_sec1_der( ecp_keypair *eck,
-                                   const unsigned char *key,
-                                   size_t keylen )
-{
-    int ret;
-    int version;
-    size_t len;
-    x509_buf params;
-    unsigned char *p = (unsigned char *) key;
-    unsigned char *end = p + keylen;
-    unsigned char *end2;
-
-    /*
-     * RFC 5915, or SEC1 Appendix C.4
-     *
-     * ECPrivateKey ::= SEQUENCE {
-     *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
-     *      privateKey     OCTET STRING,
-     *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
-     *      publicKey  [1] BIT STRING OPTIONAL
-     *    }
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( version != 1 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_VERSION );
-
-    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    p += len;
-
-    /*
-     * Is 'parameters' present?
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
-    {
-        if( ( ret = x509_get_ecparams( &p, p + len, &params) ) != 0 ||
-            ( ret = x509_use_ecparams( &params, &eck->grp )  ) != 0 )
-        {
-            ecp_keypair_free( eck );
-            return( ret );
-        }
-    }
-    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-    {
-        ecp_keypair_free( eck );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    /*
-     * Is 'publickey' present?
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
-    {
-        end2 = p + len;
-
-        if( ( ret = asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
-            return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-        if( p + len != end2 )
-            return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
-                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
-        if( ( ret = x509_get_ecpubkey( &p, end2, eck ) ) != 0 )
-            return( ret );
-    }
-    else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-    {
-        ecp_keypair_free( eck );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( ret );
-    }
-
-    return 0;
-}
-#endif /* POLARSSL_ECP_C */
-
-/*
- * Parse an unencrypted PKCS#8 encoded private key
- */
-static int x509parse_key_pkcs8_unencrypted_der(
-                                    pk_context *pk,
-                                    const unsigned char* key,
-                                    size_t keylen )
-{
-    int ret, version;
-    size_t len;
-    x509_buf params;
-    unsigned char *p = (unsigned char *) key;
-    unsigned char *end = p + keylen;
-    pk_type_t pk_alg = POLARSSL_PK_NONE;
-    const pk_info_t *pk_info;
-
-    /*
-     * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208)
-     *
-     *    PrivateKeyInfo ::= SEQUENCE {
-     *      version                   Version,
-     *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
-     *      privateKey                PrivateKey,
-     *      attributes           [0]  IMPLICIT Attributes OPTIONAL }
-     *
-     *    Version ::= INTEGER
-     *    PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
-     *    PrivateKey ::= OCTET STRING
-     *
-     *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
-     */
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( version != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
-
-    if( ( ret = x509_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( len < 1 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL )
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-    if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 )
-        return( ret );
-
-#if defined(POLARSSL_RSA_C)
-    if( pk_alg == POLARSSL_PK_RSA )
-    {
-        if( ( ret = x509parse_key_pkcs1_der( pk_rsa( *pk ), p, len ) ) != 0 )
-        {
-            pk_free( pk );
-            return( ret );
-        }
-    } else
-#endif /* POLARSSL_RSA_C */
-#if defined(POLARSSL_ECP_C)
-    if( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH )
-    {
-        if( ( ret = x509_use_ecparams( &params, &pk_ec( *pk )->grp ) ) != 0 ||
-            ( ret = x509parse_key_sec1_der( pk_ec( *pk ), p, len )  ) != 0 )
-        {
-            pk_free( pk );
-            return( ret );
-        }
-    } else
-#endif /* POLARSSL_ECP_C */
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-    return 0;
-}
-
-/*
- * Parse an encrypted PKCS#8 encoded private key
- */
-static int x509parse_key_pkcs8_encrypted_der(
-                                    pk_context *pk,
-                                    const unsigned char *key, size_t keylen,
-                                    const unsigned char *pwd, size_t pwdlen )
-{
-    int ret;
-    size_t len;
-    unsigned char buf[2048];
-    unsigned char *p, *end;
-    x509_buf pbe_alg_oid, pbe_params;
-#if defined(POLARSSL_PKCS12_C)
-    cipher_type_t cipher_alg;
-    md_type_t md_alg;
-#endif
-
-    memset( buf, 0, sizeof( buf ) );
-
-    p = (unsigned char *) key;
-    end = p + keylen;
-
-    if( pwdlen == 0 )
-        return( POLARSSL_ERR_X509_PASSWORD_REQUIRED );
-
-    /*
-     * This function parses the EncryptedPrivatKeyInfo object (PKCS#8)
-     *
-     *  EncryptedPrivateKeyInfo ::= SEQUENCE {
-     *    encryptionAlgorithm  EncryptionAlgorithmIdentifier,
-     *    encryptedData        EncryptedData
-     *  }
-     *
-     *  EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
-     *
-     *  EncryptedData ::= OCTET STRING
-     *
-     *  The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( len > sizeof( buf ) )
-        return( POLARSSL_ERR_X509_INVALID_INPUT );
-
-    /*
-     * Decrypt EncryptedData with appropriate PDE
-     */
-#if defined(POLARSSL_PKCS12_C)
-    if( oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
-    {
-        if( ( ret = pkcs12_pbe( &pbe_params, PKCS12_PBE_DECRYPT,
-                                cipher_alg, md_alg,
-                                pwd, pwdlen, p, len, buf ) ) != 0 )
-        {
-            if( ret == POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH )
-                return( POLARSSL_ERR_X509_PASSWORD_MISMATCH );
-
-            return( ret );
-        }
-    }
-    else if( OID_CMP( OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) )
-    {
-        if( ( ret = pkcs12_pbe_sha1_rc4_128( &pbe_params,
-                                             PKCS12_PBE_DECRYPT,
-                                             pwd, pwdlen,
-                                             p, len, buf ) ) != 0 )
-        {
-            return( ret );
-        }
-
-        // Best guess for password mismatch when using RC4. If first tag is
-        // not ASN1_CONSTRUCTED | ASN1_SEQUENCE
-        //
-        if( *buf != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
-            return( POLARSSL_ERR_X509_PASSWORD_MISMATCH );
-    }
-    else
-#endif /* POLARSSL_PKCS12_C */
-#if defined(POLARSSL_PKCS5_C)
-    if( OID_CMP( OID_PKCS5_PBES2, &pbe_alg_oid ) )
-    {
-        if( ( ret = pkcs5_pbes2( &pbe_params, PKCS5_DECRYPT, pwd, pwdlen,
-                                  p, len, buf ) ) != 0 )
-        {
-            if( ret == POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH )
-                return( POLARSSL_ERR_X509_PASSWORD_MISMATCH );
-
-            return( ret );
-        }
-    }
-    else
-#endif /* POLARSSL_PKCS5_C */
-        return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-
-    return( x509parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
-}
-
-/*
- * Parse a private key
- */
-int x509parse_key( pk_context *pk,
-                   const unsigned char *key, size_t keylen,
-                   const unsigned char *pwd, size_t pwdlen )
-{
-    int ret;
-    const pk_info_t *pk_info;
-
-#if defined(POLARSSL_PEM_C)
-    size_t len;
-    pem_context pem;
-
-    pem_init( &pem );
-
-#if defined(POLARSSL_RSA_C)
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN RSA PRIVATE KEY-----",
-                           "-----END RSA PRIVATE KEY-----",
-                           key, pwd, pwdlen, &len );
-    if( ret == 0 )
-    {
-        if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL )
-            return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-        if( ( ret = pk_init_ctx( pk, pk_info                     ) ) != 0 ||
-            ( ret = x509parse_key_pkcs1_der( pk_rsa( *pk ),
-                                             pem.buf, pem.buflen ) ) != 0 )
-        {
-            pk_free( pk );
-        }
-
-        pem_free( &pem );
-        return( ret );
-    }
-    else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH )
-        return( POLARSSL_ERR_X509_PASSWORD_MISMATCH );
-    else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED )
-        return( POLARSSL_ERR_X509_PASSWORD_REQUIRED );
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
-#endif /* POLARSSL_RSA_C */
-
-#if defined(POLARSSL_ECP_C)
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN EC PRIVATE KEY-----",
-                           "-----END EC PRIVATE KEY-----",
-                           key, pwd, pwdlen, &len );
-    if( ret == 0 )
-    {
-        if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL )
-            return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-        if( ( ret = pk_init_ctx( pk, pk_info                    ) ) != 0 ||
-            ( ret = x509parse_key_sec1_der( pk_ec( *pk ),
-                                            pem.buf, pem.buflen ) ) != 0 )
-        {
-            pk_free( pk );
-        }
-
-        pem_free( &pem );
-        return( ret );
-    }
-    else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH )
-        return( POLARSSL_ERR_X509_PASSWORD_MISMATCH );
-    else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED )
-        return( POLARSSL_ERR_X509_PASSWORD_REQUIRED );
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
-#endif /* POLARSSL_ECP_C */
-
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN PRIVATE KEY-----",
-                           "-----END PRIVATE KEY-----",
-                           key, NULL, 0, &len );
-    if( ret == 0 )
-    {
-        if( ( ret = x509parse_key_pkcs8_unencrypted_der( pk,
-                                                pem.buf, pem.buflen ) ) != 0 )
-        {
-            pk_free( pk );
-        }
-
-        pem_free( &pem );
-        return( ret );
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
-
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN ENCRYPTED PRIVATE KEY-----",
-                           "-----END ENCRYPTED PRIVATE KEY-----",
-                           key, NULL, 0, &len );
-    if( ret == 0 )
-    {
-        if( ( ret = x509parse_key_pkcs8_encrypted_der( pk,
-                                                pem.buf, pem.buflen,
-                                                pwd, pwdlen ) ) != 0 )
-        {
-            pk_free( pk );
-        }
-
-        pem_free( &pem );
-        return( ret );
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
-#else
-    ((void) pwd);
-    ((void) pwdlen);
-#endif /* POLARSSL_PEM_C */
-
-    /*
-    * At this point we only know it's not a PEM formatted key. Could be any
-    * of the known DER encoded private key formats
-    *
-    * We try the different DER format parsers to see if one passes without
-    * error
-    */
-    if( ( ret = x509parse_key_pkcs8_encrypted_der( pk, key, keylen,
-                                                   pwd, pwdlen ) ) == 0 )
-    {
-        return( 0 );
-    }
-
-    pk_free( pk );
-
-    if( ret == POLARSSL_ERR_X509_PASSWORD_MISMATCH )
-    {
-        return( ret );
-    }
-
-    if( ( ret = x509parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
-        return( 0 );
-
-    pk_free( pk );
-
-#if defined(POLARSSL_RSA_C)
-    if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL )
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-    if( ( ret = pk_init_ctx( pk, pk_info                            ) ) != 0 ||
-        ( ret = x509parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 )
-    {
-        return( 0 );
-    }
-
-    pk_free( pk );
-#endif /* POLARSSL_RSA_C */
-
-#if defined(POLARSSL_ECP_C)
-    if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL )
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-    if( ( ret = pk_init_ctx( pk, pk_info                          ) ) != 0 ||
-        ( ret = x509parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 )
-    {
-        return( 0 );
-    }
-
-    pk_free( pk );
-#endif /* POLARSSL_ECP_C */
-
-    return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
-}
-
-/*
- * Parse a public key
- */
-int x509parse_public_key( pk_context *ctx,
-                          const unsigned char *key, size_t keylen )
-{
-    int ret;
-    unsigned char *p;
-#if defined(POLARSSL_PEM_C)
-    size_t len;
-    pem_context pem;
-
-    pem_init( &pem );
-    ret = pem_read_buffer( &pem,
-            "-----BEGIN PUBLIC KEY-----",
-            "-----END PUBLIC KEY-----",
-            key, NULL, 0, &len );
-
-    if( ret == 0 )
-    {
-        /*
-         * Was PEM encoded
-         */
-        key = pem.buf;
-        keylen = pem.buflen;
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-    {
-        pem_free( &pem );
-        return( ret );
-    }
-#endif
-    p = (unsigned char *) key;
-
-    ret = x509_get_pubkey( &p, p + keylen, ctx );
-
-#if defined(POLARSSL_PEM_C)
-    pem_free( &pem );
-#endif
-
-    return( ret );
-}
-
-#if defined(POLARSSL_RSA_C)
-/*
- * Parse a private RSA key
- */
-int x509parse_key_rsa( rsa_context *rsa,
-                       const unsigned char *key, size_t keylen,
-                       const unsigned char *pwd, size_t pwdlen )
-{
-    int ret;
-    pk_context pk;
-
-    pk_init( &pk );
-
-    ret = x509parse_key( &pk, key, keylen, pwd, pwdlen );
-
-    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
-        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
-
-    if( ret == 0 )
-        rsa_copy( rsa, pk_rsa( pk ) );
-    else
-        rsa_free( rsa );
-
-    pk_free( &pk );
-
-    return( ret );
-}
-
-/*
- * Parse a public RSA key
- */
-int x509parse_public_key_rsa( rsa_context *rsa,
-                              const unsigned char *key, size_t keylen )
-{
-    int ret;
-    pk_context pk;
-
-    pk_init( &pk );
-
-    ret = x509parse_public_key( &pk, key, keylen );
-
-    if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
-        ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
-
-    if( ret == 0 )
-        rsa_copy( rsa, pk_rsa( pk ) );
-    else
-        rsa_free( rsa );
-
-    pk_free( &pk );
-
-    return( ret );
-}
-#endif /* POLARSSL_RSA_C */
-
-#if defined(POLARSSL_DHM_C)
-/*
- * Parse DHM parameters
- */
-int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
-{
-    int ret;
-    size_t len;
-    unsigned char *p, *end;
-#if defined(POLARSSL_PEM_C)
-    pem_context pem;
-
-    pem_init( &pem );
-
-    ret = pem_read_buffer( &pem, 
-                           "-----BEGIN DH PARAMETERS-----",
-                           "-----END DH PARAMETERS-----",
-                           dhmin, NULL, 0, &dhminlen );
-
-    if( ret == 0 )
-    {
-        /*
-         * Was PEM encoded
-         */
-        dhminlen = pem.buflen;
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-    {
-        pem_free( &pem );
-        return( ret );
-    }
-
-    p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
-#else
-    p = (unsigned char *) dhmin;
-#endif
-    end = p + dhminlen;
-
-    memset( dhm, 0, sizeof( dhm_context ) );
-
-    /*
-     *  DHParams ::= SEQUENCE {
-     *      prime            INTEGER,  -- P
-     *      generator        INTEGER,  -- g
-     *  }
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_mpi( &p, end, &dhm->P  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        dhm_free( dhm );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    if( p != end )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        dhm_free( dhm );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-#if defined(POLARSSL_PEM_C)
-    pem_free( &pem );
-#endif
-
-    return( 0 );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * Load and parse DHM parameters
- */
-int x509parse_dhmfile( dhm_context *dhm, const char *path )
-{
-    int ret;
-    size_t n;
-    unsigned char *buf;
-
-    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
-
-    ret = x509parse_dhm( dhm, buf, n );
-
-    memset( buf, 0, n + 1 );
-    polarssl_free( buf );
-
-    return( ret );
-}
-#endif /* POLARSSL_FS_IO */
-#endif /* POLARSSL_DHM_C */
-
-#if defined _MSC_VER && !defined snprintf
-#include <stdarg.h>
-
-#if !defined vsnprintf
-#define vsnprintf _vsnprintf
-#endif // vsnprintf
-
-/*
- * Windows _snprintf and _vsnprintf are not compatible to linux versions.
- * Result value is not size of buffer needed, but -1 if no fit is possible.
- *
- * This fuction tries to 'fix' this by at least suggesting enlarging the
- * size by 20.
- */
-static int compat_snprintf(char *str, size_t size, const char *format, ...)
-{
-    va_list ap;
-    int res = -1;
-
-    va_start( ap, format );
-
-    res = vsnprintf( str, size, format, ap );
-
-    va_end( ap );
-
-    // No quick fix possible
-    if ( res < 0 )
-        return( (int) size + 20 );
-    
-    return res;
-}
-
-#define snprintf compat_snprintf
-#endif
-
-#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
-
-#define SAFE_SNPRINTF()                         \
-{                                               \
-    if( ret == -1 )                             \
-        return( -1 );                           \
-                                                \
-    if ( (unsigned int) ret > n ) {             \
-        p[n - 1] = '\0';                        \
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
-    }                                           \
-                                                \
-    n -= (unsigned int) ret;                    \
-    p += (unsigned int) ret;                    \
-}
-
-/*
- * Store the name in printable form into buf; no more
- * than size characters will be written
- */
-int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
-{
-    int ret;
-    size_t i, n;
-    unsigned char c;
-    const x509_name *name;
-    const char *short_name = NULL;
-    char s[128], *p;
-
-    memset( s, 0, sizeof( s ) );
-
-    name = dn;
-    p = buf;
-    n = size;
-
-    while( name != NULL )
-    {
-        if( !name->oid.p )
-        {
-            name = name->next;
-            continue;
-        }
-
-        if( name != dn )
-        {
-            ret = snprintf( p, n, ", " );
-            SAFE_SNPRINTF();
-        }
-
-        ret = oid_get_attr_short_name( &name->oid, &short_name );
-
-        if( ret == 0 )
-            ret = snprintf( p, n, "%s=", short_name );
-        else
-            ret = snprintf( p, n, "\?\?=" );
-        SAFE_SNPRINTF();
-
-        for( i = 0; i < name->val.len; i++ )
-        {
-            if( i >= sizeof( s ) - 1 )
-                break;
-
-            c = name->val.p[i];
-            if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
-                 s[i] = '?';
-            else s[i] = c;
-        }
-        s[i] = '\0';
-        ret = snprintf( p, n, "%s", s );
-        SAFE_SNPRINTF();
-        name = name->next;
-    }
-
-    return( (int) ( size - n ) );
-}
-
-/*
- * Store the serial in printable form into buf; no more
- * than size characters will be written
- */
-int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial )
-{
-    int ret;
-    size_t i, n, nr;
-    char *p;
-
-    p = buf;
-    n = size;
-
-    nr = ( serial->len <= 32 )
-        ? serial->len  : 28;
-
-    for( i = 0; i < nr; i++ )
-    {
-        if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
-            continue;
-
-        ret = snprintf( p, n, "%02X%s",
-                serial->p[i], ( i < nr - 1 ) ? ":" : "" );
-        SAFE_SNPRINTF();
-    }
-
-    if( nr != serial->len )
-    {
-        ret = snprintf( p, n, "...." );
-        SAFE_SNPRINTF();
-    }
-
-    return( (int) ( size - n ) );
-}
-
-/*
- * Helper for writing "RSA key size", "EC key size", etc
- */
-static int x509_key_size_helper( char *buf, size_t size, const char *name )
-{
-    char *p = buf;
-    size_t n = size;
-    int ret;
-
-    if( strlen( name ) + sizeof( " key size" ) > size )
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
-
-    ret = snprintf( p, n, "%s key size", name );
-    SAFE_SNPRINTF();
-
-    return( 0 );
-}
-
-/*
- * Return an informational string about the certificate.
- */
-#define BEFORE_COLON    14
-#define BC              "14"
-int x509parse_cert_info( char *buf, size_t size, const char *prefix,
-                         const x509_cert *crt )
-{
-    int ret;
-    size_t n;
-    char *p;
-    const char *desc = NULL;
-    char key_size_str[BEFORE_COLON];
-
-    p = buf;
-    n = size;
-
-    ret = snprintf( p, n, "%scert. version : %d\n",
-                               prefix, crt->version );
-    SAFE_SNPRINTF();
-    ret = snprintf( p, n, "%sserial number : ",
-                               prefix );
-    SAFE_SNPRINTF();
-
-    ret = x509parse_serial_gets( p, n, &crt->serial);
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n%sissuer name   : ", prefix );
-    SAFE_SNPRINTF();
-    ret = x509parse_dn_gets( p, n, &crt->issuer  );
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n%ssubject name  : ", prefix );
-    SAFE_SNPRINTF();
-    ret = x509parse_dn_gets( p, n, &crt->subject );
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n%sissued  on    : " \
-                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crt->valid_from.year, crt->valid_from.mon,
-                   crt->valid_from.day,  crt->valid_from.hour,
-                   crt->valid_from.min,  crt->valid_from.sec );
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n%sexpires on    : " \
-                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crt->valid_to.year, crt->valid_to.mon,
-                   crt->valid_to.day,  crt->valid_to.hour,
-                   crt->valid_to.min,  crt->valid_to.sec );
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
-    SAFE_SNPRINTF();
-
-    ret = oid_get_sig_alg_desc( &crt->sig_oid1, &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( &crt->pk ) ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
-                          (int) pk_get_size( &crt->pk ) );
-    SAFE_SNPRINTF();
-
-    return( (int) ( size - n ) );
-}
-
-/*
- * Return an informational string describing the given OID
- */
-const char *x509_oid_get_description( x509_buf *oid )
-{
-    const char *desc = NULL;
-    int ret;
-    
-    ret = oid_get_extended_key_usage( oid, &desc );
-
-    if( ret != 0 )
-        return( NULL );
-
-    return( desc );
-}
-
-/* Return the x.y.z.... style numeric string for the given OID */
-int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
-{
-    return oid_get_numeric_string( buf, size, oid );
-}
-
-/*
- * Return an informational string about the CRL.
- */
-int x509parse_crl_info( char *buf, size_t size, const char *prefix,
-                        const x509_crl *crl )
-{
-    int ret;
-    size_t n;
-    char *p;
-    const char *desc;
-    const x509_crl_entry *entry;
-
-    p = buf;
-    n = size;
-
-    ret = snprintf( p, n, "%sCRL version   : %d",
-                               prefix, crl->version );
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n%sissuer name   : ", prefix );
-    SAFE_SNPRINTF();
-    ret = x509parse_dn_gets( p, n, &crl->issuer );
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n%sthis update   : " \
-                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crl->this_update.year, crl->this_update.mon,
-                   crl->this_update.day,  crl->this_update.hour,
-                   crl->this_update.min,  crl->this_update.sec );
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n%snext update   : " \
-                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crl->next_update.year, crl->next_update.mon,
-                   crl->next_update.day,  crl->next_update.hour,
-                   crl->next_update.min,  crl->next_update.sec );
-    SAFE_SNPRINTF();
-
-    entry = &crl->entry;
-
-    ret = snprintf( p, n, "\n%sRevoked certificates:",
-                               prefix );
-    SAFE_SNPRINTF();
-
-    while( entry != NULL && entry->raw.len != 0 )
-    {
-        ret = snprintf( p, n, "\n%sserial number: ",
-                               prefix );
-        SAFE_SNPRINTF();
-
-        ret = x509parse_serial_gets( p, n, &entry->serial);
-        SAFE_SNPRINTF();
-
-        ret = snprintf( p, n, " revocation date: " \
-                   "%04d-%02d-%02d %02d:%02d:%02d",
-                   entry->revocation_date.year, entry->revocation_date.mon,
-                   entry->revocation_date.day,  entry->revocation_date.hour,
-                   entry->revocation_date.min,  entry->revocation_date.sec );
-        SAFE_SNPRINTF();
-
-        entry = entry->next;
-    }
-
-    ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
-    SAFE_SNPRINTF();
-
-    ret = oid_get_sig_alg_desc( &crl->sig_oid1, &desc );
-    if( ret != 0 )
-        ret = snprintf( p, n, "???"  );
-    else
-        ret = snprintf( p, n, "%s", desc );
-    SAFE_SNPRINTF();
-
-    ret = snprintf( p, n, "\n" );
-    SAFE_SNPRINTF();
-
-    return( (int) ( size - n ) );
-}
-
-/*
- * 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)
-int x509parse_time_expired( const x509_time *to )
-{
-    int year, mon, day;
-    int hour, min, sec;
-
-#if defined(_WIN32)
-    SYSTEMTIME st;
-
-    GetLocalTime(&st);
-
-    year = st.wYear;
-    mon = st.wMonth;
-    day = st.wDay;
-    hour = st.wHour;
-    min = st.wMinute;
-    sec = st.wSecond;
-#else
-    struct tm *lt;
-    time_t tt;
-
-    tt = time( NULL );
-    lt = localtime( &tt );
-
-    year = lt->tm_year + 1900;
-    mon = lt->tm_mon + 1;
-    day = lt->tm_mday;
-    hour = lt->tm_hour;
-    min = lt->tm_min;
-    sec = lt->tm_sec;
-#endif
-
-    if( year  > to->year )
-        return( 1 );
-
-    if( year == to->year &&
-        mon   > to->mon )
-        return( 1 );
-
-    if( year == to->year &&
-        mon  == to->mon  &&
-        day   > to->day )
-        return( 1 );
-
-    if( year == to->year &&
-        mon  == to->mon  &&
-        day  == to->day  &&
-        hour  > to->hour )
-        return( 1 );
-
-    if( year == to->year &&
-        mon  == to->mon  &&
-        day  == to->day  &&
-        hour == to->hour &&
-        min   > to->min  )
-        return( 1 );
-
-    if( year == to->year &&
-        mon  == to->mon  &&
-        day  == to->day  &&
-        hour == to->hour &&
-        min  == to->min  &&
-        sec   > to->sec  )
-        return( 1 );
-
-    return( 0 );
-}
-#else  /* POLARSSL_HAVE_TIME */
-int x509parse_time_expired( const x509_time *to )
-{
-    ((void) to);
-    return( 0 );
-}
-#endif /* POLARSSL_HAVE_TIME */
-
-/*
- * Return 1 if the certificate is revoked, or 0 otherwise.
- */
-int x509parse_revoked( const x509_cert *crt, const x509_crl *crl )
-{
-    const x509_crl_entry *cur = &crl->entry;
-
-    while( cur != NULL && cur->serial.len != 0 )
-    {
-        if( crt->serial.len == cur->serial.len &&
-            memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
-        {
-            if( x509parse_time_expired( &cur->revocation_date ) )
-                return( 1 );
-        }
-
-        cur = cur->next;
-    }
-
-    return( 0 );
-}
-
-/*
- * Check that the given certificate is valid accoring to the CRL.
- */
-static int x509parse_verifycrl(x509_cert *crt, x509_cert *ca,
-        x509_crl *crl_list)
-{
-    int flags = 0;
-    unsigned char hash[POLARSSL_MD_MAX_SIZE];
-    const md_info_t *md_info;
-
-    if( ca == NULL )
-        return( flags );
-
-    /*
-     * TODO: What happens if no CRL is present?
-     * Suggestion: Revocation state should be unknown if no CRL is present.
-     * For backwards compatibility this is not yet implemented.
-     */
-
-    while( crl_list != NULL )
-    {
-        if( crl_list->version == 0 ||
-            crl_list->issuer_raw.len != ca->subject_raw.len ||
-            memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
-                    crl_list->issuer_raw.len ) != 0 )
-        {
-            crl_list = crl_list->next;
-            continue;
-        }
-
-        /*
-         * Check if CRL is correctly signed by the trusted CA
-         */
-        md_info = md_info_from_type( crl_list->sig_md );
-        if( md_info == NULL )
-        {
-            /*
-             * Cannot check 'unknown' hash
-             */
-            flags |= BADCRL_NOT_TRUSTED;
-            break;
-        }
-
-        md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash );
-
-        if( pk_can_do( &ca->pk, crl_list->sig_pk ) == 0 ||
-            pk_verify( &ca->pk, crl_list->sig_md, hash, md_info->size,
-                       crl_list->sig.p, crl_list->sig.len ) != 0 )
-        {
-            flags |= BADCRL_NOT_TRUSTED;
-            break;
-        }
-
-        /*
-         * Check for validity of CRL (Do not drop out)
-         */
-        if( x509parse_time_expired( &crl_list->next_update ) )
-            flags |= BADCRL_EXPIRED;
-
-        /*
-         * Check if certificate is revoked
-         */
-        if( x509parse_revoked(crt, crl_list) )
-        {
-            flags |= BADCERT_REVOKED;
-            break;
-        }
-
-        crl_list = crl_list->next;
-    }
-    return flags;
-}
-
-// Equal == 0, inequal == 1
-static int x509_name_cmp( const void *s1, const void *s2, size_t len )
-{
-    size_t i;
-    unsigned char diff;
-    const unsigned char *n1 = s1, *n2 = s2;
-
-    for( i = 0; i < len; i++ )
-    {
-        diff = n1[i] ^ n2[i];
-
-        if( ( n1[i] >= 'a' || n1[i] <= 'z' ) && ( diff == 0 || diff == 32 ) )
-            continue;
-
-        if( ( n1[i] >= 'A' || n1[i] <= 'Z' ) && ( diff == 0 || diff == 32 ) )
-            continue;
-
-        return( 1 );
-    }
-
-    return( 0 );
-}
-
-static int x509_wildcard_verify( const char *cn, x509_buf *name )
-{
-    size_t i;
-    size_t cn_idx = 0;
-
-    if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
-        return( 0 );
-
-    for( i = 0; i < strlen( cn ); ++i )
-    {
-        if( cn[i] == '.' )
-        {
-            cn_idx = i;
-            break;
-        }
-    }
-
-    if( cn_idx == 0 )
-        return( 0 );
-
-    if( strlen( cn ) - cn_idx == name->len - 1 &&
-        x509_name_cmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
-    {
-        return( 1 );
-    }
-
-    return( 0 );
-}
-
-static int x509parse_verify_top(
-                x509_cert *child, x509_cert *trust_ca,
-                x509_crl *ca_crl, int path_cnt, int *flags,
-                int (*f_vrfy)(void *, x509_cert *, int, int *),
-                void *p_vrfy )
-{
-    int ret;
-    int ca_flags = 0, check_path_cnt = path_cnt + 1;
-    unsigned char hash[POLARSSL_MD_MAX_SIZE];
-    const md_info_t *md_info;
-
-    if( x509parse_time_expired( &child->valid_to ) )
-        *flags |= BADCERT_EXPIRED;
-
-    /*
-     * Child is the top of the chain. Check against the trust_ca list.
-     */
-    *flags |= BADCERT_NOT_TRUSTED;
-
-    md_info = md_info_from_type( child->sig_md );
-    if( md_info == NULL )
-    {
-        /*
-         * Cannot check 'unknown', no need to try any CA
-         */
-        trust_ca = NULL;
-    }
-    else
-        md( md_info, child->tbs.p, child->tbs.len, hash );
-
-    while( trust_ca != NULL )
-    {
-        if( trust_ca->version == 0 ||
-            child->issuer_raw.len != trust_ca->subject_raw.len ||
-            memcmp( child->issuer_raw.p, trust_ca->subject_raw.p,
-                    child->issuer_raw.len ) != 0 )
-        {
-            trust_ca = trust_ca->next;
-            continue;
-        }
-
-        /*
-         * Reduce path_len to check against if top of the chain is
-         * the same as the trusted CA
-         */
-        if( child->subject_raw.len == trust_ca->subject_raw.len &&
-            memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
-                            child->issuer_raw.len ) == 0 )
-        {
-            check_path_cnt--;
-        }
-
-        if( trust_ca->max_pathlen > 0 &&
-            trust_ca->max_pathlen < check_path_cnt )
-        {
-            trust_ca = trust_ca->next;
-            continue;
-        }
-
-        if( pk_can_do( &trust_ca->pk, child->sig_pk ) == 0 ||
-            pk_verify( &trust_ca->pk, child->sig_md, hash, md_info->size,
-                       child->sig.p, child->sig.len ) != 0 )
-        {
-            trust_ca = trust_ca->next;
-            continue;
-        }
-
-        /*
-         * Top of chain is signed by a trusted CA
-         */
-        *flags &= ~BADCERT_NOT_TRUSTED;
-        break;
-    }
-
-    /*
-     * If top of chain is not the same as the trusted CA send a verify request
-     * to the callback for any issues with validity and CRL presence for the
-     * trusted CA certificate.
-     */
-    if( trust_ca != NULL &&
-        ( child->subject_raw.len != trust_ca->subject_raw.len ||
-          memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
-                            child->issuer_raw.len ) != 0 ) )
-    {
-        /* Check trusted CA's CRL for the chain's top crt */
-        *flags |= x509parse_verifycrl( child, trust_ca, ca_crl );
-
-        if( x509parse_time_expired( &trust_ca->valid_to ) )
-            ca_flags |= BADCERT_EXPIRED;
-
-        if( NULL != f_vrfy )
-        {
-            if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, &ca_flags ) ) != 0 )
-                return( ret );
-        }
-    }
-
-    /* Call callback on top cert */
-    if( NULL != f_vrfy )
-    {
-        if( ( ret = f_vrfy(p_vrfy, child, path_cnt, flags ) ) != 0 )
-            return( ret );
-    }
-
-    *flags |= ca_flags;
-
-    return( 0 );
-}
-
-static int x509parse_verify_child(
-                x509_cert *child, x509_cert *parent, x509_cert *trust_ca,
-                x509_crl *ca_crl, int path_cnt, int *flags,
-                int (*f_vrfy)(void *, x509_cert *, int, int *),
-                void *p_vrfy )
-{
-    int ret;
-    int parent_flags = 0;
-    unsigned char hash[POLARSSL_MD_MAX_SIZE];
-    x509_cert *grandparent;
-    const md_info_t *md_info;
-
-    if( x509parse_time_expired( &child->valid_to ) )
-        *flags |= BADCERT_EXPIRED;
-
-    md_info = md_info_from_type( child->sig_md );
-    if( md_info == NULL )
-    {
-        /*
-         * Cannot check 'unknown' hash
-         */
-        *flags |= BADCERT_NOT_TRUSTED;
-    }
-    else
-    {
-        md( md_info, child->tbs.p, child->tbs.len, hash );
-
-        if( pk_can_do( &parent->pk, child->sig_pk ) == 0 ||
-            pk_verify( &parent->pk, child->sig_md, hash, md_info->size,
-                       child->sig.p, child->sig.len ) != 0 )
-        {
-            *flags |= BADCERT_NOT_TRUSTED;
-        }
-    }
-
-    /* Check trusted CA's CRL for the given crt */
-    *flags |= x509parse_verifycrl(child, parent, ca_crl);
-
-    grandparent = parent->next;
-
-    while( grandparent != NULL )
-    {
-        if( grandparent->version == 0 ||
-            grandparent->ca_istrue == 0 ||
-            parent->issuer_raw.len != grandparent->subject_raw.len ||
-            memcmp( parent->issuer_raw.p, grandparent->subject_raw.p,
-                    parent->issuer_raw.len ) != 0 )
-        {
-            grandparent = grandparent->next;
-            continue;
-        }
-        break;
-    }
-
-    if( grandparent != NULL )
-    {
-        /*
-         * Part of the chain
-         */
-        ret = x509parse_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
-        if( ret != 0 )
-            return( ret );
-    }
-    else
-    {
-        ret = x509parse_verify_top( parent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
-        if( ret != 0 )
-            return( ret );
-    }
-
-    /* child is verified to be a child of the parent, call verify callback */
-    if( NULL != f_vrfy )
-        if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 )
-            return( ret );
-
-    *flags |= parent_flags;
-
-    return( 0 );
-}
-
-/*
- * Verify the certificate validity
- */
-int x509parse_verify( x509_cert *crt,
-                      x509_cert *trust_ca,
-                      x509_crl *ca_crl,
-                      const char *cn, int *flags,
-                      int (*f_vrfy)(void *, x509_cert *, int, int *),
-                      void *p_vrfy )
-{
-    size_t cn_len;
-    int ret;
-    int pathlen = 0;
-    x509_cert *parent;
-    x509_name *name;
-    x509_sequence *cur = NULL;
-
-    *flags = 0;
-
-    if( cn != NULL )
-    {
-        name = &crt->subject;
-        cn_len = strlen( cn );
-
-        if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
-        {
-            cur = &crt->subject_alt_names;
-
-            while( cur != NULL )
-            {
-                if( cur->buf.len == cn_len &&
-                    x509_name_cmp( cn, cur->buf.p, cn_len ) == 0 )
-                    break;
-
-                if( cur->buf.len > 2 &&
-                    memcmp( cur->buf.p, "*.", 2 ) == 0 &&
-                            x509_wildcard_verify( cn, &cur->buf ) )
-                    break;
-
-                cur = cur->next;
-            }
-
-            if( cur == NULL )
-                *flags |= BADCERT_CN_MISMATCH;
-        }
-        else
-        {
-            while( name != NULL )
-            {
-                if( OID_CMP( OID_AT_CN, &name->oid ) )
-                {
-                    if( name->val.len == cn_len &&
-                        x509_name_cmp( name->val.p, cn, cn_len ) == 0 )
-                        break;
-
-                    if( name->val.len > 2 &&
-                        memcmp( name->val.p, "*.", 2 ) == 0 &&
-                                x509_wildcard_verify( cn, &name->val ) )
-                        break;
-                }
-
-                name = name->next;
-            }
-
-            if( name == NULL )
-                *flags |= BADCERT_CN_MISMATCH;
-        }
-    }
-
-    /*
-     * Iterate upwards in the given cert chain, to find our crt parent.
-     * Ignore any upper cert with CA != TRUE.
-     */
-    parent = crt->next;
-
-    while( parent != NULL && parent->version != 0 )
-    {
-        if( parent->ca_istrue == 0 ||
-            crt->issuer_raw.len != parent->subject_raw.len ||
-            memcmp( crt->issuer_raw.p, parent->subject_raw.p,
-                    crt->issuer_raw.len ) != 0 )
-        {
-            parent = parent->next;
-            continue;
-        }
-        break;
-    }
-
-    if( parent != NULL )
-    {
-        /*
-         * Part of the chain
-         */
-        ret = x509parse_verify_child( crt, parent, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy );
-        if( ret != 0 )
-            return( ret );
-    } 
-    else
-    {
-        ret = x509parse_verify_top( crt, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy );
-        if( ret != 0 )
-            return( ret );
-    }
-
-    if( *flags != 0 )
-        return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
-
-    return( 0 );
-}
-
-/*
- * Unallocate all certificate data
- */
-void x509_free( x509_cert *crt )
-{
-    x509_cert *cert_cur = crt;
-    x509_cert *cert_prv;
-    x509_name *name_cur;
-    x509_name *name_prv;
-    x509_sequence *seq_cur;
-    x509_sequence *seq_prv;
-
-    if( crt == NULL )
-        return;
-
-    do
-    {
-        pk_free( &cert_cur->pk );
-
-        name_cur = cert_cur->issuer.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 );
-        }
-
-        name_cur = cert_cur->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 );
-        }
-
-        seq_cur = cert_cur->ext_key_usage.next;
-        while( seq_cur != NULL )
-        {
-            seq_prv = seq_cur;
-            seq_cur = seq_cur->next;
-            memset( seq_prv, 0, sizeof( x509_sequence ) );
-            polarssl_free( seq_prv );
-        }
-
-        seq_cur = cert_cur->subject_alt_names.next;
-        while( seq_cur != NULL )
-        {
-            seq_prv = seq_cur;
-            seq_cur = seq_cur->next;
-            memset( seq_prv, 0, sizeof( x509_sequence ) );
-            polarssl_free( seq_prv );
-        }
-
-        if( cert_cur->raw.p != NULL )
-        {
-            memset( cert_cur->raw.p, 0, cert_cur->raw.len );
-            polarssl_free( cert_cur->raw.p );
-        }
-
-        cert_cur = cert_cur->next;
-    }
-    while( cert_cur != NULL );
-
-    cert_cur = crt;
-    do
-    {
-        cert_prv = cert_cur;
-        cert_cur = cert_cur->next;
-
-        memset( cert_prv, 0, sizeof( x509_cert ) );
-        if( cert_prv != crt )
-            polarssl_free( cert_prv );
-    }
-    while( cert_cur != NULL );
-}
-
-/*
- * Unallocate all CRL data
- */
-void x509_crl_free( x509_crl *crl )
-{
-    x509_crl *crl_cur = crl;
-    x509_crl *crl_prv;
-    x509_name *name_cur;
-    x509_name *name_prv;
-    x509_crl_entry *entry_cur;
-    x509_crl_entry *entry_prv;
-
-    if( crl == NULL )
-        return;
-
-    do
-    {
-        name_cur = crl_cur->issuer.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 );
-        }
-
-        entry_cur = crl_cur->entry.next;
-        while( entry_cur != NULL )
-        {
-            entry_prv = entry_cur;
-            entry_cur = entry_cur->next;
-            memset( entry_prv, 0, sizeof( x509_crl_entry ) );
-            polarssl_free( entry_prv );
-        }
-
-        if( crl_cur->raw.p != NULL )
-        {
-            memset( crl_cur->raw.p, 0, crl_cur->raw.len );
-            polarssl_free( crl_cur->raw.p );
-        }
-
-        crl_cur = crl_cur->next;
-    }
-    while( crl_cur != NULL );
-
-    crl_cur = crl;
-    do
-    {
-        crl_prv = crl_cur;
-        crl_cur = crl_cur->next;
-
-        memset( crl_prv, 0, sizeof( x509_crl ) );
-        if( crl_prv != crl )
-            polarssl_free( crl_prv );
-    }
-    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"
-
-/*
- * Checkup routine
- */
-int x509_self_test( int verbose )
-{
-#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
-    int ret;
-    int flags;
-    x509_cert cacert;
-    x509_cert clicert;
-    pk_context pkey;
-#if defined(POLARSSL_DHM_C)
-    dhm_context dhm;
-#endif
-
-    if( verbose != 0 )
-        printf( "  X.509 certificate load: " );
-
-    memset( &clicert, 0, sizeof( x509_cert ) );
-
-    ret = x509parse_crt( &clicert, (const unsigned char *) test_cli_crt,
-                         strlen( test_cli_crt ) );
-    if( ret != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( ret );
-    }
-
-    memset( &cacert, 0, sizeof( x509_cert ) );
-
-    ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
-                         strlen( test_ca_crt ) );
-    if( ret != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( ret );
-    }
-
-#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) &&         \
-    defined(POLARSSL_DES_C) && defined(POLARSSL_AES_C)
-    if( verbose != 0 )
-        printf( "passed\n  X.509 private key load: " );
-
-    pk_init( &pkey );
-
-    if( ( ret = x509parse_key( &pkey,
-                               (const unsigned char *) test_ca_key,
-                               strlen( test_ca_key ),
-                               (const unsigned char *) test_ca_pwd,
-                               strlen( test_ca_pwd ) ) ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( ret );
-    }
-#endif
-
-    if( verbose != 0 )
-        printf( "passed\n  X.509 signature verify: ");
-
-    ret = x509parse_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
-    if( ret != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        printf("ret = %d, &flags = %04x\n", ret, flags);
-
-        return( ret );
-    }
-
-#if defined(POLARSSL_DHM_C)
-    if( verbose != 0 )
-        printf( "passed\n  X.509 DHM parameter load: " );
-
-    if( ( ret = x509parse_dhm( &dhm, (const unsigned char *) test_dhm_params,
-                                     strlen( test_dhm_params ) ) ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( ret );
-    }
-
-    if( verbose != 0 )
-        printf( "passed\n\n" );
-#endif
-
-    x509_free( &cacert  );
-    x509_free( &clicert );
-    pk_free( &pkey );
-#if defined(POLARSSL_DHM_C)
-    dhm_free( &dhm );
-#endif
-
-    return( 0 );
-#else
-    ((void) verbose);
-    return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-#endif
-}
-
-#endif
-
-#endif
diff --git a/library/x509write.c b/library/x509write.c
deleted file mode 100644
index d4861d7..0000000
--- a/library/x509write.c
+++ /dev/null
@@ -1,1199 +0,0 @@
-/*
- * X509 buffer writing functionality
- *
- *  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.
- */
-
-/*
- * References:
- * - certificates: RFC 5280, updated by RFC 6818
- * - CSRs: PKCS#10 v1.7 aka RFC 2986
- * - attributes: PKCS#9 v2.0 aka RFC 2985
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_X509_WRITE_C)
-
-#include "polarssl/asn1write.h"
-#include "polarssl/x509write.h"
-#include "polarssl/x509.h"
-#include "polarssl/md.h"
-#include "polarssl/oid.h"
-
-#include "polarssl/sha1.h"
-
-#if defined(POLARSSL_BASE64_C)
-#include "polarssl/base64.h"
-#endif
-
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
-#else
-#include <stdlib.h>
-#define polarssl_malloc     malloc
-#define polarssl_free       free
-#endif
-
-static int x509write_string_to_names( asn1_named_data **head, char *name )
-{
-    int ret = 0;
-    char *s = name, *c = s;
-    char *end = s + strlen( s );
-    char *oid = NULL;
-    int in_tag = 1;
-    asn1_named_data *cur;
-
-    /* Clear existing chain if present */
-    asn1_free_named_data_list( head );
-
-    while( c <= end )
-    {
-        if( in_tag && *c == '=' )
-        {
-            if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
-                oid = OID_AT_CN;
-            else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
-                oid = OID_AT_COUNTRY;
-            else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
-                oid = OID_AT_ORGANIZATION;
-            else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
-                oid = OID_AT_LOCALITY;
-            else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
-                oid = OID_PKCS9_EMAIL;
-            else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
-                oid = OID_AT_ORG_UNIT;
-            else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
-                oid = OID_AT_STATE;
-            else
-            {
-                ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
-                goto exit;
-            }
-
-            s = c + 1;
-            in_tag = 0;
-        }
-
-        if( !in_tag && ( *c == ',' || c == end ) )
-        {
-            if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
-                                               (unsigned char *) s,
-                                               c - s ) ) == NULL )
-            {
-                return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
-            }
-
-            while( c < end && *(c + 1) == ' ' )
-                c++;
-
-            s = c + 1;
-            in_tag = 1;
-        }
-        c++;
-    }
-
-exit:
-
-    return( ret );
-}
-
-#if defined(POLARSSL_RSA_C)
-/*
- *  RSAPublicKey ::= SEQUENCE {
- *      modulus           INTEGER,  -- n
- *      publicExponent    INTEGER   -- e
- *  }
- */
-static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start,
-                                  rsa_context *rsa )
-{
-    int ret;
-    size_t len = 0;
-
-    ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
-    ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
-
-    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    return( len );
-}
-#endif /* POLARSSL_RSA_C */
-
-#if defined(POLARSSL_ECP_C)
-/*
- * EC public key is an EC point
- */
-static int x509_write_ec_pubkey( unsigned char **p, unsigned char *start,
-                                 ecp_keypair *ec )
-{
-    int ret;
-    size_t len = 0;
-    unsigned char buf[POLARSSL_ECP_MAX_PT_LEN];
-
-    if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q,
-                                        POLARSSL_ECP_PF_UNCOMPRESSED,
-                                        &len, buf, sizeof( buf ) ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    if( *p - start < (int) len )
-        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
-    *p -= len;
-    memcpy( *p, buf, len );
-
-    return( len );
-}
-
-/*
- * ECParameters ::= CHOICE {
- *   namedCurve         OBJECT IDENTIFIER
- * }
- */
-static int x509_write_ec_param( unsigned char **p, unsigned char *start,
-                                ecp_keypair *ec )
-{
-    int ret;
-    size_t len = 0;
-    const char *oid;
-    size_t oid_len;
-
-    if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
-        return( ret );
-
-    ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
-
-    return( len );
-}
-#endif /* POLARSSL_ECP_C */
-
-static int x509_write_pubkey( unsigned char **p, unsigned char *start,
-                              const pk_context *key )
-{
-    int ret;
-    size_t len = 0;
-
-#if defined(POLARSSL_RSA_C)
-    if( pk_get_type( key ) == POLARSSL_PK_RSA )
-        ASN1_CHK_ADD( len, x509_write_rsa_pubkey( p, start, pk_rsa( *key ) ) );
-    else
-#endif
-#if defined(POLARSSL_ECP_C)
-    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
-        ASN1_CHK_ADD( len, x509_write_ec_pubkey( p, start, pk_ec( *key ) ) );
-    else
-#endif
-        return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-
-    return( len );
-}
-
-void x509write_csr_init( x509write_csr *ctx )
-{
-    memset( ctx, 0, sizeof(x509write_csr) );
-}
-
-void x509write_csr_free( x509write_csr *ctx )
-{
-    asn1_free_named_data_list( &ctx->subject );
-    asn1_free_named_data_list( &ctx->extensions );
-
-    memset( ctx, 0, sizeof(x509write_csr) );
-}
-
-void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
-{
-    ctx->md_alg = md_alg;
-}
-
-void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
-{
-    ctx->key = key;
-}
-
-int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
-{
-    return x509write_string_to_names( &ctx->subject, subject_name );
-}
-
-/* The first byte of the value in the asn1_named_data structure is reserved
- * to store the critical boolean for us
- */
-static int x509_set_extension( asn1_named_data **head,
-                               const char *oid, size_t oid_len,
-                               int critical,
-                               const unsigned char *val, size_t val_len )
-{
-    asn1_named_data *cur;
-
-    if( ( cur = asn1_store_named_data( head, oid, oid_len,
-                                       NULL, val_len + 1 ) ) == NULL )
-    {
-        return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
-    }
-
-    cur->val.p[0] = critical;
-    memcpy( cur->val.p + 1, val, val_len );
-
-    return( 0 );
-}
-
-int x509write_csr_set_extension( x509write_csr *ctx,
-                                 const char *oid, size_t oid_len,
-                                 const unsigned char *val, size_t val_len )
-{
-    return x509_set_extension( &ctx->extensions, oid, oid_len,
-                               0, val, val_len );
-}
-
-int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
-{
-    unsigned char buf[4];
-    unsigned char *c;
-    int ret;
-
-    c = buf + 4;
-
-    if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
-        return( ret );
-
-    ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
-                                       OID_SIZE( OID_KEY_USAGE ),
-                                       buf, 4 );
-    if( ret != 0 )
-        return( ret );
-
-    return( 0 );
-}
-
-int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
-                                    unsigned char ns_cert_type )
-{
-    unsigned char buf[4];
-    unsigned char *c;
-    int ret;
-
-    c = buf + 4;
-
-    if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
-        return( ret );
-
-    ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
-                                       OID_SIZE( OID_NS_CERT_TYPE ),
-                                       buf, 4 );
-    if( ret != 0 )
-        return( ret );
-
-    return( 0 );
-}
-
-void x509write_crt_init( x509write_cert *ctx )
-{
-    memset( ctx, 0, sizeof(x509write_cert) );
-
-    mpi_init( &ctx->serial );
-    ctx->version = X509_CRT_VERSION_3;
-}
-
-void x509write_crt_free( x509write_cert *ctx )
-{
-    mpi_free( &ctx->serial );
-
-    asn1_free_named_data_list( &ctx->subject );
-    asn1_free_named_data_list( &ctx->issuer );
-    asn1_free_named_data_list( &ctx->extensions );
-
-    memset( ctx, 0, sizeof(x509write_csr) );
-}
-
-void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
-{
-    ctx->md_alg = md_alg;
-}
-
-void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key )
-{
-    ctx->subject_key = key;
-}
-
-void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key )
-{
-    ctx->issuer_key = key;
-}
-
-int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
-{
-    return x509write_string_to_names( &ctx->subject, subject_name );
-}
-
-int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
-{
-    return x509write_string_to_names( &ctx->issuer, issuer_name );
-}
-
-int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
-{
-    int ret;
-
-    if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
-        return( ret );
-
-    return( 0 );
-}
-
-int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
-                                char *not_after )
-{
-    if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
-        strlen(not_after)  != X509_RFC5280_UTC_TIME_LEN - 1 )
-    {
-        return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
-    }
-    strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
-    strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
-    ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
-    ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
-
-    return( 0 );
-}
-
-int x509write_crt_set_extension( x509write_cert *ctx,
-                                 const char *oid, size_t oid_len,
-                                 int critical,
-                                 const unsigned char *val, size_t val_len )
-{
-    return x509_set_extension( &ctx->extensions, oid, oid_len,
-                               critical, val, val_len );
-}
-
-int x509write_crt_set_basic_constraints( x509write_cert *ctx,
-                                         int is_ca, int max_pathlen )
-{
-    int ret;
-    unsigned char buf[9];
-    unsigned char *c = buf + sizeof(buf);
-    size_t len = 0;
-
-    memset( buf, 0, sizeof(buf) );
-
-    if( is_ca && max_pathlen > 127 )
-        return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
-
-    if( is_ca )
-    {
-        if( max_pathlen >= 0 )
-        {
-            ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
-        }
-        ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
-    }
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
-                                        OID_SIZE( OID_BASIC_CONSTRAINTS ),
-                                        0, buf + sizeof(buf) - len, len );
-}
-
-int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
-{
-    int ret;
-    unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
-    unsigned char *c = buf + sizeof(buf);
-    size_t len = 0;
-
-    memset( buf, 0, sizeof(buf));
-    ASN1_CHK_ADD( len, x509_write_pubkey( &c, buf, ctx->subject_key ) );
-
-    sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
-    c = buf + sizeof(buf) - 20;
-    len = 20;
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
-
-    return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
-                                        OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
-                                        0, buf + sizeof(buf) - len, len );
-}
-
-int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
-{
-    int ret;
-    unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
-    unsigned char *c = buf + sizeof(buf);
-    size_t len = 0;
-
-    memset( buf, 0, sizeof(buf));
-    ASN1_CHK_ADD( len, x509_write_pubkey( &c, buf, ctx->issuer_key ) );
-
-    sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
-    c = buf + sizeof(buf) - 20;
-    len = 20;
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
-                                   OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
-                                   0, buf + sizeof(buf) - len, len );
-}
-
-int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
-{
-    unsigned char buf[4];
-    unsigned char *c;
-    int ret;
-
-    c = buf + 4;
-
-    if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
-        return( ret );
-
-    ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
-                                       OID_SIZE( OID_KEY_USAGE ),
-                                       1, buf, 4 );
-    if( ret != 0 )
-        return( ret );
-
-    return( 0 );
-}
-
-int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
-                                    unsigned char ns_cert_type )
-{
-    unsigned char buf[4];
-    unsigned char *c;
-    int ret;
-
-    c = buf + 4;
-
-    if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
-        return( ret );
-
-    ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
-                                       OID_SIZE( OID_NS_CERT_TYPE ),
-                                       0, buf, 4 );
-    if( ret != 0 )
-        return( ret );
-
-    return( 0 );
-}
-
-int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size )
-{
-    int ret;
-    unsigned char *c;
-    size_t len = 0, par_len = 0, oid_len;
-    const char *oid;
-
-    c = buf + size;
-
-    ASN1_CHK_ADD( len, x509_write_pubkey( &c, buf, key ) );
-
-    if( c - buf < 1 )
-        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
-    /*
-     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
-     *       algorithm            AlgorithmIdentifier,
-     *       subjectPublicKey     BIT STRING }
-     */
-    *--c = 0;
-    len += 1;
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
-
-    if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ),
-                                       &oid, &oid_len ) ) != 0 )
-    {
-        return( ret );
-    }
-
-#if defined(POLARSSL_ECP_C)
-    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
-    {
-        ASN1_CHK_ADD( par_len, x509_write_ec_param( &c, buf, pk_ec( *key ) ) );
-    }
-#endif
-
-    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
-                                                        par_len ) );
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    return( len );
-}
-
-int x509write_key_der( pk_context *key, unsigned char *buf, size_t size )
-{
-    int ret;
-    unsigned char *c = buf + size;
-    size_t len = 0;
-
-#if defined(POLARSSL_RSA_C)
-    if( pk_get_type( key ) == POLARSSL_PK_RSA )
-    {
-        rsa_context *rsa = pk_rsa( *key );
-
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
-        ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
-
-        ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-    }
-    else
-#endif
-#if defined(POLARSSL_ECP_C)
-    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
-    {
-        ecp_keypair *ec = pk_ec( *key );
-        size_t pub_len = 0, par_len = 0;
-
-        /*
-         * RFC 5915, or SEC1 Appendix C.4
-         *
-         * ECPrivateKey ::= SEQUENCE {
-         *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
-         *      privateKey     OCTET STRING,
-         *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
-         *      publicKey  [1] BIT STRING OPTIONAL
-         *    }
-         */
-
-        /* publicKey */
-        ASN1_CHK_ADD( pub_len, x509_write_ec_pubkey( &c, buf, ec ) );
-
-        if( c - buf < 1 )
-            return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-        *--c = 0;
-        pub_len += 1;
-
-        ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
-        ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
-
-        ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) );
-        ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf,
-                            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) );
-        len += pub_len;
-
-        /* parameters */
-        ASN1_CHK_ADD( par_len, x509_write_ec_param( &c, buf, ec ) );
-
-        ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) );
-        ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf,
-                            ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
-        len += par_len;
-
-        /* privateKey: write as MPI then fix tag */
-        ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) );
-        *c = ASN1_OCTET_STRING;
-
-        /* version */
-        ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) );
-
-        ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-    }
-    else
-#endif
-        return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-
-    return( len );
-}
-
-/*
- *  RelativeDistinguishedName ::=
- *    SET OF AttributeTypeAndValue
- *
- *  AttributeTypeAndValue ::= SEQUENCE {
- *    type     AttributeType,
- *    value    AttributeValue }
- *
- *  AttributeType ::= OBJECT IDENTIFIER
- *
- *  AttributeValue ::= ANY DEFINED BY AttributeType
- */
-static int x509_write_name( unsigned char **p, unsigned char *start,
-                            const char *oid, size_t oid_len,
-                            const unsigned char *name, size_t name_len )
-{
-    int ret;
-    size_t len = 0;
-
-    // Write PrintableString for all except OID_PKCS9_EMAIL
-    //
-    if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
-        memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
-    {
-        ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
-                                                  (const char *) name,
-                                                  name_len ) );
-    }
-    else
-    {
-        ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
-                                                        (const char *) name,
-                                                        name_len ) );
-    }
-
-    // Write OID
-    //
-    ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
-
-    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
-
-    return( len );
-}
-
-static int x509_write_names( unsigned char **p, unsigned char *start,
-                             asn1_named_data *first )
-{
-    int ret;
-    size_t len = 0;
-    asn1_named_data *cur = first;
-
-    while( cur != NULL )
-    {
-        ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
-                                            cur->oid.len,
-                                            cur->val.p, cur->val.len ) );
-        cur = cur->next;
-    }
-
-    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    return( len );
-}
-
-static int x509_write_sig( unsigned char **p, unsigned char *start,
-                           const char *oid, size_t oid_len,
-                           unsigned char *sig, size_t size )
-{
-    int ret;
-    size_t len = 0;
-
-    if( *p - start < (int) size + 1 )
-        return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
-    len = size;
-    (*p) -= len;
-    memcpy( *p, sig, len );
-
-    *--(*p) = 0;
-    len += 1;
-
-    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
-
-    // Write OID
-    //
-    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
-                                                        oid_len, 0 ) );
-
-    return( len );
-}
-
-static int x509_write_time( unsigned char **p, unsigned char *start,
-                            const char *time, size_t size )
-{
-    int ret;
-    size_t len = 0;
-
-    /*
-     * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
-     */
-    if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
-    {
-        ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
-                                             (const unsigned char *) time + 2,
-                                             size - 2 ) );
-        ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
-    }
-    else
-    {
-        ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
-                                                  (const unsigned char *) time,
-                                                  size ) );
-        ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
-    }
-
-    return( len );
-}
-
-static int x509_write_extension( unsigned char **p, unsigned char *start,
-                                 asn1_named_data *ext )
-{
-    int ret;
-    size_t len = 0;
-
-    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
-                                              ext->val.len - 1 ) );
-    ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
-
-    if( ext->val.p[0] != 0 )
-    {
-        ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
-    }
-
-    ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
-                                              ext->oid.len ) );
-    ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
-
-    ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    return( len );
-}
-
-/*
- * Extension  ::=  SEQUENCE  {
- *     extnID      OBJECT IDENTIFIER,
- *     critical    BOOLEAN DEFAULT FALSE,
- *     extnValue   OCTET STRING
- *                 -- contains the DER encoding of an ASN.1 value
- *                 -- corresponding to the extension type identified
- *                 -- by extnID
- *     }
- */
-static int x509_write_extensions( unsigned char **p, unsigned char *start,
-                                 asn1_named_data *first )
-{
-    int ret;
-    size_t len = 0;
-    asn1_named_data *cur_ext = first;
-
-    while( cur_ext != NULL )
-    {
-        ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
-        cur_ext = cur_ext->next;
-    }
-
-    return( len );
-}
-
-int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng )
-{
-    int ret;
-    const char *sig_oid;
-    size_t sig_oid_len = 0;
-    unsigned char *c, *c2;
-    unsigned char hash[64];
-    unsigned char sig[POLARSSL_MPI_MAX_SIZE];
-    unsigned char tmp_buf[2048];
-    size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
-    size_t len = 0;
-    pk_type_t pk_alg;
-
-    /*
-     * Prepare data to be signed in tmp_buf
-     */
-    c = tmp_buf + sizeof( tmp_buf );
-
-    ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
-
-    if( len )
-    {
-        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
-
-        ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
-                                          OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
-
-        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-    }
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
-
-    ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->key,
-                                                 tmp_buf, c - tmp_buf ) );
-    c -= pub_len;
-    len += pub_len;
-
-    /*
-     *  Subject  ::=  Name
-     */
-    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
-
-    /*
-     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
-     */
-    ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    /*
-     * Prepare signature
-     */
-    md( md_info_from_type( ctx->md_alg ), c, len, hash );
-
-    pk_alg = pk_get_type( ctx->key );
-    if( pk_alg == POLARSSL_PK_ECKEY )
-        pk_alg = POLARSSL_PK_ECDSA;
-
-    if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
-                         f_rng, p_rng ) ) != 0 ||
-        ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
-                                        &sig_oid, &sig_oid_len ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    /*
-     * Write data to output buffer
-     */
-    c2 = buf + size;
-    ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
-                                        sig_oid, sig_oid_len, sig, sig_len ) );
-
-    c2 -= len;
-    memcpy( c2, c, len );
-
-    len += sig_and_oid_len;
-    ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    return( len );
-}
-
-int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng )
-{
-    int ret;
-    const char *sig_oid;
-    size_t sig_oid_len = 0;
-    unsigned char *c, *c2;
-    unsigned char hash[64];
-    unsigned char sig[POLARSSL_MPI_MAX_SIZE];
-    unsigned char tmp_buf[2048];
-    size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
-    size_t len = 0;
-    pk_type_t pk_alg;
-
-    /*
-     * Prepare data to be signed in tmp_buf
-     */
-    c = tmp_buf + sizeof( tmp_buf );
-
-    /* Signature algorithm needed in TBS, and later for actual signature */
-    pk_alg = pk_get_type( ctx->issuer_key );
-    if( pk_alg == POLARSSL_PK_ECKEY )
-        pk_alg = POLARSSL_PK_ECDSA;
-
-    if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
-                                        &sig_oid, &sig_oid_len ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    /*
-     *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
-     */
-    ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
-    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
-
-    /*
-     *  SubjectPublicKeyInfo
-     */
-    ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->subject_key,
-                                                 tmp_buf, c - tmp_buf ) );
-    c -= pub_len;
-    len += pub_len;
-
-    /*
-     *  Subject  ::=  Name
-     */
-    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
-
-    /*
-     *  Validity ::= SEQUENCE {
-     *       notBefore      Time,
-     *       notAfter       Time }
-     */
-    sub_len = 0;
-
-    ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
-                                            X509_RFC5280_UTC_TIME_LEN ) );
-
-    ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
-                                            X509_RFC5280_UTC_TIME_LEN ) );
-
-    len += sub_len;
-    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    /*
-     *  Issuer  ::=  Name
-     */
-    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
-
-    /*
-     *  Signature   ::=  AlgorithmIdentifier
-     */
-    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
-                       sig_oid, strlen( sig_oid ), 0 ) );
-
-    /*
-     *  Serial   ::=  INTEGER
-     */
-    ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
-
-    /*
-     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
-     */
-    sub_len = 0;
-    ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
-    len += sub_len;
-    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
-
-    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    /*
-     * Make signature
-     */
-    md( md_info_from_type( ctx->md_alg ), c, len, hash );
-
-    if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
-                         f_rng, p_rng ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    /*
-     * Write data to output buffer
-     */
-    c2 = buf + size;
-    ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
-                                        sig_oid, sig_oid_len, sig, sig_len ) );
-
-    c2 -= len;
-    memcpy( c2, c, len );
-
-    len += sig_and_oid_len;
-    ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
-    return( len );
-}
-
-#define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
-#define PEM_END_CRT             "-----END CERTIFICATE-----\n"
-
-#define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
-#define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
-
-#define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
-#define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
-
-#define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
-#define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
-#define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
-#define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
-
-#if defined(POLARSSL_BASE64_C)
-static int x509write_pemify( const char *begin_str, const char *end_str,
-                             const unsigned char *der_data, size_t der_len,
-                             unsigned char *buf, size_t size )
-{
-    int ret;
-    unsigned char base_buf[4096];
-    unsigned char *c = base_buf, *p = buf;
-    size_t len = 0, olen = sizeof(base_buf);
-
-    if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
-        return( ret );
-
-    if( olen + strlen( begin_str ) + strlen( end_str ) +
-        olen / 64 > size )
-    {
-        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
-    }
-
-    memcpy( p, begin_str, strlen( begin_str ) );
-    p += strlen( begin_str );
-
-    while( olen )
-    {
-        len = ( olen > 64 ) ? 64 : olen;
-        memcpy( p, c, len );
-        olen -= len;
-        p += len;
-        c += len;
-        *p++ = '\n';
-    }
-
-    memcpy( p, end_str, strlen( end_str ) );
-    p += strlen( end_str );
-
-    *p = '\0';
-
-    return( 0 );
-}
-
-int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng )
-{
-    int ret;
-    unsigned char output_buf[4096];
-
-    if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf),
-                                   f_rng, p_rng ) ) < 0 )
-    {
-        return( ret );
-    }
-
-    if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
-                                  output_buf + sizeof(output_buf) - ret,
-                                  ret, buf, size ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    return( 0 );
-}
-
-int x509write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size )
-{
-    int ret;
-    unsigned char output_buf[4096];
-
-    if( ( ret = x509write_pubkey_der( key, output_buf,
-                                      sizeof(output_buf) ) ) < 0 )
-    {
-        return( ret );
-    }
-
-    if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
-                                  output_buf + sizeof(output_buf) - ret,
-                                  ret, buf, size ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    return( 0 );
-}
-
-int x509write_key_pem( pk_context *key, unsigned char *buf, size_t size )
-{
-    int ret;
-    unsigned char output_buf[4096];
-    char *begin, *end;
-
-    if( ( ret = x509write_key_der( key, output_buf,
-                                      sizeof(output_buf) ) ) < 0 )
-    {
-        return( ret );
-    }
-
-#if defined(POLARSSL_RSA_C)
-    if( pk_get_type( key ) == POLARSSL_PK_RSA )
-    {
-        begin = PEM_BEGIN_PRIVATE_KEY_RSA;
-        end = PEM_END_PRIVATE_KEY_RSA;
-    }
-    else
-#endif
-#if defined(POLARSSL_ECP_C)
-    if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
-    {
-        begin = PEM_BEGIN_PRIVATE_KEY_EC;
-        end = PEM_END_PRIVATE_KEY_EC;
-    }
-    else
-#endif
-        return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-
-    if( ( ret = x509write_pemify( begin, end,
-                                  output_buf + sizeof(output_buf) - ret,
-                                  ret, buf, size ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    return( 0 );
-}
-
-int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng )
-{
-    int ret;
-    unsigned char output_buf[4096];
-
-    if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
-                                   f_rng, p_rng ) ) < 0 )
-    {
-        return( ret );
-    }
-
-    if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
-                                  output_buf + sizeof(output_buf) - ret,
-                                  ret, buf, size ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    return( 0 );
-}
-#endif /* POLARSSL_BASE64_C */
-
-#endif
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
new file mode 100644
index 0000000..1761c1f
--- /dev/null
+++ b/library/x509write_crt.c
@@ -0,0 +1,426 @@
+/*
+ *  X.509 certificate writing
+ *
+ *  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.
+ */
+/*
+ * References:
+ * - certificates: RFC 5280, updated by RFC 6818
+ * - CSRs: PKCS#10 v1.7 aka RFC 2986
+ * - attributes: PKCS#9 v2.0 aka RFC 2985
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_CRT_WRITE_C)
+
+#include "polarssl/x509_crt.h"
+#include "polarssl/oid.h"
+#include "polarssl/asn1write.h"
+#include "polarssl/sha1.h"
+
+#if defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif /* POLARSSL_PEM_WRITE_C */
+
+void x509write_crt_init( x509write_cert *ctx )
+{
+    memset( ctx, 0, sizeof(x509write_cert) );
+
+    mpi_init( &ctx->serial );
+    ctx->version = X509_CRT_VERSION_3;
+}
+
+void x509write_crt_free( x509write_cert *ctx )
+{
+    mpi_free( &ctx->serial );
+
+    asn1_free_named_data_list( &ctx->subject );
+    asn1_free_named_data_list( &ctx->issuer );
+    asn1_free_named_data_list( &ctx->extensions );
+
+    memset( ctx, 0, sizeof(x509write_cert) );
+}
+
+void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
+{
+    ctx->md_alg = md_alg;
+}
+
+void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key )
+{
+    ctx->subject_key = key;
+}
+
+void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key )
+{
+    ctx->issuer_key = key;
+}
+
+int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
+{
+    return x509_string_to_names( &ctx->subject, subject_name );
+}
+
+int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
+{
+    return x509_string_to_names( &ctx->issuer, issuer_name );
+}
+
+int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
+{
+    int ret;
+
+    if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
+                                char *not_after )
+{
+    if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
+        strlen(not_after)  != X509_RFC5280_UTC_TIME_LEN - 1 )
+    {
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+    }
+    strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
+    strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
+    ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
+    ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
+
+    return( 0 );
+}
+
+int x509write_crt_set_extension( x509write_cert *ctx,
+                                 const char *oid, size_t oid_len,
+                                 int critical,
+                                 const unsigned char *val, size_t val_len )
+{
+    return x509_set_extension( &ctx->extensions, oid, oid_len,
+                               critical, val, val_len );
+}
+
+int x509write_crt_set_basic_constraints( x509write_cert *ctx,
+                                         int is_ca, int max_pathlen )
+{
+    int ret;
+    unsigned char buf[9];
+    unsigned char *c = buf + sizeof(buf);
+    size_t len = 0;
+
+    memset( buf, 0, sizeof(buf) );
+
+    if( is_ca && max_pathlen > 127 )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    if( is_ca )
+    {
+        if( max_pathlen >= 0 )
+        {
+            ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
+        }
+        ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
+                                        OID_SIZE( OID_BASIC_CONSTRAINTS ),
+                                        0, buf + sizeof(buf) - len, len );
+}
+
+int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
+{
+    int ret;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
+    unsigned char *c = buf + sizeof(buf);
+    size_t len = 0;
+
+    memset( buf, 0, sizeof(buf));
+    ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) );
+
+    sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
+    c = buf + sizeof(buf) - 20;
+    len = 20;
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
+
+    return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
+                                        OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
+                                        0, buf + sizeof(buf) - len, len );
+}
+
+int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
+{
+    int ret;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
+    unsigned char *c = buf + sizeof(buf);
+    size_t len = 0;
+
+    memset( buf, 0, sizeof(buf));
+    ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) );
+
+    sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
+    c = buf + sizeof(buf) - 20;
+    len = 20;
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
+                                   OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
+                                   0, buf + sizeof(buf) - len, len );
+}
+
+int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
+{
+    unsigned char buf[4];
+    unsigned char *c;
+    int ret;
+
+    c = buf + 4;
+
+    if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
+        return( ret );
+
+    ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
+                                       OID_SIZE( OID_KEY_USAGE ),
+                                       1, buf, 4 );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
+                                    unsigned char ns_cert_type )
+{
+    unsigned char buf[4];
+    unsigned char *c;
+    int ret;
+
+    c = buf + 4;
+
+    if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
+        return( ret );
+
+    ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
+                                       OID_SIZE( OID_NS_CERT_TYPE ),
+                                       0, buf, 4 );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+static int x509_write_time( unsigned char **p, unsigned char *start,
+                            const char *time, size_t size )
+{
+    int ret;
+    size_t len = 0;
+
+    /*
+     * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
+     */
+    if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
+    {
+        ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
+                                             (const unsigned char *) time + 2,
+                                             size - 2 ) );
+        ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
+    }
+    else
+    {
+        ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
+                                                  (const unsigned char *) time,
+                                                  size ) );
+        ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
+    }
+
+    return( len );
+}
+
+int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng )
+{
+    int ret;
+    const char *sig_oid;
+    size_t sig_oid_len = 0;
+    unsigned char *c, *c2;
+    unsigned char hash[64];
+    unsigned char sig[POLARSSL_MPI_MAX_SIZE];
+    unsigned char tmp_buf[2048];
+    size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
+    size_t len = 0;
+    pk_type_t pk_alg;
+
+    /*
+     * Prepare data to be signed in tmp_buf
+     */
+    c = tmp_buf + sizeof( tmp_buf );
+
+    /* Signature algorithm needed in TBS, and later for actual signature */
+    pk_alg = pk_get_type( ctx->issuer_key );
+    if( pk_alg == POLARSSL_PK_ECKEY )
+        pk_alg = POLARSSL_PK_ECDSA;
+
+    if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
+                                        &sig_oid, &sig_oid_len ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /*
+     *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
+     */
+    ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
+
+    /*
+     *  SubjectPublicKeyInfo
+     */
+    ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key,
+                                                tmp_buf, c - tmp_buf ) );
+    c -= pub_len;
+    len += pub_len;
+
+    /*
+     *  Subject  ::=  Name
+     */
+    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
+
+    /*
+     *  Validity ::= SEQUENCE {
+     *       notBefore      Time,
+     *       notAfter       Time }
+     */
+    sub_len = 0;
+
+    ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
+                                            X509_RFC5280_UTC_TIME_LEN ) );
+
+    ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
+                                            X509_RFC5280_UTC_TIME_LEN ) );
+
+    len += sub_len;
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    /*
+     *  Issuer  ::=  Name
+     */
+    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
+
+    /*
+     *  Signature   ::=  AlgorithmIdentifier
+     */
+    ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
+                       sig_oid, strlen( sig_oid ), 0 ) );
+
+    /*
+     *  Serial   ::=  INTEGER
+     */
+    ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
+
+    /*
+     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+     */
+    sub_len = 0;
+    ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
+    len += sub_len;
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    /*
+     * Make signature
+     */
+    md( md_info_from_type( ctx->md_alg ), c, len, hash );
+
+    if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
+                         f_rng, p_rng ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /*
+     * Write data to output buffer
+     */
+    c2 = buf + size;
+    ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
+                                        sig_oid, sig_oid_len, sig, sig_len ) );
+
+    c2 -= len;
+    memcpy( c2, c, len );
+
+    len += sig_and_oid_len;
+    ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return( len );
+}
+
+#define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
+#define PEM_END_CRT             "-----END CERTIFICATE-----\n"
+
+#if defined(POLARSSL_PEM_WRITE_C)
+int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng )
+{
+    int ret;
+    unsigned char output_buf[4096];
+    size_t olen = 0;
+
+    if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf),
+                                   f_rng, p_rng ) ) < 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
+                                  output_buf + sizeof(output_buf) - ret,
+                                  ret, buf, size, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_PEM_WRITE_C */
+
+#endif /* POLARSSL_X509_CRT_WRITE_C */
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
new file mode 100644
index 0000000..1eb2afb
--- /dev/null
+++ b/library/x509write_csr.c
@@ -0,0 +1,244 @@
+/*
+ *  X.509 Certificate Signing Request writing
+ *
+ *  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.
+ */
+/*
+ * References:
+ * - CSRs: PKCS#10 v1.7 aka RFC 2986
+ * - attributes: PKCS#9 v2.0 aka RFC 2985
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_CSR_WRITE_C)
+
+#include "polarssl/x509_csr.h"
+#include "polarssl/oid.h"
+#include "polarssl/asn1write.h"
+
+#if defined(POLARSSL_PEM_WRITE_C)
+#include "polarssl/pem.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+void x509write_csr_init( x509write_csr *ctx )
+{
+    memset( ctx, 0, sizeof(x509write_csr) );
+}
+
+void x509write_csr_free( x509write_csr *ctx )
+{
+    asn1_free_named_data_list( &ctx->subject );
+    asn1_free_named_data_list( &ctx->extensions );
+
+    memset( ctx, 0, sizeof(x509write_csr) );
+}
+
+void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
+{
+    ctx->md_alg = md_alg;
+}
+
+void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
+{
+    ctx->key = key;
+}
+
+int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
+{
+    return x509_string_to_names( &ctx->subject, subject_name );
+}
+
+int x509write_csr_set_extension( x509write_csr *ctx,
+                                 const char *oid, size_t oid_len,
+                                 const unsigned char *val, size_t val_len )
+{
+    return x509_set_extension( &ctx->extensions, oid, oid_len,
+                               0, val, val_len );
+}
+
+int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
+{
+    unsigned char buf[4];
+    unsigned char *c;
+    int ret;
+
+    c = buf + 4;
+
+    if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
+        return( ret );
+
+    ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
+                                       OID_SIZE( OID_KEY_USAGE ),
+                                       buf, 4 );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
+                                    unsigned char ns_cert_type )
+{
+    unsigned char buf[4];
+    unsigned char *c;
+    int ret;
+
+    c = buf + 4;
+
+    if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
+        return( ret );
+
+    ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
+                                       OID_SIZE( OID_NS_CERT_TYPE ),
+                                       buf, 4 );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng )
+{
+    int ret;
+    const char *sig_oid;
+    size_t sig_oid_len = 0;
+    unsigned char *c, *c2;
+    unsigned char hash[64];
+    unsigned char sig[POLARSSL_MPI_MAX_SIZE];
+    unsigned char tmp_buf[2048];
+    size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
+    size_t len = 0;
+    pk_type_t pk_alg;
+
+    /*
+     * Prepare data to be signed in tmp_buf
+     */
+    c = tmp_buf + sizeof( tmp_buf );
+
+    ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
+
+    if( len )
+    {
+        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
+
+        ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
+                                          OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
+
+        ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    }
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
+
+    ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
+                                                tmp_buf, c - tmp_buf ) );
+    c -= pub_len;
+    len += pub_len;
+
+    /*
+     *  Subject  ::=  Name
+     */
+    ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
+
+    /*
+     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+     */
+    ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    /*
+     * Prepare signature
+     */
+    md( md_info_from_type( ctx->md_alg ), c, len, hash );
+
+    pk_alg = pk_get_type( ctx->key );
+    if( pk_alg == POLARSSL_PK_ECKEY )
+        pk_alg = POLARSSL_PK_ECDSA;
+
+    if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
+                         f_rng, p_rng ) ) != 0 ||
+        ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
+                                        &sig_oid, &sig_oid_len ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /*
+     * Write data to output buffer
+     */
+    c2 = buf + size;
+    ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
+                                        sig_oid, sig_oid_len, sig, sig_len ) );
+
+    c2 -= len;
+    memcpy( c2, c, len );
+
+    len += sig_and_oid_len;
+    ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    return( len );
+}
+
+#define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
+#define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
+
+#if defined(POLARSSL_PEM_WRITE_C)
+int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng )
+{
+    int ret;
+    unsigned char output_buf[4096];
+    size_t olen = 0;
+
+    if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
+                                   f_rng, p_rng ) ) < 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
+                                  output_buf + sizeof(output_buf) - ret,
+                                  ret, buf, size, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_PEM_WRITE_C */
+
+#endif /* POLARSSL_X509_CSR_WRITE_C */
diff --git a/programs/pkey/key_app.c b/programs/pkey/key_app.c
index bea996a..de5f513 100644
--- a/programs/pkey/key_app.c
+++ b/programs/pkey/key_app.c
@@ -37,6 +37,19 @@
 #include "polarssl/rsa.h"
 #include "polarssl/x509.h"
 
+#if !defined(POLARSSL_BIGNUM_C) ||                                  \
+    !defined(POLARSSL_PK_PARSE_C) || !defined(POLARSSL_FS_IO)
+int main( int argc, char *argv[] )
+{
+    ((void) argc);
+    ((void) argv);
+
+    printf("POLARSSL_BIGNUM_C and/or "
+           "POLARSSL_PK_PARSE_C and/or POLARSSL_FS_IO not defined.\n");
+    return( 0 );
+}
+#else
+
 #define MODE_NONE               0
 #define MODE_PRIVATE            1
 #define MODE_PUBLIC             2
@@ -67,22 +80,10 @@
     "    password_file=%%s    default: \"\"\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;
-    rsa_context rsa;
+    pk_context pk;
     char buf[1024];
     int i;
     char *p, *q;
@@ -90,7 +91,7 @@
     /*
      * Set to sane values
      */
-    memset( &rsa, 0, sizeof( rsa_context ) );
+    pk_init( &pk );
     memset( buf, 0, 1024 );
 
     if( argc == 0 )
@@ -164,15 +165,12 @@
         printf( "\n  . Loading the private key ..." );
         fflush( stdout );
 
-        ret = x509parse_keyfile_rsa( &rsa, opt.filename, opt.password );
+        ret = pk_parse_keyfile( &pk, opt.filename, opt.password );
 
         if( ret != 0 )
         {
-#ifdef POLARSSL_ERROR_C
             polarssl_strerror( ret, buf, 1024 );
-#endif
-            printf( " failed\n  !  x509parse_key_rsa returned %d - %s\n\n", ret, buf );
-            rsa_free( &rsa );
+            printf( " failed\n  !  pk_parse_keyfile returned %d - %s\n\n", ret, buf );
             goto exit;
         }
 
@@ -181,15 +179,38 @@
         /*
          * 1.2 Print the key
          */
-        printf( "  . Key information    ...\n" );
-        mpi_write_file( "N:  ", &rsa.N, 16, NULL );
-        mpi_write_file( "E:  ", &rsa.E, 16, NULL );
-        mpi_write_file( "D:  ", &rsa.D, 16, NULL );
-        mpi_write_file( "P:  ", &rsa.P, 16, NULL );
-        mpi_write_file( "Q:  ", &rsa.Q, 16, NULL );
-        mpi_write_file( "DP: ", &rsa.DP, 16, NULL );
-        mpi_write_file( "DQ:  ", &rsa.DQ, 16, NULL );
-        mpi_write_file( "QP:  ", &rsa.QP, 16, NULL );
+#if defined(POLARSSL_RSA_C)
+        if( pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        {
+            rsa_context *rsa = pk_rsa( pk );
+            printf( "  . Key information    ...\n" );
+            mpi_write_file( "N:  ", &rsa->N, 16, NULL );
+            mpi_write_file( "E:  ", &rsa->E, 16, NULL );
+            mpi_write_file( "D:  ", &rsa->D, 16, NULL );
+            mpi_write_file( "P:  ", &rsa->P, 16, NULL );
+            mpi_write_file( "Q:  ", &rsa->Q, 16, NULL );
+            mpi_write_file( "DP: ", &rsa->DP, 16, NULL );
+            mpi_write_file( "DQ:  ", &rsa->DQ, 16, NULL );
+            mpi_write_file( "QP:  ", &rsa->QP, 16, NULL );
+        }
+        else
+#endif
+#if defined(POLARSSL_ECP_C)
+        if( pk_can_do( &pk, POLARSSL_PK_ECKEY ) )
+        {
+            ecp_keypair *ecp = pk_ec( pk );
+            printf( "  . Key information    ...\n" );
+            mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL );
+            mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL );
+            mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL );
+            mpi_write_file( "D   : ", &ecp->d  , 16, NULL );
+        }
+        else
+#endif
+        {
+            printf("Do not know how to print key information for this type\n" );
+            goto exit;
+        }
     }
     else if( opt.mode == MODE_PUBLIC )
     {
@@ -199,33 +220,49 @@
         printf( "\n  . Loading the public key ..." );
         fflush( stdout );
 
-        ret = x509parse_public_keyfile_rsa( &rsa, opt.filename );
+        ret = pk_parse_public_keyfile( &pk, opt.filename );
 
         if( ret != 0 )
         {
-#ifdef POLARSSL_ERROR_C
             polarssl_strerror( ret, buf, 1024 );
-#endif
-            printf( " failed\n  !  x509parse_public_key_rsa returned %d - %s\n\n", ret, buf );
-            rsa_free( &rsa );
+            printf( " failed\n  !  pk_parse_public_keyfile returned %d - %s\n\n", ret, buf );
             goto exit;
         }
 
         printf( " ok\n" );
 
-        /*
-         * 1.2 Print the key
-         */
-        printf( "  . Key information    ...\n" );
-        mpi_write_file( "N: ", &rsa.N, 16, NULL );
-        mpi_write_file( "E:  ", &rsa.E, 16, NULL );
+#if defined(POLARSSL_RSA_C)
+        if( pk_can_do( &pk, POLARSSL_PK_RSA ) )
+        {
+            rsa_context *rsa = pk_rsa( pk );
+            printf( "  . Key information    ...\n" );
+            mpi_write_file( "N:  ", &rsa->N, 16, NULL );
+            mpi_write_file( "E:  ", &rsa->E, 16, NULL );
+        }
+        else
+#endif
+#if defined(POLARSSL_ECP_C)
+        if( pk_can_do( &pk, POLARSSL_PK_ECKEY ) )
+        {
+            ecp_keypair *ecp = pk_ec( pk );
+            printf( "  . Key information    ...\n" );
+            mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL );
+            mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL );
+            mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL );
+        }
+        else
+#endif
+        {
+            printf("Do not know how to print key information for this type\n" );
+            goto exit;
+        }
     }
     else
         goto usage;
 
 exit:
 
-    rsa_free( &rsa );
+    pk_free( &pk );
 
 #if defined(_WIN32)
     printf( "  + Press Enter to exit this program.\n" );
@@ -234,5 +271,4 @@
 
     return( ret );
 }
-#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C &&
-          POLARSSL_X509_PARSE_C && POLARSSL_FS_IO */
+#endif /* POLARSSL_BIGNUM_C && POLARSSL_PK_PARSE_C && POLARSSL_FS_IO */
diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c
index 371b03a..3257635 100644
--- a/programs/pkey/key_app_writer.c
+++ b/programs/pkey/key_app_writer.c
@@ -33,16 +33,16 @@
 
 #include "polarssl/config.h"
 
-#include "polarssl/x509write.h"
+#include "polarssl/pk.h"
 #include "polarssl/error.h"
 
-#if !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_FS_IO)
+#if !defined(POLARSSL_PK_WRITE_C) || !defined(POLARSSL_FS_IO)
 int main( int argc, char *argv[] )
 {
     ((void) argc);
     ((void) argv);
 
-    printf( "POLARSSL_X509_WRITE_C and/or POLARSSL_FS_IO not defined.\n" );
+    printf( "POLARSSL_PK_WRITE_C and/or POLARSSL_FS_IO not defined.\n" );
     return( 0 );
 }
 #else
@@ -89,14 +89,14 @@
 
     if( opt.output_format == OUTPUT_FORMAT_PEM )
     {
-        if( ( ret = x509write_pubkey_pem( key, output_buf, 16000 ) ) != 0 )
+        if( ( ret = pk_write_pubkey_pem( key, output_buf, 16000 ) ) != 0 )
             return( ret );
 
         len = strlen( (char *) output_buf );
     }
     else
     {
-        if( ( ret = x509write_pubkey_der( key, output_buf, 16000 ) ) < 0 )
+        if( ( ret = pk_write_pubkey_der( key, output_buf, 16000 ) ) < 0 )
             return( ret );
 
         len = ret;
@@ -125,14 +125,14 @@
     memset(output_buf, 0, 16000);
     if( opt.output_format == OUTPUT_FORMAT_PEM )
     {
-        if( ( ret = x509write_key_pem( key, output_buf, 16000 ) ) != 0 )
+        if( ( ret = pk_write_key_pem( key, output_buf, 16000 ) ) != 0 )
             return( ret );
 
         len = strlen( (char *) output_buf );
     }
     else
     {
-        if( ( ret = x509write_key_der( key, output_buf, 16000 ) ) < 0 )
+        if( ( ret = pk_write_key_der( key, output_buf, 16000 ) ) < 0 )
             return( ret );
 
         len = ret;
@@ -250,11 +250,11 @@
         printf( "\n  . Loading the private key ..." );
         fflush( stdout );
 
-        ret = x509parse_keyfile( &key, opt.filename, NULL );
+        ret = pk_parse_keyfile( &key, opt.filename, NULL );
 
         if( ret != 0 )
         {
-            printf( " failed\n  !  x509parse_key returned %d", ret );
+            printf( " failed\n  !  pk_parse_key returned %d", ret );
             goto exit;
         }
 
@@ -291,11 +291,11 @@
         printf( "\n  . Loading the public key ..." );
         fflush( stdout );
 
-        ret = x509parse_public_keyfile( &key, opt.filename );
+        ret = pk_parse_public_keyfile( &key, opt.filename );
 
         if( ret != 0 )
         {
-            printf( " failed\n  !  x509parse_public_key returned %d", ret );
+            printf( " failed\n  !  pk_parse_public_key returned %d", ret );
             goto exit;
         }
 
diff --git a/programs/pkey/rsa_sign_pss.c b/programs/pkey/rsa_sign_pss.c
index e848f54..2384661 100644
--- a/programs/pkey/rsa_sign_pss.c
+++ b/programs/pkey/rsa_sign_pss.c
@@ -45,7 +45,7 @@
 
 #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) ||  \
     !defined(POLARSSL_RSA_C) || !defined(POLARSSL_SHA1_C) ||        \
-    !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) ||  \
+    !defined(POLARSSL_PK_PARSE_C) || !defined(POLARSSL_FS_IO) ||    \
     !defined(POLARSSL_CTR_DRBG_C)
 int main( int argc, char *argv[] )
 {
@@ -54,7 +54,7 @@
 
     printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
            "POLARSSL_RSA_C and/or POLARSSL_SHA1_C and/or "
-           "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO and/or "
+           "POLARSSL_PK_PARSE_C and/or POLARSSL_FS_IO and/or "
            "POLARSSL_CTR_DRBG_C not defined.\n");
     return( 0 );
 }
@@ -63,13 +63,14 @@
 {
     FILE *f;
     int ret;
-    rsa_context rsa;
+    pk_context pk;
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     unsigned char hash[20];
     unsigned char buf[POLARSSL_MPI_MAX_SIZE];
     char filename[512];
     const char *pers = "rsa_sign_pss";
+    size_t olen = 0;
 
     ret = 1;
 
@@ -99,15 +100,22 @@
     printf( "\n  . Reading private key from '%s'", argv[1] );
     fflush( stdout );
 
-    rsa_init( &rsa, RSA_PKCS_V21, POLARSSL_MD_SHA1 );
+    pk_init( &pk );
 
-    if( ( ret = x509parse_keyfile_rsa( &rsa, argv[1], "" ) ) != 0 )
+    if( ( ret = pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 )
     {
         ret = 1;
         printf( " failed\n  ! Could not open '%s'\n", argv[1] );
         goto exit;
     }
 
+    if( !pk_can_do( &pk, POLARSSL_PK_RSA ) )
+    {
+        ret = 1;
+        printf( " failed\n  ! Key is not an RSA key\n" );
+        goto exit;
+    }
+
     /*
      * Compute the SHA-1 hash of the input file,
      * then calculate the RSA signature of the hash.
@@ -121,11 +129,10 @@
         goto exit;
     }
 
-    if( ( ret = rsa_pkcs1_sign( &rsa, ctr_drbg_random, &ctr_drbg,
-                                RSA_PRIVATE, POLARSSL_MD_SHA1,
-                                20, hash, buf ) ) != 0 )
+    if( ( ret = pk_sign( &pk, POLARSSL_MD_SHA1, hash, 0, buf, &olen,
+                         ctr_drbg_random, &ctr_drbg ) ) != 0 )
     {
-        printf( " failed\n  ! rsa_pkcs1_sign returned %d\n\n", ret );
+        printf( " failed\n  ! pk_sign returned %d\n\n", ret );
         goto exit;
     }
 
@@ -141,7 +148,7 @@
         goto exit;
     }
 
-    if( fwrite( buf, 1, rsa.len, f ) != (size_t) rsa.len )
+    if( fwrite( buf, 1, olen, f ) != olen )
     {
         printf( "failed\n  ! fwrite failed\n\n" );
         goto exit;
@@ -152,6 +159,7 @@
     printf( "\n  . Done (created \"%s\")\n\n", filename );
 
 exit:
+    pk_free( &pk );
 
 #if defined(_WIN32)
     printf( "  + Press Enter to exit this program.\n" );
@@ -161,5 +169,5 @@
     return( ret );
 }
 #endif /* POLARSSL_BIGNUM_C && POLARSSL_ENTROPY_C && POLARSSL_RSA_C &&
-          POLARSSL_SHA1_C && POLARSSL_X509_PARSE_C && POLARSSL_FS_IO &&
+          POLARSSL_SHA1_C && POLARSSL_PK_PARSE_C && POLARSSL_FS_IO &&
           POLARSSL_CTR_DRBG_C */
diff --git a/programs/pkey/rsa_verify_pss.c b/programs/pkey/rsa_verify_pss.c
index b243772..21be848 100644
--- a/programs/pkey/rsa_verify_pss.c
+++ b/programs/pkey/rsa_verify_pss.c
@@ -34,7 +34,7 @@
 
 #include "polarssl/md.h"
 #include "polarssl/pem.h"
-#include "polarssl/rsa.h"
+#include "polarssl/pk.h"
 #include "polarssl/sha1.h"
 #include "polarssl/x509.h"
 
@@ -43,7 +43,7 @@
 #endif
 
 #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) ||      \
-    !defined(POLARSSL_SHA1_C) || !defined(POLARSSL_X509_PARSE_C) || \
+    !defined(POLARSSL_SHA1_C) || !defined(POLARSSL_PK_PARSE_C) ||   \
     !defined(POLARSSL_FS_IO)
 int main( int argc, char *argv[] )
 {
@@ -51,7 +51,7 @@
     ((void) argv);
 
     printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or "
-           "POLARSSL_SHA1_C and/or POLARSSL_X509_PARSE_C and/or "
+           "POLARSSL_SHA1_C and/or POLARSSL_PK_PARSE_C and/or "
            "POLARSSL_FS_IO not defined.\n");
     return( 0 );
 }
@@ -61,7 +61,7 @@
     FILE *f;
     int ret;
     size_t i;
-    rsa_context rsa;
+    pk_context pk;
     unsigned char hash[20];
     unsigned char buf[POLARSSL_MPI_MAX_SIZE];
     char filename[512];
@@ -81,11 +81,18 @@
     printf( "\n  . Reading public key from '%s'", argv[1] );
     fflush( stdout );
 
-    rsa_init( &rsa, RSA_PKCS_V21, POLARSSL_MD_SHA1 );
+    pk_init( &pk );
 
-    if( ( ret = x509parse_public_keyfile_rsa( &rsa, argv[1] ) ) != 0 )
+    if( ( ret = pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 )
     {
-        printf( " failed\n  ! x509parse_public_key_rsa returned %d\n\n", ret );
+        printf( " failed\n  ! pk_parse_public_keyfile returned %d\n\n", ret );
+        goto exit;
+    }
+
+    if( !pk_can_do( &pk, POLARSSL_PK_RSA ) )
+    {
+        ret = 1;
+        printf( " failed\n  ! Key is not an RSA key\n" );
         goto exit;
     }
 
@@ -101,16 +108,11 @@
         goto exit;
     }
 
-    i = fread( buf, 1, rsa.len, f );
+
+    i = fread( buf, 1, POLARSSL_MPI_MAX_SIZE, f );
 
     fclose( f );
 
-    if( i != rsa.len )
-    {
-        printf( "\n  ! Invalid RSA signature format\n\n" );
-        goto exit;
-    }
-
     /*
      * Compute the SHA-1 hash of the input file and compare
      * it with the hash decrypted from the RSA signature.
@@ -124,10 +126,10 @@
         goto exit;
     }
 
-    if( ( ret = rsa_pkcs1_verify( &rsa, NULL, NULL, RSA_PUBLIC,
-                                  POLARSSL_MD_SHA1, 20, hash, buf ) ) != 0 )
+    if( ( ret = pk_verify( &pk, POLARSSL_MD_SHA1, hash, 0,
+                           buf, i ) ) != 0 )
     {
-        printf( " failed\n  ! rsa_pkcs1_verify returned %d\n\n", ret );
+        printf( " failed\n  ! pk_verify returned %d\n\n", ret );
         goto exit;
     }
 
@@ -136,6 +138,7 @@
     ret = 0;
 
 exit:
+    pk_free( &pk );
 
 #if defined(_WIN32)
     printf( "  + Press Enter to exit this program.\n" );
@@ -145,4 +148,4 @@
     return( ret );
 }
 #endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_SHA1_C &&
-          POLARSSL_X509_PARSE_C && POLARSSL_FS_IO */
+          POLARSSL_PK_PARSE_C && POLARSSL_FS_IO */
diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c
index f4f3cca..d6e712b 100644
--- a/programs/ssl/ssl_client1.c
+++ b/programs/ssl/ssl_client1.c
@@ -39,6 +39,24 @@
 #include "polarssl/error.h"
 #include "polarssl/certs.h"
 
+#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) ||  \
+    !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \
+    !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) ||         \
+    !defined(POLARSSL_CTR_DRBG_C) || !defined(POLARSSL_X509_CRT_PARSE_C)
+int main( int argc, char *argv[] )
+{
+    ((void) argc);
+    ((void) argv);
+
+    printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
+           "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or "
+           "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
+           "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_CRT_PARSE_C "
+           "not defined.\n");
+    return( 0 );
+}
+#else
+
 #define SERVER_PORT 4433
 #define SERVER_NAME "localhost"
 #define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
@@ -54,23 +72,6 @@
     }
 }
 
-#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) ||  \
-    !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \
-    !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) ||         \
-    !defined(POLARSSL_CTR_DRBG_C) || !defined(POLARSSL_X509_PARSE_C)
-int main( int argc, char *argv[] )
-{
-    ((void) argc);
-    ((void) argv);
-
-    printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
-           "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or "
-           "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
-           "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_PARSE_C "
-           "not defined.\n");
-    return( 0 );
-}
-#else
 int main( int argc, char *argv[] )
 {
     int ret, len, server_fd;
@@ -80,7 +81,7 @@
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
-    x509_cert cacert;
+    x509_crt cacert;
 
     ((void) argc);
     ((void) argv);
@@ -89,7 +90,7 @@
      * 0. Initialize the RNG and the session data
      */
     memset( &ssl, 0, sizeof( ssl_context ) );
-    memset( &cacert, 0, sizeof( x509_cert ) );
+    x509_crt_init( &cacert );
 
     printf( "\n  . Seeding the random number generator..." );
     fflush( stdout );
@@ -112,8 +113,8 @@
     fflush( stdout );
 
 #if defined(POLARSSL_CERTS_C)
-    ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
-                         strlen( test_ca_crt ) );
+    ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
+                          strlen( test_ca_crt ) );
 #else
     ret = 1;
     printf("POLARSSL_CERTS_C not defined.");
@@ -121,7 +122,7 @@
 
     if( ret < 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
         goto exit;
     }
 
@@ -277,7 +278,7 @@
     }
 #endif
 
-    x509_free( &cacert );
+    x509_crt_free( &cacert );
     net_close( server_fd );
     ssl_free( &ssl );
 
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index f9989ff..eeeb718 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -111,17 +111,17 @@
     }
 }
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 /*
  * Enabled if debug_level > 1 in code below
  */
-static int my_verify( void *data, x509_cert *crt, int depth, int *flags )
+static int my_verify( void *data, x509_crt *crt, int depth, int *flags )
 {
     char buf[1024];
     ((void) data);
 
     printf( "\nVerify requested for (Depth %d):\n", depth );
-    x509parse_cert_info( buf, sizeof( buf ) - 1, "", crt );
+    x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
     printf( "%s", buf );
 
     if( ( (*flags) & BADCERT_EXPIRED ) != 0 )
@@ -150,9 +150,9 @@
 
     return( 0 );
 }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 #if defined(POLARSSL_FS_IO)
 #define USAGE_IO \
     "    ca_file=%%s          The single file containing the top-level CA(s) you fully trust\n" \
@@ -168,7 +168,7 @@
 #endif /* POLARSSL_FS_IO */
 #else
 #define USAGE_IO ""
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
 #define USAGE_PSK                                                   \
@@ -254,9 +254,9 @@
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
     ssl_session saved_session;
-#if defined(POLARSSL_X509_PARSE_C)
-    x509_cert cacert;
-    x509_cert clicert;
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt cacert;
+    x509_crt clicert;
     pk_context pkey;
 #endif
     char *p, *q;
@@ -268,9 +268,9 @@
     server_fd = 0;
     memset( &ssl, 0, sizeof( ssl_context ) );
     memset( &saved_session, 0, sizeof( ssl_session ) );
-#if defined(POLARSSL_X509_PARSE_C)
-    memset( &cacert, 0, sizeof( x509_cert ) );
-    memset( &clicert, 0, sizeof( x509_cert ) );
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt_init( &cacert );
+    x509_crt_init( &clicert );
     pk_init( &pkey );
 #endif
 
@@ -565,7 +565,7 @@
 
     printf( " ok\n" );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     /*
      * 1.1. Load the trusted CA
      */
@@ -574,13 +574,13 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.ca_path ) )
-        ret = x509parse_crtpath( &cacert, opt.ca_path );
+        ret = x509_crt_parse_path( &cacert, opt.ca_path );
     else if( strlen( opt.ca_file ) )
-        ret = x509parse_crtfile( &cacert, opt.ca_file );
+        ret = x509_crt_parse_file( &cacert, opt.ca_file );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
+        ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
                 strlen( test_ca_crt ) );
 #else
     {
@@ -590,7 +590,7 @@
 #endif
     if( ret < 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
         goto exit;
     }
 
@@ -606,11 +606,11 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.crt_file ) )
-        ret = x509parse_crtfile( &clicert, opt.crt_file );
+        ret = x509_crt_parse_file( &clicert, opt.crt_file );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_crt( &clicert, (const unsigned char *) test_cli_crt,
+        ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
                 strlen( test_cli_crt ) );
 #else
     {
@@ -620,17 +620,17 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
         goto exit;
     }
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.key_file ) )
-        ret = x509parse_keyfile( &pkey, opt.key_file, "" );
+        ret = pk_parse_keyfile( &pkey, opt.key_file, "" );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_key( &pkey, (const unsigned char *) test_cli_key,
+        ret = pk_parse_key( &pkey, (const unsigned char *) test_cli_key,
                 strlen( test_cli_key ), NULL, 0 );
 #else
     {
@@ -640,12 +640,12 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  pk_parse_key returned -0x%x\n\n", -ret );
         goto exit;
     }
 
     printf( " ok\n" );
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     /*
      * 2. Start the connection
@@ -677,7 +677,7 @@
 
     printf( " ok\n" );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     if( opt.debug_level > 0 )
         ssl_set_verify( &ssl, my_verify, NULL );
 #endif
@@ -709,7 +709,7 @@
     ssl_set_renegotiation( &ssl, opt.renegotiation );
     ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
     ssl_set_own_cert( &ssl, &clicert, &pkey );
 #endif
@@ -760,7 +760,7 @@
         printf( " ok\n" );
     }
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     /*
      * 5. Verify the server certificate
      */
@@ -790,11 +790,11 @@
     if( ssl_get_peer_cert( &ssl ) != NULL )
     {
         printf( "  . Peer certificate information    ...\n" );
-        x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ",
-                             ssl_get_peer_cert( &ssl ) );
+        x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
+                       ssl_get_peer_cert( &ssl ) );
         printf( "%s\n", buf );
     }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     /*
      * 6. Write the GET request
@@ -910,9 +910,9 @@
 
     if( server_fd )
         net_close( server_fd );
-#if defined(POLARSSL_X509_PARSE_C)
-    x509_free( &clicert );
-    x509_free( &cacert );
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt_free( &clicert );
+    x509_crt_free( &cacert );
     pk_free( &pkey );
 #endif
     ssl_session_free( &saved_session );
diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c
index 98a518c..3b24b31 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -56,7 +56,7 @@
     !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_SSL_TLS_C) || \
     !defined(POLARSSL_SSL_SRV_C) || !defined(POLARSSL_NET_C) ||     \
     !defined(POLARSSL_RSA_C) || !defined(POLARSSL_CTR_DRBG_C) ||    \
-    !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_TIMING_C)
+    !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_TIMING_C)
 int main( int argc, char *argv[] )
 {
     ((void) argc);
@@ -65,7 +65,7 @@
     printf("POLARSSL_BIGNUM_C and/or POLARSSL_CERTS_C and/or POLARSSL_ENTROPY_C "
            "and/or POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_SRV_C and/or "
            "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
-           "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_PARSE_C and/or "
+           "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_CRT_PARSE_C and/or "
            "POLARSSL_TIMING_C not defined.\n");
     return( 0 );
 }
@@ -103,7 +103,7 @@
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
-    x509_cert srvcert;
+    x509_crt srvcert;
     pk_context pkey;
 
     ((void) argc);
@@ -134,35 +134,35 @@
     printf( "  . Loading the server cert. and key..." );
     fflush( stdout );
 
-    memset( &srvcert, 0, sizeof( x509_cert ) );
+    x509_crt_init( &srvcert );
 
     /*
      * This demonstration program uses embedded test certificates.
-     * Instead, you may want to use x509parse_crtfile() to read the
-     * server and CA certificates, as well as x509parse_keyfile().
+     * Instead, you may want to use x509_crt_parse_file() to read the
+     * server and CA certificates, as well as pk_parse_keyfile().
      */
-    ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
-                         strlen( test_srv_crt ) );
+    ret = x509_crt_parse( &srvcert, (const unsigned char *) test_srv_crt,
+                          strlen( test_srv_crt ) );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
         goto exit;
     }
 
-    ret = x509parse_crt( &srvcert, (const unsigned char *) test_ca_crt,
-                         strlen( test_ca_crt ) );
+    ret = x509_crt_parse( &srvcert, (const unsigned char *) test_ca_crt,
+                          strlen( test_ca_crt ) );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
         goto exit;
     }
 
     pk_init( &pkey );
-    ret =  x509parse_key( &pkey, (const unsigned char *) test_srv_key,
+    ret =  pk_parse_key( &pkey, (const unsigned char *) test_srv_key,
                           strlen( test_srv_key ), NULL, 0 );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
+        printf( " failed\n  !  pk_parse_key returned %d\n\n", ret );
         goto exit;
     }
 
@@ -362,7 +362,7 @@
 exit:
 
     net_close( client_fd );
-    x509_free( &srvcert );
+    x509_crt_free( &srvcert );
     pk_free( &pkey );
     ssl_free( &ssl );
 
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index cbd1a00..e4ab1f1 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -55,6 +55,24 @@
 #include "polarssl/certs.h"
 #include "polarssl/x509.h"
 
+#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) ||  \
+    !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \
+    !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) ||         \
+    !defined(POLARSSL_CTR_DRBG_C) || !defined(POLARSSL_X509_CRT_PARSE_C)
+int main( int argc, char *argv[] )
+{
+    ((void) argc);
+    ((void) argv);
+
+    printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
+           "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or "
+           "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
+           "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_CRT_PARSE_C "
+           "not defined.\n");
+    return( 0 );
+}
+#else
+
 #define DFL_SERVER_NAME         "localhost"
 #define DFL_SERVER_PORT         465
 #define DFL_USER_NAME           "user"
@@ -101,23 +119,6 @@
     }
 }
 
-#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) ||  \
-    !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \
-    !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) ||         \
-    !defined(POLARSSL_CTR_DRBG_C) || !defined(POLARSSL_X509_PARSE_C)
-int main( int argc, char *argv[] )
-{
-    ((void) argc);
-    ((void) argv);
-
-    printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
-           "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or "
-           "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
-           "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_PARSE_C "
-           "not defined.\n");
-    return( 0 );
-}
-#else
 static int do_handshake( ssl_context *ssl, struct options *opt )
 {
     int ret;
@@ -172,8 +173,8 @@
         printf( " ok\n" );
 
     printf( "  . Peer certificate information    ...\n" );
-    x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ",
-                         ssl_get_peer_cert( ssl ) );
+    x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
+                   ssl_get_peer_cert( ssl ) );
     printf( "%s\n", buf );
 
     return( 0 );
@@ -350,8 +351,8 @@
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
-    x509_cert cacert;
-    x509_cert clicert;
+    x509_crt cacert;
+    x509_crt clicert;
     pk_context pkey;
     int i;
     size_t n;
@@ -362,8 +363,8 @@
      * Make sure memory references are valid.
      */
     server_fd = 0;
-    memset( &cacert, 0, sizeof( x509_cert ) );
-    memset( &clicert, 0, sizeof( x509_cert ) );
+    x509_crt_init( &cacert );
+    x509_crt_init( &clicert );
     pk_init( &pkey );
 
     if( argc == 0 )
@@ -482,12 +483,12 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.ca_file ) )
-        ret = x509parse_crtfile( &cacert, opt.ca_file );
+        ret = x509_crt_parse_file( &cacert, opt.ca_file );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
-                strlen( test_ca_crt ) );
+        ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
+                              strlen( test_ca_crt ) );
 #else
     {
         ret = 1;
@@ -496,7 +497,7 @@
 #endif
     if( ret < 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
         goto exit;
     }
 
@@ -512,12 +513,12 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.crt_file ) )
-        ret = x509parse_crtfile( &clicert, opt.crt_file );
-    else 
+        ret = x509_crt_parse_file( &clicert, opt.crt_file );
+    else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_crt( &clicert, (const unsigned char *) test_cli_crt,
-                strlen( test_cli_crt ) );
+        ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
+                              strlen( test_cli_crt ) );
 #else
     {
         ret = -1;
@@ -526,17 +527,17 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
         goto exit;
     }
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.key_file ) )
-        ret = x509parse_keyfile( &pkey, opt.key_file, "" );
+        ret = pk_parse_keyfile( &pkey, opt.key_file, "" );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_key( &pkey, (const unsigned char *) test_cli_key,
+        ret = pk_parse_key( &pkey, (const unsigned char *) test_cli_key,
                 strlen( test_cli_key ), NULL, 0 );
 #else
     {
@@ -546,7 +547,7 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
+        printf( " failed\n  !  pk_parse_key returned %d\n\n", ret );
         goto exit;
     }
 
@@ -789,8 +790,8 @@
 
     if( server_fd )
         net_close( server_fd );
-    x509_free( &clicert );
-    x509_free( &cacert );
+    x509_crt_free( &clicert );
+    x509_crt_free( &cacert );
     pk_free( &pkey );
     ssl_free( &ssl );
 
diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c
index 801c0c6..927a5b3 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -49,6 +49,25 @@
 #include "polarssl/ssl_cache.h"
 #endif
 
+#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_CERTS_C) ||    \
+    !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_SSL_TLS_C) || \
+    !defined(POLARSSL_SSL_SRV_C) || !defined(POLARSSL_NET_C) ||     \
+    !defined(POLARSSL_RSA_C) || !defined(POLARSSL_CTR_DRBG_C) ||    \
+    !defined(POLARSSL_X509_CRT_PARSE_C)
+int main( int argc, char *argv[] )
+{
+    ((void) argc);
+    ((void) argv);
+
+    printf("POLARSSL_BIGNUM_C and/or POLARSSL_CERTS_C and/or POLARSSL_ENTROPY_C "
+           "and/or POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_SRV_C and/or "
+           "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
+           "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_CRT_PARSE_C "
+           "not defined.\n");
+    return( 0 );
+}
+#else
+
 #define HTTP_RESPONSE \
     "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
     "<h2>PolarSSL Test Server</h2>\r\n" \
@@ -65,23 +84,6 @@
     }
 }
 
-#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_CERTS_C) ||    \
-    !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_SSL_TLS_C) || \
-    !defined(POLARSSL_SSL_SRV_C) || !defined(POLARSSL_NET_C) ||     \
-    !defined(POLARSSL_RSA_C) || !defined(POLARSSL_CTR_DRBG_C) ||    \
-    !defined(POLARSSL_X509_PARSE_C)
-int main( int argc, char *argv[] )
-{
-    ((void) argc);
-    ((void) argv);
-
-    printf("POLARSSL_BIGNUM_C and/or POLARSSL_CERTS_C and/or POLARSSL_ENTROPY_C "
-           "and/or POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_SRV_C and/or "
-           "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
-           "POLARSSL_CTR_DRBG_C and/or POLARSSL_X509_PARSE_C not defined.\n");
-    return( 0 );
-}
-#else
 int main( int argc, char *argv[] )
 {
     int ret, len;
@@ -93,7 +95,7 @@
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
-    x509_cert srvcert;
+    x509_crt srvcert;
     pk_context pkey;
 #if defined(POLARSSL_SSL_CACHE_C)
     ssl_cache_context cache;
@@ -112,35 +114,35 @@
     printf( "\n  . Loading the server cert. and key..." );
     fflush( stdout );
 
-    memset( &srvcert, 0, sizeof( x509_cert ) );
+    x509_crt_init( &srvcert );
 
     /*
      * This demonstration program uses embedded test certificates.
-     * Instead, you may want to use x509parse_crtfile() to read the
-     * server and CA certificates, as well as x509parse_keyfile().
+     * Instead, you may want to use x509_crt_parse_file() to read the
+     * server and CA certificates, as well as pk_parse_keyfile().
      */
-    ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
-                         strlen( test_srv_crt ) );
+    ret = x509_crt_parse( &srvcert, (const unsigned char *) test_srv_crt,
+                          strlen( test_srv_crt ) );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
         goto exit;
     }
 
-    ret = x509parse_crt( &srvcert, (const unsigned char *) test_ca_crt,
-                         strlen( test_ca_crt ) );
+    ret = x509_crt_parse( &srvcert, (const unsigned char *) test_ca_crt,
+                          strlen( test_ca_crt ) );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
         goto exit;
     }
 
     pk_init( &pkey );
-    ret =  x509parse_key( &pkey, (const unsigned char *) test_srv_key,
-                          strlen( test_srv_key ), NULL, 0 );
+    ret =  pk_parse_key( &pkey, (const unsigned char *) test_srv_key,
+                         strlen( test_srv_key ), NULL, 0 );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
+        printf( " failed\n  !  pk_parse_key returned %d\n\n", ret );
         goto exit;
     }
 
@@ -363,7 +365,7 @@
 #endif
 
     net_close( client_fd );
-    x509_free( &srvcert );
+    x509_crt_free( &srvcert );
     pk_free( &pkey );
     ssl_free( &ssl );
 #if defined(POLARSSL_SSL_CACHE_C)
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 8d2a8b3..595880c 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -118,7 +118,7 @@
     }
 }
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
 #if defined(POLARSSL_FS_IO)
 #define USAGE_IO \
     "    ca_file=%%s          The single file containing the top-level CA(s) you fully trust\n" \
@@ -136,7 +136,7 @@
 #endif /* POLARSSL_FS_IO */
 #else
 #define USAGE_IO ""
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
 #define USAGE_PSK                                                   \
@@ -212,9 +212,9 @@
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
-#if defined(POLARSSL_X509_PARSE_C)
-    x509_cert cacert;
-    x509_cert srvcert;
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt cacert;
+    x509_crt srvcert;
     pk_context pkey;
 #endif
 #if defined(POLARSSL_SSL_CACHE_C)
@@ -236,9 +236,9 @@
      * Make sure memory references are valid.
      */
     listen_fd = 0;
-#if defined(POLARSSL_X509_PARSE_C)
-    memset( &cacert, 0, sizeof( x509_cert ) );
-    memset( &srvcert, 0, sizeof( x509_cert ) );
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt_init( &cacert );
+    x509_crt_init( &srvcert );
     pk_init( &pkey );
 #endif
 #if defined(POLARSSL_SSL_CACHE_C)
@@ -516,7 +516,7 @@
 
     printf( " ok\n" );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     /*
      * 1.1. Load the trusted CA
      */
@@ -525,14 +525,14 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.ca_path ) )
-        ret = x509parse_crtpath( &cacert, opt.ca_path );
+        ret = x509_crt_parse_path( &cacert, opt.ca_path );
     else if( strlen( opt.ca_file ) )
-        ret = x509parse_crtfile( &cacert, opt.ca_file );
-    else 
+        ret = x509_crt_parse_file( &cacert, opt.ca_file );
+    else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
-                strlen( test_ca_crt ) );
+        ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
+                              strlen( test_ca_crt ) );
 #else
     {
         ret = 1;
@@ -541,7 +541,7 @@
 #endif
     if( ret < 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
         goto exit;
     }
 
@@ -555,12 +555,12 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.crt_file ) )
-        ret = x509parse_crtfile( &srvcert, opt.crt_file );
-    else 
+        ret = x509_crt_parse_file( &srvcert, opt.crt_file );
+    else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
-                strlen( test_srv_crt ) );
+        ret = x509_crt_parse( &srvcert, (const unsigned char *) test_srv_crt,
+                              strlen( test_srv_crt ) );
 #else
     {
         ret = 1;
@@ -569,17 +569,17 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
         goto exit;
     }
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.key_file ) )
-        ret = x509parse_keyfile( &pkey, opt.key_file, "" );
+        ret = pk_parse_keyfile( &pkey, opt.key_file, "" );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_key( &pkey, (const unsigned char *) test_srv_key,
+        ret = pk_parse_key( &pkey, (const unsigned char *) test_srv_key,
                 strlen( test_srv_key ), NULL, 0 );
 #else
     {
@@ -589,12 +589,12 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  pk_parse_key returned -0x%x\n\n", -ret );
         goto exit;
     }
 
     printf( " ok\n" );
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     /*
      * 2. Setup the listening TCP socket
@@ -647,7 +647,7 @@
     ssl_set_renegotiation( &ssl, opt.renegotiation );
     ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
     ssl_set_own_cert( &ssl, &srvcert, &pkey );
 #endif
@@ -747,7 +747,7 @@
     printf( " ok\n    [ Ciphersuite is %s ]\n",
             ssl_get_ciphersuite( &ssl ) );
 
-#if defined(POLARSSL_X509_PARSE_C)
+#if defined(POLARSSL_X509_CRT_PARSE_C)
     /*
      * 5. Verify the server certificate
      */
@@ -777,11 +777,11 @@
     if( ssl_get_peer_cert( &ssl ) )
     {
         printf( "  . Peer certificate information    ...\n" );
-        x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ",
-                             ssl_get_peer_cert( &ssl ) );
+        x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
+                       ssl_get_peer_cert( &ssl ) );
         printf( "%s\n", buf );
     }
-#endif /* POLARSSL_X509_PARSE_C */
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     /*
      * 6. Read the HTTP Request
@@ -877,9 +877,9 @@
 #endif
 
     net_close( client_fd );
-#if defined(POLARSSL_X509_PARSE_C)
-    x509_free( &srvcert );
-    x509_free( &cacert );
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    x509_crt_free( &srvcert );
+    x509_crt_free( &cacert );
     pk_free( &pkey );
 #endif
 
diff --git a/programs/test/o_p_test.c b/programs/test/o_p_test.c
index 8944940..dd488d7 100644
--- a/programs/test/o_p_test.c
+++ b/programs/test/o_p_test.c
@@ -40,20 +40,20 @@
 
 #include "polarssl/config.h"
 
+#include "polarssl/pk.h"
 #include "polarssl/x509.h"
-#include "polarssl/rsa.h"
 #include "polarssl/entropy.h"
 #include "polarssl/ctr_drbg.h"
 
 #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) ||         \
-    !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO)
+    !defined(POLARSSL_PK_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");
+           "POLARSSL_PK_PARSE_C and/or POLARSSL_FS_IO not defined.\n");
     return( 0 );
 }
 #else
@@ -62,7 +62,8 @@
     int ret;
     FILE *key_file;
     size_t olen;
-    rsa_context p_rsa;
+    pk_context p_pk;
+    rsa_context *p_rsa;
     RSA *o_rsa;
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
@@ -103,14 +104,23 @@
     printf( "  . Reading private key from %s into PolarSSL ...", argv[1] );
     fflush( stdout );
 
-    rsa_init( &p_rsa, RSA_PKCS_V15, 0 );
-    if( x509parse_keyfile_rsa( &p_rsa, argv[1], NULL ) != 0 )
+    pk_init( &p_pk );
+    if( pk_parse_keyfile( &p_pk, argv[1], NULL ) != 0 )
     {
         ret = 1;
         printf( " failed\n  ! Could not load key.\n\n" );
         goto exit;
     }
 
+    if( !pk_can_do( &p_pk, POLARSSL_PK_RSA ) )
+    {
+        ret = 1;
+        printf( " failed\n  ! Key is not an RSA key\n" );
+        goto exit;
+    }
+
+    p_rsa = pk_rsa( p_pk );
+
     printf( " passed\n");
 
     printf( "  . Reading private key from %s into OpenSSL  ...", argv[1] );
@@ -143,7 +153,7 @@
     printf( "  . Generating the RSA encrypted value with PolarSSL (RSA_PUBLIC)  ..." );
     fflush( stdout );
 
-    if( ( ret = rsa_pkcs1_encrypt( &p_rsa, ctr_drbg_random, &ctr_drbg, RSA_PUBLIC, strlen( argv[1] ), input, p_pub_encrypted ) ) != 0 )
+    if( ( ret = rsa_pkcs1_encrypt( p_rsa, ctr_drbg_random, &ctr_drbg, RSA_PUBLIC, strlen( argv[2] ), input, p_pub_encrypted ) ) != 0 )
     {
         printf( " failed\n  ! rsa_pkcs1_encrypt returned %d\n\n", ret );
         goto exit;
@@ -154,7 +164,7 @@
     printf( "  . Generating the RSA encrypted value with OpenSSL (PUBLIC)       ..." );
     fflush( stdout );
 
-    if( ( ret = RSA_public_encrypt( strlen( argv[1] ), input, o_pub_encrypted, o_rsa, RSA_PKCS1_PADDING ) ) == -1 )
+    if( ( ret = RSA_public_encrypt( strlen( argv[2] ), input, o_pub_encrypted, o_rsa, RSA_PKCS1_PADDING ) ) == -1 )
     {
         unsigned long code = ERR_get_error();
         printf( " failed\n  ! RSA_public_encrypt returned %d %s\n\n", ret, ERR_error_string( code, NULL ) );
@@ -169,7 +179,7 @@
     printf( "  . Generating the RSA encrypted value with PolarSSL (RSA_PRIVATE) ..." );
     fflush( stdout );
 
-    if( ( ret = rsa_pkcs1_encrypt( &p_rsa, ctr_drbg_random, &ctr_drbg, RSA_PRIVATE, strlen( argv[1] ), input, p_priv_encrypted ) ) != 0 )
+    if( ( ret = rsa_pkcs1_encrypt( p_rsa, ctr_drbg_random, &ctr_drbg, RSA_PRIVATE, strlen( argv[2] ), input, p_priv_encrypted ) ) != 0 )
     {
         printf( " failed\n  ! rsa_pkcs1_encrypt returned %d\n\n", ret );
         goto exit;
@@ -180,7 +190,7 @@
     printf( "  . Generating the RSA encrypted value with OpenSSL (PRIVATE)      ..." );
     fflush( stdout );
 
-    if( ( ret = RSA_private_encrypt( strlen( argv[1] ), input, o_priv_encrypted, o_rsa, RSA_PKCS1_PADDING ) ) == -1 )
+    if( ( ret = RSA_private_encrypt( strlen( argv[2] ), input, o_priv_encrypted, o_rsa, RSA_PKCS1_PADDING ) ) == -1 )
     {
         unsigned long code = ERR_get_error();
         printf( " failed\n  ! RSA_private_encrypt returned %d %s\n\n", ret, ERR_error_string( code, NULL ) );
@@ -197,7 +207,7 @@
     printf( "  . Generating the RSA decrypted value for OpenSSL (PUBLIC) with PolarSSL (PRIVATE) ..." );
     fflush( stdout );
 
-    if( ( ret = rsa_pkcs1_decrypt( &p_rsa, ctr_drbg_random, &ctr_drbg, RSA_PRIVATE, &olen, o_pub_encrypted, p_pub_decrypted, 1024 ) ) != 0 )
+    if( ( ret = rsa_pkcs1_decrypt( p_rsa, ctr_drbg_random, &ctr_drbg, RSA_PRIVATE, &olen, o_pub_encrypted, p_pub_decrypted, 1024 ) ) != 0 )
     {
         printf( " failed\n  ! rsa_pkcs1_decrypt returned %d\n\n", ret );
     }
@@ -207,7 +217,7 @@
     printf( "  . Generating the RSA decrypted value for PolarSSL (PUBLIC) with OpenSSL (PRIVATE) ..." );
     fflush( stdout );
 
-    if( ( ret = RSA_private_decrypt( p_rsa.len, p_pub_encrypted, o_pub_decrypted, o_rsa, RSA_PKCS1_PADDING ) ) == -1 )
+    if( ( ret = RSA_private_decrypt( p_rsa->len, p_pub_encrypted, o_pub_decrypted, o_rsa, RSA_PKCS1_PADDING ) ) == -1 )
     {
         unsigned long code = ERR_get_error();
         printf( " failed\n  ! RSA_private_decrypt returned %d %s\n\n", ret, ERR_error_string( code, NULL ) );
@@ -221,7 +231,7 @@
     printf( "  . Generating the RSA decrypted value for OpenSSL (PRIVATE) with PolarSSL (PUBLIC) ..." );
     fflush( stdout );
 
-    if( ( ret = rsa_pkcs1_decrypt( &p_rsa, NULL, NULL, RSA_PUBLIC, &olen, o_priv_encrypted, p_priv_decrypted, 1024 ) ) != 0 )
+    if( ( ret = rsa_pkcs1_decrypt( p_rsa, NULL, NULL, RSA_PUBLIC, &olen, o_priv_encrypted, p_priv_decrypted, 1024 ) ) != 0 )
     {
         printf( " failed\n  ! rsa_pkcs1_decrypt returned %d\n\n", ret );
     }
@@ -231,7 +241,7 @@
     printf( "  . Generating the RSA decrypted value for PolarSSL (PRIVATE) with OpenSSL (PUBLIC) ..." );
     fflush( stdout );
 
-    if( ( ret = RSA_public_decrypt( p_rsa.len, p_priv_encrypted, o_priv_decrypted, o_rsa, RSA_PKCS1_PADDING ) ) == -1 )
+    if( ( ret = RSA_public_decrypt( p_rsa->len, p_priv_encrypted, o_priv_decrypted, o_rsa, RSA_PKCS1_PADDING ) ) == -1 )
     {
         unsigned long code = ERR_get_error();
         printf( " failed\n  ! RSA_public_decrypt returned %d %s\n\n", ret, ERR_error_string( code, NULL ) );
@@ -255,4 +265,4 @@
     return( ret );
 }
 #endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C &&
-          POLARSSL_X509_PARSE_C && POLARSSL_FS_IO */
+          POLARSSL_PK_PARSE_C && POLARSSL_FS_IO */
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 02606fa..d0d36b8 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -33,6 +33,7 @@
 #include "polarssl/config.h"
 
 #include "polarssl/ctr_drbg.h"
+#include "polarssl/dhm.h"
 #include "polarssl/gcm.h"
 #include "polarssl/md2.h"
 #include "polarssl/md4.h"
@@ -142,7 +143,7 @@
         return( ret );
 #endif
 
-#if defined(POLARSSL_X509_PARSE_C) && defined(POLARSSL_BIGNUM_C)
+#if defined(POLARSSL_X509_USE_C)
     if( ( ret = x509_self_test( v ) ) != 0 )
         return( ret );
 #endif
@@ -172,6 +173,11 @@
         return( ret );
 #endif
 
+#if defined(POLARSSL_DHM_C)
+    if( ( ret = dhm_self_test( v ) ) != 0 )
+        return( ret );
+#endif
+
 #else
     printf( " POLARSSL_SELF_TEST not defined.\n" );
 #endif
diff --git a/programs/test/ssl_cert_test.c b/programs/test/ssl_cert_test.c
index a77a314..25397d0 100644
--- a/programs/test/ssl_cert_test.c
+++ b/programs/test/ssl_cert_test.c
@@ -33,7 +33,7 @@
 #include "polarssl/config.h"
 
 #include "polarssl/certs.h"
-#include "polarssl/x509.h"
+#include "polarssl/x509_crt.h"
 
 #if defined _MSC_VER && !defined snprintf
 #define snprintf _snprintf
@@ -66,29 +66,31 @@
 };
 
 #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) ||  \
-    !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO)
+    !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PK_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");
+           "POLARSSL_X509_CRT_PARSE_C and/or POLARSSL_FS_IO and/or "
+           "POLARSSL_PK_PARSE_C not defined.\n");
     return( 0 );
 }
 #else
 int main( int argc, char *argv[] )
 {
     int ret, i;
-    x509_cert cacert;
+    x509_crt cacert;
     x509_crl crl;
     char buf[10240];
 
     ((void) argc);
     ((void) argv);
 
-    memset( &cacert, 0, sizeof( x509_cert ) );
-    memset( &crl, 0, sizeof( x509_crl ) );
+    x509_crt_init( &cacert );
+    x509_crl_init( &crl );
 
     /*
      * 1.1. Load the trusted CA
@@ -98,18 +100,18 @@
 
     /*
      * Alternatively, you may load the CA certificates from a .pem or
-     * .crt file by calling x509parse_crtfile( &cacert, "myca.crt" ).
+     * .crt file by calling x509_crt_parse_file( &cacert, "myca.crt" ).
      */
-    ret = x509parse_crtfile( &cacert, "ssl/test-ca/test-ca.crt" );
+    ret = x509_crt_parse_file( &cacert, "ssl/test-ca/test-ca.crt" );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crtfile returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crt_parse_file returned %d\n\n", ret );
         goto exit;
     }
 
     printf( " ok\n" );
 
-    x509parse_cert_info( buf, 1024, "CRT: ", &cacert );
+    x509_crt_info( buf, 1024, "CRT: ", &cacert );
     printf("%s\n", buf );
 
     /*
@@ -118,16 +120,16 @@
     printf( "  . Loading the CRL ..." );
     fflush( stdout );
 
-    ret = x509parse_crlfile( &crl, "ssl/test-ca/crl.pem" );
+    ret = x509_crl_parse_file( &crl, "ssl/test-ca/crl.pem" );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crlfile returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crl_parse_file returned %d\n\n", ret );
         goto exit;
     }
 
     printf( " ok\n" );
 
-    x509parse_crl_info( buf, 1024, "CRL: ", &crl );
+    x509_crl_info( buf, 1024, "CRL: ", &crl );
     printf("%s\n", buf );
 
     for( i = 0; i < MAX_CLIENT_CERTS; i++ )
@@ -137,21 +139,21 @@
          */
         char    name[512];
         int flags;
-        x509_cert clicert;
-        rsa_context rsa;
+        x509_crt clicert;
+        pk_context pk;
 
-        memset( &clicert, 0, sizeof( x509_cert ) );
-        memset( &rsa, 0, sizeof( rsa_context ) );
+        x509_crt_init( &clicert );
+        pk_init( &pk );
 
         snprintf(name, 512, "ssl/test-ca/%s", client_certificates[i]);
 
         printf( "  . Loading the client certificate %s...", name );
         fflush( stdout );
 
-        ret = x509parse_crtfile( &clicert, name );
+        ret = x509_crt_parse_file( &clicert, name );
         if( ret != 0 )
         {
-            printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
+            printf( " failed\n  !  x509_crt_parse_file returned %d\n\n", ret );
             goto exit;
         }
 
@@ -163,7 +165,8 @@
         printf( "  . Verify the client certificate with CA certificate..." );
         fflush( stdout );
 
-        ret = x509parse_verify( &clicert, &cacert, &crl, NULL, &flags, NULL, NULL );
+        ret = x509_crt_verify( &clicert, &cacert, &crl, NULL, &flags, NULL,
+                               NULL );
         if( ret != 0 )
         {
             if( ret == POLARSSL_ERR_X509_CERT_VERIFY_FAILED )
@@ -181,7 +184,7 @@
                 if( flags & BADCRL_EXPIRED )
                     printf( " CRL_EXPIRED " );
             } else {
-                printf( " failed\n  !  x509parse_verify returned %d\n\n", ret );
+                printf( " failed\n  !  x509_crt_verify returned %d\n\n", ret );
                 goto exit;
             }
         }
@@ -196,10 +199,10 @@
         printf( "  . Loading the client private key %s...", name );
         fflush( stdout );
 
-        ret = x509parse_keyfile_rsa( &rsa, name, NULL );
+        ret = pk_parse_keyfile( &pk, name, NULL );
         if( ret != 0 )
         {
-            printf( " failed\n  !  x509parse_key_rsa returned %d\n\n", ret );
+            printf( " failed\n  !  pk_parse_keyfile returned %d\n\n", ret );
             goto exit;
         }
 
@@ -220,21 +223,21 @@
             goto exit;
         }
 
-        ret = mpi_cmp_mpi(&rsa.N, &pk_rsa( clicert.pk )->N);
+        ret = mpi_cmp_mpi(&pk_rsa( pk )->N, &pk_rsa( clicert.pk )->N);
         if( ret != 0 )
         {
             printf( " failed\n  !  mpi_cmp_mpi for N returned %d\n\n", ret );
             goto exit;
         }
 
-        ret = mpi_cmp_mpi(&rsa.E, &pk_rsa( clicert.pk )->E);
+        ret = mpi_cmp_mpi(&pk_rsa( pk )->E, &pk_rsa( clicert.pk )->E);
         if( ret != 0 )
         {
             printf( " failed\n  !  mpi_cmp_mpi for E returned %d\n\n", ret );
             goto exit;
         }
 
-        ret = rsa_check_privkey( &rsa );
+        ret = rsa_check_privkey( pk_rsa( pk ) );
         if( ret != 0 )
         {
             printf( " failed\n  !  rsa_check_privkey returned %d\n\n", ret );
@@ -243,12 +246,12 @@
 
         printf( " ok\n" );
 
-        x509_free( &clicert );
-        rsa_free( &rsa );
+        x509_crt_free( &clicert );
+        pk_free( &pk );
     }
 
 exit:
-    x509_free( &cacert );
+    x509_crt_free( &cacert );
     x509_crl_free( &crl );
 
 #if defined(_WIN32)
@@ -258,5 +261,5 @@
 
     return( ret );
 }
-#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_X509_PARSE_C &&
-          POLARSSL_FS_IO */
+#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_X509_CRT_PARSE_C &&
+          POLARSSL_FS_IO && POLARSSL_PK_PARSE_C */
diff --git a/programs/test/ssl_test.c b/programs/test/ssl_test.c
index 797226b..c8461dc 100644
--- a/programs/test/ssl_test.c
+++ b/programs/test/ssl_test.c
@@ -42,6 +42,25 @@
 #include "polarssl/timing.h"
 #endif
 
+#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) ||  \
+    !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_SRV_C) || \
+    !defined(POLARSSL_SSL_CLI_C) || !defined(POLARSSL_NET_C) ||     \
+    !defined(POLARSSL_RSA_C) || !defined(POLARSSL_CTR_DRBG_C) ||    \
+    !defined(POLARSSL_X509_CRT_PARSE_C)
+int main( int argc, char *argv[] )
+{
+    ((void) argc);
+    ((void) argv);
+
+    printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
+           "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_SRV_C and/or "
+           "POLARSSL_SSL_CLI_C and/or POLARSSL_NET_C and/or "
+           "POLARSSL_RSA_C and/or POLARSSL_CTR_DRBG_C and/or "
+           "POLARSSL_X509_CRT_PARSE_C not defined.\n");
+    return( 0 );
+}
+#else
+
 #define OPMODE_NONE             0
 #define OPMODE_CLIENT           1
 #define OPMODE_SERVER           2
@@ -118,24 +137,6 @@
         fprintf( stderr, "%s", str );
 }
 
-#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) ||  \
-    !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_SRV_C) || \
-    !defined(POLARSSL_SSL_CLI_C) || !defined(POLARSSL_NET_C) ||     \
-    !defined(POLARSSL_RSA_C) || !defined(POLARSSL_CTR_DRBG_C) ||    \
-    !defined(POLARSSL_X509_PARSE_C)
-int main( int argc, char *argv[] )
-{
-    ((void) argc);
-    ((void) argv);
-
-    printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
-           "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_SRV_C and/or "
-           "POLARSSL_SSL_CLI_C and/or POLARSSL_NET_C and/or "
-           "POLARSSL_RSA_C and/or POLARSSL_CTR_DRBG_C and/or "
-           "POLARSSL_X509_PARSE_C not defined.\n");
-    return( 0 );
-}
-#else
 /*
  * perform a single SSL connection
  */
@@ -165,7 +166,7 @@
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
-    x509_cert srvcert;
+    x509_crt srvcert;
     pk_context pkey;
 
     ret = 1;
@@ -186,7 +187,7 @@
     memset( read_state, 0, sizeof( read_state ) );
     memset( write_state, 0, sizeof( write_state ) );
 
-    memset( &srvcert, 0, sizeof( x509_cert ) );
+    x509_crt_init( &srvcert );
     pk_init( &pkey );
 
     if( opt->opmode == OPMODE_CLIENT )
@@ -213,27 +214,27 @@
         printf("POLARSSL_CERTS_C not defined.\n");
         goto exit;
 #else
-        ret =  x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
-                              strlen( test_srv_crt ) );
+        ret =  x509_crt_parse( &srvcert, (const unsigned char *) test_srv_crt,
+                               strlen( test_srv_crt ) );
         if( ret != 0 )
         {
-            printf( "  !  x509parse_crt returned %d\n\n", ret );
+            printf( "  !  x509_crt_parse returned %d\n\n", ret );
             goto exit;
         }
 
-        ret =  x509parse_crt( &srvcert, (const unsigned char *) test_ca_crt,
-                              strlen( test_ca_crt ) );
+        ret =  x509_crt_parse( &srvcert, (const unsigned char *) test_ca_crt,
+                               strlen( test_ca_crt ) );
         if( ret != 0 )
         {
-            printf( "  !  x509parse_crt returned %d\n\n", ret );
+            printf( "  !  x509_crt_parse returned %d\n\n", ret );
             goto exit;
         }
 
-        ret =  x509parse_key( &pkey, (const unsigned char *) test_srv_key,
-                              strlen( test_srv_key ), NULL, 0 );
+        ret =  pk_parse_key( &pkey, (const unsigned char *) test_srv_key,
+                             strlen( test_srv_key ), NULL, 0 );
         if( ret != 0 )
         {
-            printf( "  !  x509parse_key returned %d\n\n", ret );
+            printf( "  !  pk_parse_key returned %d\n\n", ret );
             goto exit;
         }
 #endif
@@ -399,7 +400,7 @@
         free( write_buf );
 
     ssl_close_notify( &ssl );
-    x509_free( &srvcert );
+    x509_crt_free( &srvcert );
     pk_free( &pkey );
     ssl_free( &ssl );
     net_close( client_fd );
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index 0096735..6b03266 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -42,7 +42,7 @@
 #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) ||  \
     !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \
     !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) ||         \
-    !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) ||  \
+    !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_FS_IO) ||  \
     !defined(POLARSSL_CTR_DRBG_C)
 int main( int argc, char *argv[] )
 {
@@ -52,7 +52,7 @@
     printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
            "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or "
            "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
-           "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO and/or "
+           "POLARSSL_X509_CRT_PARSE_C and/or POLARSSL_FS_IO and/or "
            "POLARSSL_CTR_DRBG_C not defined.\n");
     return( 0 );
 }
@@ -95,13 +95,13 @@
     }
 }
 
-static int my_verify( void *data, x509_cert *crt, int depth, int *flags )
+static int my_verify( void *data, x509_crt *crt, int depth, int *flags )
 {
     char buf[1024];
     ((void) data);
 
     printf( "\nVerify requested for (Depth %d):\n", depth );
-    x509parse_cert_info( buf, sizeof( buf ) - 1, "", crt );
+    x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
     printf( "%s", buf );
 
     if( ( (*flags) & BADCERT_EXPIRED ) != 0 )
@@ -156,10 +156,10 @@
     entropy_context entropy;
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
-    x509_cert cacert;
-    x509_cert clicert;
+    x509_crt cacert;
+    x509_crt clicert;
     pk_context pkey;
-    int i, j, n;
+    int i, j;
     int flags, verify = 0;
     char *p, *q;
     const char *pers = "cert_app";
@@ -168,8 +168,8 @@
      * Set to sane values
      */
     server_fd = 0;
-    memset( &cacert, 0, sizeof( x509_cert ) );
-    memset( &clicert, 0, sizeof( x509_cert ) );
+    x509_crt_init( &cacert );
+    x509_crt_init( &clicert );
     pk_init( &pkey );
 
     if( argc == 0 )
@@ -190,19 +190,17 @@
 
     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';
 
+        for( j = 0; p + j < q; j++ )
+        {
+            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
+                argv[i][j] |= 0x20;
+        }
+
         if( strcmp( p, "mode" ) == 0 )
         {
             if( strcmp( q, "file" ) == 0 )
@@ -250,18 +248,18 @@
 
     if( strlen( opt.ca_path ) )
     {
-        ret = x509parse_crtpath( &cacert, opt.ca_path );
+        ret = x509_crt_parse_path( &cacert, opt.ca_path );
         verify = 1;
     }
     else if( strlen( opt.ca_file ) )
     {
-        ret = x509parse_crtfile( &cacert, opt.ca_file );
+        ret = x509_crt_parse_file( &cacert, opt.ca_file );
         verify = 1;
     }
 
     if( ret < 0 )
     {
-        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
         goto exit;
     }
 
@@ -269,9 +267,9 @@
 
     if( opt.mode == MODE_FILE )
     {
-        x509_cert crt;
-        x509_cert *cur = &crt;
-        memset( &crt, 0, sizeof( x509_cert ) );
+        x509_crt crt;
+        x509_crt *cur = &crt;
+        x509_crt_init( &crt );
 
         /*
          * 1.1. Load the certificate(s)
@@ -279,19 +277,19 @@
         printf( "\n  . Loading the certificate(s) ..." );
         fflush( stdout );
 
-        ret = x509parse_crtfile( &crt, opt.filename );
+        ret = x509_crt_parse_file( &crt, opt.filename );
 
         if( ret < 0 )
         {
-            printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
-            x509_free( &crt );
+            printf( " failed\n  !  x509_crt_parse_file returned %d\n\n", ret );
+            x509_crt_free( &crt );
             goto exit;
         }
 
         if( opt.permissive == 0 && ret > 0 )
         {
-            printf( " failed\n  !  x509parse_crt failed to parse %d certificates\n\n", ret );
-            x509_free( &crt );
+            printf( " failed\n  !  x509_crt_parse failed to parse %d certificates\n\n", ret );
+            x509_crt_free( &crt );
             goto exit;
         }
 
@@ -303,11 +301,12 @@
         while( cur != NULL )
         {
             printf( "  . Peer certificate information    ...\n" );
-            ret = x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ", cur );
+            ret = x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
+                                 cur );
             if( ret == -1 )
             {
-                printf( " failed\n  !  x509parse_cert_info returned %d\n\n", ret );
-                x509_free( &crt );
+                printf( " failed\n  !  x509_crt_info returned %d\n\n", ret );
+                x509_crt_free( &crt );
                 goto exit;
             }
 
@@ -323,8 +322,8 @@
         {
             printf( "  . Verifying X.509 certificate..." );
 
-            if( ( ret = x509parse_verify( &crt, &cacert, NULL, NULL, &flags,
-                            my_verify, NULL ) ) != 0 )
+            if( ( ret = x509_crt_verify( &crt, &cacert, NULL, NULL, &flags,
+                                         my_verify, NULL ) ) != 0 )
             {
                 printf( " failed\n" );
 
@@ -346,7 +345,7 @@
                 printf( " ok\n" );
         }
 
-        x509_free( &crt );
+        x509_crt_free( &crt );
     }
     else if( opt.mode == MODE_SSL )
     {
@@ -428,11 +427,11 @@
          * 5. Print the certificate
          */
         printf( "  . Peer certificate information    ...\n" );
-        ret = x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ",
-                                   ssl.session->peer_cert );
+        ret = x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
+                             ssl.session->peer_cert );
         if( ret == -1 )
         {
-            printf( " failed\n  !  x509parse_cert_info returned %d\n\n", ret );
+            printf( " failed\n  !  x509_crt_info returned %d\n\n", ret );
             ssl_free( &ssl );
             goto exit;
         }
@@ -449,8 +448,8 @@
 
     if( server_fd )
         net_close( server_fd );
-    x509_free( &cacert );
-    x509_free( &clicert );
+    x509_crt_free( &cacert );
+    x509_crt_free( &clicert );
     pk_free( &pkey );
 
 #if defined(_WIN32)
@@ -462,4 +461,4 @@
 }
 #endif /* POLARSSL_BIGNUM_C && POLARSSL_ENTROPY_C && POLARSSL_SSL_TLS_C &&
           POLARSSL_SSL_CLI_C && POLARSSL_NET_C && POLARSSL_RSA_C &&
-          POLARSSL_X509_PARSE_C && POLARSSL_FS_IO && POLARSSL_CTR_DRBG_C */
+          POLARSSL_X509_CRT_PARSE_C && POLARSSL_FS_IO && POLARSSL_CTR_DRBG_C */
diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c
index c0c014f..df8d05c 100644
--- a/programs/x509/cert_req.c
+++ b/programs/x509/cert_req.c
@@ -33,21 +33,21 @@
 
 #include "polarssl/config.h"
 
-#include "polarssl/x509write.h"
+#include "polarssl/x509_csr.h"
 #include "polarssl/entropy.h"
 #include "polarssl/ctr_drbg.h"
 #include "polarssl/error.h"
 
-#if !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_X509_PARSE_C) ||   \
-    !defined(POLARSSL_FS_IO) ||                                             \
+#if !defined(POLARSSL_X509_CSR_WRITE_C) || !defined(POLARSSL_FS_IO) ||  \
+    !defined(POLARSSL_PK_PARSE_C) ||                                    \
     !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C)
 int main( int argc, char *argv[] )
 {
     ((void) argc);
     ((void) argv);
 
-    printf( "POLARSSL_X509_WRITE_C and/or POLARSSL_X509_PARSE_C and/or "
-            "POLARSSL_FS_IO and/or "
+    printf( "POLARSSL_X509_CSR_WRITE_C and/or POLARSSL_FS_IO and/or "
+            "POLARSSL_PK_PARSE_C and/or "
             "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C "
             "not defined.\n");
     return( 0 );
@@ -292,11 +292,11 @@
     printf( "  . Loading the private key ..." );
     fflush( stdout );
 
-    ret = x509parse_keyfile( &key, opt.filename, NULL );
+    ret = pk_parse_keyfile( &key, opt.filename, NULL );
 
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_keyfile returned %d", ret );
+        printf( " failed\n  !  pk_parse_keyfile returned %d", ret );
         goto exit;
     }
 
@@ -341,5 +341,5 @@
 
     return( ret );
 }
-#endif /* POLARSSL_X509_WRITE_C && POLARSSL_X509_PARSE_C && POLARSSL_FS_IO &&
+#endif /* POLARSSL_X509_CSR_WRITE_C && POLARSSL_PK_PARSE_C && POLARSSL_FS_IO &&
           POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C */
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 37cea58..2fd415a 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -33,13 +33,14 @@
 
 #include "polarssl/config.h"
 
-#include "polarssl/x509write.h"
+#include "polarssl/x509_crt.h"
+#include "polarssl/x509_csr.h"
 #include "polarssl/entropy.h"
 #include "polarssl/ctr_drbg.h"
 #include "polarssl/error.h"
 
-#if !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_X509_PARSE_C) ||   \
-    !defined(POLARSSL_FS_IO) ||                                             \
+#if !defined(POLARSSL_X509_CRT_WRITE_C) ||                                  \
+    !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_FS_IO) ||      \
     !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) ||        \
     !defined(POLARSSL_ERROR_C)
 int main( int argc, char *argv[] )
@@ -47,7 +48,7 @@
     ((void) argc);
     ((void) argv);
 
-    printf( "POLARSSL_X509_WRITE_C and/or POLARSSL_X509_PARSE_C and/or "
+    printf( "POLARSSL_X509_CRT_WRITE_C and/or POLARSSL_X509_CRT_PARSE_C and/or "
             "POLARSSL_FS_IO and/or "
             "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C and/or "
             "POLARSSL_ERROR_C not defined.\n");
@@ -123,12 +124,19 @@
     return( 0 );
 }
 
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+#define USAGE_CSR                                                           \
+    "    request_file=%%s     default: (empty)\n"                           \
+    "                        If request_file is specified, subject_key,\n"  \
+    "                        subject_pwd and subject_name are ignored!\n"
+#else
+#define USAGE_CSR ""
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+
 #define USAGE \
     "\n usage: cert_write param=<>...\n"                \
     "\n acceptable parameters:\n"                       \
-    "    request_file=%%s     default: (empty)\n"       \
-    "                        If request_file is specified, subject_key,\n"  \
-    "                        subject_pwd and subject_name are ignored!\n"  \
+    USAGE_CSR                                           \
     "    subject_key=%%s      default: subject.key\n"   \
     "    subject_pwd=%%s      default: (empty)\n"       \
     "    subject_name=%%s     default: CN=Cert,O=PolarSSL,C=NL\n"   \
@@ -173,16 +181,18 @@
 int main( int argc, char *argv[] )
 {
     int ret = 0;
-    x509_cert issuer_crt;
+    x509_crt issuer_crt;
     pk_context loaded_issuer_key, loaded_subject_key;
     pk_context *issuer_key = &loaded_issuer_key,
                 *subject_key = &loaded_subject_key;
     char buf[1024];
     char issuer_name[128];
-    char subject_name[128];
     int i, j, n;
     char *p, *q, *r;
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+    char subject_name[128];
     x509_csr csr;
+#endif
     x509write_cert crt;
     mpi serial;
     entropy_context entropy;
@@ -197,8 +207,10 @@
     pk_init( &loaded_issuer_key );
     pk_init( &loaded_subject_key );
     mpi_init( &serial );
-    memset( &csr, 0, sizeof(x509_csr) );
-    memset( &issuer_crt, 0, sizeof(x509_cert) );
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+    x509_csr_init( &csr );
+#endif
+    x509_crt_init( &issuer_crt );
     memset( buf, 0, 1024 );
 
     if( argc == 0 )
@@ -397,19 +409,19 @@
         printf( "  . Loading the issuer certificate ..." );
         fflush( stdout );
 
-        if( ( ret = x509parse_crtfile( &issuer_crt, opt.issuer_crt ) ) != 0 )
+        if( ( ret = x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 )
         {
             error_strerror( ret, buf, 1024 );
-            printf( " failed\n  !  x509parse_crtfile returned -0x%02x - %s\n\n", -ret, buf );
+            printf( " failed\n  !  x509_crt_parse_file returned -0x%02x - %s\n\n", -ret, buf );
             goto exit;
         }
 
-        ret = x509parse_dn_gets( issuer_name, sizeof(issuer_name),
+        ret = x509_dn_gets( issuer_name, sizeof(issuer_name),
                                  &issuer_crt.issuer );
         if( ret < 0 )
         {
             error_strerror( ret, buf, 1024 );
-            printf( " failed\n  !  x509parse_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
+            printf( " failed\n  !  x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
             goto exit;
         }
 
@@ -418,6 +430,7 @@
         printf( " ok\n" );
     }
 
+#if defined(POLARSSL_X509_CSR_PARSE_C)
     // Parse certificate request if present
     //
     if( !opt.selfsign && strlen( opt.request_file ) )
@@ -428,19 +441,19 @@
         printf( "  . Loading the certificate request ..." );
         fflush( stdout );
 
-        if( ( ret = x509parse_csrfile( &csr, opt.request_file ) ) != 0 )
+        if( ( ret = x509_csr_parse_file( &csr, opt.request_file ) ) != 0 )
         {
             error_strerror( ret, buf, 1024 );
-            printf( " failed\n  !  x509parse_csrfile returned -0x%02x - %s\n\n", -ret, buf );
+            printf( " failed\n  !  x509_csr_parse_file returned -0x%02x - %s\n\n", -ret, buf );
             goto exit;
         }
 
-        ret = x509parse_dn_gets( subject_name, sizeof(subject_name),
+        ret = x509_dn_gets( subject_name, sizeof(subject_name),
                                  &csr.subject );
         if( ret < 0 )
         {
             error_strerror( ret, buf, 1024 );
-            printf( " failed\n  !  x509parse_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
+            printf( " failed\n  !  x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
             goto exit;
         }
 
@@ -449,6 +462,7 @@
 
         printf( " ok\n" );
     }
+#endif /* POLARSSL_X509_CSR_PARSE_C */
 
     /*
      * 1.1. Load the keys
@@ -458,12 +472,12 @@
         printf( "  . Loading the subject key ..." );
         fflush( stdout );
 
-        ret = x509parse_keyfile( &loaded_subject_key, opt.subject_key,
+        ret = pk_parse_keyfile( &loaded_subject_key, opt.subject_key,
                                  opt.subject_pwd );
         if( ret != 0 )
         {
             error_strerror( ret, buf, 1024 );
-            printf( " failed\n  !  x509parse_keyfile returned -0x%02x - %s\n\n", -ret, buf );
+            printf( " failed\n  !  pk_parse_keyfile returned -0x%02x - %s\n\n", -ret, buf );
             goto exit;
         }
 
@@ -473,12 +487,12 @@
     printf( "  . Loading the issuer key ..." );
     fflush( stdout );
 
-    ret = x509parse_keyfile( &loaded_issuer_key, opt.issuer_key,
-                                 opt.issuer_pwd );
+    ret = pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key,
+                             opt.issuer_pwd );
     if( ret != 0 )
     {
         error_strerror( ret, buf, 1024 );
-        printf( " failed\n  !  x509parse_keyfile returned -x%02x - %s\n\n", -ret, buf );
+        printf( " failed\n  !  pk_parse_keyfile returned -x%02x - %s\n\n", -ret, buf );
         goto exit;
     }
 
@@ -648,6 +662,6 @@
 
     return( ret );
 }
-#endif /* POLARSSL_X509_WRITE_C && POLARSSL_X509_PARSE_C && POLARSSL_FS_IO &&
-          POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C &&
+#endif /* POLARSSL_X509_CRT_WRITE_C && POLARSSL_X509_CRT_PARSE_C &&
+          POLARSSL_FS_IO && POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C &&
           POLARSSL_ERROR_C */
diff --git a/programs/x509/crl_app.c b/programs/x509/crl_app.c
index c9c3ef0..20754fd 100644
--- a/programs/x509/crl_app.c
+++ b/programs/x509/crl_app.c
@@ -33,17 +33,17 @@
 
 #include "polarssl/config.h"
 
-#include "polarssl/x509.h"
+#include "polarssl/x509_crl.h"
 
 #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) ||  \
-    !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO)
+    !defined(POLARSSL_X509_CRL_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");
+           "POLARSSL_X509_CRL_PARSE_C and/or POLARSSL_FS_IO not defined.\n");
     return( 0 );
 }
 #else
@@ -76,7 +76,7 @@
     /*
      * Set to sane values
      */
-    memset( &crl, 0, sizeof( x509_crl ) );
+    x509_crl_init( &crl );
 
     if( argc == 0 )
     {
@@ -114,11 +114,11 @@
     printf( "\n  . Loading the CRL ..." );
     fflush( stdout );
 
-    ret = x509parse_crlfile( &crl, opt.filename );
+    ret = x509_crl_parse_file( &crl, opt.filename );
 
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_crl returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crl_parse_file returned %d\n\n", ret );
         x509_crl_free( &crl );
         goto exit;
     }
@@ -129,10 +129,10 @@
      * 1.2 Print the CRL
      */
     printf( "  . CRL information    ...\n" );
-    ret = x509parse_crl_info( (char *) buf, sizeof( buf ) - 1, "      ", &crl );
+    ret = x509_crl_info( (char *) buf, sizeof( buf ) - 1, "      ", &crl );
     if( ret == -1 )
     {
-        printf( " failed\n  !  x509parse_crl_info returned %d\n\n", ret );
+        printf( " failed\n  !  x509_crl_info returned %d\n\n", ret );
         x509_crl_free( &crl );
         goto exit;
     }
@@ -149,5 +149,5 @@
 
     return( ret );
 }
-#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_X509_PARSE_C &&
+#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_X509_CRL_PARSE_C &&
           POLARSSL_FS_IO */
diff --git a/programs/x509/req_app.c b/programs/x509/req_app.c
index e2faab4..6b11fc4 100644
--- a/programs/x509/req_app.c
+++ b/programs/x509/req_app.c
@@ -33,17 +33,17 @@
 
 #include "polarssl/config.h"
 
-#include "polarssl/x509.h"
+#include "polarssl/x509_csr.h"
 
 #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) ||  \
-    !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO)
+    !defined(POLARSSL_X509_CSR_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");
+           "POLARSSL_X509_CSR_PARSE_C and/or POLARSSL_FS_IO not defined.\n");
     return( 0 );
 }
 #else
@@ -76,7 +76,7 @@
     /*
      * Set to sane values
      */
-    memset( &csr, 0, sizeof( x509_csr ) );
+    x509_csr_init( &csr );
 
     if( argc == 0 )
     {
@@ -114,11 +114,11 @@
     printf( "\n  . Loading the CSR ..." );
     fflush( stdout );
 
-    ret = x509parse_csrfile( &csr, opt.filename );
+    ret = x509_csr_parse_file( &csr, opt.filename );
 
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_csr returned %d\n\n", ret );
+        printf( " failed\n  !  x509_csr_parse_file returned %d\n\n", ret );
         x509_csr_free( &csr );
         goto exit;
     }
@@ -129,10 +129,10 @@
      * 1.2 Print the CSR
      */
     printf( "  . CSR information    ...\n" );
-    ret = x509parse_csr_info( (char *) buf, sizeof( buf ) - 1, "      ", &csr );
+    ret = x509_csr_info( (char *) buf, sizeof( buf ) - 1, "      ", &csr );
     if( ret == -1 )
     {
-        printf( " failed\n  !  x509parse_csr_info returned %d\n\n", ret );
+        printf( " failed\n  !  x509_csr_info returned %d\n\n", ret );
         x509_csr_free( &csr );
         goto exit;
     }
@@ -149,5 +149,5 @@
 
     return( ret );
 }
-#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_X509_PARSE_C &&
+#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_X509_CSR_PARSE_C &&
           POLARSSL_FS_IO */
diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl
index 5b95494..85dde35 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -13,7 +13,7 @@
                           "PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY",
                           "MD2", "MD4", "MD5", "SHA1", "SHA256", "SHA512", "GCM" );
 my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL",
-                           "PK", "PKCS12", "PKCS5", "X509WRITE" );
+                           "PK", "PKCS12", "PKCS5" );
 
 my $line_separator = $/;
 undef $/;
@@ -36,6 +36,7 @@
 
 while (my $line = <GREP>)
 {
+    next if ($line =~ /compat-1.2.h/);
     my ($error_name, $error_code) = $line =~ /(POLARSSL_ERR_\w+)\s+\-(0x\w+)/;
     my ($description) = $line =~ /\/\*\*< (.*?)\.? \*\//;
     $description =~ s/\\/\\\\/g;
@@ -48,10 +49,10 @@
     $module_name = "CTR_DRBG" if ($module_name eq "CTR");
 
     my $define_name = $module_name;
-    $define_name = "X509_PARSE" if ($define_name eq "X509");
-    $define_name = "X509_WRITE" if ($define_name eq "X509WRITE");
+    $define_name = "X509_USE,X509_CREATE" if ($define_name eq "X509");
     $define_name = "ASN1_PARSE" if ($define_name eq "ASN1");
     $define_name = "SSL_TLS" if ($define_name eq "SSL");
+    $define_name = "PEM_PARSE,PEM_WRITE" if ($define_name eq "PEM");
 
     my $include_name = $module_name;
     $include_name =~ tr/A-Z/a-z/;
@@ -68,6 +69,7 @@
     my $code_check;
     my $old_define;
     my $white_space;
+    my $first;
 
     if ($found_ll)
     {
@@ -86,12 +88,30 @@
     {
         if (${$old_define} ne "")
         {
-            ${$code_check} .= "#endif /* POLARSSL_${$old_define}_C */\n\n";
+            ${$code_check} .= "#endif /* ";
+            $first = 0;
+            foreach my $dep (split(/,/, ${$old_define}))
+            {
+                ${$code_check} .= " || " if ($first++);
+                ${$code_check} .= "POLARSSL_${dep}_C";
+            }
+            ${$code_check} .= " */\n\n";
         }
 
-        ${$code_check} .= "#if defined(POLARSSL_${define_name}_C)\n";
-        $headers .= "#if defined(POLARSSL_${define_name}_C)\n".
-                    "#include \"polarssl/${include_name}.h\"\n".
+        ${$code_check} .= "#if ";
+        $headers .= "#if " if ($include_name ne "");
+        $first = 0;
+        foreach my $dep (split(/,/, ${define_name}))
+        {
+            ${$code_check} .= " || " if ($first);
+            $headers       .= " || " if ($first++);
+
+            ${$code_check} .= "defined(POLARSSL_${dep}_C)";
+            $headers       .= "defined(POLARSSL_${dep}_C)" if
+                                                    ($include_name ne "");
+        }
+        ${$code_check} .= "\n";
+        $headers .= "\n#include \"polarssl/${include_name}.h\"\n".
                     "#endif\n\n" if ($include_name ne "");
         ${$old_define} = $define_name;
     }
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 20f3c8d..dae5172 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -68,6 +68,8 @@
 add_test_suite(pbkdf2)
 add_test_suite(pkcs1_v21)
 add_test_suite(pkcs5)
+add_test_suite(pkparse)
+add_test_suite(pkwrite)
 add_test_suite(shax)
 add_test_suite(rsa)
 add_test_suite(version)
diff --git a/tests/Makefile b/tests/Makefile
index 4d2bcba..4c74e25 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -47,6 +47,7 @@
 		test_suite_md			test_suite_mdx			\
 		test_suite_mpi			test_suite_pbkdf2		\
 		test_suite_pkcs1_v21	test_suite_pkcs5		\
+		test_suite_pkparse		test_suite_pkwrite		\
 		test_suite_rsa			test_suite_shax			\
 		test_suite_x509parse	test_suite_x509write	\
 		test_suite_xtea			test_suite_version
@@ -275,6 +276,14 @@
 	echo   "  CC    	$@.c"
 	$(CC) $(CFLAGS) $(OFLAGS) $@.c	$(LDFLAGS) -o $@
 
+test_suite_pkparse: test_suite_pkparse.c ../library/libpolarssl.a
+	echo   "  CC    	$@.c"
+	$(CC) $(CFLAGS) $(OFLAGS) $@.c	$(LDFLAGS) -o $@
+
+test_suite_pkwrite: test_suite_pkwrite.c ../library/libpolarssl.a
+	echo   "  CC    	$@.c"
+	$(CC) $(CFLAGS) $(OFLAGS) $@.c	$(LDFLAGS) -o $@
+
 test_suite_rsa: test_suite_rsa.c ../library/libpolarssl.a
 	echo   "  CC    	$@.c"
 	$(CC) $(CFLAGS) $(OFLAGS) $@.c	$(LDFLAGS) -o $@
diff --git a/tests/data_files/server1.crt b/tests/data_files/server1.crt
index 7e353cc..d81b26a 100644
--- a/tests/data_files/server1.crt
+++ b/tests/data_files/server1.crt
@@ -1,60 +1,3 @@
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number: 1 (0x1)
-        Signature Algorithm: sha1WithRSAEncryption
-        Issuer: C=NL, O=PolarSSL, CN=PolarSSL Test CA
-        Validity
-            Not Before: Feb 12 14:44:06 2011 GMT
-            Not After : Feb 12 14:44:06 2021 GMT
-        Subject: C=NL, O=PolarSSL, CN=PolarSSL Server 1
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-            RSA Public Key: (2048 bit)
-                Modulus (2048 bit):
-                    00:a9:02:1f:3d:40:6a:d5:55:53:8b:fd:36:ee:82:
-                    65:2e:15:61:5e:89:bf:b8:e8:45:90:db:ee:88:16:
-                    52:d3:f1:43:50:47:96:12:59:64:87:6b:fd:2b:e0:
-                    46:f9:73:be:dd:cf:92:e1:91:5b:ed:66:a0:6f:89:
-                    29:79:45:80:d0:83:6a:d5:41:43:77:5f:39:7c:09:
-                    04:47:82:b0:57:39:70:ed:a3:ec:15:19:1e:a8:33:
-                    08:47:c1:05:42:a9:fd:4c:c3:b4:df:dd:06:1f:4d:
-                    10:51:40:67:73:13:0f:40:f8:6d:81:25:5f:0a:b1:
-                    53:c6:30:7e:15:39:ac:f9:5a:ee:7f:92:9e:a6:05:
-                    5b:e7:13:97:85:b5:23:92:d9:d4:24:06:d5:09:25:
-                    89:75:07:dd:a6:1a:8f:3f:09:19:be:ad:65:2c:64:
-                    eb:95:9b:dc:fe:41:5e:17:a6:da:6c:5b:69:cc:02:
-                    ba:14:2c:16:24:9c:4a:dc:cd:d0:f7:52:67:73:f1:
-                    2d:a0:23:fd:7e:f4:31:ca:2d:70:ca:89:0b:04:db:
-                    2e:a6:4f:70:6e:9e:ce:bd:58:89:e2:53:59:9e:6e:
-                    5a:92:65:e2:88:3f:0c:94:19:a3:dd:e5:e8:9d:95:
-                    13:ed:29:db:ab:70:12:dc:5a:ca:6b:17:ab:52:82:
-                    54:b1
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Basic Constraints: 
-                CA:FALSE
-            X509v3 Subject Key Identifier: 
-                1F:74:D6:3F:29:C1:74:74:45:3B:05:12:2C:3D:A8:BD:43:59:02:A6
-            X509v3 Authority Key Identifier: 
-                keyid:B4:5A:E4:A5:B3:DE:D2:52:F6:B9:D5:A6:95:0F:EB:3E:BC:C7:FD:FF
-
-    Signature Algorithm: sha1WithRSAEncryption
-        bd:cf:96:c1:95:1e:9a:c2:6e:d8:88:88:d8:2a:7a:96:20:3e:
-        50:0b:c8:c7:df:1d:41:ed:e4:66:cd:b3:02:81:7d:57:04:1b:
-        5d:c6:33:59:0f:c1:20:b9:23:34:89:8a:6c:f2:fd:c7:48:36:
-        8c:80:e7:e1:9b:c6:60:5c:b0:33:02:0e:fd:df:be:61:bc:18:
-        89:0c:38:db:fb:fb:46:23:32:f7:8c:c1:3e:7c:de:1e:2f:3a:
-        77:2f:f4:8e:93:8e:25:4c:77:21:74:6c:18:b7:72:8d:bf:f5:
-        4f:5d:64:95:c1:6a:1a:70:11:88:af:bc:55:8a:25:30:f3:fa:
-        69:f2:af:2d:75:fb:2b:89:22:52:9b:05:42:15:29:13:95:5e:
-        33:9a:55:d4:c7:22:d8:44:ce:25:ab:b6:70:ee:34:14:9b:c8:
-        fc:2f:56:ff:04:7e:18:00:2b:31:ac:36:7f:11:bb:ec:4d:e5:
-        69:a6:b4:2c:03:a5:7b:13:3a:03:82:8e:6f:97:f9:70:64:cc:
-        e4:88:7a:b4:41:79:15:5a:b7:ff:db:f3:34:86:0c:6b:51:6a:
-        cd:a7:01:2d:91:7c:cd:21:d8:2c:48:a6:5c:17:73:8c:1a:0d:
-        e2:a0:d4:fd:6c:d1:c9:84:41:46:30:08:e3:d9:b3:1d:7e:ab:
-        6a:57:aa:9f
 -----BEGIN CERTIFICATE-----
 MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
 MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
diff --git a/tests/scripts/generate_code.pl b/tests/scripts/generate_code.pl
index 40f993f..1e33ac6 100755
--- a/tests/scripts/generate_code.pl
+++ b/tests/scripts/generate_code.pl
@@ -61,7 +61,9 @@
 print TEST_FILE << "END";
 #include <polarssl/config.h>
 
+$suite_pre_code
 $suite_header
+$suite_post_code
 
 $test_helpers
 
diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function
index 4a34319..d5aa386 100644
--- a/tests/suites/main_test.function
+++ b/tests/suites/main_test.function
@@ -3,6 +3,9 @@
 
 static int test_errors = 0;
 
+SUITE_PRE_DEP
+#define TEST_SUITE_ACTIVE
+
 static int test_assert( int correct, char *test )
 {
     if( correct )
@@ -81,6 +84,9 @@
     return( -1 );
 }
 
+FUNCTION_CODE
+SUITE_POST_DEP
+
 int dep_check( char *str )
 {
     if( str == NULL )
@@ -91,11 +97,6 @@
     return( 1 );
 }
 
-SUITE_PRE_DEP
-#define TEST_SUITE_ACTIVE
-FUNCTION_CODE
-SUITE_POST_DEP
-
 int dispatch_test(int cnt, char *params[50])
 {
     int ret;
diff --git a/tests/suites/test_suite_debug.data b/tests/suites/test_suite_debug.data
index 81d13a5..6136d75 100644
--- a/tests/suites/test_suite_debug.data
+++ b/tests/suites/test_suite_debug.data
@@ -1,9 +1,9 @@
 Debug print certificate #1 (RSA)
-depends_on:POLARSSL_FS_IO:POLARSSL_PEM_C:POLARSSL_BASE64_C
+depends_on:POLARSSL_PEM_C:POLARSSL_BASE64_C
 debug_print_crt:"data_files/server1.crt":"MyFile":999:"PREFIX_":"MyFile(0999)\: PREFIX_ #1\:\nMyFile(0999)\: cert. version \: 3\nMyFile(0999)\: serial number \: 01\nMyFile(0999)\: issuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nMyFile(0999)\: subject name  \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nMyFile(0999)\: issued  on    \: 2011-02-12 14\:44\:06\nMyFile(0999)\: expires on    \: 2021-02-12 14\:44\:06\nMyFile(0999)\: signed using  \: RSA with SHA1\nMyFile(0999)\: RSA key size  \: 2048 bits\nMyFile(0999)\: value of 'crt->rsa.N' (2048 bits) is\:\nMyFile(0999)\:  a9 02 1f 3d 40 6a d5 55 53 8b fd 36 ee 82 65 2e\nMyFile(0999)\:  15 61 5e 89 bf b8 e8 45 90 db ee 88 16 52 d3 f1\nMyFile(0999)\:  43 50 47 96 12 59 64 87 6b fd 2b e0 46 f9 73 be\nMyFile(0999)\:  dd cf 92 e1 91 5b ed 66 a0 6f 89 29 79 45 80 d0\nMyFile(0999)\:  83 6a d5 41 43 77 5f 39 7c 09 04 47 82 b0 57 39\nMyFile(0999)\:  70 ed a3 ec 15 19 1e a8 33 08 47 c1 05 42 a9 fd\nMyFile(0999)\:  4c c3 b4 df dd 06 1f 4d 10 51 40 67 73 13 0f 40\nMyFile(0999)\:  f8 6d 81 25 5f 0a b1 53 c6 30 7e 15 39 ac f9 5a\nMyFile(0999)\:  ee 7f 92 9e a6 05 5b e7 13 97 85 b5 23 92 d9 d4\nMyFile(0999)\:  24 06 d5 09 25 89 75 07 dd a6 1a 8f 3f 09 19 be\nMyFile(0999)\:  ad 65 2c 64 eb 95 9b dc fe 41 5e 17 a6 da 6c 5b\nMyFile(0999)\:  69 cc 02 ba 14 2c 16 24 9c 4a dc cd d0 f7 52 67\nMyFile(0999)\:  73 f1 2d a0 23 fd 7e f4 31 ca 2d 70 ca 89 0b 04\nMyFile(0999)\:  db 2e a6 4f 70 6e 9e ce bd 58 89 e2 53 59 9e 6e\nMyFile(0999)\:  5a 92 65 e2 88 3f 0c 94 19 a3 dd e5 e8 9d 95 13\nMyFile(0999)\:  ed 29 db ab 70 12 dc 5a ca 6b 17 ab 52 82 54 b1\nMyFile(0999)\: value of 'crt->rsa.E' (17 bits) is\:\nMyFile(0999)\:  01 00 01\n"
 
 Debug print certificate #2 (EC)
-depends_on:POLARSSL_FS_IO:POLARSSL_PEM_C:POLARSSL_BASE64_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+depends_on:POLARSSL_PEM_C:POLARSSL_BASE64_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
 debug_print_crt:"data_files/test-ca2.crt":"MyFile":999:"PREFIX_":"MyFile(0999)\: PREFIX_ #1\:\nMyFile(0999)\: cert. version \: 3\nMyFile(0999)\: serial number \: AD\:42\:79\:76\:9E\:72\:F6\:E1\nMyFile(0999)\: issuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nMyFile(0999)\: subject name  \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nMyFile(0999)\: issued  on    \: 2013-08-09 07\:49\:46\nMyFile(0999)\: expires on    \: 2023-08-07 07\:49\:46\nMyFile(0999)\: signed using  \: ECDSA with SHA1\nMyFile(0999)\: EC key size   \: 256 bits\nMyFile(0999)\: value of 'crt->eckey.Q(X)' (256 bits) is\:\nMyFile(0999)\:  96 b8 b3 2c fb 29 21 7d be 90 db c2 f8 13 a9 26\nMyFile(0999)\:  7c 35 f6 d9 c0 8b 99 ec 52 7b 7c af a3 7e 28 3c\nMyFile(0999)\: value of 'crt->eckey.Q(Y)' (256 bits) is\:\nMyFile(0999)\:  9b 75 a5 54 5a 62 c8 a9 90 ab 8e e6 86 2b 03 9d\nMyFile(0999)\:  39 9b 65 fd b0 69 f0 a3 a9 2d 9e 14 0e e8 d5 fe\nMyFile(0999)\: value of 'crt->eckey.Q(Z)' (1 bits) is\:\nMyFile(0999)\:  01\n"
 
 Debug print mpi #1
diff --git a/tests/suites/test_suite_debug.function b/tests/suites/test_suite_debug.function
index a355eab..e7c2add 100644
--- a/tests/suites/test_suite_debug.function
+++ b/tests/suites/test_suite_debug.function
@@ -22,27 +22,27 @@
  * END_DEPENDENCIES
  */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO:POLARSSL_X509_CRT_PARSE_C */
 void debug_print_crt( char *crt_file, char *file, int line, char *prefix,
                       char *result_str )
 {
-    x509_cert   crt;
+    x509_crt   crt;
     ssl_context ssl;
     struct buffer_data buffer;
 
-    memset( &crt, 0, sizeof( x509_cert ) );
+    x509_crt_init( &crt );
     memset( &ssl, 0, sizeof( ssl_context ) );
     memset( buffer.buf, 0, 2000 );
     buffer.ptr = buffer.buf; 
 
     ssl_set_dbg(&ssl, string_debug, &buffer);
 
-    TEST_ASSERT( x509parse_crtfile( &crt, crt_file ) == 0 );
+    TEST_ASSERT( x509_crt_parse_file( &crt, crt_file ) == 0 );
     debug_print_crt( &ssl, 0, file, line, prefix, &crt);
 
     TEST_ASSERT( strcmp( buffer.buf, result_str ) == 0 );
 
-    x509_free( &crt );
+    x509_crt_free( &crt );
 }
 /* END_CASE */
 
diff --git a/tests/suites/test_suite_dhm.data b/tests/suites/test_suite_dhm.data
index 168c77c..aecbfc5 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -6,3 +6,6 @@
 
 Diffie-Hellman full exchange #3
 dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
+
+Diffie-Hellman selftest
+dhm_selftest:
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index e8d9cea..dcf2363 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -93,3 +93,10 @@
     dhm_free( &ctx_cli );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void dhm_selftest()
+{
+    TEST_ASSERT( dhm_self_test( 0 ) == 0 );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_md.data b/tests/suites/test_suite_md.data
index d97a3cd..6bc85c9 100644
--- a/tests/suites/test_suite_md.data
+++ b/tests/suites/test_suite_md.data
@@ -295,51 +295,51 @@
 md_hmac_multi:"md5":16:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d53697a652044617461":"6f630fad67cda0ee1fb1f562db3aa53e"
 
 generic MD2 Hash file #1
-depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD2_C
 md_file:"md2":"data_files/hash_file_1":"b593c098712d2e21628c8986695451a8"
 
 generic MD2 Hash file #2
-depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD2_C
 md_file:"md2":"data_files/hash_file_2":"3c027b7409909a4c4b26bbab69ad9f4f"
 
 generic MD2 Hash file #3
-depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD2_C
 md_file:"md2":"data_files/hash_file_3":"6bb43eb285e81f414083a94cdbe2989d"
 
 generic MD2 Hash file #4
-depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD2_C
 md_file:"md2":"data_files/hash_file_4":"8350e5a3e24c153df2275c9f80692773"
 
 generic MD4 Hash file #1
-depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD4_C
 md_file:"md4":"data_files/hash_file_1":"8d19772c176bd27153b9486715e2c0b9"
 
 generic MD4 Hash file #2
-depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD4_C
 md_file:"md4":"data_files/hash_file_2":"f2ac53b8542882a5a0007c6f84b4d9fd"
 
 generic MD4 Hash file #3
-depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD4_C
 md_file:"md4":"data_files/hash_file_3":"195c15158e2d07881d9a654095ce4a42"
 
 generic MD4 Hash file #4
-depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD4_C
 md_file:"md4":"data_files/hash_file_4":"31d6cfe0d16ae931b73c59d7e0c089c0"
 
 generic MD5 Hash file #1
-depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD5_C
 md_file:"md5":"data_files/hash_file_1":"52bcdc983c9ed64fc148a759b3c7a415"
 
 generic MD5 Hash file #2
-depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD5_C
 md_file:"md5":"data_files/hash_file_2":"d17d466f15891df10542207ae78277f0"
 
 generic MD5 Hash file #3
-depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD5_C
 md_file:"md5":"data_files/hash_file_3":"d945bcc6200ea95d061a2a818167d920"
 
 generic MD5 Hash file #4
-depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD5_C
 md_file:"md5":"data_files/hash_file_4":"d41d8cd98f00b204e9800998ecf8427e"
 
 generic HMAC-SHA-1 Test Vector FIPS-198a #1
@@ -951,81 +951,81 @@
 md_hex_multi:"sha512":"990d1ae71a62d7bda9bfdaa1762a68d296eee72a4cd946f287a898fbabc002ea941fd8d4d991030b4d27a637cce501a834bb95eab1b7889a3e784c7968e67cbf552006b206b68f76d9191327524fcc251aeb56af483d10b4e0c6c5e599ee8c0fe4faeca8293844a8547c6a9a90d093f2526873a19ad4a5e776794c68c742fb834793d2dfcb7fea46c63af4b70fd11cb6e41834e72ee40edb067b292a794990c288d5007e73f349fb383af6a756b8301ad6e5e0aa8cd614399bb3a452376b1575afa6bdaeaafc286cb064bb91edef97c632b6c1113d107fa93a0905098a105043c2f05397f702514439a08a9e5ddc196100721d45c8fc17d2ed659376f8a00bd5cb9a0860e26d8a29d8d6aaf52de97e9346033d6db501a35dbbaf97c20b830cd2d18c2532f3a59cc497ee64c0e57d8d060e5069b28d86edf1adcf59144b221ce3ddaef134b3124fbc7dd000240eff0f5f5f41e83cd7f5bb37c9ae21953fe302b0f6e8b68fa91c6ab99265c64b2fd9cd4942be04321bb5d6d71932376c6f2f88e02422ba6a5e2cb765df93fd5dd0728c6abdaf03bce22e0678a544e2c3636f741b6f4447ee58a8fc656b43ef817932176adbfc2e04b2c812c273cd6cbfa4098f0be036a34221fa02643f5ee2e0b38135f2a18ecd2f16ebc45f8eb31b8ab967a1567ee016904188910861ca1fa205c7adaa194b286893ffe2f4fbe0384c2aef72a4522aeafd3ebc71f9db71eeeef86c48394a1c86d5b36c352cc33a0a2c800bc99e62fd65b3a2fd69e0b53996ec13d8ce483ce9319efd9a85acefabdb5342226febb83fd1daf4b24265f50c61c6de74077ef89b6fecf9f29a1f871af1e9f89b2d345cda7499bd45c42fa5d195a1e1a6ba84851889e730da3b2b916e96152ae0c92154b49719841db7e7cc707ba8a5d7b101eb4ac7b629bb327817910fff61580b59aab78182d1a2e33473d05b00b170b29e331870826cfe45af206aa7d0246bbd8566ca7cfb2d3c10bfa1db7dd48dd786036469ce7282093d78b5e1a5b0fc81a54c8ed4ceac1e5305305e78284ac276f5d7862727aff246e17addde50c670028d572cbfc0be2e4f8b2eb28fa68ad7b4c6c2a239c460441bfb5ea049f23b08563b4e47729a59e5986a61a6093dbd54f8c36ebe87edae01f251cb060ad1364ce677d7e8d5a4a4ca966a7241cc360bc2acb280e5f9e9c1b032ad6a180a35e0c5180b9d16d026c865b252098cc1d99ba7375ca31c7702c0d943d5e3dd2f6861fa55bd46d94b67ed3e52eccd8dd06d968e01897d6de97ed3058d91dd":"8e4bc6f8b8c60fe4d68c61d9b159c8693c3151c46749af58da228442d927f23359bd6ccd6c2ec8fa3f00a86cecbfa728e1ad60b821ed22fcd309ba91a4138bc9"
 
 generic SHA1 Hash file #1
-depends_on:POLARSSL_SHA1_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA1_C
 md_file:"sha1":"data_files/hash_file_1":"d21c965b1e768bd7a6aa6869f5f821901d255f9f"
 
 generic SHA1 Hash file #2
-depends_on:POLARSSL_SHA1_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA1_C
 md_file:"sha1":"data_files/hash_file_2":"353f34271f2aef49d23a8913d4a6bd82b2cecdc6"
 
 generic SHA1 Hash file #3
-depends_on:POLARSSL_SHA1_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA1_C
 md_file:"sha1":"data_files/hash_file_3":"93640ed592076328096270c756db2fba9c486b35"
 
 generic SHA1 Hash file #4
-depends_on:POLARSSL_SHA1_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA1_C
 md_file:"sha1":"data_files/hash_file_4":"da39a3ee5e6b4b0d3255bfef95601890afd80709"
 
 generic SHA-224 Hash file #1
-depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA256_C
 md_file:"sha224":"data_files/hash_file_1":"8606da018870f0c16834a21bc3385704cb1683b9dbab04c5ddb90a48"
 
 generic SHA-224 Hash file #2
-depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA256_C
 md_file:"sha224":"data_files/hash_file_2":"733b2ab97b6f63f2e29b9a2089756d81e14c93fe4cc9615c0d5e8a03"
 
 generic SHA-224 Hash file #3
-depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA256_C
 md_file:"sha224":"data_files/hash_file_3":"e1df95867580e2cc2100e9565bf9c2e42c24fe5250c19efe33d1c4fe"
 
 generic SHA-224 Hash file #4
-depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA256_C
 md_file:"sha224":"data_files/hash_file_4":"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
 
 generic SHA-256 Hash file #1
-depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA256_C
 md_file:"sha256":"data_files/hash_file_1":"975d0c620d3936886f8a3665e585a3e84aa0501f4225bf53029710242823e391"
 
 generic SHA-256 Hash file #2
-depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA256_C
 md_file:"sha256":"data_files/hash_file_2":"11fcbf1baa36ca45745f10cc5467aee86f066f80ba2c46806d876bf783022ad2"
 
 generic SHA-256 Hash file #3
-depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA256_C
 md_file:"sha256":"data_files/hash_file_3":"9ae4b369f9f4f03b86505b46a5469542e00aaff7cf7417a71af6d6d0aba3b70c"
 
 generic SHA-256 Hash file #4
-depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA256_C
 md_file:"sha256":"data_files/hash_file_4":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
 
 generic SHA-384 Hash file #1
-depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA512_C
 md_file:"sha384":"data_files/hash_file_1":"e0a3e6259d6378001b54ef82f5dd087009c5fad86d8db226a9fe1d14ecbe33a6fc916e3a4b16f5f286424de15d5a8e0e"
 
 generic SHA-384 Hash file #2
-depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA512_C
 md_file:"sha384":"data_files/hash_file_2":"eff727afc8495c92e2f370f97a317f93c3350324b0646b0f0e264708b3c97d3d332d3c5390e1e47130f5c92f1ef4b9cf"
 
 generic SHA-384 Hash file #3
-depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA512_C
 md_file:"sha384":"data_files/hash_file_3":"6fc10ebda96a1ccf61777cac72f6034f92533d42052a4bf9f9d929c672973c71e5aeb1213268043c21527ac0f7f349c4"
 
 generic SHA-384 Hash file #4
-depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA512_C
 md_file:"sha384":"data_files/hash_file_4":"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
 
 generic SHA-512 Hash file #1
-depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA512_C
 md_file:"sha512":"data_files/hash_file_1":"d8207a2e1ff2b424f2c4163fe1b723c9bd42e464061eb411e8df730bcd24a7ab3956a6f3ff044a52eb2d262f9e4ca6b524092b544ab78f14d6f9c4cc8ddf335a"
 
 generic SHA-512 Hash file #2
-depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA512_C
 md_file:"sha512":"data_files/hash_file_2":"ecbb7f0ed8a702b49f16ad3088bcc06ea93451912a7187db15f64d93517b09630b039293aed418d4a00695777b758b1f381548c2fd7b92ce5ed996b32c8734e7"
 
 generic SHA-512 Hash file #3
-depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA512_C
 md_file:"sha512":"data_files/hash_file_3":"7ccc9b2da71ffde9966c3ce44d7f20945fccf33b1fade4da152b021f1afcc7293382944aa6c09eac67af25f22026758e2bf6bed86ae2a43592677ee50f8eea41"
 
 generic SHA-512 Hash file #4
-depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO
+depends_on:POLARSSL_SHA512_C
 md_file:"sha512":"data_files/hash_file_4":"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
diff --git a/tests/suites/test_suite_md.function b/tests/suites/test_suite_md.function
index 042af17..6ca201e 100644
--- a/tests/suites/test_suite_md.function
+++ b/tests/suites/test_suite_md.function
@@ -210,7 +210,8 @@
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
-/* BEGIN_CASE */
+
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
 void md_file( char *text_md_name, char *filename, char *hex_hash_string )
 {
     char md_name[100];
diff --git a/tests/suites/test_suite_mdx.data b/tests/suites/test_suite_mdx.data
index b0588df..8ad609e 100644
--- a/tests/suites/test_suite_mdx.data
+++ b/tests/suites/test_suite_mdx.data
@@ -159,51 +159,51 @@
 md5_hmac:16:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"4869205468657265":"5ccec34ea9656392457fa1ac27f08fbc"
 
 MD2 Hash file #1
-depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD2_C
 md2_file:"data_files/hash_file_1":"b593c098712d2e21628c8986695451a8"
 
 MD2 Hash file #2
-depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD2_C
 md2_file:"data_files/hash_file_2":"3c027b7409909a4c4b26bbab69ad9f4f"
 
 MD2 Hash file #3
-depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD2_C
 md2_file:"data_files/hash_file_3":"6bb43eb285e81f414083a94cdbe2989d"
 
 MD2 Hash file #4
-depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD2_C
 md2_file:"data_files/hash_file_4":"8350e5a3e24c153df2275c9f80692773"
 
 MD4 Hash file #1
-depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD4_C
 md4_file:"data_files/hash_file_1":"8d19772c176bd27153b9486715e2c0b9"
 
 MD4 Hash file #2
-depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD4_C
 md4_file:"data_files/hash_file_2":"f2ac53b8542882a5a0007c6f84b4d9fd"
 
 MD4 Hash file #3
-depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD4_C
 md4_file:"data_files/hash_file_3":"195c15158e2d07881d9a654095ce4a42"
 
 MD4 Hash file #4
-depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD4_C
 md4_file:"data_files/hash_file_4":"31d6cfe0d16ae931b73c59d7e0c089c0"
 
 MD5 Hash file #1
-depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD5_C
 md5_file:"data_files/hash_file_1":"52bcdc983c9ed64fc148a759b3c7a415"
 
 MD5 Hash file #2
-depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD5_C
 md5_file:"data_files/hash_file_2":"d17d466f15891df10542207ae78277f0"
 
 MD5 Hash file #3
-depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD5_C
 md5_file:"data_files/hash_file_3":"d945bcc6200ea95d061a2a818167d920"
 
 MD5 Hash file #4
-depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO
+depends_on:POLARSSL_MD5_C
 md5_file:"data_files/hash_file_4":"d41d8cd98f00b204e9800998ecf8427e"
 
 MD2 Selftest
diff --git a/tests/suites/test_suite_mdx.function b/tests/suites/test_suite_mdx.function
index 53a6801..ab02888 100644
--- a/tests/suites/test_suite_mdx.function
+++ b/tests/suites/test_suite_mdx.function
@@ -139,7 +139,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_MD2_C */
+/* BEGIN_CASE depends_on:POLARSSL_MD2_C:POLARSSL_FS_IO */
 void md2_file( char *filename, char *hex_hash_string )
 {
     unsigned char hash_str[65];
@@ -155,7 +155,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_MD4_C */
+/* BEGIN_CASE depends_on:POLARSSL_MD4_C:POLARSSL_FS_IO */
 void md4_file( char *filename, char *hex_hash_string )
 {
     unsigned char hash_str[65];
@@ -171,7 +171,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_MD5_C */
+/* BEGIN_CASE depends_on:POLARSSL_MD5_C:POLARSSL_FS_IO */
 void md5_file( char *filename, char *hex_hash_string )
 {
     unsigned char hash_str[65];
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index 8429182..dfc6b16 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -50,23 +50,18 @@
 mpi_write_binary:16:"123123123123123123123123123":"123123123123123123123123123":13:POLARSSL_ERR_MPI_BUFFER_TOO_SMALL
 
 Base test mpi_read_file #1
-depends_on:POLARSSL_FS_IO
 mpi_read_file:10:"data_files/mpi_10":"01f55332c3a48b910f9942f6c914e58bef37a47ee45cb164a5b6b8d1006bf59a059c21449939ebebfdf517d2e1dbac88010d7b1f141e997bd6801ddaec9d05910f4f2de2b2c4d714e2c14a72fc7f17aa428d59c531627f09":0
 
 Test mpi_read_file #1 (Empty file)
-depends_on:POLARSSL_FS_IO
 mpi_read_file:10:"data_files/hash_file_4":"":POLARSSL_ERR_MPI_FILE_IO_ERROR
 
 Test mpi_read_file #2 (Illegal input)
-depends_on:POLARSSL_FS_IO
 mpi_read_file:10:"data_files/hash_file_3":"":0
 
 Test mpi_read_file #3 (Input too big)
-depends_on:POLARSSL_FS_IO
 mpi_read_file:10:"data_files/mpi_too_big":"":POLARSSL_ERR_MPI_BUFFER_TOO_SMALL
 
 Base test mpi_write_file #1
-depends_on:POLARSSL_FS_IO
 mpi_write_file:10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924":16:"data_files/mpi_write"
 
 Base test mpi_lsb #1
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index 9bb5f0b..9e8338d 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -85,7 +85,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
 void mpi_read_file( int radix_X, char *input_file, char *input_A,
                     int result )
 {
@@ -118,7 +118,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
 void mpi_write_file( int radix_X, char *input_X, int output_radix,
                      char *output_file )
 {
diff --git a/tests/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data
new file mode 100644
index 0000000..0110763
--- /dev/null
+++ b/tests/suites/test_suite_pkparse.data
@@ -0,0 +1,196 @@
+Parse RSA Key #1 (No password when required)
+depends_on:POLARSSL_MD5_C:POLARSSL_PEM_PARSE_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/test-ca.key":"NULL":POLARSSL_ERR_PK_PASSWORD_REQUIRED
+
+Parse RSA Key #2 (Correct password)
+depends_on:POLARSSL_MD5_C:POLARSSL_PEM_PARSE_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/test-ca.key":"PolarSSLTest":0
+
+Parse RSA Key #3 (Wrong password)
+depends_on:POLARSSL_MD5_C:POLARSSL_PEM_PARSE_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/test-ca.key":"PolarSSLWRONG":POLARSSL_ERR_PK_PASSWORD_MISMATCH
+
+Parse RSA Key #4 (DES Encrypted)
+depends_on:POLARSSL_MD5_C:POLARSSL_DES_C:POLARSSL_PEM_PARSE_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/keyfile.des":"testkey":0
+
+Parse RSA Key #5 (3DES Encrypted)
+depends_on:POLARSSL_MD5_C:POLARSSL_DES_C:POLARSSL_PEM_PARSE_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/keyfile.3des":"testkey":0
+
+Parse RSA Key #6 (AES-128 Encrypted)
+depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_PARSE_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/keyfile.aes128":"testkey":0
+
+Parse RSA Key #7 (AES-192 Encrypted)
+depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_PARSE_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/keyfile.aes192":"testkey":0
+
+Parse RSA Key #8 (AES-256 Encrypted)
+depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_PARSE_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/keyfile.aes256":"testkey":0
+
+Parse RSA Key #9 (PKCS#8 wrapped)
+depends_on:POLARSSL_MD5_C:POLARSSL_PEM_PARSE_C
+pk_parse_keyfile_rsa:"data_files/format_gen.key":"":0
+
+Parse RSA Key #10 (PKCS#8 encrypted SHA1-3DES)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"PolarSSLTest":0
+
+Parse RSA Key #10.1 (PKCS#8 encrypted SHA1-3DES, wrong PW)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"PolarSSLTes":POLARSSL_ERR_PK_PASSWORD_MISMATCH
+
+Parse RSA Key #10.2 (PKCS#8 encrypted SHA1-3DES, no PW)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"":POLARSSL_ERR_PK_PASSWORD_REQUIRED
+
+Parse RSA Key #11 (PKCS#8 encrypted SHA1-3DES DER)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.der":"PolarSSLTest":0
+
+Parse RSA Key #12 (PKCS#8 encrypted SHA1-2DES)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"PolarSSLTest":0
+
+Parse RSA Key #12.1 (PKCS#8 encrypted SHA1-2DES, wrong PW)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"PolarSLTest":POLARSSL_ERR_PK_PASSWORD_MISMATCH
+
+Parse RSA Key #12.2 (PKCS#8 encrypted SHA1-2DES, no PW)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"":POLARSSL_ERR_PK_PASSWORD_REQUIRED
+
+Parse RSA Key #13 (PKCS#8 encrypted SHA1-RC4-128)
+depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"PolarSSLTest":0
+
+Parse RSA Key #13.1 (PKCS#8 encrypted SHA1-RC4-128, wrong PW)
+depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"PolarSSLTe":POLARSSL_ERR_PK_PASSWORD_MISMATCH
+
+Parse RSA Key #13.2 (PKCS#8 encrypted SHA1-RC4-128, no PW)
+depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS12_C
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"":POLARSSL_ERR_PK_PASSWORD_REQUIRED
+
+Parse RSA Key #14 (PKCS#8 encrypted v2 PBDFK2 3DES)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"PolarSSLTest":0
+
+Parse RSA Key #15 (PKCS#8 encrypted v2 PBDFK2 3DES, wrong PW)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"PolarSSLTes":POLARSSL_ERR_PK_PASSWORD_MISMATCH
+
+Parse RSA Key #16 (PKCS#8 encrypted v2 PBDFK2 3DES, no PW)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS5_C
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"":POLARSSL_ERR_PK_PASSWORD_REQUIRED
+
+Parse RSA Key #17 (PKCS#8 encrypted v2 PBDFK2 3DES DER)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"PolarSSLTest":0
+
+Parse RSA Key #18 (PKCS#8 encrypted v2 PBDFK2 3DES DER, wrong PW)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"PolarSSLTes":POLARSSL_ERR_PK_PASSWORD_MISMATCH
+
+Parse RSA Key #19 (PKCS#8 encrypted v2 PBDFK2 3DES DER, no PW)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PKCS5_C
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+
+Parse RSA Key #20 (PKCS#8 encrypted v2 PBDFK2 DES)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_des.key":"PolarSSLTest":0
+
+Parse Public RSA Key #1 (PKCS#8 wrapped)
+depends_on:POLARSSL_MD5_C:POLARSSL_PEM_PARSE_C
+pk_parse_public_keyfile_rsa:"data_files/format_gen.pub":0
+
+Parse Public EC Key #1 (RFC 5480, DER)
+depends_on:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_pub.der":0
+
+Parse Public EC Key #2 (RFC 5480, PEM)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_pub.pem":0
+
+Parse Public EC Key #3 (RFC 5480, secp224r1)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP224R1_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_224_pub.pem":0
+
+Parse Public EC Key #4 (RFC 5480, secp256r1)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_256_pub.pem":0
+
+Parse Public EC Key #5 (RFC 5480, secp384r1)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP384R1_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_384_pub.pem":0
+
+Parse Public EC Key #6 (RFC 5480, secp521r1)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP521R1_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_521_pub.pem":0
+
+Parse EC Key #1 (SEC1 DER)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_prv.sec1.der":"NULL":0
+
+Parse EC Key #2 (SEC1 PEM)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_prv.sec1.pem":"NULL":0
+
+Parse EC Key #3 (SEC1 PEM encrypted)
+depends_on:POLARSSL_DES_C:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_CIPHER_MODE_CBC
+pk_parse_keyfile_ec:"data_files/ec_prv.sec1.pw.pem":"polar":0
+
+Parse EC Key #4 (PKCS8 DER)
+depends_on:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_prv.pk8.der":"NULL":0
+
+Parse EC Key #5 (PKCS8 PEM)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_prv.pk8.pem":"NULL":0
+
+Parse EC Key #6 (PKCS8 encrypted DER)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_prv.pk8.pw.der":"polar":0
+
+Parse EC Key #7 (PKCS8 encrypted PEM)
+depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_prv.pk8.pw.pem":"polar":0
+
+Parse EC Key #8 (SEC1 PEM, secp224r1)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP224R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_224_prv.pem":"NULL":0
+
+Parse EC Key #9 (SEC1 PEM, secp256r1)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_256_prv.pem":"NULL":0
+
+Parse EC Key #10 (SEC1 PEM, secp384r1)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP384R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_384_prv.pem":"NULL":0
+
+Parse EC Key #11 (SEC1 PEM, secp521r1)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP521R1_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_521_prv.pem":"NULL":0
+
+Key ASN1 (Incorrect first tag)
+pk_parse_key_rsa:"":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (RSAPrivateKey, incorrect version tag)
+pk_parse_key_rsa:"300100":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (RSAPrivateKey, version tag missing)
+pk_parse_key_rsa:"3000":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (RSAPrivateKey, invalid version)
+pk_parse_key_rsa:"3003020101":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (RSAPrivateKey, correct version, incorrect tag)
+pk_parse_key_rsa:"300402010000":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (RSAPrivateKey, values present, length mismatch)
+pk_parse_key_rsa:"301c02010002010102010102010102010102010102010102010102010100":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (RSAPrivateKey, values present, check_privkey fails)
+pk_parse_key_rsa:"301b020100020101020101020101020101020101020101020101020101":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT
diff --git a/tests/suites/test_suite_pkparse.function b/tests/suites/test_suite_pkparse.function
new file mode 100644
index 0000000..5cdd844
--- /dev/null
+++ b/tests/suites/test_suite_pkparse.function
@@ -0,0 +1,136 @@
+/* BEGIN_HEADER */
+#include <polarssl/pk.h>
+#include <polarssl/pem.h>
+#include <polarssl/oid.h>
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:POLARSSL_PK_PARSE_C:POLARSSL_BIGNUM_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C:POLARSSL_FS_IO */
+void pk_parse_keyfile_rsa( char *key_file, char *password, int result )
+{
+    pk_context ctx;
+    int res;
+    char *pwd = password;
+
+    pk_init( &ctx );
+
+    if( strcmp( pwd, "NULL" ) == 0 )
+        pwd = NULL;
+
+    res = pk_parse_keyfile( &ctx, key_file, pwd );
+
+    TEST_ASSERT( res == result );
+
+    if( res == 0 )
+    {
+        rsa_context *rsa;
+        TEST_ASSERT( pk_can_do( &ctx, POLARSSL_PK_RSA ) );
+        rsa = pk_rsa( ctx );
+        TEST_ASSERT( rsa_check_privkey( rsa ) == 0 );
+    }
+
+    pk_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C:POLARSSL_FS_IO */
+void pk_parse_public_keyfile_rsa( char *key_file, int result )
+{
+    pk_context ctx;
+    int res;
+
+    pk_init( &ctx );
+
+    res = pk_parse_public_keyfile( &ctx, key_file );
+
+    TEST_ASSERT( res == result );
+
+    if( res == 0 )
+    {
+        rsa_context *rsa;
+        TEST_ASSERT( pk_can_do( &ctx, POLARSSL_PK_RSA ) );
+        rsa = pk_rsa( ctx );
+        TEST_ASSERT( rsa_check_pubkey( rsa ) == 0 );
+    }
+
+    pk_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
+void pk_parse_public_keyfile_ec( char *key_file, int result )
+{
+    pk_context ctx;
+    int res;
+
+    pk_init( &ctx );
+
+    res = pk_parse_public_keyfile( &ctx, key_file );
+
+    TEST_ASSERT( res == result );
+
+    if( res == 0 )
+    {
+        ecp_keypair *eckey;
+        TEST_ASSERT( pk_can_do( &ctx, POLARSSL_PK_ECKEY ) );
+        eckey = pk_ec( ctx );
+        TEST_ASSERT( ecp_check_pubkey( &eckey->grp, &eckey->Q ) == 0 );
+    }
+
+    pk_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
+void pk_parse_keyfile_ec( char *key_file, char *password, int result )
+{
+    pk_context ctx;
+    int res;
+
+    pk_init( &ctx );
+
+    res = pk_parse_keyfile( &ctx, key_file, password );
+
+    TEST_ASSERT( res == result );
+
+    if( res == 0 )
+    {
+        ecp_keypair *eckey;
+        TEST_ASSERT( pk_can_do( &ctx, POLARSSL_PK_ECKEY ) );
+        eckey = pk_ec( ctx );
+        TEST_ASSERT( ecp_check_privkey( &eckey->grp, &eckey->d ) == 0 );
+    }
+
+    pk_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
+void pk_parse_key_rsa( char *key_data, char *result_str, int result )
+{
+    pk_context pk;
+    unsigned char buf[2000];
+    unsigned char output[2000];
+    int data_len;
+    ((void) result_str);
+
+    pk_init( &pk );
+
+    memset( buf, 0, 2000 );
+    memset( output, 0, 2000 );
+
+    data_len = unhexify( buf, key_data );
+
+    TEST_ASSERT( pk_parse_key( &pk, buf, data_len, NULL, 0 ) == ( result ) );
+    if( ( result ) == 0 )
+    {
+        TEST_ASSERT( 1 );
+    }
+
+    pk_free( &pk );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_pkwrite.data b/tests/suites/test_suite_pkwrite.data
new file mode 100644
index 0000000..68adef6
--- /dev/null
+++ b/tests/suites/test_suite_pkwrite.data
@@ -0,0 +1,15 @@
+Public key write check RSA
+depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C
+pk_write_pubkey_check:"data_files/server1.pubkey"
+
+Public key write check EC
+depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_write_pubkey_check:"data_files/ec_pub.pem"
+
+Private key write check RSA
+depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C
+pk_write_key_check:"data_files/server1.key"
+
+Private key write check EC
+depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+pk_write_key_check:"data_files/ec_prv.sec1.pem"
diff --git a/tests/suites/test_suite_pkwrite.function b/tests/suites/test_suite_pkwrite.function
new file mode 100644
index 0000000..455b9aa
--- /dev/null
+++ b/tests/suites/test_suite_pkwrite.function
@@ -0,0 +1,68 @@
+/* BEGIN_HEADER */
+#include <polarssl/pk.h>
+#include <polarssl/pem.h>
+#include <polarssl/oid.h>
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:POLARSSL_PK_WRITE_C:POLARSSL_BIGNUM_C:POLARSSL_FS_IO
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void pk_write_pubkey_check( char *key_file )
+{
+    pk_context key;
+    unsigned char buf[5000];
+    unsigned char check_buf[5000];
+    int ret;
+    FILE *f;
+
+    memset( buf, 0, sizeof( buf ) );
+    memset( check_buf, 0, sizeof( check_buf ) );
+
+    pk_init( &key );
+    TEST_ASSERT( pk_parse_public_keyfile( &key, key_file ) == 0 );
+
+    ret = pk_write_pubkey_pem( &key, buf, sizeof( buf ) - 1);
+    TEST_ASSERT( ret >= 0 );
+
+    f = fopen( key_file, "r" );
+    TEST_ASSERT( f != NULL );
+    fread( check_buf, 1, sizeof( check_buf ) - 1, f );
+    fclose( f );
+
+    TEST_ASSERT( strncmp( (char *) buf, (char *) check_buf, sizeof( buf ) ) == 0 );
+
+    pk_free( &key );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void pk_write_key_check( char *key_file )
+{
+    pk_context key;
+    unsigned char buf[5000];
+    unsigned char check_buf[5000];
+    int ret;
+    FILE *f;
+
+    memset( buf, 0, sizeof( buf ) );
+    memset( check_buf, 0, sizeof( check_buf ) );
+
+    pk_init( &key );
+    TEST_ASSERT( pk_parse_keyfile( &key, key_file, NULL ) == 0 );
+
+    ret = pk_write_key_pem( &key, buf, sizeof( buf ) - 1);
+    TEST_ASSERT( ret >= 0 );
+
+    f = fopen( key_file, "r" );
+    TEST_ASSERT( f != NULL );
+    fread( check_buf, 1, sizeof( check_buf ) - 1, f );
+    fclose( f );
+
+    TEST_ASSERT( strncmp( (char *) buf, (char *) check_buf, sizeof( buf ) ) == 0 );
+
+    pk_free( &key );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_shax.data b/tests/suites/test_suite_shax.data
index ed4e96f..cb81cd0 100644
--- a/tests/suites/test_suite_shax.data
+++ b/tests/suites/test_suite_shax.data
@@ -159,83 +159,83 @@
 sha512:"990d1ae71a62d7bda9bfdaa1762a68d296eee72a4cd946f287a898fbabc002ea941fd8d4d991030b4d27a637cce501a834bb95eab1b7889a3e784c7968e67cbf552006b206b68f76d9191327524fcc251aeb56af483d10b4e0c6c5e599ee8c0fe4faeca8293844a8547c6a9a90d093f2526873a19ad4a5e776794c68c742fb834793d2dfcb7fea46c63af4b70fd11cb6e41834e72ee40edb067b292a794990c288d5007e73f349fb383af6a756b8301ad6e5e0aa8cd614399bb3a452376b1575afa6bdaeaafc286cb064bb91edef97c632b6c1113d107fa93a0905098a105043c2f05397f702514439a08a9e5ddc196100721d45c8fc17d2ed659376f8a00bd5cb9a0860e26d8a29d8d6aaf52de97e9346033d6db501a35dbbaf97c20b830cd2d18c2532f3a59cc497ee64c0e57d8d060e5069b28d86edf1adcf59144b221ce3ddaef134b3124fbc7dd000240eff0f5f5f41e83cd7f5bb37c9ae21953fe302b0f6e8b68fa91c6ab99265c64b2fd9cd4942be04321bb5d6d71932376c6f2f88e02422ba6a5e2cb765df93fd5dd0728c6abdaf03bce22e0678a544e2c3636f741b6f4447ee58a8fc656b43ef817932176adbfc2e04b2c812c273cd6cbfa4098f0be036a34221fa02643f5ee2e0b38135f2a18ecd2f16ebc45f8eb31b8ab967a1567ee016904188910861ca1fa205c7adaa194b286893ffe2f4fbe0384c2aef72a4522aeafd3ebc71f9db71eeeef86c48394a1c86d5b36c352cc33a0a2c800bc99e62fd65b3a2fd69e0b53996ec13d8ce483ce9319efd9a85acefabdb5342226febb83fd1daf4b24265f50c61c6de74077ef89b6fecf9f29a1f871af1e9f89b2d345cda7499bd45c42fa5d195a1e1a6ba84851889e730da3b2b916e96152ae0c92154b49719841db7e7cc707ba8a5d7b101eb4ac7b629bb327817910fff61580b59aab78182d1a2e33473d05b00b170b29e331870826cfe45af206aa7d0246bbd8566ca7cfb2d3c10bfa1db7dd48dd786036469ce7282093d78b5e1a5b0fc81a54c8ed4ceac1e5305305e78284ac276f5d7862727aff246e17addde50c670028d572cbfc0be2e4f8b2eb28fa68ad7b4c6c2a239c460441bfb5ea049f23b08563b4e47729a59e5986a61a6093dbd54f8c36ebe87edae01f251cb060ad1364ce677d7e8d5a4a4ca966a7241cc360bc2acb280e5f9e9c1b032ad6a180a35e0c5180b9d16d026c865b252098cc1d99ba7375ca31c7702c0d943d5e3dd2f6861fa55bd46d94b67ed3e52eccd8dd06d968e01897d6de97ed3058d91dd":"8e4bc6f8b8c60fe4d68c61d9b159c8693c3151c46749af58da228442d927f23359bd6ccd6c2ec8fa3f00a86cecbfa728e1ad60b821ed22fcd309ba91a4138bc9"
 
 SHA1 Hash file #1
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA1_C
+depends_on:POLARSSL_SHA1_C
 sha1_file:"data_files/hash_file_1":"d21c965b1e768bd7a6aa6869f5f821901d255f9f"
 
 SHA1 Hash file #2
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA1_C
+depends_on:POLARSSL_SHA1_C
 sha1_file:"data_files/hash_file_2":"353f34271f2aef49d23a8913d4a6bd82b2cecdc6"
 
 SHA1 Hash file #3
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA1_C
+depends_on:POLARSSL_SHA1_C
 sha1_file:"data_files/hash_file_3":"93640ed592076328096270c756db2fba9c486b35"
 
 SHA1 Hash file #4
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA1_C
+depends_on:POLARSSL_SHA1_C
 sha1_file:"data_files/hash_file_4":"da39a3ee5e6b4b0d3255bfef95601890afd80709"
 
 SHA-224 Hash file #1
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA256_C
+depends_on:POLARSSL_SHA256_C
 sha224_file:"data_files/hash_file_1":"8606da018870f0c16834a21bc3385704cb1683b9dbab04c5ddb90a48"
 
 SHA-224 Hash file #2
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA256_C
+depends_on:POLARSSL_SHA256_C
 sha224_file:"data_files/hash_file_2":"733b2ab97b6f63f2e29b9a2089756d81e14c93fe4cc9615c0d5e8a03"
 
 SHA-224 Hash file #3
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA256_C
+depends_on:POLARSSL_SHA256_C
 sha224_file:"data_files/hash_file_3":"e1df95867580e2cc2100e9565bf9c2e42c24fe5250c19efe33d1c4fe"
 
 SHA-224 Hash file #4
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA256_C
+depends_on:POLARSSL_SHA256_C
 sha224_file:"data_files/hash_file_4":"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
 
 SHA-256 Hash file #1
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA256_C
+depends_on:POLARSSL_SHA256_C
 sha256_file:"data_files/hash_file_1":"975d0c620d3936886f8a3665e585a3e84aa0501f4225bf53029710242823e391"
 
 SHA-256 Hash file #2
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA256_C
+depends_on:POLARSSL_SHA256_C
 sha256_file:"data_files/hash_file_2":"11fcbf1baa36ca45745f10cc5467aee86f066f80ba2c46806d876bf783022ad2"
 
 SHA-256 Hash file #3
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA256_C
+depends_on:POLARSSL_SHA256_C
 sha256_file:"data_files/hash_file_3":"9ae4b369f9f4f03b86505b46a5469542e00aaff7cf7417a71af6d6d0aba3b70c"
 
 SHA-256 Hash file #4
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA256_C
+depends_on:POLARSSL_SHA256_C
 sha256_file:"data_files/hash_file_4":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
 
 SHA-384 Hash file #1
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA512_C
+depends_on:POLARSSL_SHA512_C
 sha384_file:"data_files/hash_file_1":"e0a3e6259d6378001b54ef82f5dd087009c5fad86d8db226a9fe1d14ecbe33a6fc916e3a4b16f5f286424de15d5a8e0e"
 
 SHA-384 Hash file #2
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA512_C
+depends_on:POLARSSL_SHA512_C
 sha384_file:"data_files/hash_file_2":"eff727afc8495c92e2f370f97a317f93c3350324b0646b0f0e264708b3c97d3d332d3c5390e1e47130f5c92f1ef4b9cf"
 
 SHA-384 Hash file #3
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA512_C
+depends_on:POLARSSL_SHA512_C
 sha384_file:"data_files/hash_file_3":"6fc10ebda96a1ccf61777cac72f6034f92533d42052a4bf9f9d929c672973c71e5aeb1213268043c21527ac0f7f349c4"
 
 SHA-384 Hash file #4
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA512_C
+depends_on:POLARSSL_SHA512_C
 sha384_file:"data_files/hash_file_4":"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
 
 SHA-512 Hash file #1
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA512_C
+depends_on:POLARSSL_SHA512_C
 sha512_file:"data_files/hash_file_1":"d8207a2e1ff2b424f2c4163fe1b723c9bd42e464061eb411e8df730bcd24a7ab3956a6f3ff044a52eb2d262f9e4ca6b524092b544ab78f14d6f9c4cc8ddf335a"
 
 SHA-512 Hash file #2
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA512_C
+depends_on:POLARSSL_SHA512_C
 sha512_file:"data_files/hash_file_2":"ecbb7f0ed8a702b49f16ad3088bcc06ea93451912a7187db15f64d93517b09630b039293aed418d4a00695777b758b1f381548c2fd7b92ce5ed996b32c8734e7"
 
 SHA-512 Hash file #3
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA512_C
+depends_on:POLARSSL_SHA512_C
 sha512_file:"data_files/hash_file_3":"7ccc9b2da71ffde9966c3ce44d7f20945fccf33b1fade4da152b021f1afcc7293382944aa6c09eac67af25f22026758e2bf6bed86ae2a43592677ee50f8eea41"
 
 SHA-512 Hash file #4
-depends_on:POLARSSL_FS_IO:POLARSSL_SHA512_C
+depends_on:POLARSSL_SHA512_C
 sha512_file:"data_files/hash_file_4":"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
 
 SHA-1 Selftest
diff --git a/tests/suites/test_suite_shax.function b/tests/suites/test_suite_shax.function
index 3ce23e2..fe52b60 100644
--- a/tests/suites/test_suite_shax.function
+++ b/tests/suites/test_suite_shax.function
@@ -109,7 +109,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_SHA1_C */
+/* BEGIN_CASE depends_on:POLARSSL_SHA1_C:POLARSSL_FS_IO */
 void sha1_file( char *filename, char *hex_hash_string )
 {
     unsigned char hash_str[41];
@@ -125,7 +125,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_SHA256_C */
+/* BEGIN_CASE depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO */
 void sha224_file( char *filename, char *hex_hash_string )
 {
     unsigned char hash_str[57];
@@ -141,7 +141,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_SHA256_C */
+/* BEGIN_CASE depends_on:POLARSSL_SHA256_C:POLARSSL_FS_IO */
 void sha256_file( char *filename, char *hex_hash_string )
 {
     unsigned char hash_str[65];
@@ -157,7 +157,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_SHA512_C */
+/* BEGIN_CASE depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO */
 void sha384_file( char *filename, char *hex_hash_string )
 {
     unsigned char hash_str[97];
@@ -173,7 +173,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_SHA512_C */
+/* BEGIN_CASE depends_on:POLARSSL_SHA512_C:POLARSSL_FS_IO */
 void sha512_file( char *filename, char *hex_hash_string )
 {
     unsigned char hash_str[129];
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 0ac7e09..58d59db 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1,705 +1,529 @@
 X509 Certificate information #1
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/server1.crt":"cert. version \: 3\nserial number \: 01\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nissued  on    \: 2011-02-12 14\:44\:06\nexpires on    \: 2021-02-12 14\:44\:06\nsigned using  \: RSA with SHA1\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information #2
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/server2.crt":"cert. version \: 3\nserial number \: 02\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nissued  on    \: 2011-02-12 14\:44\:06\nexpires on    \: 2021-02-12 14\:44\:06\nsigned using  \: RSA with SHA1\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information #3
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/test-ca.crt":"cert. version \: 3\nserial number \: 00\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nissued  on    \: 2011-02-12 14\:44\:00\nexpires on    \: 2021-02-12 14\:44\:00\nsigned using  \: RSA with SHA1\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information MD2 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/cert_md2.crt":"cert. version \: 3\nserial number \: 09\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Cert MD2\nissued  on    \: 2009-07-12 10\:56\:59\nexpires on    \: 2011-07-12 10\:56\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information MD4 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/cert_md4.crt":"cert. version \: 3\nserial number \: 05\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Cert MD4\nissued  on    \: 2011-02-12 14\:44\:07\nexpires on    \: 2021-02-12 14\:44\:07\nsigned using  \: RSA with MD4\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information MD5 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/cert_md5.crt":"cert. version \: 3\nserial number \: 06\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Cert MD5\nissued  on    \: 2011-02-12 14\:44\:07\nexpires on    \: 2021-02-12 14\:44\:07\nsigned using  \: RSA with MD5\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information SHA1 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/cert_sha1.crt":"cert. version \: 3\nserial number \: 07\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Cert SHA1\nissued  on    \: 2011-02-12 14\:44\:07\nexpires on    \: 2021-02-12 14\:44\:07\nsigned using  \: RSA with SHA1\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information SHA224 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/cert_sha224.crt":"cert. version \: 3\nserial number \: 08\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Cert SHA224\nissued  on    \: 2011-02-12 14\:44\:07\nexpires on    \: 2021-02-12 14\:44\:07\nsigned using  \: RSA with SHA-224\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information SHA256 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/cert_sha256.crt":"cert. version \: 3\nserial number \: 09\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Cert SHA256\nissued  on    \: 2011-02-12 14\:44\:07\nexpires on    \: 2021-02-12 14\:44\:07\nsigned using  \: RSA with SHA-256\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information SHA384 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/cert_sha384.crt":"cert. version \: 3\nserial number \: 0A\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Cert SHA384\nissued  on    \: 2011-02-12 14\:44\:07\nexpires on    \: 2021-02-12 14\:44\:07\nsigned using  \: RSA with SHA-384\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information SHA512 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/cert_sha512.crt":"cert. version \: 3\nserial number \: 0B\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Cert SHA512\nissued  on    \: 2011-02-12 14\:44\:07\nexpires on    \: 2021-02-12 14\:44\:07\nsigned using  \: RSA with SHA-512\nRSA key size  \: 2048 bits\n"
 
 X509 Certificate information EC, SHA1 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C
 x509_cert_info:"data_files/server5.crt":"cert. version \: 3\nserial number \: 03\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nissued  on    \: 2013-08-09 07\:57\:40\nexpires on    \: 2023-08-07 07\:57\:40\nsigned using  \: ECDSA with SHA1\nEC key size   \: 192 bits\n"
 
 X509 Certificate information EC, SHA224 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C
 x509_cert_info:"data_files/server5-sha224.crt":"cert. version \: 3\nserial number \: 06\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nissued  on    \: 2013-08-09 08\:08\:12\nexpires on    \: 2023-08-07 08\:08\:12\nsigned using  \: ECDSA with SHA224\nEC key size   \: 192 bits\n"
 
 X509 Certificate information EC, SHA256 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C
 x509_cert_info:"data_files/server5-sha256.crt":"cert. version \: 3\nserial number \: 07\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nissued  on    \: 2013-08-09 08\:08\:17\nexpires on    \: 2023-08-07 08\:08\:17\nsigned using  \: ECDSA with SHA256\nEC key size   \: 192 bits\n"
 
 X509 Certificate information EC, SHA384 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C
 x509_cert_info:"data_files/server5-sha384.crt":"cert. version \: 3\nserial number \: 08\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nissued  on    \: 2013-08-09 08\:08\:25\nexpires on    \: 2023-08-07 08\:08\:25\nsigned using  \: ECDSA with SHA384\nEC key size   \: 192 bits\n"
 
 X509 Certificate information EC, SHA512 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C
 x509_cert_info:"data_files/server5-sha512.crt":"cert. version \: 3\nserial number \: 09\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nissued  on    \: 2013-08-09 08\:08\:32\nexpires on    \: 2023-08-07 08\:08\:32\nsigned using  \: ECDSA with SHA512\nEC key size   \: 192 bits\n"
 
 X509 Certificate information RSA signed by EC
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_cert_info:"data_files/server4.crt":"cert. version \: 3\nserial number \: 04\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nissued  on    \: 2013-08-09 07\:57\:57\nexpires on    \: 2023-08-07 07\:57\:57\nsigned using  \: ECDSA with SHA1\nRSA key size  \: 1024 bits\n"
 
 X509 Certificate information EC signed by RSA
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C
 x509_cert_info:"data_files/server3.crt":"cert. version \: 3\nserial number \: 0D\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nissued  on    \: 2013-08-09 09\:17\:03\nexpires on    \: 2023-08-07 09\:17\:03\nsigned using  \: RSA with SHA1\nEC key size   \: 192 bits\n"
 
 X509 CRL information #1
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_expired.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-20 10\:24\:19\nnext update   \: 2011-02-20 11\:24\:19\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA1\n"
 
 X509 CRL Information MD2 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_md2.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2009-07-19 19\:56\:37\nnext update   \: 2009-09-17 19\:56\:37\nRevoked certificates\:\nserial number\: 01 revocation date\: 2009-02-09 21\:12\:36\nserial number\: 03 revocation date\: 2009-02-09 21\:12\:36\nsigned using  \: RSA with MD2\n"
 
 X509 CRL Information MD4 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_md4.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with MD4\n"
 
 X509 CRL Information MD5 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_md5.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with MD5\n"
 
 X509 CRL Information SHA1 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_sha1.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA1\n"
 
 X509 CRL Information SHA224 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_sha224.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-224\n"
 
 X509 CRL Information SHA256 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_sha256.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-256\n"
 
 X509 CRL Information SHA384 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_sha384.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-384\n"
 
 X509 CRL Information SHA512 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl_sha512.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-512\n"
 
 X509 CRL Information EC, SHA1 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl-ec.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-08-09 08\:06\:26\nnext update   \: 2023-08-07 08\:06\:26\nRevoked certificates\:\nserial number\: 02 revocation date\: 2013-08-09 08\:04\:03\nsigned using  \: ECDSA with SHA1\n"
 
 X509 CRL Information EC, SHA224 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl-ec-sha224.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-08-09 08\:06\:38\nnext update   \: 2023-08-07 08\:06\:38\nRevoked certificates\:\nserial number\: 02 revocation date\: 2013-08-09 08\:04\:03\nsigned using  \: ECDSA with SHA224\n"
 
 X509 CRL Information EC, SHA256 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl-ec-sha256.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-08-09 08\:06\:44\nnext update   \: 2023-08-07 08\:06\:44\nRevoked certificates\:\nserial number\: 02 revocation date\: 2013-08-09 08\:04\:03\nsigned using  \: ECDSA with SHA256\n"
 
 X509 CRL Information EC, SHA384 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl-ec-sha384.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-08-09 08\:06\:52\nnext update   \: 2023-08-07 08\:06\:52\nRevoked certificates\:\nserial number\: 02 revocation date\: 2013-08-09 08\:04\:03\nsigned using  \: ECDSA with SHA384\n"
 
 X509 CRL Information EC, SHA512 Digest
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_PARSE_C
 x509_crl_info:"data_files/crl-ec-sha512.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-08-09 08\:07\:01\nnext update   \: 2023-08-07 08\:07\:01\nRevoked certificates\:\nserial number\: 02 revocation date\: 2013-08-09 08\:04\:03\nsigned using  \: ECDSA with SHA512\n"
 
-X509 Parse RSA Key #1 (No password when required)
-depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/test-ca.key":"NULL":POLARSSL_ERR_X509_PASSWORD_REQUIRED
-
-X509 Parse RSA Key #2 (Correct password)
-depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/test-ca.key":"PolarSSLTest":0
-
-X509 Parse RSA Key #3 (Wrong password)
-depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/test-ca.key":"PolarSSLWRONG":POLARSSL_ERR_X509_PASSWORD_MISMATCH
-
-X509 Parse RSA Key #4 (DES Encrypted)
-depends_on:POLARSSL_MD5_C:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/keyfile.des":"testkey":0
-
-X509 Parse RSA Key #5 (3DES Encrypted)
-depends_on:POLARSSL_MD5_C:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/keyfile.3des":"testkey":0
-
-X509 Parse RSA Key #6 (AES-128 Encrypted)
-depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/keyfile.aes128":"testkey":0
-
-X509 Parse RSA Key #7 (AES-192 Encrypted)
-depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/keyfile.aes192":"testkey":0
-
-X509 Parse RSA Key #8 (AES-256 Encrypted)
-depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/keyfile.aes256":"testkey":0
-
-X509 Parse RSA Key #9 (PKCS#8 wrapped)
-depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO
-x509parse_keyfile_rsa:"data_files/format_gen.key":"":0
-
-X509 Parse RSA Key #10 (PKCS#8 encrypted SHA1-3DES)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"PolarSSLTest":0
-
-X509 Parse RSA Key #10.1 (PKCS#8 encrypted SHA1-3DES, wrong PW)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH
-
-X509 Parse RSA Key #10.2 (PKCS#8 encrypted SHA1-3DES, no PW)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED
-
-X509 Parse RSA Key #11 (PKCS#8 encrypted SHA1-3DES DER)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.der":"PolarSSLTest":0
-
-X509 Parse RSA Key #12 (PKCS#8 encrypted SHA1-2DES)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"PolarSSLTest":0
-
-X509 Parse RSA Key #12.1 (PKCS#8 encrypted SHA1-2DES, wrong PW)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"PolarSLTest":POLARSSL_ERR_X509_PASSWORD_MISMATCH
-
-X509 Parse RSA Key #12.2 (PKCS#8 encrypted SHA1-2DES, no PW)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED
-
-X509 Parse RSA Key #13 (PKCS#8 encrypted SHA1-RC4-128)
-depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"PolarSSLTest":0
-
-X509 Parse RSA Key #13.1 (PKCS#8 encrypted SHA1-RC4-128, wrong PW)
-depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"PolarSSLTe":POLARSSL_ERR_X509_PASSWORD_MISMATCH
-
-X509 Parse RSA Key #13.2 (PKCS#8 encrypted SHA1-RC4-128, no PW)
-depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C
-x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED
-
-X509 Parse RSA Key #14 (PKCS#8 encrypted v2 PBDFK2 3DES)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"PolarSSLTest":0
-
-X509 Parse RSA Key #15 (PKCS#8 encrypted v2 PBDFK2 3DES, wrong PW)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH
-
-X509 Parse RSA Key #16 (PKCS#8 encrypted v2 PBDFK2 3DES, no PW)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C
-x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED
-
-X509 Parse RSA Key #17 (PKCS#8 encrypted v2 PBDFK2 3DES DER)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"PolarSSLTest":0
-
-X509 Parse RSA Key #18 (PKCS#8 encrypted v2 PBDFK2 3DES DER, wrong PW)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH
-
-X509 Parse RSA Key #19 (PKCS#8 encrypted v2 PBDFK2 3DES DER, no PW)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C
-x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
-
-X509 Parse RSA Key #20 (PKCS#8 encrypted v2 PBDFK2 DES)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_des.key":"PolarSSLTest":0
-
-X509 Parse Public RSA Key #1 (PKCS#8 wrapped)
-depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO
-x509parse_public_keyfile_rsa:"data_files/format_gen.pub":0
-
-X509 Parse Public EC Key #1 (RFC 5480, DER)
-depends_on:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_FS_IO
-x509parse_public_keyfile_ec:"data_files/ec_pub.der":0
-
-X509 Parse Public EC Key #2 (RFC 5480, PEM)
-depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_FS_IO
-x509parse_public_keyfile_ec:"data_files/ec_pub.pem":0
-
-X509 Parse Public EC Key #3 (RFC 5480, secp224r1)
-depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP224R1_ENABLED:POLARSSL_FS_IO
-x509parse_public_keyfile_ec:"data_files/ec_224_pub.pem":0
-
-X509 Parse Public EC Key #4 (RFC 5480, secp256r1)
-depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_FS_IO
-x509parse_public_keyfile_ec:"data_files/ec_256_pub.pem":0
-
-X509 Parse Public EC Key #5 (RFC 5480, secp384r1)
-depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP384R1_ENABLED:POLARSSL_FS_IO
-x509parse_public_keyfile_ec:"data_files/ec_384_pub.pem":0
-
-X509 Parse Public EC Key #6 (RFC 5480, secp521r1)
-depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP521R1_ENABLED:POLARSSL_FS_IO
-x509parse_public_keyfile_ec:"data_files/ec_521_pub.pem":0
-
-X509 Parse EC Key #1 (SEC1 DER)
-depends_on:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_prv.sec1.der":"NULL":0
-
-X509 Parse EC Key #2 (SEC1 PEM)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_prv.sec1.pem":"NULL":0
-
-X509 Parse EC Key #3 (SEC1 PEM encrypted)
-depends_on:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_CIPHER_MODE_CBC
-x509parse_keyfile_ec:"data_files/ec_prv.sec1.pw.pem":"polar":0
-
-X509 Parse EC Key #4 (PKCS8 DER)
-depends_on:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_prv.pk8.der":"NULL":0
-
-X509 Parse EC Key #5 (PKCS8 PEM)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_prv.pk8.pem":"NULL":0
-
-X509 Parse EC Key #6 (PKCS8 encrypted DER)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_prv.pk8.pw.der":"polar":0
-
-X509 Parse EC Key #7 (PKCS8 encrypted PEM)
-depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_prv.pk8.pw.pem":"polar":0
-
-X509 Parse EC Key #8 (SEC1 PEM, secp224r1)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP224R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_224_prv.pem":"NULL":0
-
-X509 Parse EC Key #9 (SEC1 PEM, secp256r1)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_256_prv.pem":"NULL":0
-
-X509 Parse EC Key #10 (SEC1 PEM, secp384r1)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP384R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_384_prv.pem":"NULL":0
-
-X509 Parse EC Key #11 (SEC1 PEM, secp521r1)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP521R1_ENABLED
-x509parse_keyfile_ec:"data_files/ec_521_prv.pem":"NULL":0
-
 X509 Get Distinguished Name #1
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_dn_gets:"data_files/server1.crt":"subject":"C=NL, O=PolarSSL, CN=PolarSSL Server 1"
 
 X509 Get Distinguished Name #2
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_dn_gets:"data_files/server1.crt":"issuer":"C=NL, O=PolarSSL, CN=PolarSSL Test CA"
 
 X509 Get Distinguished Name #3
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_dn_gets:"data_files/server2.crt":"subject":"C=NL, O=PolarSSL, CN=localhost"
 
 X509 Get Distinguished Name #4
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_dn_gets:"data_files/server2.crt":"issuer":"C=NL, O=PolarSSL, CN=PolarSSL Test CA"
 
 X509 Time Expired #1
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_time_expired:"data_files/server1.crt":"valid_from":1
 
 X509 Time Expired #2
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_time_expired:"data_files/server1.crt":"valid_to":0
 
 X509 Time Expired #3
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_time_expired:"data_files/server2.crt":"valid_from":1
 
 X509 Time Expired #4
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_time_expired:"data_files/server2.crt":"valid_to":0
 
 X509 Time Expired #5
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_time_expired:"data_files/test-ca.crt":"valid_from":1
 
 X509 Time Expired #6
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C
 x509_time_expired:"data_files/test-ca.crt":"valid_to":0
 
 X509 Certificate verification #1 (Revoked Cert, Expired CRL)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server1.crt":"data_files/test-ca.crt":"data_files/crl_expired.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_REVOKED | BADCRL_EXPIRED:"NULL"
 
 X509 Certificate verification #2 (Revoked Cert, Expired CRL)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server1.crt":"data_files/test-ca.crt":"data_files/crl_expired.pem":"PolarSSL Server 1":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_REVOKED | BADCRL_EXPIRED:"NULL"
 
 X509 Certificate verification #3 (Revoked Cert, Expired CRL, CN Mismatch)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server1.crt":"data_files/test-ca.crt":"data_files/crl_expired.pem":"PolarSSL Wrong CN":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_REVOKED | BADCRL_EXPIRED | BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #4 (Valid Cert, Expired CRL)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/test-ca.crt":"data_files/crl_expired.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCRL_EXPIRED:"NULL"
 
 X509 Certificate verification #5 (Revoked Cert)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_REVOKED:"NULL"
 
 X509 Certificate verification #6 (Revoked Cert)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"PolarSSL Server 1":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_REVOKED:"NULL"
 
 X509 Certificate verification #7 (Revoked Cert, CN Mismatch)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"PolarSSL Wrong CN":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_REVOKED | BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #8 (Valid Cert)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #9 (Not trusted Cert)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/server1.crt":"data_files/crl.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #10 (Not trusted Cert, Expired CRL)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/server1.crt":"data_files/crl_expired.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #12 (Valid Cert MD4 Digest)
-depends_on:POLARSSL_MD4_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_MD4_C:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_md4.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #13 (Valid Cert MD5 Digest)
-depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_MD5_C:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_md5.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #14 (Valid Cert SHA1 Digest)
-depends_on:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_sha1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #15 (Valid Cert SHA224 Digest)
-depends_on:POLARSSL_SHA256_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_SHA256_C:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_sha224.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #16 (Valid Cert SHA256 Digest)
-depends_on:POLARSSL_SHA256_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_SHA256_C:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_sha256.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #17 (Valid Cert SHA384 Digest)
-depends_on:POLARSSL_SHA512_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_SHA512_C:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_sha384.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #18 (Valid Cert SHA512 Digest)
-depends_on:POLARSSL_SHA512_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_SHA512_C:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_sha512.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #19 (Valid Cert, denying callback)
-depends_on:POLARSSL_SHA512_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_SHA512_C:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_sha512.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_OTHER:"verify_none"
 
 X509 Certificate verification #19 (Not trusted Cert, allowing callback)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/server1.crt":"data_files/crl_expired.pem":"NULL":0:0:"verify_all"
 
 X509 Certificate verification #21 (domain matching wildcard certificate, case insensitive)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_wildcard.crt":"data_files/test-ca.crt":"data_files/crl.pem":"mail.ExAmPlE.com":0:0:"NULL"
 
 X509 Certificate verification #22 (domain not matching wildcard certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_wildcard.crt":"data_files/test-ca.crt":"data_files/crl.pem":"mail.example.net":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #23 (domain not matching wildcard certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_wildcard.crt":"data_files/test-ca.crt":"data_files/crl.pem":"example.com":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #24 (domain matching CN of multi certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi.crt":"data_files/test-ca.crt":"data_files/crl.pem":"www.example.com":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #25 (domain matching multi certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi.crt":"data_files/test-ca.crt":"data_files/crl.pem":"example.net":0:0:"NULL"
 
 X509 Certificate verification #26 (domain not matching multi certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi.crt":"data_files/test-ca.crt":"data_files/crl.pem":"www.example.net":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #27 (domain not matching multi certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi.crt":"data_files/test-ca.crt":"data_files/crl.pem":"xample.net":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #27 (domain not matching multi certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi.crt":"data_files/test-ca.crt":"data_files/crl.pem":"bexample.net":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #28 (domain not matching wildcard in multi certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi.crt":"data_files/test-ca.crt":"data_files/crl.pem":"example.org":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_CN_MISMATCH:"NULL"
 
 X509 Certificate verification #29 (domain matching wildcard in multi certificate)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi.crt":"data_files/test-ca.crt":"data_files/crl.pem":"mail.example.org":0:0:"NULL"
 
 X509 Certificate verification #30 (domain matching multi certificate without CN)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi_nocn.crt":"data_files/test-ca.crt":"data_files/crl.pem":"www.shotokan-braunschweig.de":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #31 (domain not matching multi certificate without CN)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/cert_example_multi_nocn.crt":"data_files/test-ca.crt":"data_files/crl.pem":"www.example.net":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_CN_MISMATCH + BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #32 (Valid, EC cert, RSA CA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server3.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #33 (Valid, RSA cert, EC CA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C:POLARSSL_ECP_C:POLARSSL_SHA1_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_ECP_C:POLARSSL_SHA1_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server4.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #34 (Valid, EC cert, EC CA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_SHA1_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_SHA1_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509_verify:"data_files/server5.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #35 (Revoked, EC CA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_SHA1_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_SHA1_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509_verify:"data_files/server6.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_REVOKED:"NULL"
 
 X509 Certificate verification #36 (Valid, EC CA, SHA224 Digest)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_SHA256_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_SHA256_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509_verify:"data_files/server5-sha224.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #37 (Valid, EC CA, SHA256 Digest)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_SHA256_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_SHA256_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509_verify:"data_files/server5-sha256.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #38 (Valid, EC CA, SHA384 Digest)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_SHA512_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_SHA512_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509_verify:"data_files/server5-sha384.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #39 (Valid, EC CA, SHA512 Digest)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_SHA512_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_SHA512_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509_verify:"data_files/server5-sha512.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #40 (Valid, depth 0, RSA, CA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/test-ca.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #41 (Valid, depth 0, EC, CA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C
 x509_verify:"data_files/test-ca2.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #42 (Depth 0, not CA, RSA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/server2.crt":"data_files/crl.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #43 (Depth 0, not CA, EC)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECDSA_C
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C
 x509_verify:"data_files/server5.crt":"data_files/server5.crt":"data_files/crl-ec.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #44 (Corrupted signature, EC)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509_verify:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #45 (Corrupted signature, RSA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2-badsign.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #46 (Valid, depth 2, EC-RSA-EC)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server7_int-ca.crt":"data_files/test-ca2.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #47 (Untrusted, depth 2, EC-RSA-EC)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server7_int-ca.crt":"data_files/test-ca.crt":"data_files/crl-ec.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #48 (Missing intermediate CA, EC-RSA-EC)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server7.crt":"data_files/test-ca.crt":"data_files/crl-ec.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
 X509 Certificate verification #49 (Valid, depth 2, RSA-EC-RSA)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server8_int-ca2.crt":"data_files/test-ca.crt":"data_files/crl-ec.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #50 (Valid, multiple CAs)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/test-ca_cat12.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Certificate verification #51 (Valid, multiple CAs, reverse order)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_RSA_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/test-ca_cat21.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
 
 X509 Parse Selftest
-depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_SELF_TEST
+depends_on:POLARSSL_MD5_C:POLARSSL_PEM_PARSE_C:POLARSSL_SELF_TEST
 x509_selftest:
 
 X509 Certificate ASN1 (Incorrect first tag)
-x509parse_crt:"":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT
+x509parse_crt:"":"":POLARSSL_ERR_X509_INVALID_FORMAT
 
 X509 Certificate ASN1 (Correct first tag, data length does not match)
-x509parse_crt:"300000":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"300000":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (Correct first tag, no more data)
-x509parse_crt:"3000":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"3000":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (Correct first tag, length data incorrect)
-x509parse_crt:"30023085":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_INVALID_LENGTH
+x509parse_crt:"30023085":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_INVALID_LENGTH
 
 X509 Certificate ASN1 (Correct first tag, length data incomplete)
-x509parse_crt:"30023083":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30023083":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (Correct first tag, length data incomplete)
-x509parse_crt:"30023081":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30023081":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (Correct first tag, length data incomplete)
-x509parse_crt:"3003308200":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"3003308200":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (Correct first tag, second tag no TBSCertificate)
-x509parse_crt:"300100":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"300100":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, no version tag, serial missing)
-x509parse_crt:"3003300100":"":POLARSSL_ERR_X509_CERT_INVALID_SERIAL + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"3003300100":"":POLARSSL_ERR_X509_INVALID_SERIAL + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, invalid version tag)
-x509parse_crt:"30053003a00101":"":POLARSSL_ERR_X509_CERT_INVALID_VERSION + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"30053003a00101":"":POLARSSL_ERR_X509_INVALID_VERSION + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, valid version tag, no length)
-x509parse_crt:"30053003a00102":"":POLARSSL_ERR_X509_CERT_INVALID_VERSION + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30053003a00102":"":POLARSSL_ERR_X509_INVALID_VERSION + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, valid version tag, invalid length)
-x509parse_crt:"30163014a012021000000000000000000000000000000000":"":POLARSSL_ERR_X509_CERT_INVALID_VERSION + POLARSSL_ERR_ASN1_INVALID_LENGTH
+x509parse_crt:"30163014a012021000000000000000000000000000000000":"":POLARSSL_ERR_X509_INVALID_VERSION + POLARSSL_ERR_ASN1_INVALID_LENGTH
 
 X509 Certificate ASN1 (TBSCertificate, valid version tag, no serial)
-x509parse_crt:"30073005a003020104":"":POLARSSL_ERR_X509_CERT_INVALID_SERIAL + POLARSSL_ERR_ASN1_OUT_OF_DATA 
+x509parse_crt:"30073005a003020104":"":POLARSSL_ERR_X509_INVALID_SERIAL + POLARSSL_ERR_ASN1_OUT_OF_DATA 
 
 X509 Certificate ASN1 (TBSCertificate, invalid length version tag)
-x509parse_crt:"30083006a00402010400":"":POLARSSL_ERR_X509_CERT_INVALID_VERSION + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"30083006a00402010400":"":POLARSSL_ERR_X509_INVALID_VERSION + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate, incorrect serial tag)
-x509parse_crt:"30083006a00302010400":"":POLARSSL_ERR_X509_CERT_INVALID_SERIAL + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"30083006a00302010400":"":POLARSSL_ERR_X509_INVALID_SERIAL + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, incorrect serial length)
-x509parse_crt:"30083006a00302010482":"":POLARSSL_ERR_X509_CERT_INVALID_SERIAL + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30083006a00302010482":"":POLARSSL_ERR_X509_INVALID_SERIAL + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, correct serial, no alg)
-x509parse_crt:"300d300ba0030201048204deadbeef":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"300d300ba0030201048204deadbeef":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, correct serial, no alg oid)
-x509parse_crt:"300e300ca0030201048204deadbeef00":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"300e300ca0030201048204deadbeef00":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, alg oid no data in sequence)
-x509parse_crt:"300f300da0030201048204deadbeef3000":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"300f300da0030201048204deadbeef3000":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, alg with params)
-x509parse_crt:"30163014a0030201048204deadbeef30070604cafed00d01":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30163014a0030201048204deadbeef30070604cafed00d01":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, correct alg data, no params unknown version)
-x509parse_crt:"30153013a0030201048204deadbeef30060604cafed00d":"":POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION
+x509parse_crt:"30153013a0030201048204deadbeef30060604cafed00d":"":POLARSSL_ERR_X509_UNKNOWN_VERSION
 
 X509 Certificate ASN1 (TBSCertificate, correct alg data, unknown version)
-x509parse_crt:"30173015a0030201048204deadbeef30080604cafed00d0500":"":POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION
+x509parse_crt:"30173015a0030201048204deadbeef30080604cafed00d0500":"":POLARSSL_ERR_X509_UNKNOWN_VERSION
 
 X509 Certificate ASN1 (TBSCertificate, correct alg data, length mismatch)
-x509parse_crt:"30183016a0030201048204deadbeef30090604cafed00d050000":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"30183016a0030201048204deadbeef30090604cafed00d050000":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate, correct alg, unknown alg_id)
-x509parse_crt:"30173015a0030201028204deadbeef30080604cafed00d0500":"":POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG + POLARSSL_ERR_OID_NOT_FOUND
+x509parse_crt:"30173015a0030201028204deadbeef30080604cafed00d0500":"":POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + POLARSSL_ERR_OID_NOT_FOUND
 
 X509 Certificate ASN1 (TBSCertificate, correct alg, specific alg_id)
-x509parse_crt:"301c301aa0030201028204deadbeef300d06092a864886f70d0101020500":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"301c301aa0030201028204deadbeef300d06092a864886f70d0101020500":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, correct alg, unknown specific alg_id)
-x509parse_crt:"301c301aa0030201028204deadbeef300d06092a864886f70d0101010500":"":POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG + POLARSSL_ERR_OID_NOT_FOUND
+x509parse_crt:"301c301aa0030201028204deadbeef300d06092a864886f70d0101010500":"":POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + POLARSSL_ERR_OID_NOT_FOUND
 
 X509 Certificate ASN1 (TBSCertificate, issuer no set data)
-x509parse_crt:"301e301ca0030201028204deadbeef300d06092a864886f70d01010205003000":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"301e301ca0030201028204deadbeef300d06092a864886f70d01010205003000":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, issuer no inner seq data)
-x509parse_crt:"3020301ea0030201028204deadbeef300d06092a864886f70d010102050030023100":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"3020301ea0030201028204deadbeef300d06092a864886f70d010102050030023100":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, issuer no inner set data)
-x509parse_crt:"30223020a0030201028204deadbeef300d06092a864886f70d0101020500300431023000":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30223020a0030201028204deadbeef300d06092a864886f70d0101020500300431023000":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, issuer two inner set datas)
-x509parse_crt:"30243022a0030201028204deadbeef300d06092a864886f70d01010205003006310430003000":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"30243022a0030201028204deadbeef300d06092a864886f70d01010205003006310430003000":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, issuer no oid data)
-x509parse_crt:"30243022a0030201028204deadbeef300d06092a864886f70d01010205003006310430020600":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30243022a0030201028204deadbeef300d06092a864886f70d01010205003006310430020600":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, issuer invalid tag)
-x509parse_crt:"302a3028a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600060454657374":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"302a3028a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600060454657374":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, issuer, no string data)
-x509parse_crt:"30253023a0030201028204deadbeef300d06092a864886f70d0101020500300731053003060013":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30253023a0030201028204deadbeef300d06092a864886f70d0101020500300731053003060013":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, issuer, no full following string)
-x509parse_crt:"302b3029a0030201028204deadbeef300d06092a864886f70d0101020500300d310b3009060013045465737400":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"302b3029a0030201028204deadbeef300d06092a864886f70d0101020500300d310b3009060013045465737400":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, valid issuer, no validity)
-x509parse_crt:"302a3028a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374":"":POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"302a3028a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374":"":POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, too much date data)
-x509parse_crt:"30493047a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301d170c303930313031303030303030170c30393132333132333539353900":"":POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"30493047a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301d170c303930313031303030303030170c30393132333132333539353900":"":POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate, invalid from date)
-x509parse_crt:"30483046a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303000000000170c303931323331323300000000":"":POLARSSL_ERR_X509_CERT_INVALID_DATE
+x509parse_crt:"30483046a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303000000000170c303931323331323300000000":"":POLARSSL_ERR_X509_INVALID_DATE
 
 X509 Certificate ASN1 (TBSCertificate, invalid to date)
-x509parse_crt:"30483046a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323300000000":"":POLARSSL_ERR_X509_CERT_INVALID_DATE
+x509parse_crt:"30483046a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323300000000":"":POLARSSL_ERR_X509_INVALID_DATE
 
 X509 Certificate ASN1 (TBSCertificate, valid validity, no subject)
-x509parse_crt:"30493047a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c30393132333132333539353930":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30493047a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c30393132333132333539353930":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, valid subject, no pubkeyinfo)
-x509parse_crt:"30563054a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30563054a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374":"":POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, no alg)
-x509parse_crt:"30583056a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743000":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30583056a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743000":"":POLARSSL_ERR_PK_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, valid subject, unknown pk alg)
-x509parse_crt:"30673065a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374300f300d06092A864886F70D0101000500":"":POLARSSL_ERR_X509_UNKNOWN_PK_ALG
+x509parse_crt:"30673065a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374300f300d06092A864886F70D0101000500":"":POLARSSL_ERR_PK_UNKNOWN_PK_ALG
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, no bitstring)
-x509parse_crt:"30673065a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374300f300d06092A864886F70D0101010500":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30673065a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374300f300d06092A864886F70D0101010500":"":POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, no bitstring data)
-x509parse_crt:"30693067a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743011300d06092A864886F70D01010105000300":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_INVALID_DATA
+x509parse_crt:"30693067a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743011300d06092A864886F70D01010105000300":"":POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_INVALID_DATA
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid bitstring start)
-x509parse_crt:"306a3068a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743012300d06092A864886F70D0101010500030101":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_INVALID_DATA
+x509parse_crt:"306a3068a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743012300d06092A864886F70D0101010500030101":"":POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_INVALID_DATA
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid internal bitstring length)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"306d306ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400300000":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"306d306ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400300000":"":POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid internal bitstring tag)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"306d306ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400310000":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"306d306ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400310000":"":POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid mpi)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"30743072a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374301c300d06092A864886F70D0101010500030b0030080202ffff0302ffff":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"30743072a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374301c300d06092A864886F70D0101010500030b0030080202ffff0302ffff":"":POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, total length mismatch)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"30753073a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374301d300d06092A864886F70D0101010500030b0030080202ffff0202ffff00":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"30753073a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374301d300d06092A864886F70D0101010500030b0030080202ffff0202ffff00":"":POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, check failed)
 depends_on:POLARSSL_RSA_C
@@ -711,15 +535,15 @@
 
 X509 Certificate ASN1 (TBSCertificate v3, Optional UIDs, Extensions not present)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308183308180a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308183308180a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, issuerID wrong tag)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308184308181a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff00":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"308184308181a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff00":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate v3, UIDs, no ext)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308189308186a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bb":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308189308186a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bb":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, UIDs, invalid length)
 depends_on:POLARSSL_RSA_C
@@ -727,63 +551,63 @@
 
 X509 Certificate ASN1 (TBSCertificate v3, ext empty)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"30818b308188a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba300":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30818b308188a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba300":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext length mismatch)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"30818e30818ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba303300000":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"30818e30818ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba303300000":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate v3, first ext invalid)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"30818f30818ca0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30330023000":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30818f30818ca0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30330023000":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, first ext invalid tag)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"30819030818da0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba3043002310000":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"30819030818da0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba3043002310000":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, bool len missing)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d1301010100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d1301010100":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, data missing)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30080603551d1301010100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30080603551d1301010100":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, no octet present)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30d300b30090603551d1301010100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30d300b30090603551d1301010100":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, octet data missing)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"30819c308199a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba311300f300d0603551d130101010403300100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"30819c308199a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba311300f300d0603551d130101010403300100":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, no pathlen)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"30819f30819ca0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba314301230100603551d130101010406300402010102":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30819f30819ca0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba314301230100603551d130101010406300402010102":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, octet len mismatch)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"3081a230819fa0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba317301530130603551d130101010409300702010102010100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"3081a230819fa0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba317301530130603551d130101010409300702010102010100":"":POLARSSL_ERR_X509_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (correct pubkey, no sig_alg)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308183308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308183308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (sig_alg mismatch)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308192308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0102020500":"":POLARSSL_ERR_X509_CERT_SIG_MISMATCH
+x509parse_crt:"308192308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0102020500":"":POLARSSL_ERR_X509_SIG_MISMATCH
 
 X509 Certificate ASN1 (sig_alg, no sig)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308192308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500":"":POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308192308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500":"":POLARSSL_ERR_X509_INVALID_SIGNATURE + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (signature, invalid sig data)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308195308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030100":"":POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + POLARSSL_ERR_ASN1_INVALID_DATA
+x509parse_crt:"308195308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030100":"":POLARSSL_ERR_X509_INVALID_SIGNATURE + POLARSSL_ERR_ASN1_INVALID_DATA
 
 X509 Certificate ASN1 (signature, data left)
 depends_on:POLARSSL_RSA_C
-x509parse_crt:"308197308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff00":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crt:"308197308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff00":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (correct)
 depends_on:POLARSSL_RSA_C
@@ -842,76 +666,55 @@
 x509parse_crt:"3081E430819F020104300D06092A864886F70D0101050500300F310D300B0603550403130454657374301E170D3133303731303135303233375A170D3233303730383135303233375A300F310D300B06035504031304546573743049301306072A8648CE3D020106082A8648CE3D03010103320004E962551A325B21B50CF6B990E33D4318FD16677130726357A196E3EFE7107BCB6BDC6D9DB2A4DF7C964ACFE81798433D300D06092A864886F70D01010505000331001A6C18CD1E457474B2D3912743F44B571341A7859A0122774A8E19A671680878936949F904C9255BDD6FFFDB33A7E6D8":"cert. version \: 1\nserial number \: 04\nissuer name   \: CN=Test\nsubject name  \: CN=Test\nissued  on    \: 2013-07-10 15\:02\:37\nexpires on    \: 2023-07-08 15\:02\:37\nsigned using  \: RSA with SHA1\nEC key size   \: 192 bits\n":0
 
 X509 CRL ASN1 (Incorrect first tag)
-x509parse_crl:"":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT
+x509parse_crl:"":"":POLARSSL_ERR_X509_INVALID_FORMAT
 
 X509 CRL ASN1 (Correct first tag, data length does not match)
-x509parse_crl:"300000":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crl:"300000":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 CRL ASN1 (TBSCertList, tag missing)
-x509parse_crl:"3000":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crl:"3000":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, version tag len missing)
-x509parse_crl:"3003300102":"":POLARSSL_ERR_X509_CERT_INVALID_VERSION + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crl:"3003300102":"":POLARSSL_ERR_X509_INVALID_VERSION + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, version correct, alg missing)
-x509parse_crl:"30053003020100":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crl:"30053003020100":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, alg correct, incorrect version)
-x509parse_crl:"300b3009020102300406000500":"":POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION
+x509parse_crl:"300b3009020102300406000500":"":POLARSSL_ERR_X509_UNKNOWN_VERSION
 
 X509 CRL ASN1 (TBSCertList, correct version, sig_oid1 unknown)
-x509parse_crl:"300b3009020100300406000500":"":POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG
+x509parse_crl:"300b3009020100300406000500":"":POLARSSL_ERR_X509_UNKNOWN_SIG_ALG
 
 X509 CRL ASN1 (TBSCertList, sig_oid1 id unknown)
-x509parse_crl:"30143012020100300d06092a864886f70d01010f0500":"":POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG
+x509parse_crl:"30143012020100300d06092a864886f70d01010f0500":"":POLARSSL_ERR_X509_UNKNOWN_SIG_ALG
 
 X509 CRL ASN1 (TBSCertList, sig_oid1 correct, issuer missing)
-x509parse_crl:"30143012020100300d06092a864886f70d01010e0500":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crl:"30143012020100300d06092a864886f70d01010e0500":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, issuer set missing)
-x509parse_crl:"30163014020100300d06092a864886f70d01010e05003000":"":POLARSSL_ERR_X509_CERT_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crl:"30163014020100300d06092a864886f70d01010e05003000":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, correct issuer, thisUpdate missing)
-x509parse_crl:"30253023020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344":"":POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crl:"30253023020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344":"":POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, correct thisUpdate, nextUpdate missing, entries length missing)
 x509parse_crl:"30343032020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c30393031303130303030303030":"":POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, entries present, invalid sig_alg)
-x509parse_crl:"304a3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c30383132333132333539353900":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crl:"304a3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c30383132333132333539353900":"":POLARSSL_ERR_X509_INVALID_ALG + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 CRL ASN1 (TBSCertList, entries present, date in entry invalid)
-x509parse_crl:"304a3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd190c30383132333132333539353900":"":POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crl:"304a3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd190c30383132333132333539353900":"":POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 CRL ASN1 (TBSCertList, sig_alg present, sig_alg does not match)
-x509parse_crl:"30583047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010d0500":"":POLARSSL_ERR_X509_CERT_SIG_MISMATCH
+x509parse_crl:"30583047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010d0500":"":POLARSSL_ERR_X509_SIG_MISMATCH
 
 X509 CRL ASN1 (TBSCertList, sig present, len mismatch)
-x509parse_crl:"305d3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010e05000302000100":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
+x509parse_crl:"305d3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010e05000302000100":"":POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 CRL ASN1 (TBSCertList, sig present)
 x509parse_crl:"305c3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010e050003020001":"CRL version   \: 1\nissuer name   \: CN=ABCD\nthis update   \: 2009-01-01 00\:00\:00\nnext update   \: 0000-00-00 00\:00\:00\nRevoked certificates\:\nserial number\: AB\:CD revocation date\: 2008-12-31 23\:59\:59\nsigned using  \: RSA with SHA-224\n":0
 
 X509 CRL ASN1 (TBSCertList, no entries)
 x509parse_crl:"30463031020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030300d06092a864886f70d01010e050003020001":"CRL version   \: 1\nissuer name   \: CN=ABCD\nthis update   \: 2009-01-01 00\:00\:00\nnext update   \: 0000-00-00 00\:00\:00\nRevoked certificates\:\nsigned using  \: RSA with SHA-224\n":0
-
-X509 Key ASN1 (Incorrect first tag)
-x509parse_key_rsa:"":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
-
-X509 Key ASN1 (RSAPrivateKey, incorrect version tag)
-x509parse_key_rsa:"300100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
-
-X509 Key ASN1 (RSAPrivateKey, version tag missing)
-x509parse_key_rsa:"3000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
-
-X509 Key ASN1 (RSAPrivateKey, invalid version)
-x509parse_key_rsa:"3003020101":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
-
-X509 Key ASN1 (RSAPrivateKey, correct version, incorrect tag)
-x509parse_key_rsa:"300402010000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
-
-X509 Key ASN1 (RSAPrivateKey, values present, length mismatch)
-x509parse_key_rsa:"301c02010002010102010102010102010102010102010102010102010100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
-
-X509 Key ASN1 (RSAPrivateKey, values present, check_privkey fails)
-x509parse_key_rsa:"301b020100020101020101020101020101020101020101020101020101":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index 26ce8f5..e8d6d76 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -1,19 +1,20 @@
 /* BEGIN_HEADER */
-#include <polarssl/x509.h>
+#include <polarssl/x509_crt.h>
+#include <polarssl/x509_crl.h>
 #include <polarssl/pem.h>
 #include <polarssl/oid.h>
 
-int verify_none( void *data, x509_cert *crt, int certificate_depth, int *flags )
+int verify_none( void *data, x509_crt *crt, int certificate_depth, int *flags )
 {
     ((void) data);
     ((void) crt);
     ((void) certificate_depth);
     *flags |= BADCERT_OTHER;
-    
+
     return 0;
 }
 
-int verify_all( void *data, x509_cert *crt, int certificate_depth, int *flags )
+int verify_all( void *data, x509_crt *crt, int certificate_depth, int *flags )
 {
     ((void) data);
     ((void) crt);
@@ -26,24 +27,24 @@
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
- * depends_on:POLARSSL_X509_PARSE_C:POLARSSL_BIGNUM_C
+ * depends_on:POLARSSL_BIGNUM_C
  * END_DEPENDENCIES
  */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO:POLARSSL_X509_CRT_PARSE_C */
 void x509_cert_info( char *crt_file, char *result_str )
 {
-    x509_cert   crt;
+    x509_crt   crt;
     char buf[2000];
     int res;
 
-    memset( &crt, 0, sizeof( x509_cert ) );
+    x509_crt_init( &crt );
     memset( buf, 0, 2000 );
 
-    TEST_ASSERT( x509parse_crtfile( &crt, crt_file ) == 0 );
-    res = x509parse_cert_info( buf, 2000, "", &crt );
+    TEST_ASSERT( x509_crt_parse_file( &crt, crt_file ) == 0 );
+    res = x509_crt_info( buf, 2000, "", &crt );
 
-    x509_free( &crt );
+    x509_crt_free( &crt );
 
     TEST_ASSERT( res != -1 );
     TEST_ASSERT( res != -2 );
@@ -52,18 +53,18 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO:POLARSSL_X509_CRL_PARSE_C */
 void x509_crl_info( char *crl_file, char *result_str )
 {
     x509_crl   crl;
     char buf[2000];
     int res;
 
-    memset( &crl, 0, sizeof( x509_crl ) );
+    x509_crl_init( &crl );
     memset( buf, 0, 2000 );
 
-    TEST_ASSERT( x509parse_crlfile( &crl, crl_file ) == 0 );
-    res = x509parse_crl_info( buf, 2000, "", &crl );
+    TEST_ASSERT( x509_crl_parse_file( &crl, crl_file ) == 0 );
+    res = x509_crl_info( buf, 2000, "", &crl );
 
     x509_crl_free( &crl );
 
@@ -74,22 +75,22 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO:POLARSSL_X509_CRT_PARSE_C */
 void x509_verify( char *crt_file, char *ca_file, char *crl_file,
                   char *cn_name_str, int result, int flags_result,
                   char *verify_callback )
 {
-    x509_cert   crt;
-    x509_cert   ca;
+    x509_crt   crt;
+    x509_crt   ca;
     x509_crl    crl;
     int         flags = 0;
     int         res;
-    int (*f_vrfy)(void *, x509_cert *, int, int *) = NULL;
+    int (*f_vrfy)(void *, x509_crt *, int, int *) = NULL;
     char *      cn_name = NULL;
 
-    memset( &crt, 0, sizeof( x509_cert ) );
-    memset( &ca, 0, sizeof( x509_cert ) );
-    memset( &crl, 0, sizeof( x509_crl ) );
+    x509_crt_init( &crt );
+    x509_crt_init( &ca );
+    x509_crl_init( &crl );
 
     if( strcmp( cn_name_str, "NULL" ) != 0 )
         cn_name = cn_name_str;
@@ -103,14 +104,14 @@
     else
         TEST_ASSERT( "No known verify callback selected" == 0 );
 
-    TEST_ASSERT( x509parse_crtfile( &crt, crt_file ) == 0 );
-    TEST_ASSERT( x509parse_crtfile( &ca, ca_file ) == 0 );
-    TEST_ASSERT( x509parse_crlfile( &crl, crl_file ) == 0 );
+    TEST_ASSERT( x509_crt_parse_file( &crt, crt_file ) == 0 );
+    TEST_ASSERT( x509_crt_parse_file( &ca, ca_file ) == 0 );
+    TEST_ASSERT( x509_crl_parse_file( &crl, crl_file ) == 0 );
 
-    res = x509parse_verify( &crt, &ca, &crl, cn_name, &flags, f_vrfy, NULL );
+    res = x509_crt_verify( &crt, &ca, &crl, cn_name, &flags, f_vrfy, NULL );
 
-    x509_free( &crt );
-    x509_free( &ca );
+    x509_crt_free( &crt );
+    x509_crt_free( &ca );
     x509_crl_free( &crl );
 
     TEST_ASSERT( res == ( result ) );
@@ -118,25 +119,25 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO:POLARSSL_X509_USE_C */
 void x509_dn_gets( char *crt_file, char *entity, char *result_str )
 {
-    x509_cert   crt;
+    x509_crt   crt;
     char buf[2000];
     int res = 0;
 
-    memset( &crt, 0, sizeof( x509_cert ) );
+    x509_crt_init( &crt );
     memset( buf, 0, 2000 );
 
-    TEST_ASSERT( x509parse_crtfile( &crt, crt_file ) == 0 );
+    TEST_ASSERT( x509_crt_parse_file( &crt, crt_file ) == 0 );
     if( strcmp( entity, "subject" ) == 0 )
-        res =  x509parse_dn_gets( buf, 2000, &crt.subject );
+        res =  x509_dn_gets( buf, 2000, &crt.subject );
     else if( strcmp( entity, "issuer" ) == 0 )
-        res =  x509parse_dn_gets( buf, 2000, &crt.issuer );
+        res =  x509_dn_gets( buf, 2000, &crt.issuer );
     else
         TEST_ASSERT( "Unknown entity" == 0 );
 
-    x509_free( &crt );
+    x509_crt_free( &crt );
 
     TEST_ASSERT( res != -1 );
     TEST_ASSERT( res != -2 );
@@ -145,138 +146,44 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO:POLARSSL_X509_USE_C */
 void x509_time_expired( char *crt_file, char *entity, int result )
 {
-    x509_cert   crt;
+    x509_crt   crt;
 
-    memset( &crt, 0, sizeof( x509_cert ) );
+    x509_crt_init( &crt );
 
-    TEST_ASSERT( x509parse_crtfile( &crt, crt_file ) == 0 );
+    TEST_ASSERT( x509_crt_parse_file( &crt, crt_file ) == 0 );
 
     if( strcmp( entity, "valid_from" ) == 0 )
-        TEST_ASSERT( x509parse_time_expired( &crt.valid_from ) == result );
+        TEST_ASSERT( x509_time_expired( &crt.valid_from ) == result );
     else if( strcmp( entity, "valid_to" ) == 0 )
-        TEST_ASSERT( x509parse_time_expired( &crt.valid_to ) == result );
+        TEST_ASSERT( x509_time_expired( &crt.valid_to ) == result );
     else
         TEST_ASSERT( "Unknown entity" == 0 );
 
-    x509_free( &crt );
+    x509_crt_free( &crt );
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
-void x509parse_keyfile_rsa( char *key_file, char *password, int result )
-{
-    rsa_context rsa;
-    int res;
-    char *pwd = password;
-
-    memset( &rsa, 0, sizeof( rsa_context ) );
-
-    if( strcmp( pwd, "NULL" ) == 0 )
-        pwd = NULL;
-
-    res = x509parse_keyfile_rsa( &rsa, key_file, pwd );
-
-    TEST_ASSERT( res == result );
-
-    if( res == 0 )
-    {
-        TEST_ASSERT( rsa_check_privkey( &rsa ) == 0 );
-    }
-
-    rsa_free( &rsa );
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
-void x509parse_public_keyfile_rsa( char *key_file, int result )
-{
-    rsa_context rsa;
-    int res;
-
-    memset( &rsa, 0, sizeof( rsa_context ) );
-
-    res = x509parse_public_keyfile_rsa( &rsa, key_file );
-
-    TEST_ASSERT( res == result );
-
-    if( res == 0 )
-    {
-        TEST_ASSERT( rsa_check_pubkey( &rsa ) == 0 );
-    }
-
-    rsa_free( &rsa );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void x509parse_public_keyfile_ec( char *key_file, int result )
-{
-    pk_context ctx;
-    int res;
-
-    pk_init( &ctx );
-
-    res = x509parse_public_keyfile( &ctx, key_file );
-
-    TEST_ASSERT( res == result );
-
-    if( res == 0 )
-    {
-        ecp_keypair *eckey;
-        TEST_ASSERT( pk_can_do( &ctx, POLARSSL_PK_ECKEY ) );
-        eckey = pk_ec( ctx );
-        TEST_ASSERT( ecp_check_pubkey( &eckey->grp, &eckey->Q ) == 0 );
-    }
-
-    pk_free( &ctx );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void x509parse_keyfile_ec( char *key_file, char *password, int result )
-{
-    pk_context ctx;
-    int res;
-
-    pk_init( &ctx );
-
-    res = x509parse_keyfile( &ctx, key_file, password );
-
-    TEST_ASSERT( res == result );
-
-    if( res == 0 )
-    {
-        ecp_keypair *eckey;
-        TEST_ASSERT( pk_can_do( &ctx, POLARSSL_PK_ECKEY ) );
-        eckey = pk_ec( ctx );
-        TEST_ASSERT( ecp_check_privkey( &eckey->grp, &eckey->d ) == 0 );
-    }
-
-    pk_free( &ctx );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_X509_CRT_PARSE_C */
 void x509parse_crt( char *crt_data, char *result_str, int result )
 {
-    x509_cert   crt;
+    x509_crt   crt;
     unsigned char buf[2000];
     unsigned char output[2000];
     int data_len, res;
 
-    memset( &crt, 0, sizeof( x509_cert ) );
+    x509_crt_init( &crt );
     memset( buf, 0, 2000 );
     memset( output, 0, 2000 );
 
     data_len = unhexify( buf, crt_data );
 
-    TEST_ASSERT( x509parse_crt( &crt, buf, data_len ) == ( result ) );
+    TEST_ASSERT( x509_crt_parse( &crt, buf, data_len ) == ( result ) );
     if( ( result ) == 0 )
     {
-        res = x509parse_cert_info( (char *) output, 2000, "", &crt );
+        res = x509_crt_info( (char *) output, 2000, "", &crt );
 
         TEST_ASSERT( res != -1 );
         TEST_ASSERT( res != -2 );
@@ -284,11 +191,11 @@
         TEST_ASSERT( strcmp( (char *) output, result_str ) == 0 );
     }
 
-    x509_free( &crt );
+    x509_crt_free( &crt );
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_X509_CRL_PARSE_C */
 void x509parse_crl( char *crl_data, char *result_str, int result )
 {
     x509_crl   crl;
@@ -296,16 +203,16 @@
     unsigned char output[2000];
     int data_len, res;
 
-    memset( &crl, 0, sizeof( x509_crl ) );
+    x509_crl_init( &crl );
     memset( buf, 0, 2000 );
     memset( output, 0, 2000 );
 
     data_len = unhexify( buf, crl_data );
 
-    TEST_ASSERT( x509parse_crl( &crl, buf, data_len ) == ( result ) );
+    TEST_ASSERT( x509_crl_parse( &crl, buf, data_len ) == ( result ) );
     if( ( result ) == 0 )
     {
-        res = x509parse_crl_info( (char *) output, 2000, "", &crl );
+        res = x509_crl_info( (char *) output, 2000, "", &crl );
 
         TEST_ASSERT( res != -1 );
         TEST_ASSERT( res != -2 );
@@ -317,32 +224,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
-void x509parse_key_rsa( char *key_data, char *result_str, int result )
-{
-    rsa_context   rsa;
-    unsigned char buf[2000];
-    unsigned char output[2000];
-    int data_len;
-    ((void) result_str);
-
-    memset( &rsa, 0, sizeof( rsa_context ) );
-    memset( buf, 0, 2000 );
-    memset( output, 0, 2000 );
-
-    data_len = unhexify( buf, key_data );
-
-    TEST_ASSERT( x509parse_key_rsa( &rsa, buf, data_len, NULL, 0 ) == ( result ) );
-    if( ( result ) == 0 )
-    {
-        TEST_ASSERT( 1 );
-    }
-
-    rsa_free( &rsa );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_X509_CRT_PARSE_C */
 void x509_selftest()
 {
     TEST_ASSERT( x509_self_test( 0 ) == 0 );
diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data
index dcb137a..1b2754e 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -29,19 +29,3 @@
 Certificate write check Server1 SHA1
 depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_DES_C:POLARSSL_CIPHER_MODE_CBC:POLARSSL_MD5_C
 x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":POLARSSL_MD_SHA1:"data_files/server1.crt"
-
-Public key write check RSA
-depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C
-x509_pubkey_check:"data_files/server1.pubkey"
-
-Public key write check EC
-depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
-x509_pubkey_check:"data_files/ec_pub.pem"
-
-Private key write check RSA
-depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C
-x509_key_check:"data_files/server1.key"
-
-Private key write check EC
-depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
-x509_key_check:"data_files/ec_prv.sec1.pem"
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index 9352c9e..32336178 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -1,27 +1,25 @@
 /* BEGIN_HEADER */
-#include <polarssl/x509write.h>
-#include <polarssl/x509.h>
+#include <polarssl/x509_crt.h>
+#include <polarssl/x509_csr.h>
 #include <polarssl/pem.h>
 #include <polarssl/oid.h>
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
- * depends_on:POLARSSL_X509_WRITE_C:POLARSSL_BIGNUM_C
+ * depends_on:POLARSSL_BIGNUM_C:POLARSSL_FS_IO:POLARSSL_PK_PARSE_C
  * END_DEPENDENCIES
  */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_PEM_WRITE_C:POLARSSL_X509_CSR_WRITE_C */
 void x509_csr_check( char *key_file, int md_type,
                           char *cert_req_check_file )
 {
     pk_context key;
-    pem_context pem;
     x509write_csr req;
-    unsigned char *c;
     unsigned char buf[4000];
     unsigned char check_buf[4000];
     int ret;
-    size_t olen = sizeof( check_buf );
+    size_t olen = 0, pem_len = 0;
     FILE *f;
     char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
     rnd_pseudo_info rnd_info;
@@ -29,37 +27,33 @@
     memset( &rnd_info, 0x2a, sizeof( rnd_pseudo_info ) );
 
     pk_init( &key );
-    TEST_ASSERT( x509parse_keyfile( &key, key_file, NULL ) == 0 );
+    TEST_ASSERT( pk_parse_keyfile( &key, key_file, NULL ) == 0 );
 
     x509write_csr_init( &req );
     x509write_csr_set_md_alg( &req, md_type );
     x509write_csr_set_key( &req, &key );
     TEST_ASSERT( x509write_csr_set_subject_name( &req, subject_name ) == 0 );
 
-    ret = x509write_csr_der( &req, buf, sizeof( buf ),
+    ret = x509write_csr_pem( &req, buf, sizeof(buf),
                              rnd_pseudo_rand, &rnd_info );
-    TEST_ASSERT( ret >= 0 );
+    TEST_ASSERT( ret == 0 );
 
-    c = buf + sizeof( buf ) - ret;
+    pem_len = strlen( (char *) buf );
 
     f = fopen( cert_req_check_file, "r" );
     TEST_ASSERT( f != NULL );
-    fread( check_buf, 1, sizeof( check_buf ), f );
+    olen = fread( check_buf, 1, sizeof( check_buf ), f );
     fclose( f );
 
-    pem_init( &pem );
-    pem_read_buffer( &pem, "-----BEGIN CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----", check_buf, NULL, 0, &olen );
-
-    TEST_ASSERT( pem.buflen == (size_t) ret );
-    TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 );
+    TEST_ASSERT( olen >= pem_len - 1 );
+    TEST_ASSERT( memcmp( buf, check_buf, pem_len - 1 ) == 0 );
 
     x509write_csr_free( &req );
-    pem_free( &pem );
     pk_free( &key );
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_PEM_WRITE_C:POLARSSL_X509_CRT_WRITE_C */
 void x509_crt_check( char *subject_key_file, char *subject_pwd,
                      char *subject_name, char *issuer_key_file,
                      char *issuer_pwd, char *issuer_name,
@@ -67,14 +61,12 @@
                      int md_type, char *cert_check_file )
 {
     pk_context subject_key, issuer_key;
-    pem_context pem;
     x509write_cert crt;
-    unsigned char *c;
     unsigned char buf[4000];
     unsigned char check_buf[5000];
     mpi serial;
     int ret;
-    size_t olen = sizeof( check_buf );
+    size_t olen = 0, pem_len = 0;
     FILE *f;
     rnd_pseudo_info rnd_info;
 
@@ -83,9 +75,9 @@
     pk_init( &subject_key );
     pk_init( &issuer_key );
 
-    TEST_ASSERT( x509parse_keyfile( &subject_key, subject_key_file,
+    TEST_ASSERT( pk_parse_keyfile( &subject_key, subject_key_file,
                                          subject_pwd ) == 0 );
-    TEST_ASSERT( x509parse_keyfile( &issuer_key, issuer_key_file,
+    TEST_ASSERT( pk_parse_keyfile( &issuer_key, issuer_key_file,
                                          issuer_pwd ) == 0 );
     TEST_ASSERT( mpi_read_string( &serial, 10, serial_str ) == 0 );
 
@@ -103,85 +95,24 @@
     TEST_ASSERT( x509write_crt_set_subject_key_identifier( &crt ) == 0 );
     TEST_ASSERT( x509write_crt_set_authority_key_identifier( &crt ) == 0 );
 
-    ret = x509write_crt_der( &crt, buf, sizeof(buf),
+    ret = x509write_crt_pem( &crt, buf, sizeof(buf),
                              rnd_pseudo_rand, &rnd_info );
-    TEST_ASSERT( ret >= 0 );
+    TEST_ASSERT( ret == 0 );
 
-    c = buf + sizeof( buf ) - ret;
+    pem_len = strlen( (char *) buf );
 
     f = fopen( cert_check_file, "r" );
     TEST_ASSERT( f != NULL );
-    TEST_ASSERT( fread( check_buf, 1, sizeof(check_buf), f ) < sizeof(check_buf) );
+    TEST_ASSERT( ( olen = fread( check_buf, 1, sizeof(check_buf), f ) ) <
+                 sizeof(check_buf) );
     fclose( f );
 
-    pem_init( &pem );
-    TEST_ASSERT( pem_read_buffer( &pem, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----", check_buf, NULL, 0, &olen ) >= 0 );
-
-    TEST_ASSERT( pem.buflen == (size_t) ret );
-    TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 );
+    TEST_ASSERT( olen >= pem_len - 1 );
+    TEST_ASSERT( memcmp( buf, check_buf, pem_len - 1 ) == 0 );
 
     x509write_crt_free( &crt );
     pk_free( &issuer_key );
     pk_free( &subject_key );
-    pem_free( &pem );
     mpi_free( &serial );
 }
 /* END_CASE */
-
-/* BEGIN_CASE */
-void x509_pubkey_check( char *key_file )
-{
-    pk_context key;
-    unsigned char buf[5000];
-    unsigned char check_buf[5000];
-    int ret;
-    FILE *f;
-
-    memset( buf, 0, sizeof( buf ) );
-    memset( check_buf, 0, sizeof( check_buf ) );
-
-    pk_init( &key );
-    TEST_ASSERT( x509parse_public_keyfile( &key, key_file ) == 0 );
-
-    ret = x509write_pubkey_pem( &key, buf, sizeof( buf ) - 1);
-    TEST_ASSERT( ret >= 0 );
-
-    f = fopen( key_file, "r" );
-    TEST_ASSERT( f != NULL );
-    fread( check_buf, 1, sizeof( check_buf ) - 1, f );
-    fclose( f );
-
-    TEST_ASSERT( strncmp( (char *) buf, (char *) check_buf, sizeof( buf ) ) == 0 );
-
-    pk_free( &key );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void x509_key_check( char *key_file )
-{
-    pk_context key;
-    unsigned char buf[5000];
-    unsigned char check_buf[5000];
-    int ret;
-    FILE *f;
-
-    memset( buf, 0, sizeof( buf ) );
-    memset( check_buf, 0, sizeof( check_buf ) );
-
-    pk_init( &key );
-    TEST_ASSERT( x509parse_keyfile( &key, key_file, NULL ) == 0 );
-
-    ret = x509write_key_pem( &key, buf, sizeof( buf ) - 1);
-    TEST_ASSERT( ret >= 0 );
-
-    f = fopen( key_file, "r" );
-    TEST_ASSERT( f != NULL );
-    fread( check_buf, 1, sizeof( check_buf ) - 1, f );
-    fclose( f );
-
-    TEST_ASSERT( strncmp( (char *) buf, (char *) check_buf, sizeof( buf ) ) == 0 );
-
-    pk_free( &key );
-}
-/* END_CASE */