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>
29 #include <utilities/SecCFWrappers.h>
32 #include <Security/SecRSAKey.h>
35 #include "ssl-utils.h"
36 #import "STLegacyTests.h"
38 #pragma clang diagnostic push
39 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
41 @implementation STLegacyTests (dhe)
46 Test both the client and server side.
49 - Make sure that handshake fail when dh param size is too small.
52 - handshake pass or fail
57 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
60 uint8_t *ptr = (uint8_t *)data;
65 ret = write((int)conn, ptr, len);
66 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
75 *length = *length - len;
79 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
82 uint8_t *ptr = (uint8_t *)data;
87 ret = read((int)conn, ptr, len);
88 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
93 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
98 *length = *length - len;
108 -(ssl_client_handle *)ssl_client_handle_create:(int) comm trustedCA:(CFArrayRef) trustedCA dhe_size:(unsigned) dhe_size
110 ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle));
111 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
113 require(handle, out);
116 XCTAssertEqual(errSecSuccess, SSLSetIOFuncs(ctx,
117 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite));
118 XCTAssertEqual(errSecSuccess, SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm));
119 SSLConnectionRef getConn;
120 XCTAssertEqual(errSecSuccess, SSLGetConnection(ctx, &getConn));
121 static const char *peer_domain_name = "localhost";
122 XCTAssertEqual(errSecSuccess, SSLSetPeerDomainName(ctx, peer_domain_name,
123 strlen(peer_domain_name)));
125 XCTAssertEqual(errSecSuccess, SSLSetTrustedRoots(ctx, trustedCA, true));
127 XCTAssertEqual(errSecSuccess, SSLSetDHEEnabled(ctx, true));
129 XCTAssertEqual(errSecSuccess, SSLGetDHEEnabled(ctx, &enabled));
130 XCTAssertEqual(enabled, true);
133 XCTAssertEqual(errSecSuccess, SSLSetMinimumDHGroupSize(ctx, dhe_size));
134 unsigned int nbits = 0;
135 XCTAssertEqual(errSecSuccess, SSLGetMinimumDHGroupSize(ctx, &nbits));
139 handle->dhe_size = dhe_size;
153 ssl_client_handle_destroy(ssl_client_handle *handle)
156 SSLClose(handle->st);
157 CFRelease(handle->st);
162 static void *securetransport_ssl_client_thread(void *arg)
165 ssl_client_handle * ssl = (ssl_client_handle *)arg;
166 SSLContextRef ctx = ssl->st;
167 SSLSessionState ssl_state;
169 pthread_setname_np("client thread");
171 require_noerr(ortn = SSLGetSessionState(ctx,&ssl_state), out);
172 require_action(ssl_state == kSSLIdle, out, ortn = -1);
175 ortn = SSLHandshake(ctx);
176 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
178 if (ortn == errSSLWouldBlock) {
179 require_string(ssl_state == kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
181 } while (ortn == errSSLWouldBlock);
186 pthread_exit((void *)(intptr_t)ortn);
198 -(ssl_server_handle *)ssl_server_handle_create:(int) comm certs: (CFArrayRef) certs dhParams: (const void *)dhParams dhParamsLen: (size_t) dhParamsLen
200 ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle));
201 XCTAssert(handle, "handle allocation failed");
203 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
204 XCTAssert(ctx, "SSLCreateContext failed");
206 SSLCipherSuite cipher = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
208 XCTAssertEqual(errSecSuccess, SSLSetIOFuncs(ctx,
209 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), "Failed to Set IO");
210 XCTAssertEqual(errSecSuccess, SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), "Failed to set SSL connection");
212 XCTAssertEqual(errSecSuccess, SSLSetCertificate(ctx, certs), "Failed to set certificate");
213 CFArrayRef inputCerts = NULL;
214 XCTAssertEqual(errSecSuccess, SSLGetCertificate(ctx, &inputCerts), "Failed to get certificates");
216 XCTAssertEqual(errSecSuccess, SSLSetEnabledCiphers(ctx, &cipher, 1), "SSLSetEnabledCiphers failed");
219 XCTAssertEqual(errSecSuccess, SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen),
220 "Failed to set DH parameters");
221 const void *inputDH = NULL;
223 XCTAssertEqual(errSecSuccess, SSLGetDiffieHellmanParams(ctx, &inputDH, &inputDHLen),
224 "Failed to get DH parameters");
228 handle->certs = certs;
235 ssl_server_handle_destroy(ssl_server_handle *handle)
238 SSLClose(handle->st);
239 CFRelease(handle->st);
244 static void *securetransport_ssl_server_thread(void *arg)
247 ssl_server_handle * ssl = (ssl_server_handle *)arg;
248 SSLContextRef ctx = ssl->st;
249 SSLSessionState ssl_state;
251 pthread_setname_np("server thread");
253 require_noerr(ortn = SSLGetSessionState(ctx,&ssl_state), out);
254 require_action(ssl_state == kSSLIdle, out, ortn = -1);
257 ortn = SSLHandshake(ctx);
258 require_noerr(SSLGetSessionState(ctx, &ssl_state), out);
260 if (ortn == errSSLWouldBlock) {
261 require_action(ssl_state == kSSLHandshake, out, ortn = -1);
263 } while (ortn == errSSLWouldBlock);
265 require_noerr_quiet(ortn, out);
267 require_action(ssl_state == kSSLConnected, out, ortn = -1);
272 pthread_exit((void *)(intptr_t)ortn);
279 unsigned client_dhe_sizes[] = {
280 0, // default, don't set.
281 256, // will resolve to 512.
286 4096, // will resolve to 2048.
290 static const unsigned n_client_dhe_sizes = sizeof(client_dhe_sizes)/sizeof(client_dhe_sizes[0]);
292 static uint8_t dh_parameters_256_data[] = {
293 0x30, 0x26, 0x02, 0x21, 0x00, 0xd8, 0x23, 0xeb, 0xcb, 0x41, 0xd0, 0x3a,
294 0xc4, 0x9a, 0x2a, 0x2a, 0x4f, 0x35, 0xf7, 0x4f, 0xd9, 0xc5, 0x2e, 0xf8,
295 0x44, 0xa7, 0x74, 0xe3, 0x84, 0x98, 0x9f, 0xad, 0x58, 0xd5, 0x15, 0xb4,
296 0xf3, 0x02, 0x01, 0x02
299 static uint8_t dh_parameters_512_data[] = {
300 0x30, 0x46, 0x02, 0x41, 0x00, 0x85, 0xcd, 0xc1, 0x7e, 0x26, 0xeb, 0x37,
301 0x84, 0x13, 0xd0, 0x3b, 0x07, 0xc1, 0x57, 0x7d, 0xf3, 0x55, 0x8d, 0xa0,
302 0xc4, 0xa5, 0x03, 0xc4, 0x2c, 0xc6, 0xd5, 0xa6, 0x31, 0xcb, 0x68, 0xdf,
303 0x5d, 0x96, 0x20, 0x1a, 0x15, 0x57, 0x49, 0x7d, 0xd7, 0x51, 0x65, 0x6e,
304 0x37, 0xa8, 0xe3, 0xe9, 0xe1, 0x59, 0x2e, 0xd4, 0x57, 0x4a, 0xf0, 0xcb,
305 0x0e, 0x85, 0x07, 0xdd, 0x35, 0xa7, 0xe3, 0xc6, 0xbb, 0x02, 0x01, 0x02
308 static uint8_t dh_parameters_768_data[] = {
309 0x30, 0x66, 0x02, 0x61, 0x00, 0xe1, 0xa2, 0x50, 0xab, 0xb0, 0xdc, 0xef,
310 0xe1, 0x2f, 0xd9, 0xde, 0x59, 0x86, 0x24, 0x43, 0x3b, 0xf3, 0x40, 0x9d,
311 0x02, 0xcc, 0xe2, 0x70, 0x63, 0x46, 0x8d, 0x0f, 0xf3, 0x8a, 0xc6, 0xa0,
312 0x1d, 0x7b, 0x30, 0x83, 0x10, 0x48, 0x40, 0x28, 0xa4, 0x3e, 0xbe, 0x4d,
313 0xb6, 0xea, 0x90, 0x02, 0xae, 0x25, 0x93, 0xc0, 0xe8, 0x36, 0x5c, 0xc8,
314 0xc8, 0x0b, 0x04, 0xd5, 0x05, 0xac, 0x67, 0x24, 0x4b, 0xa9, 0x42, 0x5a,
315 0x03, 0x65, 0x4d, 0xd0, 0xc0, 0xbd, 0x78, 0x32, 0xd0, 0x8c, 0x0a, 0xf4,
316 0xbf, 0xd1, 0x61, 0x86, 0x13, 0x13, 0x3b, 0x83, 0xce, 0xbf, 0x3b, 0xbc,
317 0x8f, 0xf9, 0x4e, 0x50, 0xe3, 0x02, 0x01, 0x02
320 static uint8_t dh_parameters_1024_data[] = {
321 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xd5, 0x06, 0x69, 0xc6, 0xd4,
322 0x98, 0x2b, 0xe3, 0x49, 0xe2, 0xa1, 0x9b, 0x82, 0xaf, 0x3f, 0xaa, 0xc3,
323 0x86, 0x2a, 0x7a, 0xfa, 0x62, 0x12, 0x33, 0x45, 0x9f, 0x34, 0x57, 0xc6,
324 0x6c, 0x88, 0x81, 0xa6, 0x5d, 0xa3, 0x43, 0xe5, 0x4d, 0x87, 0x4f, 0x69,
325 0x3d, 0x2b, 0xc8, 0x18, 0xb6, 0xd7, 0x29, 0x53, 0x94, 0x0d, 0x73, 0x9b,
326 0x08, 0x22, 0x73, 0x84, 0x7b, 0x5a, 0x03, 0x2e, 0xfc, 0x10, 0x9b, 0x35,
327 0xc6, 0xa1, 0xca, 0x36, 0xd0, 0xcc, 0x3e, 0xa2, 0x04, 0x3a, 0x8a, 0xe8,
328 0x87, 0xe8, 0x60, 0x72, 0xee, 0x99, 0xf3, 0x04, 0x0a, 0xd8, 0x1a, 0xe6,
329 0xfc, 0xbc, 0xe1, 0xc5, 0x9d, 0x3a, 0xca, 0xf9, 0xfd, 0xbf, 0x58, 0xd3,
330 0x4d, 0xde, 0x8b, 0x4a, 0xb5, 0x37, 0x1e, 0x6d, 0xf4, 0x22, 0x0f, 0xb7,
331 0x48, 0x0a, 0xda, 0x82, 0x40, 0xc9, 0x55, 0x20, 0x01, 0x3b, 0x35, 0xb2,
332 0x94, 0x68, 0xab, 0x02, 0x01, 0x02
338 const void *dhParams;
340 } server_dhe_params[] = {
341 {dh_parameters_256_data, sizeof(dh_parameters_256_data)},
342 {dh_parameters_512_data, sizeof(dh_parameters_512_data)},
343 {dh_parameters_768_data, sizeof(dh_parameters_768_data)},
344 {dh_parameters_1024_data, sizeof(dh_parameters_1024_data)},
345 {NULL, 0}, // default is a 2048
348 static const unsigned n_server_dhe_params = sizeof(server_dhe_params)/sizeof(server_dhe_params[0]);
351 int expected_client_error[n_server_dhe_params][n_client_dhe_sizes] = {
354 // 1024, 512, 512, 768, 1024, 2048, 2048 // Server:
355 { -9850, -9850, -9850, -9850, -9850, -9850, -9850}, // 256
356 { -9850, 0, 0, -9850, -9850, -9850, -9850}, // 512
357 { -9850, 0, 0, 0, -9850, -9850, -9850}, // 768
358 { 0, 0, 0, 0, 0, -9850, -9850}, // 1024
359 { 0, 0, 0, 0, 0, 0, 0}, // default(2048)
364 pthread_t client_thread, server_thread;
365 CFArrayRef server_certs = server_chain();
366 CFArrayRef trusted_ca = trusted_roots();
368 XCTAssert(server_certs, "got server certs");
369 XCTAssert(trusted_ca, "got trusted roots");
373 for (i = 0; i < (int)n_server_dhe_params; i++) {
374 for (j = 0; j < (int)n_client_dhe_sizes; j++) {
377 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
378 fcntl(sp[0], F_SETNOSIGPIPE, 1);
379 fcntl(sp[1], F_SETNOSIGPIPE, 1);
381 ssl_client_handle *client;
382 client = [self ssl_client_handle_create:sp[0] trustedCA:trusted_ca dhe_size:client_dhe_sizes[j]];
383 XCTAssert(client != NULL, "could not create client handle (%d:%d)", i, j);
386 ssl_server_handle *server;
387 server = [self ssl_server_handle_create:sp[1] certs:server_certs dhParams:server_dhe_params[i].dhParams dhParamsLen:server_dhe_params[i].dhParamsLen];
388 XCTAssert(server != NULL, "could not create server handle (%d:%d)", i, j);
390 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
391 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
393 intptr_t server_err, client_err;
395 pthread_join(client_thread, (void*)&client_err);
396 pthread_join(server_thread, (void*)&server_err);
399 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);
401 ssl_server_handle_destroy(server);
402 ssl_client_handle_destroy(client);
406 CFReleaseSafe(server_certs);
407 CFReleaseSafe(trusted_ca);
412 #pragma clang diagnostic pop