2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * GnuTLS is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * GnuTLS is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GnuTLS; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
31 #include <gnutls/gnutls.h>
32 #include <gnutls/crypto.h>
37 fprintf(stderr, __VA_ARGS__); \
41 #include "../tests/eagain-common.h"
42 #include "benchmark.h"
44 const char* side
= "";
46 #define PRIO_DH "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+DHE-RSA"
47 #define PRIO_ECDH "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ECDHE-RSA:+CURVE-SECP192R1"
48 #define PRIO_ECDHE_ECDSA "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ECDHE-ECDSA:+CURVE-SECP192R1"
49 #define PRIO_RSA "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+RSA"
51 #define PRIO_AES_CBC_SHA1 "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ANON-DH"
52 #define PRIO_ARCFOUR_128_MD5 "NONE:+VERS-TLS1.0:+ARCFOUR-128:+MD5:+SIGN-ALL:+COMP-NULL:+ANON-DH"
53 #define PRIO_AES_GCM "NONE:+VERS-TLS1.2:+AES-128-GCM:+AEAD:+SIGN-ALL:+COMP-NULL:+ANON-DH"
54 #define PRIO_CAMELLIA_CBC_SHA1 "NONE:+VERS-TLS1.0:+CAMELLIA-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ANON-DH"
56 static const int rsa_bits
= 1776, ec_bits
= 192;
58 /* DH of 1840 bits that is pretty close equivalent to 192 bits of ECDH.
61 "-----BEGIN DH PARAMETERS-----\n"
62 "MIIBxgKB3gNZMD2odqYk7HGnT+kh72vcnGrDhFMad1m4VlYZoLClkRUOH05W9gKF\n"
63 "hjBzlg5zO1Pp14hpSNWdfXcd2glWE2wzkxxxztzt23gdXK1GjfupnALyPS2Q0Oj7\n"
64 "UiLDfos46vXOSzqO3vBElM2HJQ6N1TRU+EqD5t/6aTAV6iAD+yz2Fyv4Xs+rgJC2\n"
65 "IbpunLzM2IhH2u9tLUXGkBzHPW/6Q+fJRhn88OLBC9vwOHPQvw779+FB0NPue1Qs\n"
66 "vb+4HSywpOr4BtNLWST2MzhCYBApvV1dKcZLI5k5Cfmp5ryV+wKB3gEUe9uAk+5I\n"
67 "ENkTLC7XLLNGjPEKwQhBzE7Nh7RKWlZRX+B/cX5/iT7ZF9+N83O/wf2AxEV6CRWV\n"
68 "WiCjvML/wbskpGoGmrPyef7bLHI62x4/nNacGGWEichPW8Sn/qaT80FHyYM0m7Ha\n"
69 "+Q9kYUSx0u1CW//3nGvma5dh/c2iiq8r7J9w2PSYynHts4bYMrRRx2PVeGhvU8+X\n"
70 "nRkYOqptEqoB6NG5kPRL8b5jJSp7J2hN7shDjQB/s9/N8rvF8tRmMUTJpk3Fwr9F\n"
71 "LVdX3640cbukwFTKlkqZ1evymVzx0wICAL0=\n"
72 "-----END DH PARAMETERS-----\n";
74 static unsigned char server_cert_pem
[] =
75 "-----BEGIN CERTIFICATE-----\n"
76 "MIIEEzCCAx6gAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBuDELMAkGA1UEBhMCR1Ix\n"
77 "EjAQBgNVBAoTCUtva28gaW5jLjEXMBUGA1UECxMOc2xlZXBpbmcgZGVwdC4xDzAN\n"
78 "BgNVBAgTBkF0dGlraTEVMBMGA1UEAxMMQ2luZHkgTGF1cGVyMRcwFQYKCZImiZPy\n"
79 "LGQBARMHY2xhdXBlcjEMMAoGA1UEDBMDRHIuMQ8wDQYDVQRBEwZqYWNrYWwxHDAa\n"
80 "BgkqhkiG9w0BCQEWDW5vbmVAbm9uZS5vcmcwIhgPMjAxMjA2MDYxOTAxMjdaGA8y\n"
81 "MDE5MDcxMDE5MDEyN1owgbgxCzAJBgNVBAYTAkdSMRIwEAYDVQQKEwlLb2tvIGlu\n"
82 "Yy4xFzAVBgNVBAsTDnNsZWVwaW5nIGRlcHQuMQ8wDQYDVQQIEwZBdHRpa2kxFTAT\n"
83 "BgNVBAMTDENpbmR5IExhdXBlcjEXMBUGCgmSJomT8ixkAQETB2NsYXVwZXIxDDAK\n"
84 "BgNVBAwTA0RyLjEPMA0GA1UEQRMGamFja2FsMRwwGgYJKoZIhvcNAQkBFg1ub25l\n"
85 "QG5vbmUub3JnMIH9MA0GCSqGSIb3DQEBAQUAA4HrADCB5wKB3wC/VSBHG5adM0r0\n"
86 "E80dgVvt+oVnnDcKYcm9q2WbknTL6dFgjjcEbiHDKmnr1hgyT9jfQVE/ve2XnZqA\n"
87 "kbpYMNrQbdieclNycjoXCj3BJSJXXz3Ra6O4DLNh0/XwsxbVd/tMSQvwAK0MR60K\n"
88 "/yfruL2oxe8j7uDmS5oY8b5O9nP/EVW2u7P1KVhrNxC2rGoaK6iRpgkAX3oP2YVM\n"
89 "hLfPONpDgYGxBvrO0tlpHCYL+miWdRzIDPMYtdcU1v1zVSKAsvJ2dgEwP6FoSiWP\n"
90 "nkw3U41i4oe+T7kVEk1F9QLCnXsCAwEAAaNrMGkwDAYDVR0TAQH/BAIwADAUBgNV\n"
91 "HREEDTALgglsb2NhbGhvc3QwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0PAQH/\n"
92 "BAUDAwegADAdBgNVHQ4EFgQUMwvofEmn5CtM4GygipfIuebOssgwDQYJKoZIhvcN\n"
93 "AQELBQADgd8AdP87xzJGv3ddODGoCaVNipkO96HDwt1fC4Jtp1VTn1V4JRaL4e4D\n"
94 "0dlFMq30kmrLTxNSET7MJ5l2m0XZS7jhbl5UW9jLCv1GurMaVuYK4v0LGGezODoH\n"
95 "8naZkxWYGS16kssPu0SDE0V9gWF31IXs2qs0PHvvpI5WFmjrOPX3RfFeVNhmc5sv\n"
96 "1cy+hnM9wxcT2r+jpKn3mYVVcnG7ANZyLKzLwN/PGkYB+tv8sS0ojxMKZLQjr9xs\n"
97 "z1plHeDzm0/t7gsAkrL8ynSkBBJ1SLqaKMmlP1DmgU/zTlMTyKrG\n"
98 "-----END CERTIFICATE-----\n";
100 static unsigned char server_key_pem
[] =
101 "-----BEGIN RSA PRIVATE KEY-----\n"
102 "MIIEBAIBAAKB3wC/VSBHG5adM0r0E80dgVvt+oVnnDcKYcm9q2WbknTL6dFgjjcE\n"
103 "biHDKmnr1hgyT9jfQVE/ve2XnZqAkbpYMNrQbdieclNycjoXCj3BJSJXXz3Ra6O4\n"
104 "DLNh0/XwsxbVd/tMSQvwAK0MR60K/yfruL2oxe8j7uDmS5oY8b5O9nP/EVW2u7P1\n"
105 "KVhrNxC2rGoaK6iRpgkAX3oP2YVMhLfPONpDgYGxBvrO0tlpHCYL+miWdRzIDPMY\n"
106 "tdcU1v1zVSKAsvJ2dgEwP6FoSiWPnkw3U41i4oe+T7kVEk1F9QLCnXsCAwEAAQKB\n"
107 "3iYR2gpMAvvkaNWH2xgz1QbVAhZLjugR7QJASEdcLMEmFPMRWQEYqL8cgVbbkpTw\n"
108 "Lka9yFzWfZ/dTBCo7lr93Yv7T063kMME12oeL4tuyBZ6bOJueHT2kfq1Igpyl+iB\n"
109 "pw7WuflXKRd4a4X0nwzYBQxYWH7bKkQRZDlViKuOXKVzgT7GqD6cbTZbc/8wUTi7\n"
110 "HoyMlz4d+YH/XL5Zt6SM7cMuJ/VOGGUcBiXqlixzulloihkPwJeg6zxx0e1dVy4q\n"
111 "jvVhb+hmypWajjBDPUwIGFih0lZJ6rqIDyls/ZK2AQJwAPFeAMubo1KWcFU+nHoK\n"
112 "Q/jdOjpuAt7fwczkqhb6uOrJtS4RUtF3x3jfESFYf6Btnt6Slj1HpNKHbud2Weyw\n"
113 "i3lIkkmQq4+8uRjZXlNtp2Sd33NFeYE1D8ll3V2wiwiCOPJxYWpOOwHs7pkcOsAD\n"
114 "ywJwAMruluGFAUhoCxXOGzbJeXOC0U+LbwU72Xgk9zhEX6chaklKgdSnJ8DlHnYe\n"
115 "R+wc2vXRfSGlT1OH0X8ezn82QV8UmYo6cNpMTNarW0rzpFir51owvYSBPnPB+DLX\n"
116 "0JausRZoI6fyZSw4Vxt9PN13EQJwANnEX2FUfcmQs68le1ZclrEdIGEBSpO9PARZ\n"
117 "tuBeu6IR9OaoeJlGwXDbiYAVcajT3oefp++ICTxtNvGchUuYiW4WvO2kmjVoJ3Q1\n"
118 "Afaxs1qDWcyNvS+HKUQjJNNX6kj1/N040JRyGqkFFMyNfLArewJwAL/KfLkJjmvT\n"
119 "QV7LW3cNNYbRRWdLXZLxvJfLQAdiv5BiiWRZUZkcnfq10HNMLSdfIiYfZocNCIrm\n"
120 "mz3sbLdYHLJy8qXsk8oNQLXGX9LXsCTJ2y6nUAZSbCbVVPEgfRhcZCvMIp7Q/YOs\n"
121 "f88QLx0UMQJvYsEnYagLe9EfC0d8fXTKJr143FMxas7j3eftxLEBnx7ZsqCbJD1o\n"
122 "UsvWkp5I3kqIABEqY1ZJV/gU41MceuWURSVADpuuRDLzv8WPdeffad9o2hX/bkI6\n"
123 "2INKeuq1nILiEHAZLloH6/fdjpWZYF0D\n"
124 "-----END RSA PRIVATE KEY-----\n";
126 static unsigned char server_ecc_key_pem
[] =
127 "-----BEGIN EC PRIVATE KEY-----\n"
128 "MGACAQEEGQCovzs4UsfRncfJXO3WOZUe/Zf+usKzEcWgCgYIKoZIzj0DAQGhNAMy\n"
129 "AAREwuCcUHKNWyetsymkAaqA0GCgksI2AjewpOWsraGrfea3GPw1uuyOQRMR7kka\n"
131 "-----END EC PRIVATE KEY-----\n";
133 static unsigned char server_ecc_cert_pem
[] =
134 "-----BEGIN CERTIFICATE-----\n"
135 "MIIBYDCCARWgAwIBAgIETuILrDAKBggqhkjOPQQDAjAcMQswCQYDVQQGEwJCRTEN\n"
136 "MAsGA1UEChMEVGVzdDAeFw0xMTEyMDkxMzIyNTJaFw0xNzA4MTExMzIyNTlaMBwx\n"
137 "CzAJBgNVBAYTAkJFMQ0wCwYDVQQKEwRUZXN0MEkwEwYHKoZIzj0CAQYIKoZIzj0D\n"
138 "AQEDMgAERMLgnFByjVsnrbMppAGqgNBgoJLCNgI3sKTlrK2hq33mtxj8NbrsjkET\n"
139 "Ee5JGr+ro1UwUzAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8G\n"
140 "A1UdDwEB/wQFAwMHgAAwHQYDVR0OBBYEFKeR27mtYWFaH43U2zEvjd28Zf+CMAoG\n"
141 "CCqGSM49BAMCAzkAMDYCGQD7WWWiFV+ddI7tIyMFepKFA1dX4nlc/+ICGQCCPdHc\n"
142 "gMyHv2XyfOGHLhq0HmDTOOiwfC4=\n"
143 "-----END CERTIFICATE-----\n";
145 const gnutls_datum_t server_cert
= { server_cert_pem
,
146 sizeof (server_cert_pem
)
149 const gnutls_datum_t server_key
= { server_key_pem
,
150 sizeof (server_key_pem
)
153 const gnutls_datum_t server_ecc_cert
= { server_ecc_cert_pem
,
154 sizeof (server_ecc_cert_pem
)
157 const gnutls_datum_t server_ecc_key
= { server_ecc_key_pem
,
158 sizeof (server_ecc_key_pem
)
161 char buffer
[64 * 1024];
163 static void tls_log_func(int level
, const char *str
)
165 fprintf(stderr
, "%s|<%d>| %s", side
, level
, str
);
168 static void test_ciphersuite(const char *cipher_prio
, int size
)
171 gnutls_anon_server_credentials_t s_anoncred
;
172 const gnutls_datum_t p3
= { (void*) pkcs3
, strlen(pkcs3
) };
173 static gnutls_dh_params_t dh_params
;
174 gnutls_session_t server
;
178 gnutls_anon_client_credentials_t c_anoncred
;
179 gnutls_session_t client
;
180 /* Need to enable anonymous KX specifically. */
182 struct benchmark_st st
;
185 gnutls_anon_allocate_server_credentials(&s_anoncred
);
186 gnutls_dh_params_init(&dh_params
);
187 gnutls_dh_params_import_pkcs3(dh_params
, &p3
, GNUTLS_X509_FMT_PEM
);
188 gnutls_anon_set_server_dh_params(s_anoncred
, dh_params
);
189 gnutls_init(&server
, GNUTLS_SERVER
);
190 ret
= gnutls_priority_set_direct(server
, cipher_prio
, &str
);
192 fprintf(stderr
, "Error in %s\n", str
);
195 gnutls_credentials_set(server
, GNUTLS_CRD_ANON
, s_anoncred
);
196 gnutls_dh_set_prime_bits(server
, 1024);
197 gnutls_transport_set_push_function(server
, server_push
);
198 gnutls_transport_set_pull_function(server
, server_pull
);
199 gnutls_transport_set_ptr(server
, (gnutls_transport_ptr_t
) server
);
203 gnutls_anon_allocate_client_credentials(&c_anoncred
);
204 gnutls_init(&client
, GNUTLS_CLIENT
);
206 ret
= gnutls_priority_set_direct(client
, cipher_prio
, &str
);
208 fprintf(stderr
, "Error in %s\n", str
);
211 gnutls_credentials_set(client
, GNUTLS_CRD_ANON
, c_anoncred
);
212 gnutls_transport_set_push_function(client
, client_push
);
213 gnutls_transport_set_pull_function(client
, client_pull
);
214 gnutls_transport_set_ptr(client
, (gnutls_transport_ptr_t
) client
);
216 HANDSHAKE(client
, server
);
218 fprintf(stdout
, "Testing %s with %d packet size...\n",
219 gnutls_cipher_suite_get_name(gnutls_kx_get(server
),
220 gnutls_cipher_get(server
),
221 gnutls_mac_get(server
)), size
);
224 gnutls_rnd(GNUTLS_RND_NONCE
, buffer
, sizeof(buffer
));
226 start_benchmark(&st
);
230 ret
= gnutls_record_send(client
, buffer
, size
);
232 while (ret
== GNUTLS_E_AGAIN
);
235 fprintf(stderr
, "Failed sending to server\n");
240 ret
= gnutls_record_recv(server
, buffer
, sizeof(buffer
));
242 while (ret
== GNUTLS_E_AGAIN
);
245 fprintf(stderr
, "Failed receiving from client\n");
251 while (benchmark_must_finish
== 0);
253 stop_benchmark(&st
, NULL
);
254 fprintf(stdout
, "\n");
256 gnutls_bye(client
, GNUTLS_SHUT_WR
);
257 gnutls_bye(server
, GNUTLS_SHUT_WR
);
259 gnutls_deinit(client
);
260 gnutls_deinit(server
);
262 gnutls_anon_free_client_credentials(c_anoncred
);
263 gnutls_anon_free_server_credentials(s_anoncred
);
265 gnutls_dh_params_deinit(dh_params
);
270 double calc_avg(unsigned int *diffs
, unsigned int diffs_size
)
275 for(i
=0;i
<diffs_size
;i
++)
284 double calc_sstdev(unsigned int *diffs
, unsigned int diffs_size
, double avg
)
289 for (i
=0;i
<diffs_size
;i
++) {
290 d
= ((double)diffs
[i
] - avg
);
295 sum
/= diffs_size
- 1;
301 unsigned int diffs
[32*1024];
302 unsigned int diffs_size
= 0;
304 static void test_ciphersuite_kx(const char *cipher_prio
)
307 gnutls_anon_server_credentials_t s_anoncred
;
308 const gnutls_datum_t p3
= { (void*) pkcs3
, strlen(pkcs3
) };
309 static gnutls_dh_params_t dh_params
;
310 gnutls_session_t server
;
313 const char *suite
= NULL
;
315 gnutls_anon_client_credentials_t c_anoncred
;
316 gnutls_certificate_credentials_t c_certcred
, s_certcred
;
317 gnutls_session_t client
;
318 /* Need to enable anonymous KX specifically. */
320 struct benchmark_st st
;
321 struct timespec tr_start
, tr_stop
;
327 gnutls_certificate_allocate_credentials(&s_certcred
);
328 gnutls_anon_allocate_server_credentials(&s_anoncred
);
329 gnutls_dh_params_init(&dh_params
);
330 if ((ret
=gnutls_dh_params_import_pkcs3(dh_params
, &p3
, GNUTLS_X509_FMT_PEM
)) < 0) {
331 fprintf(stderr
, "Error importing the PKCS #3 params: %s\n", gnutls_strerror(ret
));
334 gnutls_anon_set_server_dh_params(s_anoncred
, dh_params
);
335 gnutls_certificate_set_dh_params(s_certcred
, dh_params
);
337 gnutls_certificate_set_x509_key_mem (s_certcred
, &server_cert
, &server_key
,
338 GNUTLS_X509_FMT_PEM
);
339 gnutls_certificate_set_x509_key_mem (s_certcred
, &server_ecc_cert
, &server_ecc_key
,
340 GNUTLS_X509_FMT_PEM
);
343 gnutls_anon_allocate_client_credentials(&c_anoncred
);
344 gnutls_certificate_allocate_credentials(&c_certcred
);
346 start_benchmark(&st
);
350 gnutls_init(&server
, GNUTLS_SERVER
);
351 ret
= gnutls_priority_set_direct(server
, cipher_prio
, &str
);
353 fprintf(stderr
, "Error in %s\n", str
);
356 gnutls_credentials_set(server
, GNUTLS_CRD_ANON
, s_anoncred
);
357 gnutls_credentials_set(server
, GNUTLS_CRD_CERTIFICATE
, s_certcred
);
358 gnutls_transport_set_push_function(server
, server_push
);
359 gnutls_transport_set_pull_function(server
, server_pull
);
360 gnutls_transport_set_ptr(server
, (gnutls_transport_ptr_t
) server
);
363 gnutls_init(&client
, GNUTLS_CLIENT
);
365 ret
= gnutls_priority_set_direct(client
, cipher_prio
, &str
);
367 fprintf(stderr
, "Error in %s\n", str
);
370 gnutls_credentials_set(client
, GNUTLS_CRD_ANON
, c_anoncred
);
371 gnutls_credentials_set(client
, GNUTLS_CRD_CERTIFICATE
, c_certcred
);
373 gnutls_transport_set_push_function(client
, client_push
);
374 gnutls_transport_set_pull_function(client
, client_pull
);
375 gnutls_transport_set_ptr(client
, (gnutls_transport_ptr_t
) client
);
379 HANDSHAKE(client
, server
);
384 suite
= gnutls_cipher_suite_get_name(gnutls_kx_get(server
),
385 gnutls_cipher_get(server
),
386 gnutls_mac_get(server
));
388 gnutls_deinit(client
);
389 gnutls_deinit(server
);
391 diffs
[diffs_size
++] = timespec_sub_ms(&tr_stop
, &tr_start
);
392 if (diffs_size
> sizeof(diffs
))
397 while (benchmark_must_finish
== 0);
399 fprintf(stdout
, "Benchmarked %s.\n", suite
);
400 stop_benchmark(&st
, "transactions");
402 avg
= calc_avg(diffs
, diffs_size
);
403 sstddev
= calc_sstdev(diffs
, diffs_size
, avg
);
405 printf(" Average handshake time: %.2f ms, sample variance: %.2f\n\n", avg
, sstddev
);
407 gnutls_anon_free_client_credentials(c_anoncred
);
408 gnutls_anon_free_server_credentials(s_anoncred
);
410 gnutls_dh_params_deinit(dh_params
);
414 void benchmark_tls(int debug_level
, int ciphers
)
416 gnutls_global_set_log_function(tls_log_func
);
417 gnutls_global_set_log_level(debug_level
);
418 gnutls_global_init();
422 printf("Testing throughput in cipher/MAC combinations:\n\n");
424 test_ciphersuite(PRIO_ARCFOUR_128_MD5
, 1024);
425 test_ciphersuite(PRIO_ARCFOUR_128_MD5
, 4096);
426 test_ciphersuite(PRIO_ARCFOUR_128_MD5
, 8 * 1024);
427 test_ciphersuite(PRIO_ARCFOUR_128_MD5
, 15 * 1024);
429 test_ciphersuite(PRIO_AES_GCM
, 1024);
430 test_ciphersuite(PRIO_AES_GCM
, 4096);
431 test_ciphersuite(PRIO_AES_GCM
, 8 * 1024);
432 test_ciphersuite(PRIO_AES_GCM
, 15 * 1024);
434 test_ciphersuite(PRIO_AES_CBC_SHA1
, 1024);
435 test_ciphersuite(PRIO_AES_CBC_SHA1
, 4096);
436 test_ciphersuite(PRIO_AES_CBC_SHA1
, 8 * 1024);
437 test_ciphersuite(PRIO_AES_CBC_SHA1
, 15 * 1024);
439 test_ciphersuite(PRIO_CAMELLIA_CBC_SHA1
, 1024);
440 test_ciphersuite(PRIO_CAMELLIA_CBC_SHA1
, 4096);
441 test_ciphersuite(PRIO_CAMELLIA_CBC_SHA1
, 8 * 1024);
442 test_ciphersuite(PRIO_CAMELLIA_CBC_SHA1
, 15 * 1024);
446 printf("\nTesting key exchanges (RSA/DH bits: %d, EC bits: %d):\n\n", rsa_bits
, ec_bits
);
447 test_ciphersuite_kx(PRIO_DH
);
448 test_ciphersuite_kx(PRIO_ECDH
);
449 test_ciphersuite_kx(PRIO_ECDHE_ECDSA
);
450 test_ciphersuite_kx(PRIO_RSA
);
453 gnutls_global_deinit();