8 #include <CoreFoundation/CoreFoundation.h>
10 #include <AssertMacros.h>
11 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
12 #include <Security/SecureTransport.h>
13 #include <Security/SecPolicy.h>
14 #include <Security/SecTrust.h>
15 #include <Security/SecIdentity.h>
16 #include <Security/SecIdentityPriv.h>
17 #include <Security/SecCertificatePriv.h>
18 #include <Security/SecKeyPriv.h>
19 #include <Security/SecItem.h>
20 #include <Security/SecRandom.h>
22 #include <utilities/array_size.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
28 #include <mach/mach_time.h>
31 #include <Security/SecRSAKey.h>
34 #include "ssl-utils.h"
35 #import "STLegacyTests.h"
37 @implementation STLegacyTests (dhe)
42 Test both the client and server side.
45 - Make sure that handshake fail when dh param size is too small.
48 - handshake pass or fail
53 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
56 uint8_t *ptr = (uint8_t *)data;
61 ret = write((int)conn, ptr, len);
62 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
71 *length = *length - len;
75 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
78 uint8_t *ptr = (uint8_t *)data;
83 ret = read((int)conn, ptr, len);
84 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
89 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
94 *length = *length - len;
104 static ssl_client_handle *
105 ssl_client_handle_create(int comm, CFArrayRef trustedCA, unsigned dhe_size)
107 ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle));
108 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
110 require(handle, out);
113 require_noerr(SSLSetIOFuncs(ctx,
114 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
115 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
116 static const char *peer_domain_name = "localhost";
117 require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name,
118 strlen(peer_domain_name)), out);
120 require_noerr(SSLSetTrustedRoots(ctx, trustedCA, true), out);
122 require_noerr(SSLSetDHEEnabled(ctx, true), out);
125 require_noerr(SSLSetMinimumDHGroupSize(ctx, dhe_size), out);
129 handle->dhe_size = dhe_size;
143 ssl_client_handle_destroy(ssl_client_handle *handle)
146 SSLClose(handle->st);
147 CFRelease(handle->st);
152 static void *securetransport_ssl_client_thread(void *arg)
155 ssl_client_handle * ssl = (ssl_client_handle *)arg;
156 SSLContextRef ctx = ssl->st;
157 SSLSessionState ssl_state;
159 pthread_setname_np("client thread");
161 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
162 require_action(ssl_state==kSSLIdle, out, ortn = -1);
165 ortn = SSLHandshake(ctx);
166 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
168 if (ortn == errSSLWouldBlock) {
169 require_string(ssl_state==kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
171 } while (ortn == errSSLWouldBlock);
176 pthread_exit((void *)(intptr_t)ortn);
188 static ssl_server_handle *
189 ssl_server_handle_create(int comm, CFArrayRef certs, const void *dhParams, size_t dhParamsLen)
191 ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle));
192 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
193 SSLCipherSuite cipher = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
195 require(handle, out);
198 require_noerr(SSLSetIOFuncs(ctx,
199 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
200 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
202 require_noerr(SSLSetCertificate(ctx, certs), out);
204 require_noerr(SSLSetEnabledCiphers(ctx, &cipher, 1), out);
207 require_noerr(SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen), out);
210 handle->certs = certs;
225 ssl_server_handle_destroy(ssl_server_handle *handle)
228 SSLClose(handle->st);
229 CFRelease(handle->st);
234 static void *securetransport_ssl_server_thread(void *arg)
237 ssl_server_handle * ssl = (ssl_server_handle *)arg;
238 SSLContextRef ctx = ssl->st;
239 SSLSessionState ssl_state;
241 pthread_setname_np("server thread");
243 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
244 require_action(ssl_state==kSSLIdle, out, ortn = -1);
247 ortn = SSLHandshake(ctx);
248 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
250 if (ortn == errSSLWouldBlock) {
251 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
253 } while (ortn == errSSLWouldBlock);
255 require_noerr_quiet(ortn, out);
257 require_action(ssl_state==kSSLConnected, out, ortn = -1);
262 pthread_exit((void *)(intptr_t)ortn);
269 unsigned client_dhe_sizes[] = {
270 0, // default, don't set.
271 256, // will resolve to 512.
276 4096, // will resolve to 2048.
280 static const unsigned n_client_dhe_sizes = sizeof(client_dhe_sizes)/sizeof(client_dhe_sizes[0]);
282 static uint8_t dh_parameters_256_data[] = {
283 0x30, 0x26, 0x02, 0x21, 0x00, 0xd8, 0x23, 0xeb, 0xcb, 0x41, 0xd0, 0x3a,
284 0xc4, 0x9a, 0x2a, 0x2a, 0x4f, 0x35, 0xf7, 0x4f, 0xd9, 0xc5, 0x2e, 0xf8,
285 0x44, 0xa7, 0x74, 0xe3, 0x84, 0x98, 0x9f, 0xad, 0x58, 0xd5, 0x15, 0xb4,
286 0xf3, 0x02, 0x01, 0x02
289 static uint8_t dh_parameters_512_data[] = {
290 0x30, 0x46, 0x02, 0x41, 0x00, 0x85, 0xcd, 0xc1, 0x7e, 0x26, 0xeb, 0x37,
291 0x84, 0x13, 0xd0, 0x3b, 0x07, 0xc1, 0x57, 0x7d, 0xf3, 0x55, 0x8d, 0xa0,
292 0xc4, 0xa5, 0x03, 0xc4, 0x2c, 0xc6, 0xd5, 0xa6, 0x31, 0xcb, 0x68, 0xdf,
293 0x5d, 0x96, 0x20, 0x1a, 0x15, 0x57, 0x49, 0x7d, 0xd7, 0x51, 0x65, 0x6e,
294 0x37, 0xa8, 0xe3, 0xe9, 0xe1, 0x59, 0x2e, 0xd4, 0x57, 0x4a, 0xf0, 0xcb,
295 0x0e, 0x85, 0x07, 0xdd, 0x35, 0xa7, 0xe3, 0xc6, 0xbb, 0x02, 0x01, 0x02
298 static uint8_t dh_parameters_768_data[] = {
299 0x30, 0x66, 0x02, 0x61, 0x00, 0xe1, 0xa2, 0x50, 0xab, 0xb0, 0xdc, 0xef,
300 0xe1, 0x2f, 0xd9, 0xde, 0x59, 0x86, 0x24, 0x43, 0x3b, 0xf3, 0x40, 0x9d,
301 0x02, 0xcc, 0xe2, 0x70, 0x63, 0x46, 0x8d, 0x0f, 0xf3, 0x8a, 0xc6, 0xa0,
302 0x1d, 0x7b, 0x30, 0x83, 0x10, 0x48, 0x40, 0x28, 0xa4, 0x3e, 0xbe, 0x4d,
303 0xb6, 0xea, 0x90, 0x02, 0xae, 0x25, 0x93, 0xc0, 0xe8, 0x36, 0x5c, 0xc8,
304 0xc8, 0x0b, 0x04, 0xd5, 0x05, 0xac, 0x67, 0x24, 0x4b, 0xa9, 0x42, 0x5a,
305 0x03, 0x65, 0x4d, 0xd0, 0xc0, 0xbd, 0x78, 0x32, 0xd0, 0x8c, 0x0a, 0xf4,
306 0xbf, 0xd1, 0x61, 0x86, 0x13, 0x13, 0x3b, 0x83, 0xce, 0xbf, 0x3b, 0xbc,
307 0x8f, 0xf9, 0x4e, 0x50, 0xe3, 0x02, 0x01, 0x02
310 static uint8_t dh_parameters_1024_data[] = {
311 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xd5, 0x06, 0x69, 0xc6, 0xd4,
312 0x98, 0x2b, 0xe3, 0x49, 0xe2, 0xa1, 0x9b, 0x82, 0xaf, 0x3f, 0xaa, 0xc3,
313 0x86, 0x2a, 0x7a, 0xfa, 0x62, 0x12, 0x33, 0x45, 0x9f, 0x34, 0x57, 0xc6,
314 0x6c, 0x88, 0x81, 0xa6, 0x5d, 0xa3, 0x43, 0xe5, 0x4d, 0x87, 0x4f, 0x69,
315 0x3d, 0x2b, 0xc8, 0x18, 0xb6, 0xd7, 0x29, 0x53, 0x94, 0x0d, 0x73, 0x9b,
316 0x08, 0x22, 0x73, 0x84, 0x7b, 0x5a, 0x03, 0x2e, 0xfc, 0x10, 0x9b, 0x35,
317 0xc6, 0xa1, 0xca, 0x36, 0xd0, 0xcc, 0x3e, 0xa2, 0x04, 0x3a, 0x8a, 0xe8,
318 0x87, 0xe8, 0x60, 0x72, 0xee, 0x99, 0xf3, 0x04, 0x0a, 0xd8, 0x1a, 0xe6,
319 0xfc, 0xbc, 0xe1, 0xc5, 0x9d, 0x3a, 0xca, 0xf9, 0xfd, 0xbf, 0x58, 0xd3,
320 0x4d, 0xde, 0x8b, 0x4a, 0xb5, 0x37, 0x1e, 0x6d, 0xf4, 0x22, 0x0f, 0xb7,
321 0x48, 0x0a, 0xda, 0x82, 0x40, 0xc9, 0x55, 0x20, 0x01, 0x3b, 0x35, 0xb2,
322 0x94, 0x68, 0xab, 0x02, 0x01, 0x02
328 const void *dhParams;
330 } server_dhe_params[] = {
331 {dh_parameters_256_data, sizeof(dh_parameters_256_data)},
332 {dh_parameters_512_data, sizeof(dh_parameters_512_data)},
333 {dh_parameters_768_data, sizeof(dh_parameters_768_data)},
334 {dh_parameters_1024_data, sizeof(dh_parameters_1024_data)},
335 {NULL, 0}, // default is a 2048
338 static const unsigned n_server_dhe_params = sizeof(server_dhe_params)/sizeof(server_dhe_params[0]);
341 int expected_client_error[n_server_dhe_params][n_client_dhe_sizes] = {
344 // 1024, 512, 512, 768, 1024, 2048, 2048 // Server:
345 { -9850, -9850, -9850, -9850, -9850, -9850, -9850}, // 256
346 { -9850, 0, 0, -9850, -9850, -9850, -9850}, // 512
347 { -9850, 0, 0, 0, -9850, -9850, -9850}, // 768
348 { 0, 0, 0, 0, 0, -9850, -9850}, // 1024
349 { 0, 0, 0, 0, 0, 0, 0}, // default(2048)
354 pthread_t client_thread, server_thread;
355 CFArrayRef server_certs = server_chain();
356 CFArrayRef trusted_ca = trusted_roots();
358 XCTAssert(server_certs, "got server certs");
359 XCTAssert(trusted_ca, "got trusted roots");
363 for (i=0; i<n_server_dhe_params; i++) {
364 for (j=0; j<n_client_dhe_sizes; j++) {
367 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
368 fcntl(sp[0], F_SETNOSIGPIPE, 1);
369 fcntl(sp[1], F_SETNOSIGPIPE, 1);
371 ssl_client_handle *client;
372 client = ssl_client_handle_create(sp[0], trusted_ca, client_dhe_sizes[j]);
373 XCTAssert(client!=NULL, "could not create client handle (%d:%d)", i, j);
376 ssl_server_handle *server;
377 server = ssl_server_handle_create(sp[1], server_certs, server_dhe_params[i].dhParams, server_dhe_params[i].dhParamsLen);
378 XCTAssert(server!=NULL, "could not create server handle (%d:%d)", i, j);
380 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
381 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
383 intptr_t server_err, client_err;
385 pthread_join(client_thread, (void*)&client_err);
386 pthread_join(server_thread, (void*)&server_err);
389 XCTAssertEqual(client_err, expected_client_error[i][j], "unexpected error %d!=%d (client %d:%d)", (int)client_err, expected_client_error[i][j], i, j);
391 ssl_server_handle_destroy(server);
392 ssl_client_handle_destroy(client);
396 CFReleaseSafe(server_certs);
397 CFReleaseSafe(trusted_ca);