- 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 );
+}