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>
36 fprintf(stderr, __VA_ARGS__); \
40 #include "../tests/eagain-common.h"
41 #include "benchmark.h"
43 const char* side
= "";
45 #define PRIO_DH "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+DHE-RSA"
46 #define PRIO_ECDH "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ECDHE-RSA:+CURVE-SECP192R1"
47 #define PRIO_ECDHE_ECDSA "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ECDHE-ECDSA:+CURVE-SECP192R1"
48 #define PRIO_RSA "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+RSA"
50 #define PRIO_AES_CBC_SHA1 "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ANON-DH"
51 #define PRIO_ARCFOUR_128_MD5 "NONE:+VERS-TLS1.0:+ARCFOUR-128:+MD5:+SIGN-ALL:+COMP-NULL:+ANON-DH"
52 #define PRIO_AES_GCM "NONE:+VERS-TLS1.2:+AES-128-GCM:+AEAD:+SIGN-ALL:+COMP-NULL:+ANON-DH"
53 #define PRIO_CAMELLIA_CBC_SHA1 "NONE:+VERS-TLS1.0:+CAMELLIA-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ANON-DH"
55 static const int rsa_bits
= 1776, ec_bits
= 192;
57 /* DH of 1840 bits that is pretty close equivalent to 192 bits of ECDH.
60 "-----BEGIN DH PARAMETERS-----\n"
61 "MIIBxgKB3gNZMD2odqYk7HGnT+kh72vcnGrDhFMad1m4VlYZoLClkRUOH05W9gKF\n"
62 "hjBzlg5zO1Pp14hpSNWdfXcd2glWE2wzkxxxztzt23gdXK1GjfupnALyPS2Q0Oj7\n"
63 "UiLDfos46vXOSzqO3vBElM2HJQ6N1TRU+EqD5t/6aTAV6iAD+yz2Fyv4Xs+rgJC2\n"
64 "IbpunLzM2IhH2u9tLUXGkBzHPW/6Q+fJRhn88OLBC9vwOHPQvw779+FB0NPue1Qs\n"
65 "vb+4HSywpOr4BtNLWST2MzhCYBApvV1dKcZLI5k5Cfmp5ryV+wKB3gEUe9uAk+5I\n"
66 "ENkTLC7XLLNGjPEKwQhBzE7Nh7RKWlZRX+B/cX5/iT7ZF9+N83O/wf2AxEV6CRWV\n"
67 "WiCjvML/wbskpGoGmrPyef7bLHI62x4/nNacGGWEichPW8Sn/qaT80FHyYM0m7Ha\n"
68 "+Q9kYUSx0u1CW//3nGvma5dh/c2iiq8r7J9w2PSYynHts4bYMrRRx2PVeGhvU8+X\n"
69 "nRkYOqptEqoB6NG5kPRL8b5jJSp7J2hN7shDjQB/s9/N8rvF8tRmMUTJpk3Fwr9F\n"
70 "LVdX3640cbukwFTKlkqZ1evymVzx0wICAL0=\n"
71 "-----END DH PARAMETERS-----\n";
73 static unsigned char server_cert_pem
[] =
74 "-----BEGIN CERTIFICATE-----\n"
75 "MIIEEzCCAx6gAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBuDELMAkGA1UEBhMCR1Ix\n"
76 "EjAQBgNVBAoTCUtva28gaW5jLjEXMBUGA1UECxMOc2xlZXBpbmcgZGVwdC4xDzAN\n"
77 "BgNVBAgTBkF0dGlraTEVMBMGA1UEAxMMQ2luZHkgTGF1cGVyMRcwFQYKCZImiZPy\n"
78 "LGQBARMHY2xhdXBlcjEMMAoGA1UEDBMDRHIuMQ8wDQYDVQRBEwZqYWNrYWwxHDAa\n"
79 "BgkqhkiG9w0BCQEWDW5vbmVAbm9uZS5vcmcwIhgPMjAxMjA2MDYxOTAxMjdaGA8y\n"
80 "MDE5MDcxMDE5MDEyN1owgbgxCzAJBgNVBAYTAkdSMRIwEAYDVQQKEwlLb2tvIGlu\n"
81 "Yy4xFzAVBgNVBAsTDnNsZWVwaW5nIGRlcHQuMQ8wDQYDVQQIEwZBdHRpa2kxFTAT\n"
82 "BgNVBAMTDENpbmR5IExhdXBlcjEXMBUGCgmSJomT8ixkAQETB2NsYXVwZXIxDDAK\n"
83 "BgNVBAwTA0RyLjEPMA0GA1UEQRMGamFja2FsMRwwGgYJKoZIhvcNAQkBFg1ub25l\n"
84 "QG5vbmUub3JnMIH9MA0GCSqGSIb3DQEBAQUAA4HrADCB5wKB3wC/VSBHG5adM0r0\n"
85 "E80dgVvt+oVnnDcKYcm9q2WbknTL6dFgjjcEbiHDKmnr1hgyT9jfQVE/ve2XnZqA\n"
86 "kbpYMNrQbdieclNycjoXCj3BJSJXXz3Ra6O4DLNh0/XwsxbVd/tMSQvwAK0MR60K\n"
87 "/yfruL2oxe8j7uDmS5oY8b5O9nP/EVW2u7P1KVhrNxC2rGoaK6iRpgkAX3oP2YVM\n"
88 "hLfPONpDgYGxBvrO0tlpHCYL+miWdRzIDPMYtdcU1v1zVSKAsvJ2dgEwP6FoSiWP\n"
89 "nkw3U41i4oe+T7kVEk1F9QLCnXsCAwEAAaNrMGkwDAYDVR0TAQH/BAIwADAUBgNV\n"
90 "HREEDTALgglsb2NhbGhvc3QwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0PAQH/\n"
91 "BAUDAwegADAdBgNVHQ4EFgQUMwvofEmn5CtM4GygipfIuebOssgwDQYJKoZIhvcN\n"
92 "AQELBQADgd8AdP87xzJGv3ddODGoCaVNipkO96HDwt1fC4Jtp1VTn1V4JRaL4e4D\n"
93 "0dlFMq30kmrLTxNSET7MJ5l2m0XZS7jhbl5UW9jLCv1GurMaVuYK4v0LGGezODoH\n"
94 "8naZkxWYGS16kssPu0SDE0V9gWF31IXs2qs0PHvvpI5WFmjrOPX3RfFeVNhmc5sv\n"
95 "1cy+hnM9wxcT2r+jpKn3mYVVcnG7ANZyLKzLwN/PGkYB+tv8sS0ojxMKZLQjr9xs\n"
96 "z1plHeDzm0/t7gsAkrL8ynSkBBJ1SLqaKMmlP1DmgU/zTlMTyKrG\n"
97 "-----END CERTIFICATE-----\n";
99 static unsigned char server_key_pem
[] =
100 "-----BEGIN RSA PRIVATE KEY-----\n"
101 "MIIEBAIBAAKB3wC/VSBHG5adM0r0E80dgVvt+oVnnDcKYcm9q2WbknTL6dFgjjcE\n"
102 "biHDKmnr1hgyT9jfQVE/ve2XnZqAkbpYMNrQbdieclNycjoXCj3BJSJXXz3Ra6O4\n"
103 "DLNh0/XwsxbVd/tMSQvwAK0MR60K/yfruL2oxe8j7uDmS5oY8b5O9nP/EVW2u7P1\n"
104 "KVhrNxC2rGoaK6iRpgkAX3oP2YVMhLfPONpDgYGxBvrO0tlpHCYL+miWdRzIDPMY\n"
105 "tdcU1v1zVSKAsvJ2dgEwP6FoSiWPnkw3U41i4oe+T7kVEk1F9QLCnXsCAwEAAQKB\n"
106 "3iYR2gpMAvvkaNWH2xgz1QbVAhZLjugR7QJASEdcLMEmFPMRWQEYqL8cgVbbkpTw\n"
107 "Lka9yFzWfZ/dTBCo7lr93Yv7T063kMME12oeL4tuyBZ6bOJueHT2kfq1Igpyl+iB\n"
108 "pw7WuflXKRd4a4X0nwzYBQxYWH7bKkQRZDlViKuOXKVzgT7GqD6cbTZbc/8wUTi7\n"
109 "HoyMlz4d+YH/XL5Zt6SM7cMuJ/VOGGUcBiXqlixzulloihkPwJeg6zxx0e1dVy4q\n"
110 "jvVhb+hmypWajjBDPUwIGFih0lZJ6rqIDyls/ZK2AQJwAPFeAMubo1KWcFU+nHoK\n"
111 "Q/jdOjpuAt7fwczkqhb6uOrJtS4RUtF3x3jfESFYf6Btnt6Slj1HpNKHbud2Weyw\n"
112 "i3lIkkmQq4+8uRjZXlNtp2Sd33NFeYE1D8ll3V2wiwiCOPJxYWpOOwHs7pkcOsAD\n"
113 "ywJwAMruluGFAUhoCxXOGzbJeXOC0U+LbwU72Xgk9zhEX6chaklKgdSnJ8DlHnYe\n"
114 "R+wc2vXRfSGlT1OH0X8ezn82QV8UmYo6cNpMTNarW0rzpFir51owvYSBPnPB+DLX\n"
115 "0JausRZoI6fyZSw4Vxt9PN13EQJwANnEX2FUfcmQs68le1ZclrEdIGEBSpO9PARZ\n"
116 "tuBeu6IR9OaoeJlGwXDbiYAVcajT3oefp++ICTxtNvGchUuYiW4WvO2kmjVoJ3Q1\n"
117 "Afaxs1qDWcyNvS+HKUQjJNNX6kj1/N040JRyGqkFFMyNfLArewJwAL/KfLkJjmvT\n"
118 "QV7LW3cNNYbRRWdLXZLxvJfLQAdiv5BiiWRZUZkcnfq10HNMLSdfIiYfZocNCIrm\n"
119 "mz3sbLdYHLJy8qXsk8oNQLXGX9LXsCTJ2y6nUAZSbCbVVPEgfRhcZCvMIp7Q/YOs\n"
120 "f88QLx0UMQJvYsEnYagLe9EfC0d8fXTKJr143FMxas7j3eftxLEBnx7ZsqCbJD1o\n"
121 "UsvWkp5I3kqIABEqY1ZJV/gU41MceuWURSVADpuuRDLzv8WPdeffad9o2hX/bkI6\n"
122 "2INKeuq1nILiEHAZLloH6/fdjpWZYF0D\n"
123 "-----END RSA PRIVATE KEY-----\n";
125 static unsigned char server_ecc_key_pem
[] =
126 "-----BEGIN EC PRIVATE KEY-----\n"
127 "MGACAQEEGQCovzs4UsfRncfJXO3WOZUe/Zf+usKzEcWgCgYIKoZIzj0DAQGhNAMy\n"
128 "AAREwuCcUHKNWyetsymkAaqA0GCgksI2AjewpOWsraGrfea3GPw1uuyOQRMR7kka\n"
130 "-----END EC PRIVATE KEY-----\n";
132 static unsigned char server_ecc_cert_pem
[] =
133 "-----BEGIN CERTIFICATE-----\n"
134 "MIIBYDCCARWgAwIBAgIETuILrDAKBggqhkjOPQQDAjAcMQswCQYDVQQGEwJCRTEN\n"
135 "MAsGA1UEChMEVGVzdDAeFw0xMTEyMDkxMzIyNTJaFw0xNzA4MTExMzIyNTlaMBwx\n"
136 "CzAJBgNVBAYTAkJFMQ0wCwYDVQQKEwRUZXN0MEkwEwYHKoZIzj0CAQYIKoZIzj0D\n"
137 "AQEDMgAERMLgnFByjVsnrbMppAGqgNBgoJLCNgI3sKTlrK2hq33mtxj8NbrsjkET\n"
138 "Ee5JGr+ro1UwUzAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8G\n"
139 "A1UdDwEB/wQFAwMHgAAwHQYDVR0OBBYEFKeR27mtYWFaH43U2zEvjd28Zf+CMAoG\n"
140 "CCqGSM49BAMCAzkAMDYCGQD7WWWiFV+ddI7tIyMFepKFA1dX4nlc/+ICGQCCPdHc\n"
141 "gMyHv2XyfOGHLhq0HmDTOOiwfC4=\n"
142 "-----END CERTIFICATE-----\n";
144 const gnutls_datum_t server_cert
= { server_cert_pem
,
145 sizeof (server_cert_pem
)
148 const gnutls_datum_t server_key
= { server_key_pem
,
149 sizeof (server_key_pem
)
152 const gnutls_datum_t server_ecc_cert
= { server_ecc_cert_pem
,
153 sizeof (server_ecc_cert_pem
)
156 const gnutls_datum_t server_ecc_key
= { server_ecc_key_pem
,
157 sizeof (server_ecc_key_pem
)
160 char buffer
[64 * 1024];
162 static void tls_log_func(int level
, const char *str
)
164 fprintf(stderr
, "%s|<%d>| %s", side
, level
, str
);
167 static void test_ciphersuite(const char *cipher_prio
, int size
)
170 gnutls_anon_server_credentials_t s_anoncred
;
171 const gnutls_datum_t p3
= { (void*) pkcs3
, strlen(pkcs3
) };
172 static gnutls_dh_params_t dh_params
;
173 gnutls_session_t server
;
177 gnutls_anon_client_credentials_t c_anoncred
;
178 gnutls_session_t client
;
179 /* Need to enable anonymous KX specifically. */
181 struct benchmark_st st
;
184 gnutls_anon_allocate_server_credentials(&s_anoncred
);
185 gnutls_dh_params_init(&dh_params
);
186 gnutls_dh_params_import_pkcs3(dh_params
, &p3
, GNUTLS_X509_FMT_PEM
);
187 gnutls_anon_set_server_dh_params(s_anoncred
, dh_params
);
188 gnutls_init(&server
, GNUTLS_SERVER
);
189 ret
= gnutls_priority_set_direct(server
, cipher_prio
, &str
);
191 fprintf(stderr
, "Error in %s\n", str
);
194 gnutls_credentials_set(server
, GNUTLS_CRD_ANON
, s_anoncred
);
195 gnutls_dh_set_prime_bits(server
, 1024);
196 gnutls_transport_set_push_function(server
, server_push
);
197 gnutls_transport_set_pull_function(server
, server_pull
);
198 gnutls_transport_set_ptr(server
, (gnutls_transport_ptr_t
) server
);
202 gnutls_anon_allocate_client_credentials(&c_anoncred
);
203 gnutls_init(&client
, GNUTLS_CLIENT
);
205 ret
= gnutls_priority_set_direct(client
, cipher_prio
, &str
);
207 fprintf(stderr
, "Error in %s\n", str
);
210 gnutls_credentials_set(client
, GNUTLS_CRD_ANON
, c_anoncred
);
211 gnutls_transport_set_push_function(client
, client_push
);
212 gnutls_transport_set_pull_function(client
, client_pull
);
213 gnutls_transport_set_ptr(client
, (gnutls_transport_ptr_t
) client
);
215 HANDSHAKE(client
, server
);
217 fprintf(stdout
, "Testing %s with %d packet size: ",
218 gnutls_cipher_suite_get_name(gnutls_kx_get(server
),
219 gnutls_cipher_get(server
),
220 gnutls_mac_get(server
)), size
);
223 gnutls_rnd(GNUTLS_RND_NONCE
, buffer
, sizeof(buffer
));
225 start_benchmark(&st
);
229 ret
= gnutls_record_send(client
, buffer
, size
);
231 while (ret
== GNUTLS_E_AGAIN
);
234 fprintf(stderr
, "Failed sending to server\n");
239 ret
= gnutls_record_recv(server
, buffer
, sizeof(buffer
));
241 while (ret
== GNUTLS_E_AGAIN
);
244 fprintf(stderr
, "Failed receiving from client\n");
250 while (benchmark_must_finish
== 0);
252 stop_benchmark(&st
, NULL
);
254 gnutls_bye(client
, GNUTLS_SHUT_WR
);
255 gnutls_bye(server
, GNUTLS_SHUT_WR
);
257 gnutls_deinit(client
);
258 gnutls_deinit(server
);
260 gnutls_anon_free_client_credentials(c_anoncred
);
261 gnutls_anon_free_server_credentials(s_anoncred
);
263 gnutls_dh_params_deinit(dh_params
);
267 static void test_ciphersuite_kx(const char *cipher_prio
)
270 gnutls_anon_server_credentials_t s_anoncred
;
271 const gnutls_datum_t p3
= { (void*) pkcs3
, strlen(pkcs3
) };
272 static gnutls_dh_params_t dh_params
;
273 gnutls_session_t server
;
276 const char *suite
= NULL
;
278 gnutls_anon_client_credentials_t c_anoncred
;
279 gnutls_certificate_credentials_t c_certcred
, s_certcred
;
280 gnutls_session_t client
;
281 /* Need to enable anonymous KX specifically. */
283 struct benchmark_st st
;
286 gnutls_certificate_allocate_credentials(&s_certcred
);
287 gnutls_anon_allocate_server_credentials(&s_anoncred
);
288 gnutls_dh_params_init(&dh_params
);
289 if ((ret
=gnutls_dh_params_import_pkcs3(dh_params
, &p3
, GNUTLS_X509_FMT_PEM
)) < 0) {
290 fprintf(stderr
, "Error importing the PKCS #3 params: %s\n", gnutls_strerror(ret
));
293 gnutls_anon_set_server_dh_params(s_anoncred
, dh_params
);
294 gnutls_certificate_set_dh_params(s_certcred
, dh_params
);
296 gnutls_certificate_set_x509_key_mem (s_certcred
, &server_cert
, &server_key
,
297 GNUTLS_X509_FMT_PEM
);
298 gnutls_certificate_set_x509_key_mem (s_certcred
, &server_ecc_cert
, &server_ecc_key
,
299 GNUTLS_X509_FMT_PEM
);
301 start_benchmark(&st
);
304 gnutls_init(&server
, GNUTLS_SERVER
);
305 ret
= gnutls_priority_set_direct(server
, cipher_prio
, &str
);
307 fprintf(stderr
, "Error in %s\n", str
);
310 gnutls_credentials_set(server
, GNUTLS_CRD_ANON
, s_anoncred
);
311 gnutls_credentials_set(server
, GNUTLS_CRD_CERTIFICATE
, s_certcred
);
312 gnutls_transport_set_push_function(server
, server_push
);
313 gnutls_transport_set_pull_function(server
, server_pull
);
314 gnutls_transport_set_ptr(server
, (gnutls_transport_ptr_t
) server
);
318 gnutls_anon_allocate_client_credentials(&c_anoncred
);
319 gnutls_certificate_allocate_credentials(&c_certcred
);
321 gnutls_init(&client
, GNUTLS_CLIENT
);
323 ret
= gnutls_priority_set_direct(client
, cipher_prio
, &str
);
325 fprintf(stderr
, "Error in %s\n", str
);
328 gnutls_credentials_set(client
, GNUTLS_CRD_ANON
, c_anoncred
);
329 gnutls_credentials_set(client
, GNUTLS_CRD_CERTIFICATE
, c_certcred
);
331 gnutls_transport_set_push_function(client
, client_push
);
332 gnutls_transport_set_pull_function(client
, client_pull
);
333 gnutls_transport_set_ptr(client
, (gnutls_transport_ptr_t
) client
);
335 HANDSHAKE(client
, server
);
338 suite
= gnutls_cipher_suite_get_name(gnutls_kx_get(server
),
339 gnutls_cipher_get(server
),
340 gnutls_mac_get(server
));
342 gnutls_deinit(client
);
343 gnutls_deinit(server
);
347 while (benchmark_must_finish
== 0);
349 fprintf(stdout
, "Tested %s: ", suite
);
350 stop_benchmark(&st
, "transactions");
352 gnutls_anon_free_client_credentials(c_anoncred
);
353 gnutls_anon_free_server_credentials(s_anoncred
);
355 gnutls_dh_params_deinit(dh_params
);
359 void benchmark_tls(int debug_level
, int ciphers
)
361 gnutls_global_set_log_function(tls_log_func
);
362 gnutls_global_set_log_level(debug_level
);
363 gnutls_global_init();
367 printf("Testing throughput in cipher/MAC combinations:\n");
369 test_ciphersuite(PRIO_ARCFOUR_128_MD5
, 1024);
370 test_ciphersuite(PRIO_ARCFOUR_128_MD5
, 4096);
371 test_ciphersuite(PRIO_ARCFOUR_128_MD5
, 8 * 1024);
372 test_ciphersuite(PRIO_ARCFOUR_128_MD5
, 15 * 1024);
374 test_ciphersuite(PRIO_AES_GCM
, 1024);
375 test_ciphersuite(PRIO_AES_GCM
, 4096);
376 test_ciphersuite(PRIO_AES_GCM
, 8 * 1024);
377 test_ciphersuite(PRIO_AES_GCM
, 15 * 1024);
379 test_ciphersuite(PRIO_AES_CBC_SHA1
, 1024);
380 test_ciphersuite(PRIO_AES_CBC_SHA1
, 4096);
381 test_ciphersuite(PRIO_AES_CBC_SHA1
, 8 * 1024);
382 test_ciphersuite(PRIO_AES_CBC_SHA1
, 15 * 1024);
384 test_ciphersuite(PRIO_CAMELLIA_CBC_SHA1
, 1024);
385 test_ciphersuite(PRIO_CAMELLIA_CBC_SHA1
, 4096);
386 test_ciphersuite(PRIO_CAMELLIA_CBC_SHA1
, 8 * 1024);
387 test_ciphersuite(PRIO_CAMELLIA_CBC_SHA1
, 15 * 1024);
391 printf("\nTesting key exchanges (RSA/DH bits: %d, EC bits: %d):\n", rsa_bits
, ec_bits
);
392 test_ciphersuite_kx(PRIO_DH
);
393 test_ciphersuite_kx(PRIO_ECDH
);
394 test_ciphersuite_kx(PRIO_ECDHE_ECDSA
);
395 test_ciphersuite_kx(PRIO_RSA
);
398 gnutls_global_deinit();