dh_server.c 9.08 KB
Newer Older
1 2 3
/*
 *  Diffie-Hellman-Merkle key exchange (server side)
 *
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
4
 *  Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
Paul Bakker's avatar
Paul Bakker committed
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker's avatar
Paul Bakker committed
7
 *
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *  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.
 */

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
23
#if !defined(MBEDTLS_CONFIG_FILE)
24
#include "mbedtls/config.h"
25
#else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
26
#include MBEDTLS_CONFIG_FILE
27
#endif
28

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
29
#if defined(MBEDTLS_PLATFORM_C)
30
#include "mbedtls/platform.h"
31
#else
Rich Evans's avatar
Rich Evans committed
32
#include <stdio.h>
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
33
#define mbedtls_printf     printf
34 35
#endif

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
36 37 38 39
#if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
    defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
    defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) && \
    defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C)
40 41 42 43 44 45 46
#include "mbedtls/net.h"
#include "mbedtls/aes.h"
#include "mbedtls/dhm.h"
#include "mbedtls/rsa.h"
#include "mbedtls/sha1.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
47

Rich Evans's avatar
Rich Evans committed
48 49 50 51
#include <stdio.h>
#include <string.h>
#endif

52 53 54
#define SERVER_PORT 11999
#define PLAINTEXT "==Hello there!=="

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
55 56 57 58
#if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) ||     \
    !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) ||  \
    !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) ||    \
    !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C)
Rich Evans's avatar
Rich Evans committed
59
int main( void )
60
{
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
61 62 63 64
    mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_C "
           "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
           "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO and/or "
           "MBEDTLS_CTR_DRBG_C not defined.\n");
65 66 67
    return( 0 );
}
#else
Rich Evans's avatar
Rich Evans committed
68
int main( void )
69 70 71
{
    FILE *f;

72 73
    int ret;
    size_t n, buflen;
74 75 76
    int listen_fd = -1;
    int client_fd = -1;

77
    unsigned char buf[2048];
78 79
    unsigned char hash[20];
    unsigned char buf2[2];
80
    const char *pers = "dh_server";
81

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
82 83 84 85 86
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_rsa_context rsa;
    mbedtls_dhm_context dhm;
    mbedtls_aes_context aes;
87 88

    memset( &rsa, 0, sizeof( rsa ) );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
89 90
    mbedtls_dhm_init( &dhm );
    mbedtls_aes_init( &aes );
91
    mbedtls_ctr_drbg_init( &ctr_drbg );
92 93 94 95

    /*
     * 1. Setup the RNG
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
96
    mbedtls_printf( "\n  . Seeding the random number generator" );
97 98
    fflush( stdout );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
99
    mbedtls_entropy_init( &entropy );
100
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
101 102
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
103
    {
104
        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
105 106
        goto exit;
    }
107 108 109 110

    /*
     * 2a. Read the server's private RSA key
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
111
    mbedtls_printf( "\n  . Reading private key from rsa_priv.txt" );
112 113 114 115 116
    fflush( stdout );

    if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
    {
        ret = 1;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
117
        mbedtls_printf( " failed\n  ! Could not open rsa_priv.txt\n" \
118 119 120 121
                "  ! Please run rsa_genkey first\n\n" );
        goto exit;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
122
    mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
123

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
124 125 126 127 128 129 130 131
    if( ( ret = mbedtls_mpi_read_file( &rsa.N , 16, f ) ) != 0 ||
        ( ret = mbedtls_mpi_read_file( &rsa.E , 16, f ) ) != 0 ||
        ( ret = mbedtls_mpi_read_file( &rsa.D , 16, f ) ) != 0 ||
        ( ret = mbedtls_mpi_read_file( &rsa.P , 16, f ) ) != 0 ||
        ( ret = mbedtls_mpi_read_file( &rsa.Q , 16, f ) ) != 0 ||
        ( ret = mbedtls_mpi_read_file( &rsa.DP, 16, f ) ) != 0 ||
        ( ret = mbedtls_mpi_read_file( &rsa.DQ, 16, f ) ) != 0 ||
        ( ret = mbedtls_mpi_read_file( &rsa.QP, 16, f ) ) != 0 )
132
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
133
        mbedtls_printf( " failed\n  ! mbedtls_mpi_read_file returned %d\n\n", ret );
134 135 136
        goto exit;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
137
    rsa.len = ( mbedtls_mpi_msb( &rsa.N ) + 7 ) >> 3;
138

139 140 141 142 143
    fclose( f );

    /*
     * 2b. Get the DHM modulus and generator
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
144
    mbedtls_printf( "\n  . Reading DH parameters from dh_prime.txt" );
145 146 147 148 149
    fflush( stdout );

    if( ( f = fopen( "dh_prime.txt", "rb" ) ) == NULL )
    {
        ret = 1;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
150
        mbedtls_printf( " failed\n  ! Could not open dh_prime.txt\n" \
151 152 153 154
                "  ! Please run dh_genprime first\n\n" );
        goto exit;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
155 156
    if( mbedtls_mpi_read_file( &dhm.P, 16, f ) != 0 ||
        mbedtls_mpi_read_file( &dhm.G, 16, f ) != 0 )
157
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
158
        mbedtls_printf( " failed\n  ! Invalid DH parameter file\n\n" );
159 160 161 162 163 164 165 166
        goto exit;
    }

    fclose( f );

    /*
     * 3. Wait for a client to connect
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
167
    mbedtls_printf( "\n  . Waiting for a remote connection" );
168 169
    fflush( stdout );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
170
    if( ( ret = mbedtls_net_bind( &listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
171
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
172
        mbedtls_printf( " failed\n  ! mbedtls_net_bind returned %d\n\n", ret );
173 174 175
        goto exit;
    }

176 177
    if( ( ret = mbedtls_net_accept( listen_fd, &client_fd,
                                    NULL, 0, NULL ) ) != 0 )
178
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
179
        mbedtls_printf( " failed\n  ! mbedtls_net_accept returned %d\n\n", ret );
180 181 182 183 184 185
        goto exit;
    }

    /*
     * 4. Setup the DH parameters (P,G,Ys)
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
186
    mbedtls_printf( "\n  . Sending the server's DH parameters" );
187 188 189 190
    fflush( stdout );

    memset( buf, 0, sizeof( buf ) );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
191 192
    if( ( ret = mbedtls_dhm_make_params( &dhm, (int) mbedtls_mpi_size( &dhm.P ), buf, &n,
                                 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
193
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
194
        mbedtls_printf( " failed\n  ! mbedtls_dhm_make_params returned %d\n\n", ret );
195 196 197 198 199 200
        goto exit;
    }

    /*
     * 5. Sign the parameters and send them
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
201
    mbedtls_sha1( buf, n, hash );
202 203 204 205

    buf[n    ] = (unsigned char)( rsa.len >> 8 );
    buf[n + 1] = (unsigned char)( rsa.len      );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
206
    if( ( ret = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256,
207 208
                                0, hash, buf + n + 2 ) ) != 0 )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
209
        mbedtls_printf( " failed\n  ! mbedtls_rsa_pkcs1_sign returned %d\n\n", ret );
210 211 212 213 214 215 216
        goto exit;
    }

    buflen = n + 2 + rsa.len;
    buf2[0] = (unsigned char)( buflen >> 8 );
    buf2[1] = (unsigned char)( buflen      );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
217 218
    if( ( ret = mbedtls_net_send( &client_fd, buf2, 2 ) ) != 2 ||
        ( ret = mbedtls_net_send( &client_fd, buf, buflen ) ) != (int) buflen )
219
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
220
        mbedtls_printf( " failed\n  ! mbedtls_net_send returned %d\n\n", ret );
221 222 223 224 225 226
        goto exit;
    }

    /*
     * 6. Get the client's public value: Yc = G ^ Xc mod P
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
227
    mbedtls_printf( "\n  . Receiving the client's public value" );
228 229 230 231
    fflush( stdout );

    memset( buf, 0, sizeof( buf ) );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
232
    if( ( ret = mbedtls_net_recv( &client_fd, buf, n ) ) != (int) n )
233
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
234
        mbedtls_printf( " failed\n  ! mbedtls_net_recv returned %d\n\n", ret );
235 236 237
        goto exit;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
238
    if( ( ret = mbedtls_dhm_read_public( &dhm, buf, dhm.len ) ) != 0 )
239
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
240
        mbedtls_printf( " failed\n  ! mbedtls_dhm_read_public returned %d\n\n", ret );
241 242 243 244 245 246
        goto exit;
    }

    /*
     * 7. Derive the shared secret: K = Ys ^ Xc mod P
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
247
    mbedtls_printf( "\n  . Shared secret: " );
248 249
    fflush( stdout );

250
    if( ( ret = mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &n,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
251
                                 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
252
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
253
        mbedtls_printf( " failed\n  ! mbedtls_dhm_calc_secret returned %d\n\n", ret );
254 255 256 257
        goto exit;
    }

    for( n = 0; n < 16; n++ )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
258
        mbedtls_printf( "%02x", buf[n] );
259 260 261 262 263 264 265 266 267

    /*
     * 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.
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
268
    mbedtls_printf( "...\n  . Encrypting and sending the ciphertext" );
269 270
    fflush( stdout );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
271
    mbedtls_aes_setkey_enc( &aes, buf, 256 );
272
    memcpy( buf, PLAINTEXT, 16 );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
273
    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
274

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
275
    if( ( ret = mbedtls_net_send( &client_fd, buf, 16 ) ) != 16 )
276
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
277
        mbedtls_printf( " failed\n  ! mbedtls_net_send returned %d\n\n", ret );
278 279 280
        goto exit;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
281
    mbedtls_printf( "\n\n" );
282 283 284

exit:

285
    if( client_fd != -1 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
286
        mbedtls_net_close( client_fd );
287

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
288 289 290 291 292
    mbedtls_aes_free( &aes );
    mbedtls_rsa_free( &rsa );
    mbedtls_dhm_free( &dhm );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );
293

294
#if defined(_WIN32)
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
295
    mbedtls_printf( "  + Press Enter to exit this program.\n" );
296 297 298 299 300
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
301 302 303
#endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
          MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
          MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */