dh_server.c 9.15 KB
Newer Older
1 2 3
/*
 *  Diffie-Hellman-Merkle key exchange (server side)
 *
4
 *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5
 *  SPDX-License-Identifier: Apache-2.0
6
 *
7 8 9
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may
 *  not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
10
 *
11
 *  http://www.apache.org/licenses/LICENSE-2.0
12
 *
13 14 15 16 17
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
18
 *
19
 *  This file is part of mbed TLS (https://tls.mbed.org)
20 21
 */

22
#if !defined(MBEDTLS_CONFIG_FILE)
23
#include "mbedtls/config.h"
24
#else
25
#include MBEDTLS_CONFIG_FILE
26
#endif
27

28
#if defined(MBEDTLS_PLATFORM_C)
29
#include "mbedtls/platform.h"
30
#else
Rich Evans's avatar
Rich Evans committed
31
#include <stdio.h>
32
#define mbedtls_printf     printf
33
#define mbedtls_time_t     time_t
34 35
#endif

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
#include "mbedtls/net_sockets.h"
41 42 43 44 45 46
#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
#define SERVER_PORT "11999"
53 54
#define PLAINTEXT "==Hello there!=="

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
{
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
    mbedtls_net_context listen_fd, client_fd;
75

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

81 82 83 84 85
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_rsa_context rsa;
    mbedtls_dhm_context dhm;
    mbedtls_aes_context aes;
86

87 88 89
    mbedtls_net_init( &listen_fd );
    mbedtls_net_init( &client_fd );
    mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256 );
90 91
    mbedtls_dhm_init( &dhm );
    mbedtls_aes_init( &aes );
92
    mbedtls_ctr_drbg_init( &ctr_drbg );
93 94 95 96

    /*
     * 1. Setup the RNG
     */
97
    mbedtls_printf( "\n  . Seeding the random number generator" );
98 99
    fflush( stdout );

100
    mbedtls_entropy_init( &entropy );
101
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
102 103
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
104
    {
105
        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
106 107
        goto exit;
    }
108 109 110 111

    /*
     * 2a. Read the server's private RSA key
     */
112
    mbedtls_printf( "\n  . Reading private key from rsa_priv.txt" );
113 114 115 116 117
    fflush( stdout );

    if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
    {
        ret = 1;
118
        mbedtls_printf( " failed\n  ! Could not open rsa_priv.txt\n" \
119 120 121 122
                "  ! Please run rsa_genkey first\n\n" );
        goto exit;
    }

123
    mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
124

125 126 127 128 129 130 131 132
    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 )
133
    {
134
        mbedtls_printf( " failed\n  ! mbedtls_mpi_read_file returned %d\n\n", ret );
135
        fclose( f );
136 137 138
        goto exit;
    }

139
    rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3;
140

141 142 143 144 145
    fclose( f );

    /*
     * 2b. Get the DHM modulus and generator
     */
146
    mbedtls_printf( "\n  . Reading DH parameters from dh_prime.txt" );
147 148 149 150 151
    fflush( stdout );

    if( ( f = fopen( "dh_prime.txt", "rb" ) ) == NULL )
    {
        ret = 1;
152
        mbedtls_printf( " failed\n  ! Could not open dh_prime.txt\n" \
153 154 155 156
                "  ! Please run dh_genprime first\n\n" );
        goto exit;
    }

157 158
    if( mbedtls_mpi_read_file( &dhm.P, 16, f ) != 0 ||
        mbedtls_mpi_read_file( &dhm.G, 16, f ) != 0 )
159
    {
160
        mbedtls_printf( " failed\n  ! Invalid DH parameter file\n\n" );
161
        fclose( f );
162 163 164 165 166 167 168 169
        goto exit;
    }

    fclose( f );

    /*
     * 3. Wait for a client to connect
     */
170
    mbedtls_printf( "\n  . Waiting for a remote connection" );
171 172
    fflush( stdout );

173
    if( ( ret = mbedtls_net_bind( &listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
174
    {
175
        mbedtls_printf( " failed\n  ! mbedtls_net_bind returned %d\n\n", ret );
176 177 178
        goto exit;
    }

179
    if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
180
                                    NULL, 0, NULL ) ) != 0 )
181
    {
182
        mbedtls_printf( " failed\n  ! mbedtls_net_accept returned %d\n\n", ret );
183 184 185 186 187 188
        goto exit;
    }

    /*
     * 4. Setup the DH parameters (P,G,Ys)
     */
189
    mbedtls_printf( "\n  . Sending the server's DH parameters" );
190 191 192 193
    fflush( stdout );

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

194 195
    if( ( ret = mbedtls_dhm_make_params( &dhm, (int) mbedtls_mpi_size( &dhm.P ), buf, &n,
                                 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
196
    {
197
        mbedtls_printf( " failed\n  ! mbedtls_dhm_make_params returned %d\n\n", ret );
198 199 200 201 202 203
        goto exit;
    }

    /*
     * 5. Sign the parameters and send them
     */
204
    mbedtls_sha1( buf, n, hash );
205 206 207 208

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

209
    if( ( ret = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256,
210 211
                                0, hash, buf + n + 2 ) ) != 0 )
    {
212
        mbedtls_printf( " failed\n  ! mbedtls_rsa_pkcs1_sign returned %d\n\n", ret );
213 214 215 216 217 218 219
        goto exit;
    }

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

220 221
    if( ( ret = mbedtls_net_send( &client_fd, buf2, 2 ) ) != 2 ||
        ( ret = mbedtls_net_send( &client_fd, buf, buflen ) ) != (int) buflen )
222
    {
223
        mbedtls_printf( " failed\n  ! mbedtls_net_send returned %d\n\n", ret );
224 225 226 227 228 229
        goto exit;
    }

    /*
     * 6. Get the client's public value: Yc = G ^ Xc mod P
     */
230
    mbedtls_printf( "\n  . Receiving the client's public value" );
231 232 233 234
    fflush( stdout );

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

235
    if( ( ret = mbedtls_net_recv( &client_fd, buf, n ) ) != (int) n )
236
    {
237
        mbedtls_printf( " failed\n  ! mbedtls_net_recv returned %d\n\n", ret );
238 239 240
        goto exit;
    }

241
    if( ( ret = mbedtls_dhm_read_public( &dhm, buf, dhm.len ) ) != 0 )
242
    {
243
        mbedtls_printf( " failed\n  ! mbedtls_dhm_read_public returned %d\n\n", ret );
244 245 246 247 248 249
        goto exit;
    }

    /*
     * 7. Derive the shared secret: K = Ys ^ Xc mod P
     */
250
    mbedtls_printf( "\n  . Shared secret: " );
251 252
    fflush( stdout );

253
    if( ( ret = mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &n,
254
                                 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
255
    {
256
        mbedtls_printf( " failed\n  ! mbedtls_dhm_calc_secret returned %d\n\n", ret );
257 258 259 260
        goto exit;
    }

    for( n = 0; n < 16; n++ )
261
        mbedtls_printf( "%02x", buf[n] );
262 263 264 265 266 267 268 269 270

    /*
     * 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.
     */
271
    mbedtls_printf( "...\n  . Encrypting and sending the ciphertext" );
272 273
    fflush( stdout );

274
    mbedtls_aes_setkey_enc( &aes, buf, 256 );
275
    memcpy( buf, PLAINTEXT, 16 );
276
    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
277

278
    if( ( ret = mbedtls_net_send( &client_fd, buf, 16 ) ) != 16 )
279
    {
280
        mbedtls_printf( " failed\n  ! mbedtls_net_send returned %d\n\n", ret );
281 282 283
        goto exit;
    }

284
    mbedtls_printf( "\n\n" );
285 286 287

exit:

288 289
    mbedtls_net_free( &client_fd );
    mbedtls_net_free( &listen_fd );
290

291 292 293 294 295
    mbedtls_aes_free( &aes );
    mbedtls_rsa_free( &rsa );
    mbedtls_dhm_free( &dhm );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );
296

297
#if defined(_WIN32)
298
    mbedtls_printf( "  + Press Enter to exit this program.\n" );
299 300 301 302 303
    fflush( stdout ); getchar();
#endif

    return( ret );
}
304 305 306
#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 */