- Renamed include directory to polarssl

diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
new file mode 100644
index 0000000..2122078
--- /dev/null
+++ b/programs/pkey/dh_client.c
@@ -0,0 +1,249 @@
+/*
+ *  Diffie-Hellman-Merkle key exchange (client side)
+ *
+ *  Copyright (C) 2006-2007  Christophe Devine
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include "xyssl/net.h"
+#include "xyssl/aes.h"
+#include "xyssl/dhm.h"
+#include "xyssl/rsa.h"
+#include "xyssl/sha1.h"
+#include "xyssl/havege.h"
+
+#define SERVER_NAME "localhost"
+#define SERVER_PORT 11999
+
+int main( void )
+{
+    FILE *f;
+
+    int ret, n, buflen;
+    int server_fd = -1;
+
+    unsigned char *p, *end;
+    unsigned char buf[1024];
+    unsigned char hash[20];
+
+    havege_state hs;
+    rsa_context rsa;
+    dhm_context dhm;
+    aes_context aes;
+
+    memset( &rsa, 0, sizeof( rsa ) );
+    memset( &dhm, 0, sizeof( dhm ) );
+
+    /*
+     * 1. Setup the RNG
+     */
+    printf( "\n  . Seeding the random number generator" );
+    fflush( stdout );
+
+    havege_init( &hs );
+
+    /*
+     * 2. Read the server's public RSA key
+     */
+    printf( "\n  . Reading public key from rsa_pub.txt" );
+    fflush( stdout );
+
+    if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
+    {
+        ret = 1;
+        printf( " failed\n  ! Could not open rsa_pub.txt\n" \
+                "  ! Please run rsa_genkey first\n\n" );
+        goto exit;
+    }
+
+    rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL );
+
+    if( ( ret = mpi_read_file( &rsa.N, 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.E, 16, f ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_read_file returned %d\n\n", ret );
+        goto exit;
+    }
+
+    rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3;
+
+    fclose( f );
+
+    /*
+     * 3. Initiate the connection
+     */
+    printf( "\n  . Connecting to tcp/%s/%d", SERVER_NAME,
+                                             SERVER_PORT );
+    fflush( stdout );
+
+    if( ( ret = net_connect( &server_fd, SERVER_NAME,
+                                         SERVER_PORT ) ) != 0 )
+    {
+        printf( " failed\n  ! net_connect returned %d\n\n", ret );
+        goto exit;
+    }
+
+    /*
+     * 4a. First get the buffer length
+     */
+    printf( "\n  . Receiving the server's DH parameters" );
+    fflush( stdout );
+
+    memset( buf, 0, sizeof( buf ) );
+
+    if( ( ret = net_recv( &server_fd, buf, 2 ) ) != 2 )
+    {
+        printf( " failed\n  ! net_recv returned %d\n\n", ret );
+        goto exit;
+    }
+
+    n = buflen = ( buf[0] << 8 ) | buf[1];
+    if( buflen < 1 || buflen > (int) sizeof( buf ) )
+    {
+        printf( " failed\n  ! Got an invalid buffer length\n\n" );
+        goto exit;
+    }
+
+    /*
+     * 4b. Get the DHM parameters: P, G and Ys = G^Xs mod P
+     */
+    memset( buf, 0, sizeof( buf ) );
+
+    if( ( ret = net_recv( &server_fd, buf, n ) ) != n )
+    {
+        printf( " failed\n  ! net_recv returned %d\n\n", ret );
+        goto exit;
+    }
+
+    p = buf, end = buf + buflen;
+
+    if( ( ret = dhm_read_params( &dhm, &p, end ) ) != 0 )
+    {
+        printf( " failed\n  ! dhm_read_params returned %d\n\n", ret );
+        goto exit;
+    }
+
+    if( dhm.len < 64 || dhm.len > 256 )
+    {
+        ret = 1;
+        printf( " failed\n  ! Invalid DHM modulus size\n\n" );
+        goto exit;
+    }
+
+    /*
+     * 5. Check that the server's RSA signature matches
+     *    the SHA-1 hash of (P,G,Ys)
+     */
+    printf( "\n  . Verifying the server's RSA signature" );
+    fflush( stdout );
+
+    if( ( n = (int)( end - p ) ) != rsa.len )
+    {
+        ret = 1;
+        printf( " failed\n  ! Invalid RSA signature size\n\n" );
+        goto exit;
+    }
+
+    sha1( buf, (int)( p - 2 - buf ), hash );
+
+    if( ( ret = rsa_pkcs1_verify( &rsa, RSA_PUBLIC, RSA_SHA1,
+                                  0, hash, p ) ) != 0 )
+    {
+        printf( " failed\n  ! rsa_pkcs1_verify returned %d\n\n", ret );
+        goto exit;
+    }
+
+    /*
+     * 6. Send our public value: Yc = G ^ Xc mod P
+     */
+    printf( "\n  . Sending own public value to server" );
+    fflush( stdout );
+
+    n = dhm.len;
+    if( ( ret = dhm_make_public( &dhm, 256, buf, n,
+                                 havege_rand, &hs ) ) != 0 )
+    {
+        printf( " failed\n  ! dhm_make_public returned %d\n\n", ret );
+        goto exit;
+    }
+
+    if( ( ret = net_send( &server_fd, buf, n ) ) != n )
+    {
+        printf( " failed\n  ! net_send returned %d\n\n", ret );
+        goto exit;
+    }
+
+    /*
+     * 7. Derive the shared secret: K = Ys ^ Xc mod P
+     */
+    printf( "\n  . Shared secret: " );
+    fflush( stdout );
+
+    n = dhm.len;
+    if( ( ret = dhm_calc_secret( &dhm, buf, &n ) ) != 0 )
+    {
+        printf( " failed\n  ! dhm_calc_secret returned %d\n\n", ret );
+        goto exit;
+    }
+
+    for( n = 0; n < 16; n++ )
+        printf( "%02x", buf[n] );
+
+    /*
+     * 8. Setup the AES-256 decryption key
+     *
+     * This is an overly simplified example; best practice is
+     * to hash the shared secret with a random value to derive
+     * the keying material for the encryption/decryption keys,
+     * IVs and MACs.
+     */
+    printf( "...\n  . Receiving and decrypting the ciphertext" );
+    fflush( stdout );
+
+    aes_setkey_dec( &aes, buf, 256 );
+
+    memset( buf, 0, sizeof( buf ) );
+
+    if( ( ret = net_recv( &server_fd, buf, 16 ) ) != 16 )
+    {
+        printf( " failed\n  ! net_recv returned %d\n\n", ret );
+        goto exit;
+    }
+
+    aes_crypt_ecb( &aes, AES_DECRYPT, buf, buf );
+    buf[16] = '\0';
+    printf( "\n  . Plaintext is \"%s\"\n\n", (char *) buf );
+
+exit:
+
+    net_close( server_fd );
+    rsa_free( &rsa );
+    dhm_free( &dhm );
+
+#ifdef WIN32
+    printf( "  + Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( ret );
+}
diff --git a/programs/pkey/dh_genprime.c b/programs/pkey/dh_genprime.c
new file mode 100644
index 0000000..09d9b1d
--- /dev/null
+++ b/programs/pkey/dh_genprime.c
@@ -0,0 +1,122 @@
+/*
+ *  Diffie-Hellman-Merkle key exchange (prime generation)
+ *
+ *  Copyright (C) 2006-2007  Christophe Devine
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <stdio.h>
+
+#include "xyssl/bignum.h"
+#include "xyssl/config.h"
+#include "xyssl/havege.h"
+
+/*
+ * Note: G = 4 is always a quadratic residue mod P,
+ * so it is a generator of order Q (with P = 2*Q+1).
+ */
+#define DH_P_SIZE 1024
+#define GENERATOR "4"
+
+int main( void )
+{
+    int ret = 1;
+
+#if defined(XYSSL_GENPRIME)
+    mpi G, P, Q;
+    havege_state hs;
+    FILE *fout;
+
+    mpi_init( &G, &P, &Q, NULL );
+    mpi_read_string( &G, 10, GENERATOR );
+
+    printf( "\n  . Seeding the random number generator..." );
+    fflush( stdout );
+
+    havege_init( &hs );
+
+    printf( " ok\n  . Generating the modulus, please wait..." );
+    fflush( stdout );
+
+    /*
+     * This can take a long time...
+     */
+    if( ( ret = mpi_gen_prime( &P, DH_P_SIZE, 1,
+                               havege_rand, &hs ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_gen_prime returned %d\n\n", ret );
+        goto exit;
+    }
+
+    printf( " ok\n  . Verifying that Q = (P-1)/2 is prime..." );
+    fflush( stdout );
+
+    if( ( ret = mpi_sub_int( &Q, &P, 1 ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_sub_int returned %d\n\n", ret );
+        goto exit;
+    }
+
+    if( ( ret = mpi_div_int( &Q, NULL, &Q, 2 ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_div_int returned %d\n\n", ret );
+        goto exit;
+    }
+
+    if( ( ret = mpi_is_prime( &Q, havege_rand, &hs ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_is_prime returned %d\n\n", ret );
+        goto exit;
+    }
+
+    printf( " ok\n  . Exporting the value in dh_prime.txt..." );
+    fflush( stdout );
+
+    if( ( fout = fopen( "dh_prime.txt", "wb+" ) ) == NULL )
+    {
+        ret = 1;
+        printf( " failed\n  ! Could not create dh_prime.txt\n\n" );
+        goto exit;
+    }
+
+    if( ( ret = mpi_write_file( "P = ", &P, 16, fout ) != 0 ) ||
+        ( ret = mpi_write_file( "G = ", &G, 16, fout ) != 0 ) )
+    {
+        printf( " failed\n  ! mpi_write_file returned %d\n\n", ret );
+        goto exit;
+    }
+
+    printf( " ok\n\n" );
+    fclose( fout );
+
+exit:
+
+    mpi_free( &Q, &P, &G, NULL );
+#else
+    printf( "\n  ! Prime-number generation is not available.\n\n" );
+#endif
+
+#ifdef WIN32
+    printf( "  Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( ret );
+}
diff --git a/programs/pkey/dh_prime.txt b/programs/pkey/dh_prime.txt
new file mode 100644
index 0000000..e62c279
--- /dev/null
+++ b/programs/pkey/dh_prime.txt
@@ -0,0 +1,2 @@
+P = C3CF8BCFD9E88B0CC35EC526F3D63FA001DC9392E6CA81F3B414173955C582758B52038FAFBF402B8C29DC32F5231B0D2E25B252850C7DCDBFF46D0E7989E51DEA07A53BCF7947D4C95EBA28F9CBAFB0267EC3BCF57B15A49964236B56773851D6621E546F410D504F13827218CD14A1FDB69522DC72DD67D880E51B2E00894F

+G = 04

diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
new file mode 100644
index 0000000..4990dcf
--- /dev/null
+++ b/programs/pkey/dh_server.c
@@ -0,0 +1,252 @@
+/*
+ *  Diffie-Hellman-Merkle key exchange (server side)
+ *
+ *  Copyright (C) 2006-2007  Christophe Devine
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include "xyssl/net.h"
+#include "xyssl/aes.h"
+#include "xyssl/dhm.h"
+#include "xyssl/rsa.h"
+#include "xyssl/sha1.h"
+#include "xyssl/havege.h"
+
+#define SERVER_PORT 11999
+#define PLAINTEXT "==Hello there!=="
+
+int main( void )
+{
+    FILE *f;
+
+    int ret, n, buflen;
+    int listen_fd = -1;
+    int client_fd = -1;
+
+    unsigned char buf[1024];
+    unsigned char hash[20];
+    unsigned char buf2[2];
+
+    havege_state hs;
+    rsa_context rsa;
+    dhm_context dhm;
+    aes_context aes;
+
+    memset( &rsa, 0, sizeof( rsa ) );
+    memset( &dhm, 0, sizeof( dhm ) );
+
+    /*
+     * 1. Setup the RNG
+     */
+    printf( "\n  . Seeding the random number generator" );
+    fflush( stdout );
+
+    havege_init( &hs );
+
+    /*
+     * 2a. Read the server's private RSA key
+     */
+    printf( "\n  . Reading private key from rsa_priv.txt" );
+    fflush( stdout );
+
+    if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
+    {
+        ret = 1;
+        printf( " failed\n  ! Could not open rsa_priv.txt\n" \
+                "  ! Please run rsa_genkey first\n\n" );
+        goto exit;
+    }
+
+    rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL );
+
+    if( ( ret = mpi_read_file( &rsa.N , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.E , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.D , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.P , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.Q , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.DP, 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.DQ, 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.QP, 16, f ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_read_file returned %d\n\n", ret );
+        goto exit;
+    }
+
+    rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3;
+    
+    fclose( f );
+
+    /*
+     * 2b. Get the DHM modulus and generator
+     */
+    printf( "\n  . Reading DH parameters from dh_prime.txt" );
+    fflush( stdout );
+
+    if( ( f = fopen( "dh_prime.txt", "rb" ) ) == NULL )
+    {
+        ret = 1;
+        printf( " failed\n  ! Could not open dh_prime.txt\n" \
+                "  ! Please run dh_genprime first\n\n" );
+        goto exit;
+    }
+
+    if( mpi_read_file( &dhm.P, 16, f ) != 0 ||
+        mpi_read_file( &dhm.G, 16, f ) != 0 )
+    {
+        printf( " failed\n  ! Invalid DH parameter file\n\n" );
+        goto exit;
+    }
+
+    fclose( f );
+
+    /*
+     * 3. Wait for a client to connect
+     */
+    printf( "\n  . Waiting for a remote connection" );
+    fflush( stdout );
+
+    if( ( ret = net_bind( &listen_fd, NULL, SERVER_PORT ) ) != 0 )
+    {
+        printf( " failed\n  ! net_bind returned %d\n\n", ret );
+        goto exit;
+    }
+
+    if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
+    {
+        printf( " failed\n  ! net_accept returned %d\n\n", ret );
+        goto exit;
+    }
+
+    /*
+     * 4. Setup the DH parameters (P,G,Ys)
+     */
+    printf( "\n  . Sending the server's DH parameters" );
+    fflush( stdout );
+
+    memset( buf, 0, sizeof( buf ) );
+
+    if( ( ret = dhm_make_params( &dhm, 256, buf, &n,
+                                 havege_rand, &hs ) ) != 0 )
+    {
+        printf( " failed\n  ! dhm_make_params returned %d\n\n", ret );
+        goto exit;
+    }
+
+    /*
+     * 5. Sign the parameters and send them
+     */
+    sha1( buf, n, hash );
+
+    buf[n    ] = (unsigned char)( rsa.len >> 8 );
+    buf[n + 1] = (unsigned char)( rsa.len      );
+
+    if( ( ret = rsa_pkcs1_sign( &rsa, RSA_PRIVATE, RSA_SHA1,
+                                0, hash, buf + n + 2 ) ) != 0 )
+    {
+        printf( " failed\n  ! rsa_pkcs1_sign returned %d\n\n", ret );
+        goto exit;
+    }
+
+    buflen = n + 2 + rsa.len;
+    buf2[0] = (unsigned char)( buflen >> 8 );
+    buf2[1] = (unsigned char)( buflen      );
+
+    if( ( ret = net_send( &client_fd, buf2, 2 ) ) != 2 ||
+        ( ret = net_send( &client_fd, buf, buflen ) ) != buflen )
+    {
+        printf( " failed\n  ! net_send returned %d\n\n", ret );
+        goto exit;
+    }
+
+    /*
+     * 6. Get the client's public value: Yc = G ^ Xc mod P
+     */
+    printf( "\n  . Receiving the client's public value" );
+    fflush( stdout );
+
+    memset( buf, 0, sizeof( buf ) );
+    n = dhm.len;
+
+    if( ( ret = net_recv( &client_fd, buf, n ) ) != n )
+    {
+        printf( " failed\n  ! net_recv returned %d\n\n", ret );
+        goto exit;
+    }
+
+    if( ( ret = dhm_read_public( &dhm, buf, dhm.len ) ) != 0 )
+    {
+        printf( " failed\n  ! dhm_read_public returned %d\n\n", ret );
+        goto exit;
+    }
+
+    /*
+     * 7. Derive the shared secret: K = Ys ^ Xc mod P
+     */
+    printf( "\n  . Shared secret: " );
+    fflush( stdout );
+
+    if( ( ret = dhm_calc_secret( &dhm, buf, &n ) ) != 0 )
+    {
+        printf( " failed\n  ! dhm_calc_secret returned %d\n\n", ret );
+        goto exit;
+    }
+
+    for( n = 0; n < 16; n++ )
+        printf( "%02x", buf[n] );
+
+    /*
+     * 8. Setup the AES-256 encryption key
+     *
+     * This is an overly simplified example; best practice is
+     * to hash the shared secret with a random value to derive
+     * the keying material for the encryption/decryption keys
+     * and MACs.
+     */
+    printf( "...\n  . Encrypting and sending the ciphertext" );
+    fflush( stdout );
+
+    aes_setkey_enc( &aes, buf, 256 );
+    memcpy( buf, PLAINTEXT, 16 );
+    aes_crypt_ecb( &aes, AES_ENCRYPT, buf, buf );
+
+    if( ( ret = net_send( &client_fd, buf, 16 ) ) != 16 )
+    {
+        printf( " failed\n  ! net_send returned %d\n\n", ret );
+        goto exit;
+    }
+
+    printf( "\n\n" );
+
+exit:
+
+    net_close( client_fd );
+    rsa_free( &rsa );
+    dhm_free( &dhm );
+
+#ifdef WIN32
+    printf( "  + Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( ret );
+}
diff --git a/programs/pkey/mpi_demo.c b/programs/pkey/mpi_demo.c
new file mode 100644
index 0000000..699fa5a
--- /dev/null
+++ b/programs/pkey/mpi_demo.c
@@ -0,0 +1,76 @@
+/*
+ *  Simple MPI demonstration program
+ *
+ *  Copyright (C) 2006-2007  Christophe Devine
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <stdio.h>
+
+#include "xyssl/bignum.h"
+
+int main( void )
+{
+    mpi E, P, Q, N, H, D, X, Y, Z;
+
+    mpi_init( &E, &P, &Q, &N, &H,
+              &D, &X, &Y, &Z, NULL );
+
+    mpi_read_string( &P, 10, "2789" );
+    mpi_read_string( &Q, 10, "3203" );
+    mpi_read_string( &E, 10,  "257" );
+    mpi_mul_mpi( &N, &P, &Q );
+
+    printf( "\n  Public key:\n\n" );
+    mpi_write_file( "  N = ", &N, 10, NULL );
+    mpi_write_file( "  E = ", &E, 10, NULL );
+
+    printf( "\n  Private key:\n\n" );
+    mpi_write_file( "  P = ", &P, 10, NULL );
+    mpi_write_file( "  Q = ", &Q, 10, NULL );
+
+    mpi_sub_int( &P, &P, 1 );
+    mpi_sub_int( &Q, &Q, 1 );
+    mpi_mul_mpi( &H, &P, &Q );
+    mpi_inv_mod( &D, &E, &H );
+
+    mpi_write_file( "  D = E^-1 mod (P-1)*(Q-1) = ",
+                    &D, 10, NULL );
+
+    mpi_read_string( &X, 10, "55555" );
+    mpi_exp_mod( &Y, &X, &E, &N, NULL );
+    mpi_exp_mod( &Z, &Y, &D, &N, NULL );
+
+    printf( "\n  RSA operation:\n\n" );
+    mpi_write_file( "  X (plaintext)  = ", &X, 10, NULL );
+    mpi_write_file( "  Y (ciphertext) = X^E mod N = ", &Y, 10, NULL );
+    mpi_write_file( "  Z (decrypted)  = Y^D mod N = ", &Z, 10, NULL );
+    printf( "\n" );
+
+    mpi_free( &Z, &Y, &X, &D, &H,
+              &N, &Q, &P, &E, NULL );
+
+#ifdef WIN32
+    printf( "  Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( 0 );
+}
diff --git a/programs/pkey/rsa_genkey.c b/programs/pkey/rsa_genkey.c
new file mode 100644
index 0000000..0619f15
--- /dev/null
+++ b/programs/pkey/rsa_genkey.c
@@ -0,0 +1,130 @@
+/*
+ *  Example RSA key generation program
+ *
+ *  Copyright (C) 2006-2007  Christophe Devine
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <stdio.h>
+
+#include "xyssl/havege.h"
+#include "xyssl/bignum.h"
+#include "xyssl/x509.h"
+#include "xyssl/rsa.h"
+
+#define KEY_SIZE 1024
+#define EXPONENT 65537
+
+int main( void )
+{
+    int ret;
+    rsa_context rsa;
+    havege_state hs;
+    FILE *fpub  = NULL;
+    FILE *fpriv = NULL;
+    x509_raw cert;
+
+    printf( "\n  . Seeding the random number generator..." );
+    fflush( stdout );
+
+    havege_init( &hs );
+
+    printf( " ok\n  . Generating the RSA key [ %d-bit ]...", KEY_SIZE );
+    fflush( stdout );
+
+    rsa_init( &rsa, RSA_PKCS_V15, 0, havege_rand, &hs );
+    
+    if( ( ret = rsa_gen_key( &rsa, KEY_SIZE, EXPONENT ) ) != 0 )
+    {
+        printf( " failed\n  ! rsa_gen_key returned %d\n\n", ret );
+        goto exit;
+    }
+
+    printf( " ok\n  . Exporting the public  key in rsa_pub.txt...." );
+    fflush( stdout );
+
+    if( ( fpub = fopen( "rsa_pub.txt", "wb+" ) ) == NULL )
+    {
+        printf( " failed\n  ! could not open rsa_pub.txt for writing\n\n" );
+        ret = 1;
+        goto exit;
+    }
+
+    if( ( ret = mpi_write_file( "N = ", &rsa.N, 16, fpub ) ) != 0 ||
+        ( ret = mpi_write_file( "E = ", &rsa.E, 16, fpub ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_write_file returned %d\n\n", ret );
+        goto exit;
+    }
+
+    printf( " ok\n  . Exporting the private key in rsa_priv.txt..." );
+    fflush( stdout );
+
+    if( ( fpriv = fopen( "rsa_priv.txt", "wb+" ) ) == NULL )
+    {
+        printf( " failed\n  ! could not open rsa_priv.txt for writing\n" );
+        ret = 1;
+        goto exit;
+    }
+
+    if( ( ret = mpi_write_file( "N = " , &rsa.N , 16, fpriv ) ) != 0 ||
+        ( ret = mpi_write_file( "E = " , &rsa.E , 16, fpriv ) ) != 0 ||
+        ( ret = mpi_write_file( "D = " , &rsa.D , 16, fpriv ) ) != 0 ||
+        ( ret = mpi_write_file( "P = " , &rsa.P , 16, fpriv ) ) != 0 ||
+        ( ret = mpi_write_file( "Q = " , &rsa.Q , 16, fpriv ) ) != 0 ||
+        ( ret = mpi_write_file( "DP = ", &rsa.DP, 16, fpriv ) ) != 0 ||
+        ( ret = mpi_write_file( "DQ = ", &rsa.DQ, 16, fpriv ) ) != 0 ||
+        ( ret = mpi_write_file( "QP = ", &rsa.QP, 16, fpriv ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_write_file returned %d\n\n", ret );
+        goto exit;
+    }
+/*
+    printf( " ok\n  . Generating the certificate..." );
+
+    x509write_init_raw( &cert );
+    x509write_add_pubkey( &cert, &rsa );
+    x509write_add_subject( &cert, "CN='localhost'" );
+    x509write_add_validity( &cert, "2007-09-06 17:00:32",
+                                   "2010-09-06 17:00:32" );
+    x509write_create_selfsign( &cert, &rsa );
+    x509write_crtfile( &cert, "cert.der", X509_OUTPUT_DER );
+    x509write_crtfile( &cert, "cert.pem", X509_OUTPUT_PEM );
+    x509write_free_raw( &cert );
+*/
+    printf( " ok\n\n" );
+
+exit:
+
+    if( fpub  != NULL )
+        fclose( fpub );
+
+    if( fpriv != NULL )
+        fclose( fpriv );
+
+    rsa_free( &rsa );
+
+#ifdef WIN32
+    printf( "  Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( ret );
+}
diff --git a/programs/pkey/rsa_priv.txt b/programs/pkey/rsa_priv.txt
new file mode 100644
index 0000000..06b2e4d
--- /dev/null
+++ b/programs/pkey/rsa_priv.txt
@@ -0,0 +1,8 @@
+N = 807E3526556FADF8D4CA64074ADA36862646D5ECB24E363821306588722AF2B58058CFB88E8C0BEA5C7084F3055D232F110E59C8837A0D132A4B907E91DB4A4924134A85E7445935E55A772C0B72E12C94501D9DF66B71BA030F842531721AEF43AE48F9505BF7504CDEEA3CAA6F94530835648D770AE2E6C628DD484D10AA57

+E = 010001

+D = 56B3D2AD612D10993D0CAC5E7755B340E6071A46B3322F47C4AD6175A683F06E2482C8F761C88229CBE268F38B0503BEB8A59453C6D3CE8AC6196310E4DEB1CA939DF7F7EE26C4697EEDD1E5122795BFC83861DE2E3EC9E3E84F42B3A9DD25EB09B30FDDFFACCE5091493BC5577530CE9CD9C8BA244EC5FD3DF91BCECFD73961

+P = F8DAD6A5651CED9011D979A076D70C4FBD095AAE2E53EF51415832C63AD61618F0BB369F29D1363345FE481FE6C28F0830FE33A1C41F8743A4E02DD682A2E099

+Q = 842EABF3171F972DE7D6B571B70F969F8F1C305851785BB042CDAE3B794014659A744EA7D16D881B7168463CEEAF52BA0F78755BBE89CFE1361076CE3E20886F

+DP = B1C694047FE1548CD1538D21E703E595A933DF86032E8F0E7B21E8D3D8004CB4F074ADA6B296F4A35863395F20D8E8992F76C9A7CC95C169BF852EF9C9455631

+DQ = 143C54E49D289FEB4E2FC78D461A23D3FF83B03F0511E8EF7DFAA0EEC7EC3073318716B7884F3D63FE239985208144A7E950669F09F76D14AC432EFCF9F3DF0F

+QP = C2F98F412476BDA2B14F5882D929090C62BB24ED74E8B78A3BE287EABDB3FADC445D041F1DE04EBE2D39A8913DAF03C23FF632D1B3FB6CCBDD65B2A576F127F5

diff --git a/programs/pkey/rsa_pub.txt b/programs/pkey/rsa_pub.txt
new file mode 100644
index 0000000..dddb25c
--- /dev/null
+++ b/programs/pkey/rsa_pub.txt
@@ -0,0 +1,2 @@
+N = 807E3526556FADF8D4CA64074ADA36862646D5ECB24E363821306588722AF2B58058CFB88E8C0BEA5C7084F3055D232F110E59C8837A0D132A4B907E91DB4A4924134A85E7445935E55A772C0B72E12C94501D9DF66B71BA030F842531721AEF43AE48F9505BF7504CDEEA3CAA6F94530835648D770AE2E6C628DD484D10AA57

+E = 010001

diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c
new file mode 100644
index 0000000..0e7077e
--- /dev/null
+++ b/programs/pkey/rsa_sign.c
@@ -0,0 +1,130 @@
+/*
+ *  RSA/SHA-1 signature creation program
+ *
+ *  Copyright (C) 2006-2007  Christophe Devine
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include "xyssl/rsa.h"
+#include "xyssl/sha1.h"
+
+int main( int argc, char *argv[] )
+{
+    FILE *f;
+    int ret, i;
+    rsa_context rsa;
+    unsigned char hash[20];
+    unsigned char buf[512];
+
+    ret = 1;
+
+    if( argc != 2 )
+    {
+        printf( "usage: rsa_sign <filename>\n" );
+
+#ifdef WIN32
+        printf( "\n" );
+#endif
+
+        goto exit;
+    }
+
+    printf( "\n  . Reading private key from rsa_priv.txt" );
+    fflush( stdout );
+
+    if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
+    {
+        ret = 1;
+        printf( " failed\n  ! Could not open rsa_priv.txt\n" \
+                "  ! Please run rsa_genkey first\n\n" );
+        goto exit;
+    }
+
+    rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL );
+    
+    if( ( ret = mpi_read_file( &rsa.N , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.E , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.D , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.P , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.Q , 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.DP, 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.DQ, 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.QP, 16, f ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_read_file returned %d\n\n", ret );
+        goto exit;
+    }
+
+    rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3;
+
+    fclose( f );
+
+    /*
+     * Compute the SHA-1 hash of the input file,
+     * then calculate the RSA signature of the hash.
+     */
+    printf( "\n  . Generating the RSA/SHA-1 signature" );
+    fflush( stdout );
+
+    if( ( ret = sha1_file( argv[1], hash ) ) != 0 )
+    {
+        printf( " failed\n  ! Could not open or read %s\n\n", argv[1] );
+        goto exit;
+    }
+
+    if( ( ret = rsa_pkcs1_sign( &rsa, RSA_PRIVATE, RSA_SHA1,
+                                20, hash, buf ) ) != 0 )
+    {
+        printf( " failed\n  ! rsa_pkcs1_sign returned %d\n\n", ret );
+        goto exit;
+    }
+
+    /*
+     * Write the signature into <filename>-sig.txt
+     */
+    memcpy( argv[1] + strlen( argv[1] ), ".sig", 5 );
+
+    if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
+    {
+        ret = 1;
+        printf( " failed\n  ! Could not create %s\n\n", argv[1] );
+        goto exit;
+    }
+
+    for( i = 0; i < rsa.len; i++ )
+        fprintf( f, "%02X%s", buf[i],
+                 ( i + 1 ) % 16 == 0 ? "\r\n" : " " );
+
+    fclose( f );
+
+    printf( "\n  . Done (created \"%s\")\n\n", argv[1] );
+
+exit:
+
+#ifdef WIN32
+    printf( "  + Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( ret );
+}
diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c
new file mode 100644
index 0000000..aacc664
--- /dev/null
+++ b/programs/pkey/rsa_verify.c
@@ -0,0 +1,133 @@
+/*
+ *  RSA/SHA-1 signature verification program
+ *
+ *  Copyright (C) 2006-2007  Christophe Devine
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include "xyssl/rsa.h"
+#include "xyssl/sha1.h"
+
+int main( int argc, char *argv[] )
+{
+    FILE *f;
+    int ret, i, c;
+    rsa_context rsa;
+    unsigned char hash[20];
+    unsigned char buf[512];
+
+    ret = 1;
+    if( argc != 2 )
+    {
+        printf( "usage: rsa_verify <filename>\n" );
+
+#ifdef WIN32
+        printf( "\n" );
+#endif
+
+        goto exit;
+    }
+
+    printf( "\n  . Reading public key from rsa_pub.txt" );
+    fflush( stdout );
+
+    if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
+    {
+        printf( " failed\n  ! Could not open rsa_pub.txt\n" \
+                "  ! Please run rsa_genkey first\n\n" );
+        goto exit;
+    }
+
+    rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL );
+
+    if( ( ret = mpi_read_file( &rsa.N, 16, f ) ) != 0 ||
+        ( ret = mpi_read_file( &rsa.E, 16, f ) ) != 0 )
+    {
+        printf( " failed\n  ! mpi_read_file returned %d\n\n", ret );
+        goto exit;
+    }
+
+    rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3;
+
+    fclose( f );
+
+    /*
+     * Extract the RSA signature from the text file
+     */
+    ret = 1;
+    i = strlen( argv[1] );
+    memcpy( argv[1] + i, ".sig", 5 );
+
+    if( ( f = fopen( argv[1], "rb" ) ) == NULL )
+    {
+        printf( "\n  ! Could not open %s\n\n", argv[1] );
+        goto exit;
+    }
+
+    argv[1][i] = '\0', i = 0;
+
+    while( fscanf( f, "%02X", &c ) > 0 &&
+           i < (int) sizeof( buf ) )
+        buf[i++] = (unsigned char) c;
+
+    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.
+     */
+    printf( "\n  . Verifying the RSA/SHA-1 signature" );
+    fflush( stdout );
+
+    if( ( ret = sha1_file( argv[1], hash ) ) != 0 )
+    {
+        printf( " failed\n  ! Could not open or read %s\n\n", argv[1] );
+        goto exit;
+    }
+
+    if( ( ret = rsa_pkcs1_verify( &rsa, RSA_PUBLIC, RSA_SHA1,
+                                  20, hash, buf ) ) != 0 )
+    {
+        printf( " failed\n  ! rsa_pkcs1_verify returned %d\n\n", ret );
+        goto exit;
+    }
+
+    printf( "\n  . OK (the decrypted SHA-1 hash matches)\n\n" );
+
+    ret = 0;
+
+exit:
+
+#ifdef WIN32
+    printf( "  + Press Enter to exit this program.\n" );
+    fflush( stdout ); getchar();
+#endif
+
+    return( ret );
+}