/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/programs/pkey/dh_client.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 174 $ : Last Committed Revision
00003  * $Date: 2008-06-24 10:50:29 -0700 (Tue, 24 Jun 2008) $ : Last Committed Date */
00004 /*
00005  *  Diffie-Hellman-Merkle key exchange (client side)
00006  *
00007  *  Copyright (C) 2006-2007  Christophe Devine
00008  *
00009  *  This library is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU Lesser General Public
00011  *  License, version 2.1 as published by the Free Software Foundation.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public
00019  *  License along with this library; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00021  *  MA  02110-1301  USA
00022  */
00023 
00024 #ifndef _CRT_SECURE_NO_DEPRECATE
00025 #define _CRT_SECURE_NO_DEPRECATE 1
00026 #endif
00027 
00028 #include <string.h>
00029 #include <stdio.h>
00030 
00031 #include "xyssl/net.h"
00032 #include "xyssl/aes.h"
00033 #include "xyssl/dhm.h"
00034 #include "xyssl/rsa.h"
00035 #include "xyssl/sha1.h"
00036 #include "xyssl/havege.h"
00037 
00038 #define SERVER_NAME "localhost"
00039 #define SERVER_PORT 11999
00040 
00041 int main( void )
00042 {
00043     FILE *f;
00044 
00045     int ret, n, buflen;
00046     int server_fd = -1;
00047 
00048     unsigned char *p, *end;
00049     unsigned char buf[1024];
00050     unsigned char hash[20];
00051 
00052     havege_state hs;
00053     rsa_context rsa;
00054     dhm_context dhm;
00055     aes_context aes;
00056 
00057     memset( &rsa, 0, sizeof( rsa ) );
00058     memset( &dhm, 0, sizeof( dhm ) );
00059 
00060     /*
00061      * 1. Setup the RNG
00062      */
00063     printf( "\n  . Seeding the random number generator" );
00064     fflush( stdout );
00065 
00066     havege_init( &hs );
00067 
00068     /*
00069      * 2. Read the server's public RSA key
00070      */
00071     printf( "\n  . Reading public key from rsa_pub.txt" );
00072     fflush( stdout );
00073 
00074     if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
00075     {
00076         ret = 1;
00077         printf( " failed\n  ! Could not open rsa_pub.txt\n" \
00078                 "  ! Please run rsa_genkey first\n\n" );
00079         goto exit;
00080     }
00081 
00082     if( ( ret = rsa_read_public( &rsa, f ) ) != 0 )
00083     {
00084         printf( " failed\n  ! rsa_read_public returned %08x\n\n", ret );
00085         goto exit;
00086     }
00087 
00088     fclose( f );
00089 
00090     /*
00091      * 3. Initiate the connection
00092      */
00093     printf( "\n  . Connecting to tcp/%s/%d", SERVER_NAME,
00094                                              SERVER_PORT );
00095     fflush( stdout );
00096 
00097     if( ( ret = net_connect( &server_fd, SERVER_NAME,
00098                                          SERVER_PORT ) ) != 0 )
00099     {
00100         printf( " failed\n  ! net_connect returned %08x\n\n", ret );
00101         goto exit;
00102     }
00103 
00104     /*
00105      * 4a. First get the buffer length
00106      */
00107     printf( "\n  . Receiving the server's DH parameters" );
00108     fflush( stdout );
00109 
00110     memset( buf, 0, sizeof( buf ) );
00111 
00112     n = 2;
00113     if( ( ret = net_recv( server_fd, buf, &n ) ) != 0 )
00114     {
00115         printf( " failed\n  ! net_recv returned %08x\n\n", ret );
00116         goto exit;
00117     }
00118 
00119     n = buflen = ( buf[0] << 8 ) | buf[1];
00120     if( buflen < 1 || buflen > (int) sizeof( buf ) )
00121     {
00122         printf( " failed\n  ! Got an invalid buffer length\n\n" );
00123         goto exit;
00124     }
00125 
00126     /*
00127      * 4b. Get the DHM parameters: P, G and Ys = G^Xs mod P
00128      */
00129     if( ( ret = net_recv( server_fd, buf, &n ) ) != 0 )
00130     {
00131         printf( " failed\n  ! net_recv returned %08x\n\n", ret );
00132         goto exit;
00133     }
00134 
00135     p = buf, end = buf + buflen;
00136 
00137     if( ( ret = dhm_read_params( &dhm, &p, end ) ) != 0 )
00138     {
00139         printf( " failed\n  ! dhm_read_params returned %08x\n\n", ret );
00140         goto exit;
00141     }
00142 
00143     if( dhm.len < 64 || dhm.len > 256 )
00144     {
00145         ret = 1;
00146         printf( " failed\n  ! Invalid DHM modulus size\n\n" );
00147         goto exit;
00148     }
00149 
00150     /*
00151      * 5. Check that the server's RSA signature matches
00152      *    the SHA-1 hash of (P,G,Ys)
00153      */
00154     printf( "\n  . Verifying the server's RSA signature" );
00155     fflush( stdout );
00156 
00157     if( ( n = (int)( end - p ) ) != rsa.len )
00158     {
00159         ret = 1;
00160         printf( " failed\n  ! Invalid RSA signature size\n\n" );
00161         goto exit;
00162     }
00163 
00164     sha1( buf, (int)( p - 2 - buf ), hash );
00165 
00166     if( ( ret = rsa_pkcs1_verify( &rsa, RSA_SHA1,
00167                                   hash, 20, p, n ) ) != 0 )
00168     {
00169         printf( " failed\n  ! rsa_pkcs1_verify returned "
00170                 "%08x\n\n", ret );
00171         goto exit;
00172     }
00173 
00174     /*
00175      * 6. Send our public value: Yc = G ^ Xc mod P
00176      */
00177     printf( "\n  . Sending own public value to server" );
00178     fflush( stdout );
00179 
00180     n = dhm.len;
00181     if( ( ret = dhm_make_public( &dhm, buf, n,
00182                                  havege_rand, &hs ) ) != 0 )
00183     {
00184         printf( " failed\n  ! dhm_make_public returned %08x\n\n", ret );
00185         goto exit;
00186     }
00187 
00188     if( ( ret = net_send( server_fd, buf, &n ) ) != 0 )
00189     {
00190         printf( " failed\n  ! net_recv returned %08x\n\n", ret );
00191         goto exit;
00192     }
00193 
00194     /*
00195      * 7. Derive the shared secret: K = Ys ^ Xc mod P
00196      */
00197     printf( "\n  . Shared secret: " );
00198     fflush( stdout );
00199 
00200     n = dhm.len;
00201     if( ( ret = dhm_calc_secret( &dhm, buf, &n ) ) != 0 )
00202     {
00203         printf( " failed\n  ! dhm_calc_secret returned %08x\n\n", ret );
00204         goto exit;
00205     }
00206 
00207     for( n = 0; n < 16; n++ )
00208         printf( "%02x", buf[n] );
00209 
00210     /*
00211      * 8. Setup the AES-256 decryption key
00212      *
00213      * This is an overly simplified example; best practice is
00214      * to hash the shared secret with a random value to derive
00215      * the keying material for the encryption/decryption keys
00216      * and MACs.
00217      */
00218     printf( "...\n  . Receiving and decrypting the ciphertext" );
00219     fflush( stdout );
00220 
00221     aes_set_key( &aes, buf, 256 );
00222 
00223     n = 16;
00224     if( ( ret = net_recv( server_fd, buf, &n ) ) != 0 )
00225     {
00226         printf( " failed\n  ! net_recv returned %08x\n\n", ret );
00227         goto exit;
00228     }
00229 
00230     aes_decrypt( &aes, buf, buf );  buf[16] = '\0';
00231     printf( "\n  . Plaintext is \"%s\"\n\n", buf );
00232 
00233 exit:
00234 
00235     net_close( server_fd );
00236     rsa_free( &rsa );
00237     dhm_free( &dhm );
00238 
00239 #ifdef WIN32
00240     printf( "  + Press Enter to exit this program.\n" );
00241     fflush( stdout ); getchar();
00242 #endif
00243 
00244     return( ret );
00245 }

Generated on Tue Jul 1 15:29:59 2008 for Mobile-C by  doxygen 1.5.4