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>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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
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"
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";
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;
116 u
^= (v
<< 12) ^ (v
>> 12);
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
)
145 int offset_to_read
= 0;
146 int offset_to_write
= 0;
151 unsigned long read_state
[5];
152 unsigned long write_state
[5];
154 unsigned char *read_buf
= NULL
;
155 unsigned char *write_buf
= NULL
;
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
);
182 if ((ret
= ssl_init(&ssl
)) != 0) {
183 printf(" ! ssl_init returned %d\n\n", 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
));
194 printf(" ! x509parse_crt returned %d\n\n", ret
);
198 ret
= x509parse_crt(&srvcert
, (const unsigned char *)test_ca_crt
,
199 strlen(test_ca_crt
));
201 printf(" ! x509parse_crt returned %d\n\n", ret
);
205 ret
= x509parse_key(&rsa
, (const unsigned char *)test_srv_key
,
206 strlen(test_srv_key
), NULL
, 0);
208 printf(" ! x509parse_key returned %d\n\n", ret
);
213 if ((ret
= net_bind(&server_fd
, NULL
,
214 opt
->server_port
)) != 0) {
215 printf(" ! net_bind returned %d\n\n", ret
);
220 if ((ret
= net_accept(server_fd
, &client_fd
, NULL
)) != 0) {
221 printf(" ! net_accept returned %d\n\n", ret
);
225 if ((ret
= ssl_init(&ssl
)) != 0) {
226 printf(" ! ssl_init returned %d\n\n", 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
);
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
);
260 nb_read
= bytes_to_read
= 0;
261 nb_written
= bytes_to_write
= 0;
264 if (opt
->command
& COMMAND_WRITE
) {
265 if (bytes_to_write
== 0) {
266 while (bytes_to_write
== 0)
268 rand() % opt
->buffer_size
;
270 for (i
= 0; i
< bytes_to_write
; i
++)
272 (unsigned char)lcppm5(write_state
);
277 ret
= ssl_write(&ssl
, write_buf
+ offset_to_write
,
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
) {
292 if (ret
< 0 && ret
!= TROPICSSL_ERR_NET_TRY_AGAIN
) {
293 printf(" ! ssl_write returned %d\n\n", ret
);
298 if (opt
->command
& COMMAND_READ
) {
299 if (bytes_to_read
== 0) {
300 bytes_to_read
= rand() % opt
->buffer_size
;
304 ret
= ssl_read(&ssl
, read_buf
+ offset_to_read
,
308 for (i
= 0; i
< ret
; i
++) {
309 if (read_buf
[offset_to_read
+ i
] !=
310 (unsigned char)lcppm5(read_state
)) {
313 (" ! plaintext mismatch\n\n");
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
) {
329 if (ret
< 0 && ret
!= TROPICSSL_ERR_NET_TRY_AGAIN
) {
330 printf(" ! ssl_read returned %d\n\n", ret
);
337 if (opt
->max_bytes
!= 0 &&
338 (opt
->max_bytes
<= nb_read
|| opt
->max_bytes
<= nb_written
))
341 if (opt
->conn_timeout
!= 0 &&
342 opt
->conn_timeout
<= (int)get_timer(&t
, 0))
350 if (read_buf
!= NULL
)
353 if (write_buf
!= NULL
)
356 ssl_close_notify(&ssl
);
360 net_close(client_fd
);
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
[])
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
++) {
419 for (j
= 0; j
< n
; j
++) {
420 if (argv
[i
][j
] >= 'A' && argv
[i
][j
] <= 'Z')
425 if ((q
= strchr(p
, '=')) == NULL
)
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
;
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
;
447 if (strcmp(p
, "server_name") == 0)
450 if (strcmp(p
, "server_port") == 0) {
451 opt
.server_port
= atoi(q
);
452 if (opt
.server_port
< 1 || opt
.server_port
> 65535)
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
;
468 if (strcmp(p
, "buffer_size") == 0) {
469 opt
.buffer_size
= atoi(q
);
470 if (opt
.buffer_size
< 1 || opt
.buffer_size
> 1048576)
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;
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)
535 opt
.force_cipher
[1] = 0;
539 switch (opt
.opmode
) {
554 ret
= ssl_test(&opt
);
555 if (opt
.max_connections
!= 0 && opt
.max_connections
<= nb_conn
)
563 printf(" Press Enter to exit this program.\n");