Index: CHANGELOG
===================================================================
--- CHANGELOG	(revision 4461)
+++ CHANGELOG	(working copy)
@@ -147,6 +147,7 @@
     * libpcap 1.0.0
     * libpng 1.2.42
     * libpopt 1.15
+    * libpolarssl 0.12.1
     * liblzo 2.03
     * libneon 0.29.3
     * linux-atm 2.5.0
Index: make/libs/Makefile.in
===================================================================
--- make/libs/Makefile.in	(revision 4461)
+++ make/libs/Makefile.in	(working copy)
@@ -105,6 +105,10 @@
 LIBS+=xyssl
 endif
 
+ifeq ($(strip $(FREETZ_LIB_libpolarssl)),y)
+LIBS+=polarssl
+endif
+
 ifeq ($(strip $(FREETZ_LIB_libusb)),y)
 LIBS+=libusb
 endif
Index: make/libs/patches/020-shared.polarssl.patch
===================================================================
--- make/libs/patches/020-shared.polarssl.patch	(revision 0)
+++ make/libs/patches/020-shared.polarssl.patch	(revision 0)
@@ -0,0 +1,37 @@
+--- library/Makefile
++++ library/Makefile
+@@ -17,6 +17,11 @@
+ # OSX shared library extension:
+ # DLEXT=dylib
+ 
++VERSION=0.12.1
++LIB_SO=libpolarssl.$(DLEXT)
++LIB_SO_VERSION=$(LIB_SO).$(VERSION)
++LIB_SO_MAJOR=$(LIB_SO).$(firstword $(subst ., ,$(VERSION)))
++
+ OBJS=	aes.o		arc4.o		base64.o	\
+ 	bignum.o	certs.o		debug.o		\
+ 	des.o		dhm.o		havege.o	\
+@@ -33,7 +38,7 @@
+ 
+ static: libpolarssl.a
+ 
+-shared: libpolarssl.$(DLEXT)
++shared: $(LIB_SO_VERSION)
+ 
+ libpolarssl.a: $(OBJS)
+ 	echo "  AR    $@"
+@@ -41,9 +46,11 @@
+ 	echo "  RL    $@"
+ 	ranlib $@
+ 
+-libpolarssl.so: libpolarssl.a
++$(LIB_SO_VERSION): $(OBJS)
+ 	echo "  LD    $@"
+-	$(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS)
++	$(CC) -shared -Wl,-soname,$(LIB_SO_MAJOR) -o $@ $(OBJS) \
++	&& ln -fs $@ $(LIB_SO_MAJOR) \
++	&& ln -fs $(LIB_SO_MAJOR) $(LIB_SO)
+ 
+ libpolarssl.dylib: libpolarssl.a
+ 	echo "  LD    $@"
Index: make/libs/patches/030-do_not_omit_last_cert_in_chain.polarssl.patch
===================================================================
--- make/libs/patches/030-do_not_omit_last_cert_in_chain.polarssl.patch	(revision 0)
+++ make/libs/patches/030-do_not_omit_last_cert_in_chain.polarssl.patch	(revision 0)
@@ -0,0 +1,33 @@
+--- library/debug.c
++++ library/debug.c
+@@ -182,7 +182,7 @@
+     prefix[maxlen] = '\0';
+     maxlen = sizeof( str ) - 1;
+ 
+-    while( crt != NULL && crt->next != NULL )
++    while( crt != NULL )
+     {
+         char buf[1024];
+         x509parse_cert_info( buf, sizeof( buf ) - 1, prefix, crt );
+--- library/ssl_srv.c
++++ library/ssl_srv.c
+@@ -485,7 +485,7 @@
+     p += 2;
+     crt = ssl->ca_chain;
+ 
+-    while( crt != NULL && crt->next != NULL )
++    while( crt != NULL )
+     {
+         if( p - buf > 4096 )
+             break;
+--- library/ssl_tls.c
++++ library/ssl_tls.c
+@@ -1160,7 +1160,7 @@
+     i = 7;
+     crt = ssl->own_cert;
+ 
+-    while( crt != NULL && crt->next != NULL )
++    while( crt != NULL )
+     {
+         n = crt->raw.len;
+         if( i + 3 + n > SSL_MAX_CONTENT_LEN )
Index: make/libs/patches/010-config.polarssl.patch
===================================================================
--- make/libs/patches/010-config.polarssl.patch	(revision 0)
+++ make/libs/patches/010-config.polarssl.patch	(revision 0)
@@ -0,0 +1,35 @@
+--- include/polarssl/config.h
++++ include/polarssl/config.h
+@@ -71,12 +71,12 @@
+ /*
+  * Enable all SSL/TLS debugging messages.
+  */
+-#define POLARSSL_DEBUG_MSG
++/* #define POLARSSL_DEBUG_MSG */
+ 
+ /*
+  * Enable the checkup functions (*_self_test).
+  */
+-#define POLARSSL_SELF_TEST
++/* #define POLARSSL_SELF_TEST */
+ 
+ /*
+  * Enable the prime-number generation code.
+@@ -156,7 +156,7 @@
+  *
+  * This module provides debugging functions.
+  */
+-#define POLARSSL_DEBUG_C
++/* #define POLARSSL_DEBUG_C */
+ 
+ /*
+  * Module:  library/des.c
+@@ -229,7 +229,7 @@
+  *
+  * This modules adds support for the VIA PadLock on x86.
+  */
+-#define POLARSSL_PADLOCK_C
++/* #define POLARSSL_PADLOCK_C */
+ 
+ /*
+  * Module:  library/rsa.c
Index: make/libs/patches/001-x509write.polarssl.patch
===================================================================
--- make/libs/patches/001-x509write.polarssl.patch	(revision 0)
+++ make/libs/patches/001-x509write.polarssl.patch	(revision 0)
@@ -0,0 +1,1381 @@
+--- include/polarssl/x509.h
++++ include/polarssl/x509.h
+@@ -429,6 +429,229 @@
+  */
+ int x509_self_test( int verbose );
+ 
++/**
++ * \brief          Write a certificate info file
++ *
++ * \param chain    points to the raw certificate data
++ * \param path     filename to write the certificate to
++ * \param format   X509_OUTPUT_DER or X509_OUTPUT_PEM
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_crtfile( x509_raw *chain,
++                       unsigned char *path,
++                       int format );
++
++/**
++ * \brief          Write a certificate signing request message format file
++ *
++ * \param chain    points to the raw certificate (with x509write_create_csr) data
++ * \param path     filename to write the certificate to
++ * \param format   X509_OUTPUT_DER or X509_OUTPUT_PEM
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_csrfile( x509_raw *chain,
++                       unsigned char *path,
++                       int format );
++
++/*
++ * \brief          Write a private RSA key into a file
++ *
++ * \param rsa      points to an RSA key
++ * \param path     filename to write the key to
++ * \param format   X509_OUTPUT_DER or X509_OUTPUT_PEM
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_keyfile( rsa_context *rsa,
++                       char *path,
++                       int format );
++
++/**
++ * \brief          Add a public key to certificate
++ *
++ * \param chain    points to the raw certificate data
++ * \param pubkey   points to an RSA key
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_add_pubkey( x509_raw *chain, rsa_context *pubkey );
++
++/**
++ * \brief          Create x509 subject/issuer field to raw certificate
++ *                 from string or CA cert. Make string NULL if you will
++ *                 use the CA copy function or make CA NULL then used
++ *                 the string parse.
++ *
++ * \param chain    points to the raw certificate data
++ * \param names    a string that can hold (separete with ";"):
++ *                     CN=CommonName
++ *                 --   O=Organization
++ *                 --  OU=OrgUnit
++ *                 --  ST=State
++ *                 --   L=Locality
++ *                 --   R=Email
++ *                 --   C=Country
++ *                 . Make that NULL if you didn't need that.
++ * \param flag     flag is X509_ISSUER or X509_SUBJECT that defined
++ *                 where change
++ * \param ca       the certificate for copy data. Make that NULL if you
++ *                 didn't need that.
++ * \param ca_flag  set the ca field from copy to crt
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_add_customize ( x509_raw *crt,
++                          unsigned char *names,
++                          int flag,
++                          x509_cert *ca,
++                          int ca_flag );
++
++/**
++* \brief          Add x509 issuer field
++*
++* \param chain    points to the raw certificate data
++* \param issuer   a string holding (separete with ";"):
++*                     CN=CommonName
++*                 --   O=Organization
++*                 --  OU=OrgUnit
++*                 --  ST=State
++*                 --   L=Locality
++*                 --   R=Email
++*                 --   C=Country
++*                 . Set this to NULL if not needed.
++* \return         0 if successful, or a specific X509 error code
++*/
++int x509write_add_issuer( x509_raw *crt, unsigned char *issuer);
++
++/**
++ * \brief          Add x509 subject field
++ *
++ * \param chain    points to the raw certificate data
++ * \param subject  a string holding (separete with ";"):
++ *                     CN=CommonName
++ *                 --   O=Organization
++ *                 --  OU=OrgUnit
++ *                 --  ST=State
++ *                 --   L=Locality
++ *                 --   R=Email
++ *                 --   C=Country
++ *                 . Set this to NULL if not needed.
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_add_subject( x509_raw *crt, unsigned char *subject);
++
++/**
++* \brief          Copy x509 issuer field from another certificate
++*
++* \param chain    points to the raw certificate data
++* \param from_crt the certificate whose issuer is to be copied.
++* \return         0 if successful, or a specific X509 error code
++*/
++int x509write_copy_issuer(x509_raw *crt, x509_cert *from_crt);
++
++/**
++* \brief          Copy x509 subject field from another certificate
++*
++* \param chain    points to the raw certificate data
++* \param from_crt the certificate whose subject is to be copied.
++* \return         0 if successful, or a specific X509 error code
++*/
++int x509write_copy_subject(x509_raw *crt, x509_cert *from_crt);
++
++/**
++* \brief          Copy x509 issuer field from the subject of another certificate
++*
++* \param chain    points to the raw certificate data
++* \param from_crt the certificate whose subject is to be copied.
++* \return         0 if successful, or a specific X509 error code
++*/
++int x509write_copy_issuer_from_subject(x509_raw *crt, x509_cert *from_crt);
++
++/**
++* \brief          Copy x509 subject field from the issuer of another certificate
++*
++* \param chain    points to the raw certificate data
++* \param from_crt the certificate whose issuer is to be copied.
++* \return         0 if successful, or a specific X509 error code
++*/
++int x509write_copy_subject_from_issuer(x509_raw *crt, x509_cert *from_crt);
++
++/**
++ * \brief          Create x509 validity time in UTC
++ *
++ * \param chain    points to the raw certificate data
++ * \param before   valid not before in format YYYY-MM-DD hh:mm:ss
++ * \param after    valid not after  in format YYYY-MM-DD hh:mm:ss
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_add_validity( x509_raw *crt,
++                               unsigned char *before,
++                               unsigned char *after );
++
++/**
++ * \brief          Create a self-signed certificate
++ *
++ * \param chain    points to the raw certificate data
++ * \param rsa      a private key to sign the certificate
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_create_selfsign( x509_raw *crt, rsa_context *raw );
++
++/**
++ * \brief          Create a certificate
++ *
++ * \param chain    points to the raw certificate data
++ * \param rsa      a private key to sign the certificate
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_create_sign( x509_raw *crt, rsa_context *raw );
++
++/**
++ * \brief          Create a certificate signing request
++ *
++ * \param chain    points to the raw certificate data. Didn't use the
++ *                 same chain that u have use for certificate.
++ * \param privkey  a rsa private key
++ *
++ * \return         0 if successful, or a specific X509 error code
++ */
++int x509write_create_csr( x509_raw *chain, rsa_context *privkey );
++
++/**
++ * \brief           Serialize an rsa key into DER
++ *
++ * \param rsa       a rsa key for output
++ * \param node      a x509 node for write into
++ *
++ * \return          0 if successful, or a specific X509 error code
++ */
++int x509write_serialize_key( rsa_context *rsa, x509_node *node );
++
++/**
++ * \brief          Unallocate all raw certificate data
++ */
++void x509write_free_raw( x509_raw *crt );
++
++/**
++ * \brief          Allocate all raw certificate data
++ */
++void x509write_init_raw( x509_raw *crt );
++
++/**
++ * \brief          Unallocate all node certificate data
++ */
++void x509write_free_node( x509_node *crt_node );
++
++/**
++ * \brief          Allocate all node certificate data
++ */
++void x509write_init_node( x509_node *crt_node );
++
+ #ifdef __cplusplus
+ }
+ #endif
+--- library/Makefile
++++ library/Makefile
+@@ -25,7 +25,7 @@
+ 	sha1.o		sha2.o		sha4.o		\
+ 	ssl_cli.o	ssl_srv.o	ssl_tls.o	\
+ 	timing.o	x509parse.o	xtea.o		\
+-	camellia.o
++	camellia.o	x509write.o
+ 
+ .SILENT:
+ 
+--- library/x509write.c
++++ library/x509write.c
+@@ -0,0 +1,1135 @@
++/*
++ *  X.509 certificate and private key writing
++ *
++ *  Copyright (C) 2006-2007  Pascal Vizeli <pvizeli@yahoo.de>
++ *  Modifications (C) 2009 Steven Barth <steven@midlink.org>
++ *
++ *  This library is free software; you can redistribute it and/or
++ *  modify it under the terms of the GNU Lesser General Public
++ *  License, version 2.1 as published by the Free Software Foundation.
++ *
++ *  This library 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
++ *  Lesser General Public License for more details.
++ *
++ *  You should have received a copy of the GNU Lesser General Public
++ *  License along with this library; 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 certificat format for PKI.
++ *
++ *  http://www.ietf.org/rfc/rfc2459.txt
++ *  http://www.ietf.org/rfc/rfc3279.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
++ *
++ *  For CRS:
++ *  http://www.faqs.org/rfcs/rfc2314.html
++ */
++#include "polarssl/config.h"
++#include "polarssl/x509.h"
++#include "polarssl/base64.h"
++#include "polarssl/sha1.h"
++
++#include <string.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <stdarg.h>
++#include <time.h>
++
++#define and &&
++#define or ||
++
++#if defined _MSC_VER && !defined snprintf
++#define snprintf _snprintf
++#endif
++
++static int x509write_realloc_node(x509_node *node, size_t larger);
++static int x509write_file(x509_node *node, char *path, int format, const char* pem_prolog, const char* pem_epilog);
++
++/*
++ * evaluate how mani octet have this integer
++ */
++static int asn1_eval_octet(unsigned int digit)
++{
++    int i, byte;
++
++    for (byte = 4, i = 24; i >= 0; i -= 8, --byte)
++        if (((digit >> i) & 0xFF) != 0)
++            return byte;
++
++    return 0;
++}
++
++/*
++ * write the asn.1 lenght form into p
++ */
++static int asn1_add_len(unsigned int size, x509_node *node)
++{
++    if (size > 127) {
++
++        /* long size */
++        int byte = asn1_eval_octet(size);
++        int i = 0;
++
++        *(node->p) = (0x80 | byte) & 0xFF;
++        ++node->p;
++
++        for (i = byte; i > 0; --i) {
++
++            *(node->p) = (size >> ((i - 1) * 8)) & 0xFF;
++            ++node->p;
++        }
++
++    } else {
++
++        /* short size */
++        *(node->p) = size & 0xFF;
++        if (size != 0)
++            ++node->p;
++    }
++
++    return 0;
++}
++
++/*
++ * write a ans.1 object into p
++ */
++static int asn1_add_obj(unsigned char *value, unsigned int size, int tag,
++        x509_node *node)
++{
++    int tl = 2;
++
++    if (tag == ASN1_BIT_STRING)
++        ++tl;
++
++    if (size > 127)
++        x509write_realloc_node(node, (size_t) size + tl +
++                asn1_eval_octet(size));
++    else
++        x509write_realloc_node(node, (size_t) size + tl);
++
++    if (node->data == NULL)
++        return 1;
++
++    /* tag */
++    *(node->p) = tag & 0xFF;
++    ++node->p;
++
++    /* len */
++    if (tag == ASN1_BIT_STRING) {
++        asn1_add_len((unsigned int) size + 1, node);
++        *(node->p) = 0x00;
++        ++node->p;
++    } else {
++        asn1_add_len((unsigned int) size, node);
++    }
++
++    /* value */
++    if (size > 0) {
++
++        memcpy(node->p, value, (size_t) size);
++        if ((node->p += size -1) != node->end)
++            return POLARSSL_ERR_X509_POINT_ERROR;
++    } else {
++        /* make nothing -> NULL */
++    }
++
++    return 0;
++}
++
++/*
++ * write a asn.1 conform integer object
++ */
++static int asn1_add_int(signed int value, x509_node *node)
++{
++    signed int i = 0, neg = 1;
++    unsigned int byte, u_val = 0, tmp_val = 0;
++
++    /* if negate? */
++    if (value < 0) {
++        neg = -1;
++        u_val = ~value;
++    } else {
++        u_val = value;
++    }
++
++    byte = asn1_eval_octet(u_val);
++    /* 0 isn't NULL */
++    if (byte == 0)
++        byte = 1;
++
++    /* ASN.1 integer is signed! */
++    if (byte < 4 and ((u_val >> ((byte -1) * 8)) & 0xFF) == 0x80)
++        byte += 1;
++
++    if (x509write_realloc_node(node, (size_t) byte + 2) != 0)
++        return 1;
++
++    /* tag */
++    *(node->p) = ASN1_INTEGER;
++    ++node->p;
++
++    /* len */
++    asn1_add_len(byte, node);
++
++    /* value */
++    for (i = byte; i > 0; --i) {
++
++        tmp_val = (u_val >> ((i - 1) * 8)) & 0xFF;
++        if (neg == 1)
++            *(node->p) = tmp_val;
++        else
++            *(node->p) = ~tmp_val;
++
++        if (i > 1)
++          ++node->p;
++    }
++
++    if (node->p != node->end)
++        return POLARSSL_ERR_X509_POINT_ERROR;
++
++    return 0;
++}
++
++/*
++ * write a asn.1 conform mpi object
++ */
++static int asn1_add_mpi(mpi *value, int tag, x509_node *node)
++{
++    size_t size = (mpi_msb(value) / 8) + 1;
++    unsigned char *buf;
++    int buf_len = (int) size, tl = 2;
++
++    if (tag == ASN1_BIT_STRING)
++        ++tl;
++
++    if (size > 127)
++        x509write_realloc_node(node, size + (size_t) tl +
++            asn1_eval_octet((unsigned int)size));
++    else
++        x509write_realloc_node(node, size + (size_t) tl);
++
++    if (node->data == NULL)
++        return 1;
++
++    buf = (unsigned char*) malloc(size);
++    if (mpi_write_binary(value, buf, buf_len) != 0)
++        return POLARSSL_ERR_MPI_BUFFER_TOO_SMALL;
++
++    /* tag */
++    *(node->p) = tag & 0xFF;
++    ++node->p;
++
++    /* len */
++    if (tag == ASN1_BIT_STRING) {
++        asn1_add_len((unsigned int) size + 1, node);
++        *(node->p) = 0x00;
++        ++node->p;
++    } else {
++        asn1_add_len((unsigned int) size, node);
++    }
++
++    /* value */
++    memcpy(node->p, buf, size);
++    free(buf);
++
++    if ((node->p += (int) size -1) != node->end)
++        return POLARSSL_ERR_X509_POINT_ERROR;
++
++    return 0;
++}
++
++/*
++ * write a node into asn.1 conform object
++ */
++static int asn1_append_tag(x509_node *node, int tag)
++{
++    int tl = 2;
++
++    x509_node tmp;
++    x509write_init_node(&tmp);
++
++    if (tag == ASN1_BIT_STRING)
++        ++tl;
++
++    if (node->len > 127)
++        x509write_realloc_node(&tmp, node->len + (size_t) tl +
++            asn1_eval_octet((unsigned int)node->len));
++    else
++        x509write_realloc_node(&tmp, node->len + (size_t) tl);
++
++    if (tmp.data == NULL) {
++        x509write_free_node(&tmp);
++        return 1;
++    }
++
++    /* tag */
++    *(tmp.p) = tag & 0xFF;
++    ++tmp.p;
++
++    /* len */
++    if (tag == ASN1_BIT_STRING) {
++        asn1_add_len((unsigned int) node->len + 1, &tmp);
++        *(tmp.p) = 0x00;
++        ++tmp.p;
++    } else {
++        asn1_add_len((unsigned int) node->len, &tmp);
++    }
++
++    /* value */
++    memcpy(tmp.p, node->data, node->len);
++
++    /* good? */
++    if ((tmp.p += (int) node->len -1) != tmp.end) {
++        x509write_free_node(&tmp);
++        return POLARSSL_ERR_X509_POINT_ERROR;
++    }
++
++    free(node->data);
++    node->data = tmp.data;
++    node->p = tmp.p;
++    node->end = tmp.end;
++    node->len = tmp.len;
++
++    return 0;
++}
++
++/*
++ * write nodes into a asn.1 object
++ */
++static int asn1_append_nodes(x509_node *node, int tag, int anz, ...)
++{
++    va_list ap;
++    size_t size = 0;
++    x509_node *tmp;
++    int count;
++
++    va_start(ap, anz);
++    count = anz;
++
++    while (count--) {
++
++        tmp = va_arg(ap, x509_node*);
++        if (tmp->data != NULL)
++            size += tmp->len;
++    }
++
++    if ( size > 127) {
++        if (x509write_realloc_node(node, size + (size_t) 2 +
++                    asn1_eval_octet(size)) != 0)
++            return 1;
++    } else {
++        if (x509write_realloc_node(node, size + (size_t) 2) != 0)
++            return 1;
++    }
++
++    /* tag */
++    *(node->p) = tag & 0xFF;
++    ++node->p;
++
++    /* len */
++    asn1_add_len(size, node);
++
++    /* value */
++    va_start(ap, anz);
++    count = anz;
++
++    while (count--) {
++
++        tmp = va_arg(ap, x509_node*);
++        if (tmp->data != NULL) {
++
++            memcpy(node->p, tmp->data, tmp->len);
++            if ((node->p += (int) tmp->len -1) != node->end)
++                ++node->p;
++        }
++    }
++
++    va_end(ap);
++    return 0;
++}
++
++/*
++ * write a ASN.1 conform object identifiere include a "tag"
++ */
++static int asn1_add_oid(x509_node *node, unsigned char *oid, size_t len,
++        int tag, int tag_val, unsigned char *value, size_t val_len)
++{
++    int ret;
++    x509_node tmp;
++
++    x509write_init_node(&tmp);
++
++    /* OBJECT IDENTIFIER */
++    if ((ret = asn1_add_obj(oid, len, ASN1_OID, &tmp)) != 0) {
++        x509write_free_node(&tmp);
++        return ret;
++    }
++
++    /* value */
++    if ((ret = asn1_add_obj(value, val_len, tag_val, &tmp)) != 0) {
++        x509write_free_node(&tmp);
++        return ret;
++    }
++
++    /* SET/SEQUENCE */
++    if ((ret = asn1_append_nodes(node, tag, 1, &tmp)) != 0) {
++        x509write_free_node(&tmp);
++        return ret;
++    }
++
++    x509write_free_node(&tmp);
++    return 0;
++}
++
++/*
++ *  utcTime        UTCTime
++ */
++static int asn1_add_date_utc(unsigned char *time, x509_node *node)
++{
++    unsigned char date[13], *sp;
++    x509_time xtime;
++    int ret;
++
++    sscanf((char*)time, "%d-%d-%d %d:%d:%d", &xtime.year, &xtime.mon,
++    	&xtime.day, &xtime.hour, &xtime.min, &xtime.sec);
++
++    /* convert to YY */
++    if (xtime.year > 2000)
++        xtime.year -= 2000;
++    else
++        xtime.year -= 1900;
++
++    snprintf((char*)date, 13, "%2d%2d%2d%2d%2d%2d", xtime.year, xtime.mon, xtime.day,
++        xtime.hour, xtime.min, xtime.sec);
++
++    /* replace ' ' to '0' */
++    for (sp = date; *sp != '\0'; ++sp)
++        if (*sp == '\x20')
++            *sp = '\x30';
++
++    date[12] = 'Z';
++
++    if ((ret = asn1_add_obj(date, 13, ASN1_UTC_TIME, node)) != 0)
++        return ret;
++
++    return 0;
++}
++
++/*
++ * serialize an rsa key into DER
++ */
++
++int x509write_serialize_key(rsa_context *rsa, x509_node *node)
++{
++    int ret = 0;
++    x509write_init_node(node);
++
++    /* vers, n, e, d, p, q, dp, dq, pq */
++    if ((ret = asn1_add_int(rsa->ver, node)) != 0)
++        return ret;
++    if ((ret = asn1_add_mpi(&rsa->N, ASN1_INTEGER, node)) != 0)
++        return ret;
++    if ((ret = asn1_add_mpi(&rsa->E, ASN1_INTEGER, node)) != 0)
++        return ret;
++    if ((ret = asn1_add_mpi(&rsa->D, ASN1_INTEGER, node)) != 0)
++        return ret;
++    if ((ret = asn1_add_mpi(&rsa->P, ASN1_INTEGER, node)) != 0)
++        return ret;
++    if ((ret = asn1_add_mpi(&rsa->Q, ASN1_INTEGER, node)) != 0)
++        return ret;
++    if ((ret = asn1_add_mpi(&rsa->DP, ASN1_INTEGER, node)) != 0)
++        return ret;
++    if ((ret = asn1_add_mpi(&rsa->DQ, ASN1_INTEGER, node)) != 0)
++        return ret;
++    if ((ret = asn1_add_mpi(&rsa->QP, ASN1_INTEGER, node)) != 0)
++        return ret;
++    if ((ret = asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
++        return ret;
++
++    return 0;
++}
++
++/*
++ * write a der/pem encoded rsa private key into a file
++ */
++int x509write_keyfile(rsa_context *rsa, char *path, int out_flag)
++{
++    int ret = 0;
++    const char	key_beg[] = "-----BEGIN RSA PRIVATE KEY-----\n",
++                key_end[] = "-----END RSA PRIVATE KEY-----\n";
++    x509_node node;
++
++    x509write_init_node(&node);
++    if ((ret = x509write_serialize_key(rsa,&node)) != 0) {
++        x509write_free_node(&node);
++	      return ret;
++    }
++
++    ret = x509write_file(&node,path,out_flag,key_beg,key_end);
++    x509write_free_node(&node);
++
++    return ret;
++}
++
++
++/*
++ * reasize the memory for node
++ */
++static int x509write_realloc_node(x509_node *node, size_t larger)
++{
++    /* init len */
++    if (node->data == NULL) {
++        node->len = 0;
++        node->data = malloc(larger);
++        if(node->data == NULL)
++            return 1;
++    } else {
++        /* realloc memory */
++        if ((node->data = realloc(node->data, node->len + larger)) == NULL)
++            return 1;
++    }
++
++    /* init pointer */
++    node->p = &node->data[node->len];
++    node->len += larger;
++    node->end = &node->data[node->len -1];
++
++    return 0;
++}
++
++/*
++ * init node
++ */
++void x509write_init_node(x509_node *node)
++{
++    memset(node, 0, sizeof(x509_node));
++}
++
++/*
++ * clean memory
++ */
++void x509write_free_node(x509_node *node)
++{
++    if (node->data != NULL)
++        free(node->data);
++    node->p = NULL;
++    node->end = NULL;
++    node->len = 0;
++}
++
++/*
++ * write a x509 certificate into file
++ */
++int x509write_crtfile(x509_raw *chain, unsigned char *path, int out_flag)
++{
++    const char	cer_beg[] = "-----BEGIN CERTIFICATE-----\n",
++		cer_end[] = "-----END CERTIFICATE-----\n";
++
++    return x509write_file(&chain->raw, (char*)path, out_flag, cer_beg, cer_end);
++}
++
++/*
++ * write a x509 certificate into file
++ */
++int x509write_csrfile(x509_raw *chain, unsigned char *path, int out_flag)
++{
++    const char	cer_beg[] = "-----BEGIN CERTIFICATE REQUEST-----\n",
++		cer_end[] = "-----END CERTIFICATE REQUEST-----\n";
++
++    return x509write_file(&chain->raw, (char*)path, out_flag, cer_beg, cer_end);
++}
++
++/*
++ * write an x509 file
++ */
++static int x509write_file(x509_node *node, char *path, int format,
++        const char* pem_prolog, const char* pem_epilog)
++{
++    FILE *ofstream;
++    int is_err = 1, buf_len, i, n;
++    char* base_buf;
++
++    if ((ofstream = fopen(path, "wb")) == NULL)
++        return 1;
++
++    switch (format) {
++        case X509_OUTPUT_DER:
++            if (fwrite(node->data, 1, node->len, ofstream)
++                != node->len)
++                is_err = -1;
++            break;
++        case X509_OUTPUT_PEM:
++            if (fprintf(ofstream,pem_prolog)<0) {
++                is_err = -1;
++                break;
++            }
++
++            buf_len = node->len << 1;
++            base_buf = (char*) malloc((size_t)buf_len);
++            memset(base_buf,0,buf_len);
++            if (base64_encode(base_buf, &buf_len, node->data,
++                        (int) node->len) != 0) {
++                is_err = -1;
++                break;
++            }
++
++            n=strlen(base_buf);
++            for(i=0;i<n;i+=64) {
++                fprintf(ofstream,"%.64s\n",&base_buf[i]);
++            }
++
++            if (fprintf(ofstream, pem_epilog)<0) {
++                is_err = -1;
++                break;
++            }
++
++            free(base_buf);
++    }
++
++    fclose(ofstream);
++
++    if (is_err == -1)
++        return 1;
++
++    return 0;
++}
++
++
++/*
++ * add the owner public key to x509 certificate
++ */
++int x509write_add_pubkey(x509_raw *chain, rsa_context *pubkey)
++{
++    x509_node n_tmp, n_tmp2, *node;
++    int ret;
++
++    node = &chain->subpubkey;
++
++    x509write_init_node(&n_tmp);
++    x509write_init_node(&n_tmp2);
++
++    /*
++    *  RSAPublicKey ::= SEQUENCE {
++    *      modulus           INTEGER,  -- n
++    *      publicExponent    INTEGER   -- e
++    *  }
++    */
++    if ((ret = asn1_add_mpi(&pubkey->N, ASN1_INTEGER, &n_tmp)) != 0) {
++        x509write_free_node(&n_tmp);
++        x509write_free_node(&n_tmp2);
++        return ret;
++    }
++    if ((ret = asn1_add_mpi(&pubkey->E, ASN1_INTEGER, &n_tmp)) != 0) {
++        x509write_free_node(&n_tmp);
++        x509write_free_node(&n_tmp2);
++        return ret;
++    }
++    if ((ret = asn1_append_tag(&n_tmp, ASN1_CONSTRUCTED | ASN1_SEQUENCE))
++            != 0) {
++        x509write_free_node(&n_tmp);
++        x509write_free_node(&n_tmp2);
++        return ret;
++    }
++
++    /*
++     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
++     *       algorithm            AlgorithmIdentifier,
++     *       subjectPublicKey     BIT STRING }
++     */
++    if ((ret = asn1_append_tag(&n_tmp, ASN1_BIT_STRING)) != 0) {
++        x509write_free_node(&n_tmp);
++        x509write_free_node(&n_tmp2);
++       return ret;
++    }
++    if ((ret = asn1_add_oid(&n_tmp2, (unsigned char*)OID_PKCS1_RSA, 9,
++                  ASN1_CONSTRUCTED | ASN1_SEQUENCE, ASN1_NULL,
++                  (unsigned char *)"", 0)) != 0) {
++        x509write_free_node(&n_tmp);
++        x509write_free_node(&n_tmp2);
++        return ret;
++    }
++
++    if ((ret = asn1_append_nodes(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE, 2,
++                   &n_tmp2, &n_tmp))) {
++        x509write_free_node(&n_tmp);
++        x509write_free_node(&n_tmp2);
++        return ret;
++    }
++
++    x509write_free_node(&n_tmp);
++    x509write_free_node(&n_tmp2);
++    return 0;
++}
++
++/*
++ *  RelativeDistinguishedName ::=
++ *    SET OF AttributeTypeAndValue
++ *
++ *  AttributeTypeAndValue ::= SEQUENCE {
++ *    type     AttributeType,
++ *    value    AttributeValue }
++ */
++static int x509write_add_name(x509_node *node, unsigned char *oid,
++        unsigned int oid_len, unsigned char *value, int len, int value_tag)
++{
++    int ret;
++    x509_node n_tmp;
++
++    x509write_init_node(&n_tmp);
++
++    if ((ret = asn1_add_oid(&n_tmp, oid, oid_len,
++                ASN1_CONSTRUCTED | ASN1_SEQUENCE, value_tag,
++                value, len))) {
++        x509write_free_node(&n_tmp);
++        return ret;
++    }
++
++    if ((asn1_append_nodes(node, ASN1_CONSTRUCTED | ASN1_SET, 1, &n_tmp))
++            != 0) {
++        x509write_free_node(&n_tmp);
++        return ret;
++    }
++
++    x509write_free_node(&n_tmp);
++    return 0;
++}
++
++/*
++ * Parse the name string and add to node
++ */
++static int x509write_parse_names(x509_node *node, unsigned char *names)
++{
++    unsigned char *sp, *begin = NULL;
++    unsigned char oid[3] = OID_X520, tag[4], *tag_sp = tag;
++    unsigned char *C = NULL, *CN = NULL, *O = NULL, *OU = NULL,
++                  *ST = NULL, *L = NULL, *R = NULL;
++    int C_len = 0, CN_len = 0, O_len = 0, OU_len = 0, ST_len = 0,
++		L_len = 0, R_len = 0;
++    int ret = 0, is_tag = 1, is_begin = -1, len = 0;
++
++
++    for (sp = names; ; ++sp) {
++
++        /* filter tag */
++        if (is_tag == 1) {
++
++            if (tag_sp == &tag[3])
++                return POLARSSL_ERR_X509_VALUE_TO_LENGTH;
++
++            /* is tag end? */
++            if (*sp == '=') {
++                is_tag = -1;
++                *tag_sp = '\0';
++                is_begin = 1;
++                /* set len 0 (reset) */
++                len = 0;
++            } else {
++                /* tag hasn't ' '! */
++                if (*sp != ' ') {
++                    *tag_sp = *sp;
++                    ++tag_sp;
++                }
++            }
++        /* filter value */
++        } else {
++
++            /* set pointer of value begin */
++            if (is_begin == 1) {
++                begin = sp;
++                is_begin = -1;
++            }
++
++            /* is value at end? */
++            if (*sp == ';' or *sp == '\0') {
++                is_tag = 1;
++
++                /* common name */
++                if (tag[0] == 'C' and tag[1] == 'N') {
++                    CN = begin;
++                    CN_len = len;
++
++                /* organization */
++                } else if (tag[0] == 'O' and tag[1] == '\0') {
++                    O = begin;
++                    O_len = len;
++
++                /* country */
++                } else if (tag[0] == 'C' and tag[1] == '\0') {
++                    C = begin;
++                    C_len = len;
++
++                /* organisation unit */
++                } else if (tag[0] == 'O' and tag[1] == 'U') {
++                    OU = begin;
++                    OU_len = len;
++
++                /* state */
++                } else if (tag[0] == 'S' and tag[1] == 'T') {
++                    ST = begin;
++                    ST_len = len;
++
++                /* locality */
++                } else if (tag[0] == 'L' and tag[1] == '\0') {
++                    L = begin;
++                    L_len = len;
++
++                /* email */
++                } else if (tag[0] == 'R' and tag[1] == '\0') {
++                    R = begin;
++                    R_len = len;
++                }
++
++                /* set tag poiner to begin */
++                tag_sp = tag;
++
++                /* is at end? */
++                if (*sp == '\0' or *(sp +1) == '\0')
++                    break;
++            } else {
++                ++len;
++            }
++        }
++
++        /* make saver */
++        if (*sp == '\0')
++          break;
++    } /* end for */
++
++    /* country */
++    if (C != NULL) {
++        oid[2] = X520_COUNTRY;
++        if ((ret = x509write_add_name(node, oid, 3, C, C_len,
++                        ASN1_PRINTABLE_STRING)) != 0)
++            return ret;
++    }
++
++    /* state */
++    if (ST != NULL) {
++        oid[2] = X520_STATE;
++        if ((ret = x509write_add_name(node, oid, 3, ST, ST_len,
++                        ASN1_PRINTABLE_STRING)) != 0)
++            return ret;
++    }
++
++    /* locality */
++    if (L != NULL) {
++        oid[2] = X520_LOCALITY;
++        if ((ret = x509write_add_name(node, oid, 3, L, L_len,
++                        ASN1_PRINTABLE_STRING)) != 0)
++            return ret;
++    }
++
++    /* organization */
++    if (O != NULL) {
++        oid[2] = X520_ORGANIZATION;
++        if ((ret = x509write_add_name(node, oid, 3, O, O_len,
++                        ASN1_PRINTABLE_STRING)) != 0)
++            return ret;
++    }
++
++    /* organisation unit */
++    if (OU != NULL) {
++        oid[2] = X520_ORG_UNIT;
++        if ((ret = x509write_add_name(node, oid, 3, OU, OU_len,
++                        ASN1_PRINTABLE_STRING)) != 0)
++            return ret;
++    }
++
++    /* common name */
++    if (CN != NULL) {
++        oid[2] = X520_COMMON_NAME;
++        if ((ret = x509write_add_name(node, oid, 3, CN, CN_len,
++                        ASN1_PRINTABLE_STRING)) != 0)
++            return ret;
++    }
++
++    /* email */
++    if (R != NULL) {
++        if ((ret = x509write_add_name(node, (unsigned char*)OID_PKCS9_EMAIL,
++        		9, R, R_len, ASN1_IA5_STRING)) != 0)
++            return ret;
++    }
++
++    if ((asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
++        return ret;
++
++    return 0;
++}
++
++/*
++ * Copy raw data from orginal ca to node
++ */
++static int x509write_copy_from_raw(x509_node *node, x509_buf *raw)
++{
++    if (x509write_realloc_node(node, raw->len) != 0)
++        return 1;
++
++    memcpy(node->p, raw->p, (size_t)raw->len);
++    if ((node->p += raw->len -1) != node->end)
++        return POLARSSL_ERR_X509_POINT_ERROR;
++
++    return 0;
++}
++
++/*
++ * Add the issuer
++ */
++
++int x509write_add_issuer(x509_raw *crt, unsigned char *issuer)
++{
++    return x509write_parse_names(&crt->issuer, issuer);
++}
++
++/*
++ * Add the subject
++ */
++int x509write_add_subject(x509_raw *crt, unsigned char *subject)
++{
++    return x509write_parse_names(&crt->subject, subject);
++}
++
++/*
++ * Copy issuer line from another cert to issuer
++ */
++int x509write_copy_issuer(x509_raw *crt, x509_cert *from_crt)
++{
++    return x509write_copy_from_raw(&crt->issuer, &from_crt->issuer_raw);
++}
++
++/*
++ * Copy subject line from another cert
++ */
++int x509write_copy_subject(x509_raw *crt, x509_cert *from_crt)
++{
++    return x509write_copy_from_raw(&crt->subject, &from_crt->subject_raw);
++}
++
++/*
++ * Copy subject line form antoher cert into issuer
++ */
++int x509write_copy_issuer_form_subject(x509_raw *crt,
++        x509_cert *from_crt)
++{
++    return x509write_copy_from_raw(&crt->issuer, &from_crt->subject_raw);
++}
++
++/*
++ * Copy issuer line from another cert into subject
++ */
++int x509write_copy_subject_from_issuer(x509_raw *crt,
++        x509_cert * from_crt)
++{
++    return x509write_copy_from_raw(&crt->subject, &from_crt->issuer_raw);
++}
++
++/*
++ *  Validity ::= SEQUENCE {
++ *       notBefore      Time,
++ *       notAfter       Time }
++ *
++ *  Time ::= CHOICE {
++ *       utcTime        UTCTime,
++ *       generalTime    GeneralizedTime }
++ */
++/* TODO: No handle GeneralizedTime! */
++int x509write_add_validity(x509_raw *chain, unsigned char *befor,
++        unsigned char *after)
++{
++    int ret;
++
++    x509_node *node = &chain->validity;
++
++    /* notBefore */
++    if ((ret = asn1_add_date_utc(befor, node)) != 0)
++        return ret;
++
++    /* notAfter */
++    if ((ret = asn1_add_date_utc(after, node)) != 0)
++        return ret;
++
++    if ((ret = asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
++        return ret;
++
++    return 0;
++}
++
++/*
++ * make hash from tbs and sign that with private key
++ */
++static int x509write_make_sign(x509_raw *chain, rsa_context *privkey)
++{
++    int ret;
++    unsigned char hash[20], *sign;
++    size_t sign_len = (size_t) mpi_size(&privkey->N);
++
++    /* make hash */
++    sha1(chain->tbs.data, chain->tbs.len, hash);
++
++    /* create sign */
++    sign = (unsigned char *) malloc(sign_len);
++    if (sign == NULL)
++        return 1;
++
++    if ((ret = rsa_pkcs1_sign(privkey, RSA_PRIVATE, SIG_RSA_SHA1, 20, hash,
++                    sign)) != 0)
++        return ret;
++
++    if ((ret = asn1_add_obj(sign, sign_len, ASN1_BIT_STRING,
++                    &chain->sign)) != 0)
++        return ret;
++
++    /*
++     *  AlgorithmIdentifier  ::=  SEQUENCE  {
++     *       algorithm               OBJECT IDENTIFIER,
++     *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
++     */
++    return asn1_add_oid(&chain->signalg, (unsigned char*)OID_PKCS1_RSA_SHA, 9,
++                  ASN1_CONSTRUCTED | ASN1_SEQUENCE, ASN1_NULL,
++                  (unsigned char*)"", 0);
++}
++
++/*
++ * Create a self signed certificate
++ */
++int x509write_create_sign(x509_raw *chain, rsa_context *privkey)
++{
++    int ret, serial;
++
++    /*
++     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
++     */
++    if ((ret = asn1_add_int(2, &chain->version)) != 0)
++        return ret;
++
++    if ((ret = asn1_append_tag(&chain->version, ASN1_CONTEXT_SPECIFIC |
++                    ASN1_CONSTRUCTED)) != 0)
++        return ret;
++
++
++    /*
++     *  CertificateSerialNumber  ::=  INTEGER
++     */
++    srand((unsigned int) time(NULL));
++    serial = rand();
++    if ((ret = asn1_add_int(serial, &chain->serial)) != 0)
++        return ret;
++
++    /*
++     *  AlgorithmIdentifier  ::=  SEQUENCE  {
++     *       algorithm               OBJECT IDENTIFIER,
++     *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
++     */
++    if ((ret = asn1_add_oid(&chain->tbs_signalg,
++				(unsigned char*)OID_PKCS1_RSA_SHA, 9, ASN1_CONSTRUCTED |
++				ASN1_SEQUENCE, ASN1_NULL, (unsigned char*)"", 0)) != 0)
++        return ret;
++
++   /*
++    *  Create the tbs
++    */
++    if ((ret = asn1_append_nodes(&chain->tbs, ASN1_CONSTRUCTED |
++                    ASN1_SEQUENCE, 7, &chain->version, &chain->serial,
++                    &chain->tbs_signalg, &chain->issuer, &chain->validity,
++                    &chain->subject, &chain->subpubkey)) != 0)
++        return ret;
++
++    /* make signing */
++    if ((ret = x509write_make_sign(chain, privkey)) != 0)
++        return ret;
++
++    /* finishing */
++    if ((ret = asn1_append_nodes(&chain->raw, ASN1_CONSTRUCTED |
++                    ASN1_SEQUENCE, 3, &chain->tbs, &chain->signalg,
++                    &chain->sign)) != 0)
++        return ret;
++
++    return 0;
++}
++
++int x509write_create_selfsign(x509_raw *chain, rsa_context *privkey)
++{
++    /*
++     * On self signed certificate are subject and issuer the same
++     */
++    x509write_free_node(&chain->issuer);
++    chain->issuer = chain->subject;
++    return x509write_create_sign(chain, privkey);
++}
++
++/*
++ * CertificationRequestInfo ::= SEQUENCE                    {
++ *    version                       Version,
++ *    subject                       Name,
++ *    subjectPublicKeyInfo          SubjectPublicKeyInfo,
++ *    attributes                    [0] IMPLICIT Attributes }
++ *
++ * CertificationRequest ::=   SEQUENCE                      {
++ *    certificationRequestInfo  CertificationRequestInfo,
++ *    signatureAlgorithm        SignatureAlgorithmIdentifier,
++ *    signature                 Signature                   }
++ *
++ * It use chain.serail for attributes!
++ *
++ */
++int x509write_create_csr(x509_raw *chain, rsa_context *privkey)
++{
++    int ret;
++
++    /* version ::= INTEGER */
++    if ((ret = asn1_add_int(0, &chain->version)) != 0)
++        return ret;
++
++    /* write attributes */
++    if ((ret = asn1_add_obj((unsigned char*)"", 0, ASN1_CONTEXT_SPECIFIC |
++                    ASN1_CONSTRUCTED, &chain->serial)) != 0)
++        return ret;
++
++    /* create CertificationRequestInfo */
++    if ((ret = asn1_append_nodes(&chain->tbs, ASN1_CONSTRUCTED |
++                    ASN1_SEQUENCE, 4, &chain->version, &chain->subject,
++                    &chain->subpubkey, &chain->serial)) != 0)
++        return ret;
++
++    /* make signing */
++    if ((ret = x509write_make_sign(chain, privkey)) != 0)
++        return ret;
++
++    /* finish */
++    if ((ret = asn1_append_nodes(&chain->raw, ASN1_CONSTRUCTED | ASN1_SEQUENCE,
++                    3, &chain->tbs, &chain->signalg, &chain->sign)) != 0)
++        return ret;
++
++    return ret;
++}
++
++/*
++ * Free memory
++ */
++void x509write_free_raw(x509_raw *chain)
++{
++    x509write_free_node(&chain->raw);
++    x509write_free_node(&chain->tbs);
++    x509write_free_node(&chain->version);
++    x509write_free_node(&chain->serial);
++    x509write_free_node(&chain->tbs_signalg);
++    x509write_free_node(&chain->issuer);
++    x509write_free_node(&chain->validity);
++    if (chain->subject.data != chain->issuer.data)
++        x509write_free_node(&chain->subject);
++    x509write_free_node(&chain->subpubkey);
++    x509write_free_node(&chain->signalg);
++    x509write_free_node(&chain->sign);
++}
++
++void x509write_init_raw(x509_raw *chain)
++{
++    memset((void *) chain, 0, sizeof(x509_raw));
++}
Index: make/libs/external.in
===================================================================
--- make/libs/external.in	(revision 4461)
+++ make/libs/external.in	(working copy)
@@ -280,6 +280,14 @@
 		externals these file(s):
 		 /usr/lib/freetz/libpng12.so.0.42.0
 
+config EXTERNAL_FREETZ_LIB_libpolarssl
+	depends on EXTERNAL_ENABLED && FREETZ_LIB_libpolarssl
+	bool "libpolarssl"
+	default n
+	help
+		externals these file(s):
+		 /usr/lib/freetz/libpolarssl.so.0.12.1
+
 config EXTERNAL_FREETZ_LIB_libpopt
 	depends on EXTERNAL_ENABLED && FREETZ_LIB_libpopt
 	bool "libpopt"
Index: make/libs/polarssl.mk
===================================================================
--- make/libs/polarssl.mk	(revision 0)
+++ make/libs/polarssl.mk	(revision 0)
@@ -0,0 +1,47 @@
+$(call PKG_INIT_LIB, 0.12.1)
+$(PKG)_SOURCE:=$(pkg)-$($(PKG)_VERSION)-gpl.tgz
+$(PKG)_SOURCE_MD5:=08bc85a19bbe65493076b9968b421e80
+$(PKG)_SITE:=http://$(pkg).org/code/releases
+
+$(PKG)_LIBNAME:=lib$(pkg).so.$($(PKG)_VERSION)
+$(PKG)_BINARY:=$($(PKG)_DIR)/library/$($(PKG)_LIBNAME)
+$(PKG)_STAGING_BINARY:=$(TARGET_TOOLCHAIN_STAGING_DIR)/usr/lib/$($(PKG)_LIBNAME)
+$(PKG)_TARGET_BINARY:=$($(PKG)_TARGET_DIR)/$($(PKG)_LIBNAME)
+
+$(PKG_SOURCE_DOWNLOAD)
+$(PKG_UNPACKED)
+$(PKG_CONFIGURED_NOP)
+
+$($(PKG)_BINARY): $($(PKG)_DIR)/.configured
+	$(SUBMAKE) -C $(POLARSSL_DIR)/library \
+		VERSION="$(POLARSSL_VERSION)" \
+		CC="$(TARGET_CC)" \
+		CFLAGS="$(TARGET_CFLAGS) $(FPIC) -I../include" \
+		OFLAGS="" \
+		AR="$(TARGET_CROSS)ar" \
+		RANLIB="$(TARGET_CROSS)ranlib" \
+		STRIP="$(TARGET_CROSS)strip" \
+		shared
+
+$($(PKG)_STAGING_BINARY): $($(PKG)_BINARY)
+	mkdir -p $(TARGET_TOOLCHAIN_STAGING_DIR)/usr/include
+	cp -a $(POLARSSL_DIR)/include/polarssl $(TARGET_TOOLCHAIN_STAGING_DIR)/usr/include/
+	$(INSTALL_LIBRARY)
+
+$($(PKG)_TARGET_BINARY): $($(PKG)_STAGING_BINARY)
+	$(INSTALL_LIBRARY_STRIP)
+
+$(pkg): $($(PKG)_STAGING_BINARY)
+
+$(pkg)-precompiled: $($(PKG)_TARGET_BINARY)
+
+$(pkg)-clean:
+	-$(SUBMAKE) -C $(POLARSSL_DIR)/library clean
+	$(RM) -r \
+		$(TARGET_TOOLCHAIN_STAGING_DIR)/usr/lib/libpolarssl* \
+		$(TARGET_TOOLCHAIN_STAGING_DIR)/usr/include/polarssl/
+
+$(pkg)-uninstall:
+	$(RM) $(POLARSSL_TARGET_DIR)/libpolarssl.so*
+
+$(PKG_FINISH)
Index: make/libs/Config.in
===================================================================
--- make/libs/Config.in	(revision 4461)
+++ make/libs/Config.in	(working copy)
@@ -138,6 +138,24 @@
 
 		In Freetz, xrelayd depends on XySSL.
 
+config FREETZ_LIB_libpolarssl
+	bool "PolarSSL (libpolarssl.so)"
+	default n
+	help
+		The aim of the PolarSSL project is to provide a quality, open-source
+		cryptographic library written in C and targeted at embedded systems.
+		PolarSSL is licensed accoring to the dual licensing model. This means
+		that PolarSSL is available under the open source GPL version 2 license
+		as well as a commercial license for closed source projects. More
+		information about licensing is available on the Licensing page:
+		http://polarssl.org/?page=licensing
+
+		For more information about this project, please contact:
+		http://polarssl.org/?page=contact
+		Web site: http://polarssl.org/
+
+		In Freetz, umurmur depends on PolarSSL.
+
 config FREETZ_LIB_libcrypto
 	bool "OpenSSL cryptographic library (libcrypto.so)"
 	select FREETZ_LIB_libssl if FREETZ_HAS_LIBSSL
Index: tools/external
===================================================================
--- tools/external	(revision 4461)
+++ tools/external	(working copy)
@@ -73,6 +73,7 @@
 [ "$EXTERNAL_FREETZ_LIB_libpcre" == "y" ] && EXTERNAL_FILES+=" /usr/lib/freetz/libpcre.so.0.0.1"
 [ "$EXTERNAL_FREETZ_LIB_libpcreposix" == "y" ] && EXTERNAL_FILES+=" /usr/lib/freetz/libpcreposix.so.0.0.0"
 [ "$EXTERNAL_FREETZ_LIB_libpng12" == "y" ] && EXTERNAL_FILES+=" /usr/lib/freetz/libpng12.so.0.42.0"
+[ "$EXTERNAL_FREETZ_LIB_libpolarssl" == "y" ] && EXTERNAL_FILES+=" /usr/lib/freetz/libpolarssl.so.0.12.1"
 [ "$EXTERNAL_FREETZ_LIB_libpopt" == "y" ] && EXTERNAL_FILES+=" /usr/lib/freetz/libpopt.so.0.0.0"
 [ "$EXTERNAL_FREETZ_LIB_libreadline" == "y" ] && EXTERNAL_FILES+=" /usr/lib/freetz/libreadline.so.6.1"
 [ "$EXTERNAL_FREETZ_LIB_libresolv" == "y" ] && EXTERNAL_FILES+=" /lib/libresolv-${FREETZ_TARGET_UCLIBC_VERSION}.so"
