blob: 1405fdbbfd93a231e8906e7cded0e35e31d2e14b [file] [log] [blame]
b.liud440f9f2025-04-18 10:44:31 +08001#include <stdio.h>
2
3#ifdef MBTK_POLARSSL_SUPPORT
4#include "mbtk_log.h"
5#include "ql/ql_mcm_sim.h"
6#include <sys/socket.h>
7#include <polarssl/net.h>
8#include <polarssl/ssl.h>
9#include <polarssl/entropy.h>
10#include <polarssl/ctr_drbg.h>
11#include <polarssl/certs.h>
12#include <polarssl/x509.h>
13#include <polarssl/error.h>
14#include <polarssl/debug.h>
15#include <polarssl/config.h>
16
17#define DFL_SERVER_NAME "asr"
18#define DFL_SERVER_ADDR NULL
19#define DFL_SERVER_PORT 4433
20#define DFL_REQUEST_PAGE "/"
21#define DFL_REQUEST_SIZE -1
22#define DFL_DEBUG_LEVEL 0
23#define DFL_NBIO 0
24#define DFL_CA_FILE "/ca.crt"
25#define DFL_CA_PATH "/ca.crt"
26#define DFL_CRT_FILE "/client.crt"
27#define DFL_KEY_FILE "/client.key"
28#define DFL_PSK ""
29#define DFL_PSK_IDENTITY "Client_identity"
30#define DFL_FORCE_CIPHER 0
31#define DFL_RENEGOTIATION SSL_RENEGOTIATION_DISABLED
32#define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION
33#define DFL_RENEGOTIATE 0
34#define DFL_EXCHANGES 1
35#define DFL_MIN_VERSION SSL_MINOR_VERSION_3
36#define DFL_MAX_VERSION SSL_MINOR_VERSION_3
37#define DFL_AUTH_MODE SSL_VERIFY_REQUIRED
38#define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE
39#define DFL_TRUNC_HMAC 0
40#define DFL_RECONNECT 0
41#define DFL_RECO_DELAY 0
42#define DFL_TICKETS SSL_SESSION_TICKETS_ENABLED
43#define DFL_ALPN_STRING NULL
44
45#define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: "
46#define GET_REQUEST_END "\r\n\r\n"
47
48#define CA_CERT \
49"-----BEGIN CERTIFICATE-----\r\n" \
50"MIIDKjCCAhICCQCOewfZiRCiNjANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJD\r\n" \
51"TjEQMA4GA1UECBMHU2lDaHVhbjEVMBMGA1UEChMMTU9CSUxFVEVLLkNBMQswCQYD\r\n" \
52"VQQLEwJJVDESMBAGA1UEAxMJTU9CSUxFVEVLMB4XDTE4MDkxODA4MDUzMloXDTMz\r\n" \
53"MDkxOTA4MDUzMlowVzELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB1NpQ2h1YW4xFTAT\r\n" \
54"BgNVBAoTDE1PQklMRVRFSy5DQTELMAkGA1UECxMCSVQxEjAQBgNVBAMTCU1PQklM\r\n" \
55"RVRFSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOkdYJF1h1xjKbY0\r\n" \
56"ipbl88G653PiCh8ZMjmIUYeiDKC8+0wtXZtHvQIl6AncOzBy9XHVOctbKn34exC8\r\n" \
57"SEotMuo2T49vs9VtE8GYu2pOrf3m42NpLRnYAxfm9qw53CMHx+Jn7Oa9fnxa8haA\r\n" \
58"pRc2BTVadWGoS8EEwoZFk0eNb7Z2Gc7U0c+GhISI4oVTTocGvGgMzkvduu5JJbbc\r\n" \
59"BOcNFrii9sRO9vtOYQtqOEg01Uum2Dwp/o2bDLXNJEqAIh4WACiM4iPmmlRHWT2y\r\n" \
60"NjQ3vcbEdrFwbHRtO46+Vw54HnSyCoFb3uCHMNMvXObZ/8AU9E3Cgat4j0sgEeB0\r\n" \
61"hqA4MiMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAtEAjf0CjsLgG9ROdmp1qXYft\r\n" \
62"+ndIT5l82KRK57ZQsfdFbnJOvALeF/ICKU0M2TXgJNiGOA5RxDi00YYdMbOIPwVZ\r\n" \
63"JH4b87J/LYdLAGf+Q+kVI6gWH3hPm4Jzfzq/40KVrf3mpa54yWz6ZYtwfxBjrMgr\r\n" \
64"IVe0O5SIJ99lsddgzgUkqYN2vWJW2zZ50xuXOAyo+pOnjzX0wuOcaBT3JCHWJRAb\r\n" \
65"VhJCf9JbswDgnddJerqFtB8pnpAOdGokLCOoM06q3s3P9mhGX+72HXdX7G8CSAuG\r\n" \
66"PVCGf6RaF0/G4B9R1c3du3lZRlQWfx2pxyU0LS86iFQFWqzqcWEXIcULVdcErQ==\r\n" \
67"-----END CERTIFICATE-----\r\n"
68
69const char ca1_cert[]= CA_CERT;
70
71
72struct options
73{
74 const char *server_name; /* hostname of the server (client only) */
75 const char *server_addr; /* address of the server (client only) */
76 int server_port; /* port on which the ssl service runs */
77 int debug_level; /* level of debugging */
78 int nbio; /* should I/O be blocking? */
79 const char *request_page; /* page on server to request */
80 int request_size; /* pad request with header to requested size */
81 const char *ca_file; /* the file with the CA certificate(s) */
82 const char *ca_path; /* the path with the CA certificate(s) reside */
83 const char *crt_file; /* the file with the client certificate */
84 const char *key_file; /* the file with the client key */
85 const char *psk; /* the pre-shared key */
86 const char *psk_identity; /* the pre-shared key identity */
87 int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
88 int renegotiation; /* enable / disable renegotiation */
89 int allow_legacy; /* allow legacy renegotiation */
90 int renegotiate; /* attempt renegotiation? */
91 int renego_delay; /* delay before enforcing renegotiation */
92 int exchanges; /* number of data exchanges */
93 int min_version; /* minimum protocol version accepted */
94 int max_version; /* maximum protocol version accepted */
95 int auth_mode; /* verify mode for connection */
96 unsigned char mfl_code; /* code for maximum fragment length */
97 int trunc_hmac; /* negotiate truncated hmac or not */
98 int reconnect; /* attempt to resume session */
99 int reco_delay; /* delay in seconds before resuming session */
100 int tickets; /* enable / disable session tickets */
101 const char *alpn_string; /* ALPN supported protocols */
102} opt;
103
104
105static sim_client_handle_type cli_handle;
106int server_fd = -1;
107
108static void my_debug( void *ctx, int level, const char *str )
109{
110 ((void) level);
111
112 fprintf( (FILE *) ctx, "%s", str );
113 fflush( (FILE *) ctx );
114}
115
116
117static int ssl_client_init()
118{
119 int ret = 0, len, tail_len, i, written, frags;
120 unsigned char buf[SSL_MAX_CONTENT_LEN + 1];
121 const char *pers = "ssl_client";
122
123 entropy_context entropy;
124 ctr_drbg_context ctr_drbg;
125 ssl_context ssl;
126 ssl_session saved_session;
127 x509_crt cacert;
128 x509_crt clicert;
129 pk_context pkey;
130
131 memset( &ssl, 0, sizeof( ssl_context ) );
132 memset( &saved_session, 0, sizeof( ssl_session ) );
133 x509_crt_init( &cacert );
134 x509_crt_init( &clicert );
135 pk_init( &pkey );
136
137 fflush( stdout );
138
139 /*
140 * 0. Initialize the RNG and the session data
141 */
142
143 entropy_init( &entropy );
144 if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
145 (const unsigned char *) pers,
146 strlen( pers ) ) ) != 0 )
147 {
148 printf( " failed\n ! ctr_drbg_init returned -0x%x\n", -ret );
149 goto exit;
150 }
151
152 printf( " ok\n" );
153
154 /*
155 * 1.1. Load the trusted CA
156 */
157 //ret = x509_crt_parse(&cacert,ca1_cert,strlen(ca1_cert));
158 ret = x509_crt_parse_file( &cacert, opt.ca_path );
159 if( ret < 0 )
160 {
161 printf( " failed\n ! ca x509_crt_parse returned -0x%x\n\n", -ret );
162 goto exit;
163 }
164 printf( " ok\n" );
165
166 /*
167 * 1.2. Load own certificate and private key
168 *
169 * (can be skipped if client authentication is not required)
170 */
171
172 ret = x509_crt_parse_file( &clicert, opt.crt_file );
173 if( ret != 0 )
174 {
175 printf( " failed\n ! crt x509_crt_parse returned -0x%x\n\n", -ret );
176 goto exit;
177 }
178
179 ret = pk_parse_keyfile( &pkey, opt.key_file, NULL);
180 if( ret != 0 )
181 {
182 printf( " failed\n ! key x509_crt_parse returned -0x%x\n\n", -ret );
183 goto exit;
184 }
185
186 printf( " ok\n" );
187
188 /*
189 * 2. Setup stuff
190 */
191 printf( " . Setting up the SSL/TLS structure..." );
192 fflush( stdout );
193
194 if( ( ret = ssl_init( &ssl ) ) != 0 )
195 {
196 printf( " failed\n ! ssl_init returned -0x%x\n\n", -ret );
197 goto exit;
198 }
199
200 ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
201 ssl_set_authmode( &ssl, opt.auth_mode );
202
203 ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
204 ssl_set_dbg( &ssl, my_debug, stdout );
205
206 ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd );
207
208 ssl_set_renegotiation( &ssl, opt.renegotiation );
209 ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
210
211 ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
212
213 if( ( ret = ssl_set_own_cert( &ssl, &clicert, &pkey ) ) != 0 )
214 {
215 printf( " failed\n ! ssl_set_own_cert returned %d\n\n", ret );
216 goto exit;
217 }
218 if( opt.min_version != -1 )
219 ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );
220 if( opt.max_version != -1 )
221 ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, opt.max_version );
222 printf( " ok\n" );
223 /*
224 * 3. Handshake
225 */
226 printf( " . Performing the SSL/TLS handshake..." );
227 fflush( stdout );
228
229 while( ( ret = ssl_handshake( &ssl ) ) != 0 )
230 {
231 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
232 {
233 printf( " failed\n ! ssl_handshake returned -0x%x\n", -ret );
234 if( ret == POLARSSL_ERR_X509_CERT_VERIFY_FAILED )
235 printf(
236 " Unable to verify the server's certificate. "
237 "Either it is invalid,\n"
238 " or you didn't set ca_file or ca_path "
239 "to an appropriate value.\n"
240 " Alternatively, you may want to use "
241 "auth_mode=optional for testing purposes.\n" );
242 printf( "\n" );
243 goto exit;
244 }
245 }
246
247 printf( " ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n",
248 ssl_get_version( &ssl ), ssl_get_ciphersuite( &ssl ) );
249
250 /*
251 * 4. Verify the server certificate
252 */
253 printf( " . Verifying peer X.509 certificate..." );
254
255 if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
256 {
257 printf( " failed\n" );
258
259 if( ( ret & BADCERT_EXPIRED ) != 0 )
260 printf( " ! server certificate has expired\n" );
261
262 if( ( ret & BADCERT_REVOKED ) != 0 )
263 printf( " ! server certificate has been revoked\n" );
264
265 if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
266 printf( " ! CN mismatch (expected CN=%s)\n", opt.server_name );
267
268 if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
269 printf( " ! self-signed or not signed by a trusted CA\n" );
270
271 printf( "\n" );
272 }
273 else
274 printf( " ok\n" );
275
276 if( ssl_get_peer_cert( &ssl ) != NULL )
277 {
278 printf( " . Peer certificate information ...\n" );
279 x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ",
280 ssl_get_peer_cert( &ssl ) );
281 printf( "%s\n", buf );
282 }
283 /*
284 * 5. Write the GET request
285 */
286 printf( " > Write to server:" );
287 fflush( stdout );
288
289 len = snprintf( (char *) buf, sizeof(buf) - 1, GET_REQUEST,
290 opt.request_page );
291 tail_len = strlen( GET_REQUEST_END );
292
293 /* Add padding to GET request to reach opt.request_size in length */
294 if( opt.request_size != DFL_REQUEST_SIZE &&
295 len + tail_len < opt.request_size )
296 {
297 memset( buf + len, 'A', opt.request_size - len - tail_len );
298 len += opt.request_size - len - tail_len;
299 }
300
301 strncpy( (char *) buf + len, GET_REQUEST_END, sizeof(buf) - len - 1 );
302 len += tail_len;
303
304 /* Truncate if request size is smaller than the "natural" size */
305 if( opt.request_size != DFL_REQUEST_SIZE &&
306 len > opt.request_size )
307 {
308 len = opt.request_size;
309
310 /* Still end with \r\n unless that's really not possible */
311 if( len >= 2 ) buf[len - 2] = '\r';
312 if( len >= 1 ) buf[len - 1] = '\n';
313 }
314
315 for( written = 0, frags = 0; written < len; written += ret, frags++ )
316 {
317 while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 )
318 {
319 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
320 {
321 printf( " failed\n ! ssl_write returned -0x%x\n\n", -ret );
322 goto exit;
323 }
324 }
325 }
326
327 buf[written] = '\0';
328 printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf );
329
330 /*
331 * 6. Read the HTTP response
332 */
333 printf( " < Read from server:" );
334 fflush( stdout );
335
336 do
337 {
338 len = sizeof( buf ) - 1;
339 memset( buf, 0, sizeof( buf ) );
340 ret = ssl_read( &ssl, buf, len );
341
342 if( ret == POLARSSL_ERR_NET_WANT_READ ||
343 ret == POLARSSL_ERR_NET_WANT_WRITE )
344 continue;
345
346 if( ret <= 0 )
347 {
348 switch( ret )
349 {
350 case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
351 printf( " connection was closed gracefully\n" );
352 ret = 0;
353 goto close_notify;
354
355 case 0:
356 case POLARSSL_ERR_NET_CONN_RESET:
357 printf( " connection was reset by peer\n" );
358 ret = 0;
359 goto exit;
360
361 default:
362 printf( " ssl_read returned -0x%x\n", -ret );
363 goto exit;
364 }
365 }
366
367 len = ret;
368 buf[len] = '\0';
369 printf( " %d bytes read\n\n%s", len, (char *) buf );
370
371 /* End of message should be detected according to the syntax of the
372 * application protocol (eg HTTP), just use a dummy test here. */
373 if( ret > 0 && buf[len-1] == '\n' )
374 {
375 ret = 0;
376 break;
377 }
378 }
379 while( 1 );
380
381 /*
382 * 7. Done, cleanly close the connection
383 */
384close_notify:
385 printf( " . Closing the connection..." );
386
387 while( ( ret = ssl_close_notify( &ssl ) ) < 0 )
388 {
389 if( ret == POLARSSL_ERR_NET_CONN_RESET )
390 {
391 printf( " ok (already closed by peer)\n" );
392 ret = 0;
393 goto exit;
394 }
395
396 if( ret != POLARSSL_ERR_NET_WANT_READ &&
397 ret != POLARSSL_ERR_NET_WANT_WRITE )
398 {
399 printf( " failed\n ! ssl_close_notify returned %d\n\n", ret );
400 goto exit;
401 }
402 }
403
404 printf( " ok\n" );
405exit:
406 if( server_fd )
407 net_close( server_fd );
408
409 x509_crt_free( &clicert );
410 x509_crt_free( &cacert );
411 pk_free( &pkey );
412 ssl_session_free( &saved_session );
413 ssl_free( &ssl );
414 ctr_drbg_free( &ctr_drbg );
415 entropy_free( &entropy );
416
417 printf( " ok end\n" );
418 return 0;
419}
420
421int main(int argc, char *argv[])
422{
423 printf("Start!\n");
424
425 opt.server_name = DFL_SERVER_NAME;
426 opt.server_addr = DFL_SERVER_ADDR;
427 opt.server_port = DFL_SERVER_PORT;
428 opt.debug_level = DFL_DEBUG_LEVEL;
429 opt.nbio = DFL_NBIO;
430 opt.request_page = DFL_REQUEST_PAGE;
431 opt.request_size = DFL_REQUEST_SIZE;
432 opt.ca_file = DFL_CA_FILE;
433 opt.ca_path = DFL_CA_PATH;
434 opt.crt_file = DFL_CRT_FILE;
435 opt.key_file = DFL_KEY_FILE;
436 opt.psk = DFL_PSK;
437 opt.psk_identity = DFL_PSK_IDENTITY;
438 opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
439 opt.renegotiation = DFL_RENEGOTIATION;
440 opt.allow_legacy = DFL_ALLOW_LEGACY;
441 opt.renegotiate = DFL_RENEGOTIATE;
442 opt.exchanges = DFL_EXCHANGES;
443 opt.min_version = DFL_MIN_VERSION;
444 opt.max_version = DFL_MAX_VERSION;
445 opt.auth_mode = DFL_AUTH_MODE;
446 opt.mfl_code = DFL_MFL_CODE;
447 opt.trunc_hmac = DFL_TRUNC_HMAC;
448 opt.reconnect = DFL_RECONNECT;
449 opt.reco_delay = DFL_RECO_DELAY;
450 opt.tickets = DFL_TICKETS;
451 opt.alpn_string = DFL_ALPN_STRING;
452
453
454 if(argc < 3)
455 {
456 printf("input error \n example: mbtk_test ip prot\n");
457 return -1;
458 }
459 opt.server_addr = argv[1];
460 opt.server_port = atoi(argv[2]);
461
462 int ret = -1;
463 if( ( ret = net_connect( &server_fd, opt.server_addr,
464 opt.server_port ) ) != 0 )
465 {
466 printf( " failed\n ! net_connect returned -0x%x\n\n", -ret );
467 return -1;
468 }
469
470 ret = net_set_nonblock( server_fd );
471 if( ret != 0 )
472 {
473 printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret );
474 return -1;
475 }
476 printf( " ok\n" );
477 ret = ssl_client_init();
478 printf("ret is %d\n",ret);
479 printf("End!\n");
480 return 0;
481}
482#else
483int main(int argc, char *argv[])
484{
485 printf("No support polarssl.\n");
486 return 0;
487}
488#endif