ssl_tls: fix format warning in ssl_parse_certificate() on x86_64
[tropicssl.git] / programs / test / ssl_test.c
blob35e724bbc9c83dd7b96bd85fb279853f8768f3c5
1 /*
2 * SSL/TLS stress testing program
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #ifndef _CRT_SECURE_NO_DEPRECATE
37 #define _CRT_SECURE_NO_DEPRECATE 1
38 #endif
40 #include <string.h>
41 #include <stdlib.h>
42 #include <stdio.h>
44 #include "tropicssl/net.h"
45 #include "tropicssl/ssl.h"
46 #include "tropicssl/havege.h"
47 #include "tropicssl/timing.h"
48 #include "tropicssl/certs.h"
50 #define OPMODE_NONE 0
51 #define OPMODE_CLIENT 1
52 #define OPMODE_SERVER 2
54 #define IOMODE_BLOCK 0
55 #define IOMODE_NONBLOCK 1
57 #define COMMAND_READ 1
58 #define COMMAND_WRITE 2
59 #define COMMAND_BOTH 3
61 #define DFL_OPMODE OPMODE_NONE
62 #define DFL_IOMODE IOMODE_BLOCK
63 #define DFL_SERVER_NAME "localhost"
64 #define DFL_SERVER_PORT 4433
65 #define DFL_COMMAND COMMAND_READ
66 #define DFL_BUFFER_SIZE 1024
67 #define DFL_MAX_BYTES 0
68 #define DFL_DEBUG_LEVEL 0
69 #define DFL_CONN_TIMEOUT 0
70 #define DFL_MAX_CONNECTIONS 0
71 #define DFL_SESSION_REUSE 1
72 #define DFL_SESSION_LIFETIME 86400
73 #define DFL_FORCE_CIPHER 0
76 * server-specific data
78 static const char *dhm_G = "4";
79 static const char *dhm_P =
80 "E4004C1F94182000103D883A448B3F802CE4B44A83301270002C20D0321CFD00"
81 "11CCEF784C26A400F43DFB901BCA7538F2C6B176001CF5A0FD16D2C48B1D0C1C"
82 "F6AC8E1DA6BCC3B4E1F96B0564965300FFA1D0B601EB2800F489AA512C4B248C"
83 "01F76949A60BB7F00A40B1EAB64BDD48E8A700D60B7F1200FA8E77B0A979DABF";
85 int server_fd = -1;
88 * global options
90 struct options {
91 int opmode; /* operation mode (client or server) */
92 int iomode; /* I/O mode (blocking or non-blocking) */
93 const char *server_name; /* hostname of the server (client only) */
94 int server_port; /* port on which the ssl service runs */
95 int command; /* what to do: read or write operation */
96 int buffer_size; /* size of the send/receive buffer */
97 int max_bytes; /* max. # of bytes before a reconnect */
98 int debug_level; /* level of debugging */
99 int conn_timeout; /* max. delay before a reconnect */
100 int max_connections; /* max. number of reconnections */
101 int session_reuse; /* flag to reuse the keying material */
102 int session_lifetime; /* if reached, session data is expired */
103 int force_cipher[2]; /* protocol/cipher to use, or all */
107 * Although this PRNG has good statistical properties (eg. passes
108 * DIEHARD), it is not cryptographically secure.
110 static unsigned long int lcppm5(unsigned long int *state)
112 unsigned long int u, v;
114 u = v = state[4] ^ 1;
115 state[u & 3] ^= u;
116 u ^= (v << 12) ^ (v >> 12);
117 u ^= v * state[0];
118 v >>= 8;
119 u ^= v * state[1];
120 v >>= 8;
121 u ^= v * state[2];
122 v >>= 8;
123 u ^= v * state[3];
124 u &= 0xFFFFFFFF;
125 state[4] = u;
127 return (u);
130 static void my_debug(void *ctx, int level, const char *str)
132 if (level < ((struct options *)ctx)->debug_level)
133 fprintf(stderr, "%s", str);
137 * perform a single SSL connection
139 static int ssl_test(struct options *opt)
141 int ret, i;
142 int client_fd;
143 int bytes_to_read;
144 int bytes_to_write;
145 int offset_to_read = 0;
146 int offset_to_write = 0;
148 long int nb_read;
149 long int nb_written;
151 unsigned long read_state[5];
152 unsigned long write_state[5];
154 unsigned char *read_buf = NULL;
155 unsigned char *write_buf = NULL;
157 struct hr_time t;
158 havege_state hs;
159 ssl_context ssl;
160 ssl_session ssn;
161 x509_cert srvcert;
162 rsa_context rsa;
164 ret = 1;
166 havege_init(&hs);
167 get_timer(&t, 1);
169 memset(read_state, 0, sizeof(read_state));
170 memset(write_state, 0, sizeof(write_state));
172 memset(&srvcert, 0, sizeof(x509_cert));
173 memset(&rsa, 0, sizeof(rsa_context));
175 if (opt->opmode == OPMODE_CLIENT) {
176 if ((ret = net_connect(&client_fd, opt->server_name,
177 opt->server_port)) != 0) {
178 printf(" ! net_connect returned %d\n\n", ret);
179 return (ret);
182 if ((ret = ssl_init(&ssl)) != 0) {
183 printf(" ! ssl_init returned %d\n\n", ret);
184 return (ret);
187 ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
190 if (opt->opmode == OPMODE_SERVER) {
191 ret = x509parse_crt(&srvcert, (const unsigned char *)test_srv_crt,
192 strlen(test_srv_crt));
193 if (ret != 0) {
194 printf(" ! x509parse_crt returned %d\n\n", ret);
195 goto exit;
198 ret = x509parse_crt(&srvcert, (const unsigned char *)test_ca_crt,
199 strlen(test_ca_crt));
200 if (ret != 0) {
201 printf(" ! x509parse_crt returned %d\n\n", ret);
202 goto exit;
205 ret = x509parse_key(&rsa, (const unsigned char *)test_srv_key,
206 strlen(test_srv_key), NULL, 0);
207 if (ret != 0) {
208 printf(" ! x509parse_key returned %d\n\n", ret);
209 goto exit;
212 if (server_fd < 0) {
213 if ((ret = net_bind(&server_fd, NULL,
214 opt->server_port)) != 0) {
215 printf(" ! net_bind returned %d\n\n", ret);
216 return (ret);
220 if ((ret = net_accept(server_fd, &client_fd, NULL)) != 0) {
221 printf(" ! net_accept returned %d\n\n", ret);
222 return (ret);
225 if ((ret = ssl_init(&ssl)) != 0) {
226 printf(" ! ssl_init returned %d\n\n", ret);
227 return (ret);
230 ssl_set_endpoint(&ssl, SSL_IS_SERVER);
231 ssl_set_dh_param(&ssl, dhm_P, dhm_G);
232 ssl_set_ca_chain(&ssl, srvcert.next, NULL);
233 ssl_set_own_cert(&ssl, &srvcert, &rsa);
236 ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
238 ssl_set_rng(&ssl, havege_rand, &hs);
239 ssl_set_dbg(&ssl, my_debug, opt);
240 ssl_set_bio(&ssl, net_recv, &client_fd, net_send, &client_fd);
242 ssl_set_session(&ssl, opt->session_reuse, opt->session_lifetime, &ssn);
244 if (opt->force_cipher[0] == DFL_FORCE_CIPHER)
245 ssl_set_ciphers(&ssl, ssl_default_ciphers);
246 else
247 ssl_set_ciphers(&ssl, opt->force_cipher);
249 if (opt->iomode == IOMODE_NONBLOCK)
250 net_set_nonblock(client_fd);
252 read_buf = (unsigned char *)malloc(opt->buffer_size);
253 write_buf = (unsigned char *)malloc(opt->buffer_size);
255 if (read_buf == NULL || write_buf == NULL) {
256 printf(" ! malloc(%d bytes) failed\n\n", opt->buffer_size);
257 goto exit;
260 nb_read = bytes_to_read = 0;
261 nb_written = bytes_to_write = 0;
263 while (1) {
264 if (opt->command & COMMAND_WRITE) {
265 if (bytes_to_write == 0) {
266 while (bytes_to_write == 0)
267 bytes_to_write =
268 rand() % opt->buffer_size;
270 for (i = 0; i < bytes_to_write; i++)
271 write_buf[i] =
272 (unsigned char)lcppm5(write_state);
274 offset_to_write = 0;
277 ret = ssl_write(&ssl, write_buf + offset_to_write,
278 bytes_to_write);
280 if (ret >= 0) {
281 nb_written += ret;
282 bytes_to_write -= ret;
283 offset_to_write += ret;
286 if (ret == TROPICSSL_ERR_SSL_PEER_CLOSE_NOTIFY ||
287 ret == TROPICSSL_ERR_NET_CONN_RESET) {
288 ret = 0;
289 goto exit;
292 if (ret < 0 && ret != TROPICSSL_ERR_NET_TRY_AGAIN) {
293 printf(" ! ssl_write returned %d\n\n", ret);
294 break;
298 if (opt->command & COMMAND_READ) {
299 if (bytes_to_read == 0) {
300 bytes_to_read = rand() % opt->buffer_size;
301 offset_to_read = 0;
304 ret = ssl_read(&ssl, read_buf + offset_to_read,
305 bytes_to_read);
307 if (ret >= 0) {
308 for (i = 0; i < ret; i++) {
309 if (read_buf[offset_to_read + i] !=
310 (unsigned char)lcppm5(read_state)) {
311 ret = 1;
312 printf
313 (" ! plaintext mismatch\n\n");
314 goto exit;
318 nb_read += ret;
319 bytes_to_read -= ret;
320 offset_to_read += ret;
323 if (ret == TROPICSSL_ERR_SSL_PEER_CLOSE_NOTIFY ||
324 ret == TROPICSSL_ERR_NET_CONN_RESET) {
325 ret = 0;
326 goto exit;
329 if (ret < 0 && ret != TROPICSSL_ERR_NET_TRY_AGAIN) {
330 printf(" ! ssl_read returned %d\n\n", ret);
331 break;
335 ret = 0;
337 if (opt->max_bytes != 0 &&
338 (opt->max_bytes <= nb_read || opt->max_bytes <= nb_written))
339 break;
341 if (opt->conn_timeout != 0 &&
342 opt->conn_timeout <= (int)get_timer(&t, 0))
343 break;
346 exit:
348 fflush(stdout);
350 if (read_buf != NULL)
351 free(read_buf);
353 if (write_buf != NULL)
354 free(write_buf);
356 ssl_close_notify(&ssl);
357 x509_free(&srvcert);
358 rsa_free(&rsa);
359 ssl_free(&ssl);
360 net_close(client_fd);
362 return (ret);
365 #define USAGE \
366 "\n usage: ssl_test opmode=<> command=<>...\n" \
367 "\n acceptable parameters:\n" \
368 " opmode=client/server default: <none>\n" \
369 " iomode=block/nonblock default: block\n" \
370 " server_name=%%s default: localhost\n" \
371 " server_port=%%d default: 4433\n" \
372 " command=read/write/both default: read\n" \
373 " buffer_size=%%d (bytes) default: 1024\n" \
374 " max_bytes=%%d (bytes) default: 0 (no limit)\n" \
375 " debug_level=%%d default: 0 (disabled)\n" \
376 " conn_timeout=%%d (ms) default: 0 (no timeout)\n" \
377 " max_connections=%%d default: 0 (no limit)\n" \
378 " session_reuse=on/off default: on (enabled)\n" \
379 " session_lifetime=%%d (s) default: 86400\n" \
380 " force_cipher=<name> default: all enabled\n" \
381 " acceptable cipher names:\n" \
382 " SSL_RSA_RC4_128_MD5 SSL_RSA_RC4_128_SHA\n" \
383 " SSL_RSA_DES_168_SHA SSL_EDH_RSA_DES_168_SHA\n" \
384 " SSL_RSA_AES_128_SHA SSL_EDH_RSA_AES_256_SHA\n" \
385 " SSL_RSA_AES_256_SHA SSL_EDH_RSA_CAMELLIA_256_SHA\n" \
386 " SSL_RSA_CAMELLIA_128_SHA SSL_RSA_CAMELLIA_256_SHA\n\n"
388 int main(int argc, char *argv[])
390 int i, j, n;
391 int ret = 1;
392 int nb_conn;
393 char *p, *q;
394 struct options opt;
396 if (argc == 1) {
397 usage:
398 printf(USAGE);
399 goto exit;
402 opt.opmode = DFL_OPMODE;
403 opt.iomode = DFL_IOMODE;
404 opt.server_name = DFL_SERVER_NAME;
405 opt.server_port = DFL_SERVER_PORT;
406 opt.command = DFL_COMMAND;
407 opt.buffer_size = DFL_BUFFER_SIZE;
408 opt.max_bytes = DFL_MAX_BYTES;
409 opt.debug_level = DFL_DEBUG_LEVEL;
410 opt.conn_timeout = DFL_CONN_TIMEOUT;
411 opt.max_connections = DFL_MAX_CONNECTIONS;
412 opt.session_reuse = DFL_SESSION_REUSE;
413 opt.session_lifetime = DFL_SESSION_LIFETIME;
414 opt.force_cipher[0] = DFL_FORCE_CIPHER;
416 for (i = 1; i < argc; i++) {
417 n = strlen(argv[i]);
419 for (j = 0; j < n; j++) {
420 if (argv[i][j] >= 'A' && argv[i][j] <= 'Z')
421 argv[i][j] |= 0x20;
424 p = argv[i];
425 if ((q = strchr(p, '=')) == NULL)
426 continue;
427 *q++ = '\0';
429 if (strcmp(p, "opmode") == 0) {
430 if (strcmp(q, "client") == 0)
431 opt.opmode = OPMODE_CLIENT;
432 else if (strcmp(q, "server") == 0)
433 opt.opmode = OPMODE_SERVER;
434 else
435 goto usage;
438 if (strcmp(p, "iomode") == 0) {
439 if (strcmp(q, "block") == 0)
440 opt.iomode = IOMODE_BLOCK;
441 else if (strcmp(q, "nonblock") == 0)
442 opt.iomode = IOMODE_NONBLOCK;
443 else
444 goto usage;
447 if (strcmp(p, "server_name") == 0)
448 opt.server_name = q;
450 if (strcmp(p, "server_port") == 0) {
451 opt.server_port = atoi(q);
452 if (opt.server_port < 1 || opt.server_port > 65535)
453 goto usage;
456 if (strcmp(p, "command") == 0) {
457 if (strcmp(q, "read") == 0)
458 opt.command = COMMAND_READ;
459 else if (strcmp(q, "write") == 0)
460 opt.command = COMMAND_WRITE;
461 else if (strcmp(q, "both") == 0) {
462 opt.iomode = IOMODE_NONBLOCK;
463 opt.command = COMMAND_BOTH;
464 } else
465 goto usage;
468 if (strcmp(p, "buffer_size") == 0) {
469 opt.buffer_size = atoi(q);
470 if (opt.buffer_size < 1 || opt.buffer_size > 1048576)
471 goto usage;
474 if (strcmp(p, "max_bytes") == 0)
475 opt.max_bytes = atoi(q);
477 if (strcmp(p, "debug_level") == 0)
478 opt.debug_level = atoi(q);
480 if (strcmp(p, "conn_timeout") == 0)
481 opt.conn_timeout = atoi(q);
483 if (strcmp(p, "max_connections") == 0)
484 opt.max_connections = atoi(q);
486 if (strcmp(p, "session_reuse") == 0) {
487 if (strcmp(q, "on") == 0)
488 opt.session_reuse = 1;
489 else if (strcmp(q, "off") == 0)
490 opt.session_reuse = 0;
491 else
492 goto usage;
495 if (strcmp(p, "session_lifetime") == 0)
496 opt.session_lifetime = atoi(q);
498 if (strcmp(p, "force_cipher") == 0) {
499 opt.force_cipher[0] = -1;
501 if (strcmp(q, "ssl_rsa_rc4_128_md5") == 0)
502 opt.force_cipher[0] = SSL_RSA_RC4_128_MD5;
504 if (strcmp(q, "ssl_rsa_rc4_128_sha") == 0)
505 opt.force_cipher[0] = SSL_RSA_RC4_128_SHA;
507 if (strcmp(q, "ssl_rsa_des_168_sha") == 0)
508 opt.force_cipher[0] = SSL_RSA_DES_168_SHA;
510 if (strcmp(q, "ssl_edh_rsa_des_168_sha") == 0)
511 opt.force_cipher[0] = SSL_EDH_RSA_DES_168_SHA;
513 if (strcmp(q, "ssl_rsa_aes_128_sha") == 0)
514 opt.force_cipher[0] = SSL_RSA_AES_128_SHA;
516 if (strcmp(q, "ssl_rsa_aes_256_sha") == 0)
517 opt.force_cipher[0] = SSL_RSA_AES_256_SHA;
519 if (strcmp(q, "ssl_edh_rsa_aes_256_sha") == 0)
520 opt.force_cipher[0] = SSL_EDH_RSA_AES_256_SHA;
522 if (strcmp(q, "ssl_rsa_camellia_128_sha") == 0)
523 opt.force_cipher[0] = SSL_RSA_CAMELLIA_128_SHA;
525 if (strcmp(q, "ssl_rsa_camellia_256_sha") == 0)
526 opt.force_cipher[0] = SSL_RSA_CAMELLIA_256_SHA;
528 if (strcmp(q, "ssl_edh_rsa_camellia_256_sha") == 0)
529 opt.force_cipher[0] =
530 SSL_EDH_RSA_CAMELLIA_256_SHA;
532 if (opt.force_cipher[0] < 0)
533 goto usage;
535 opt.force_cipher[1] = 0;
539 switch (opt.opmode) {
540 case OPMODE_CLIENT:
541 break;
543 case OPMODE_SERVER:
544 break;
546 default:
547 goto usage;
550 nb_conn = 0;
552 do {
553 nb_conn++;
554 ret = ssl_test(&opt);
555 if (opt.max_connections != 0 && opt.max_connections <= nb_conn)
556 break;
558 while (ret == 0);
560 exit:
562 #ifdef WIN32
563 printf(" Press Enter to exit this program.\n");
564 fflush(stdout);
565 getchar();
566 #endif
568 return (ret);