1 /*
2 * SSL client demonstration program
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * 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
31 #include <stdio.h>
32 #include <stdlib.h>
33 #define mbedtls_time time
34 #define mbedtls_time_t time_t
35 #define mbedtls_fprintf fprintf
36 #define mbedtls_printf printf
37 #define mbedtls_exit exit
38 #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
39 #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
40 #endif /* MBEDTLS_PLATFORM_C */
41
42 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
43 !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
44 !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \
45 !defined(MBEDTLS_CERTS_C) || !defined(MBEDTLS_PEM_PARSE_C) || \
46 !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C)
main(void)47 int main( void )
48 {
49 mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
50 "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
51 "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
52 "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
53 "not defined.\n");
54 return( 0 );
55 }
56 #else
57
58 #include "mbedtls/net_sockets.h"
59 #include "mbedtls/debug.h"
60 #include "mbedtls/ssl.h"
61 #include "mbedtls/entropy.h"
62 #include "mbedtls/ctr_drbg.h"
63 #include "mbedtls/error.h"
64 #include "mbedtls/certs.h"
65
66 #include <string.h>
67
68 #define SERVER_PORT "4433"
69 #define SERVER_NAME "localhost"
70 #define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
71
72 #define DEBUG_LEVEL 1
73
74 #if defined(MBEDTLS_CHECK_PARAMS)
75 #include "mbedtls/platform_util.h"
mbedtls_param_failed(const char * failure_condition,const char * file,int line)76 void mbedtls_param_failed( const char *failure_condition,
77 const char *file,
78 int line )
79 {
80 mbedtls_printf( "%s:%i: Input param failed - %s\n",
81 file, line, failure_condition );
82 mbedtls_exit( MBEDTLS_EXIT_FAILURE );
83 }
84 #endif
85
my_debug(void * ctx,int level,const char * file,int line,const char * str)86 static void my_debug( void *ctx, int level,
87 const char *file, int line,
88 const char *str )
89 {
90 ((void) level);
91
92 mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
93 fflush( (FILE *) ctx );
94 }
95
main(void)96 int main( void )
97 {
98 int ret = 1, len;
99 int exit_code = MBEDTLS_EXIT_FAILURE;
100 mbedtls_net_context server_fd;
101 uint32_t flags;
102 unsigned char buf[1024];
103 const char *pers = "ssl_client1";
104
105 mbedtls_entropy_context entropy;
106 mbedtls_ctr_drbg_context ctr_drbg;
107 mbedtls_ssl_context ssl;
108 mbedtls_ssl_config conf;
109 mbedtls_x509_crt cacert;
110
111 #if defined(MBEDTLS_DEBUG_C)
112 mbedtls_debug_set_threshold( DEBUG_LEVEL );
113 #endif
114
115 /*
116 * 0. Initialize the RNG and the session data
117 */
118 mbedtls_net_init( &server_fd );
119 mbedtls_ssl_init( &ssl );
120 mbedtls_ssl_config_init( &conf );
121 mbedtls_x509_crt_init( &cacert );
122 mbedtls_ctr_drbg_init( &ctr_drbg );
123
124 mbedtls_printf( "\n . Seeding the random number generator..." );
125 fflush( stdout );
126
127 mbedtls_entropy_init( &entropy );
128 if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
129 (const unsigned char *) pers,
130 strlen( pers ) ) ) != 0 )
131 {
132 mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
133 goto exit;
134 }
135
136 mbedtls_printf( " ok\n" );
137
138 /*
139 * 0. Initialize certificates
140 */
141 mbedtls_printf( " . Loading the CA root certificate ..." );
142 fflush( stdout );
143
144 ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
145 mbedtls_test_cas_pem_len );
146 if( ret < 0 )
147 {
148 mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
149 goto exit;
150 }
151
152 mbedtls_printf( " ok (%d skipped)\n", ret );
153
154 /*
155 * 1. Start the connection
156 */
157 mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT );
158 fflush( stdout );
159
160 if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME,
161 SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
162 {
163 mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret );
164 goto exit;
165 }
166
167 mbedtls_printf( " ok\n" );
168
169 /*
170 * 2. Setup stuff
171 */
172 mbedtls_printf( " . Setting up the SSL/TLS structure..." );
173 fflush( stdout );
174
175 if( ( ret = mbedtls_ssl_config_defaults( &conf,
176 MBEDTLS_SSL_IS_CLIENT,
177 MBEDTLS_SSL_TRANSPORT_STREAM,
178 MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
179 {
180 mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
181 goto exit;
182 }
183
184 mbedtls_printf( " ok\n" );
185
186 /* OPTIONAL is not optimal for security,
187 * but makes interop easier in this simplified example */
188 mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
189 mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
190 mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
191 mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
192
193 if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
194 {
195 mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
196 goto exit;
197 }
198
199 if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 )
200 {
201 mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
202 goto exit;
203 }
204
205 mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
206
207 /*
208 * 4. Handshake
209 */
210 mbedtls_printf( " . Performing the SSL/TLS handshake..." );
211 fflush( stdout );
212
213 while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
214 {
215 if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
216 {
217 mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
218 goto exit;
219 }
220 }
221
222 mbedtls_printf( " ok\n" );
223
224 /*
225 * 5. Verify the server certificate
226 */
227 mbedtls_printf( " . Verifying peer X.509 certificate..." );
228
229 /* In real life, we probably want to bail out when ret != 0 */
230 if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 )
231 {
232 char vrfy_buf[512];
233
234 mbedtls_printf( " failed\n" );
235
236 mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
237
238 mbedtls_printf( "%s\n", vrfy_buf );
239 }
240 else
241 mbedtls_printf( " ok\n" );
242
243 /*
244 * 3. Write the GET request
245 */
246 mbedtls_printf( " > Write to server:" );
247 fflush( stdout );
248
249 len = sprintf( (char *) buf, GET_REQUEST );
250
251 while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 )
252 {
253 if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
254 {
255 mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
256 goto exit;
257 }
258 }
259
260 len = ret;
261 mbedtls_printf( " %d bytes written\n\n%s", len, (char *) buf );
262
263 /*
264 * 7. Read the HTTP response
265 */
266 mbedtls_printf( " < Read from server:" );
267 fflush( stdout );
268
269 do
270 {
271 len = sizeof( buf ) - 1;
272 memset( buf, 0, sizeof( buf ) );
273 ret = mbedtls_ssl_read( &ssl, buf, len );
274
275 if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
276 continue;
277
278 if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
279 break;
280
281 if( ret < 0 )
282 {
283 mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret );
284 break;
285 }
286
287 if( ret == 0 )
288 {
289 mbedtls_printf( "\n\nEOF\n\n" );
290 break;
291 }
292
293 len = ret;
294 mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf );
295 }
296 while( 1 );
297
298 mbedtls_ssl_close_notify( &ssl );
299
300 exit_code = MBEDTLS_EXIT_SUCCESS;
301
302 exit:
303
304 #ifdef MBEDTLS_ERROR_C
305 if( exit_code != MBEDTLS_EXIT_SUCCESS )
306 {
307 char error_buf[100];
308 mbedtls_strerror( ret, error_buf, 100 );
309 mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf );
310 }
311 #endif
312
313 mbedtls_net_free( &server_fd );
314
315 mbedtls_x509_crt_free( &cacert );
316 mbedtls_ssl_free( &ssl );
317 mbedtls_ssl_config_free( &conf );
318 mbedtls_ctr_drbg_free( &ctr_drbg );
319 mbedtls_entropy_free( &entropy );
320
321 #if defined(_WIN32)
322 mbedtls_printf( " + Press Enter to exit this program.\n" );
323 fflush( stdout ); getchar();
324 #endif
325
326 return( exit_code );
327 }
328 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
329 MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
330 MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C &&
331 MBEDTLS_X509_CRT_PARSE_C */
332