]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+dhe.m
Security-59306.41.2.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / SecureTransportTests / STLegacyTests+dhe.m
1
2 #include <stdbool.h>
3 #include <pthread.h>
4 #include <fcntl.h>
5 #include <sys/mman.h>
6 #include <unistd.h>
7
8 #include <CoreFoundation/CoreFoundation.h>
9
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>
21
22 #include <utilities/array_size.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <mach/mach_time.h>
29 #include <utilities/SecCFWrappers.h>
30
31 #if TARGET_OS_IPHONE
32 #include <Security/SecRSAKey.h>
33 #endif
34
35 #include "ssl-utils.h"
36 #import "STLegacyTests.h"
37
38 #pragma clang diagnostic push
39 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
40
41 @implementation STLegacyTests (dhe)
42
43 /*
44 SSL DHE tests:
45
46 Test both the client and server side.
47
48 Test Goal:
49 - Make sure that handshake fail when dh param size is too small.
50
51 Behavior to verify:
52 - handshake pass or fail
53
54 */
55
56
57 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
58 {
59 size_t len = *length;
60 uint8_t *ptr = (uint8_t *)data;
61
62 do {
63 ssize_t ret;
64 do {
65 ret = write((int)conn, ptr, len);
66 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
67 if (ret > 0) {
68 len -= ret;
69 ptr += ret;
70 }
71 else
72 return -36;
73 } while (len > 0);
74
75 *length = *length - len;
76 return errSecSuccess;
77 }
78
79 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
80 {
81 size_t len = *length;
82 uint8_t *ptr = (uint8_t *)data;
83
84 do {
85 ssize_t ret;
86 do {
87 ret = read((int)conn, ptr, len);
88 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
89 if (ret > 0) {
90 len -= ret;
91 ptr += ret;
92 } else {
93 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
94 return -errno;
95 }
96 } while (len > 0);
97
98 *length = *length - len;
99 return errSecSuccess;
100 }
101
102 typedef struct {
103 SSLContextRef st;
104 int comm;
105 unsigned dhe_size;
106 } ssl_client_handle;
107
108 -(ssl_client_handle *)ssl_client_handle_create:(int) comm trustedCA:(CFArrayRef) trustedCA dhe_size:(unsigned) dhe_size
109 {
110 ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle));
111 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
112
113 require(handle, out);
114 require(ctx, out);
115
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)));
124
125 XCTAssertEqual(errSecSuccess, SSLSetTrustedRoots(ctx, trustedCA, true));
126
127 XCTAssertEqual(errSecSuccess, SSLSetDHEEnabled(ctx, true));
128 bool enabled;
129 XCTAssertEqual(errSecSuccess, SSLGetDHEEnabled(ctx, &enabled));
130 XCTAssertEqual(enabled, true);
131
132 if(dhe_size) {
133 XCTAssertEqual(errSecSuccess, SSLSetMinimumDHGroupSize(ctx, dhe_size));
134 unsigned int nbits = 0;
135 XCTAssertEqual(errSecSuccess, SSLGetMinimumDHGroupSize(ctx, &nbits));
136 }
137 handle->comm = comm;
138 handle->st = ctx;
139 handle->dhe_size = dhe_size;
140
141 return handle;
142
143 out:
144 if (ctx)
145 CFRelease(ctx);
146 if (handle)
147 free(handle);
148
149 return NULL;
150 }
151
152 static void
153 ssl_client_handle_destroy(ssl_client_handle *handle)
154 {
155 if (handle) {
156 SSLClose(handle->st);
157 CFRelease(handle->st);
158 free(handle);
159 }
160 }
161
162 static void *securetransport_ssl_client_thread(void *arg)
163 {
164 OSStatus ortn;
165 ssl_client_handle * ssl = (ssl_client_handle *)arg;
166 SSLContextRef ctx = ssl->st;
167 SSLSessionState ssl_state;
168
169 pthread_setname_np("client thread");
170
171 require_noerr(ortn = SSLGetSessionState(ctx,&ssl_state), out);
172 require_action(ssl_state == kSSLIdle, out, ortn = -1);
173
174 do {
175 ortn = SSLHandshake(ctx);
176 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
177
178 if (ortn == errSSLWouldBlock) {
179 require_string(ssl_state == kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
180 }
181 } while (ortn == errSSLWouldBlock);
182
183 out:
184 SSLClose(ssl->st);
185 close(ssl->comm);
186 pthread_exit((void *)(intptr_t)ortn);
187 return NULL;
188 }
189
190
191 typedef struct {
192 SSLContextRef st;
193 int comm;
194 CFArrayRef certs;
195
196 } ssl_server_handle;
197
198 -(ssl_server_handle *)ssl_server_handle_create:(int) comm certs: (CFArrayRef) certs dhParams: (const void *)dhParams dhParamsLen: (size_t) dhParamsLen
199 {
200 ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle));
201 XCTAssert(handle, "handle allocation failed");
202
203 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
204 XCTAssert(ctx, "SSLCreateContext failed");
205
206 SSLCipherSuite cipher = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
207
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");
211
212 XCTAssertEqual(errSecSuccess, SSLSetCertificate(ctx, certs), "Failed to set certificate");
213 CFArrayRef inputCerts = NULL;
214 XCTAssertEqual(errSecSuccess, SSLGetCertificate(ctx, &inputCerts), "Failed to get certificates");
215
216 XCTAssertEqual(errSecSuccess, SSLSetEnabledCiphers(ctx, &cipher, 1), "SSLSetEnabledCiphers failed");
217
218 if (dhParams) {
219 XCTAssertEqual(errSecSuccess, SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen),
220 "Failed to set DH parameters");
221 const void *inputDH = NULL;
222 size_t inputDHLen;
223 XCTAssertEqual(errSecSuccess, SSLGetDiffieHellmanParams(ctx, &inputDH, &inputDHLen),
224 "Failed to get DH parameters");
225 }
226
227 handle->comm = comm;
228 handle->certs = certs;
229 handle->st = ctx;
230
231 return handle;
232 }
233
234 static void
235 ssl_server_handle_destroy(ssl_server_handle *handle)
236 {
237 if(handle) {
238 SSLClose(handle->st);
239 CFRelease(handle->st);
240 free(handle);
241 }
242 }
243
244 static void *securetransport_ssl_server_thread(void *arg)
245 {
246 OSStatus ortn;
247 ssl_server_handle * ssl = (ssl_server_handle *)arg;
248 SSLContextRef ctx = ssl->st;
249 SSLSessionState ssl_state;
250
251 pthread_setname_np("server thread");
252
253 require_noerr(ortn = SSLGetSessionState(ctx,&ssl_state), out);
254 require_action(ssl_state == kSSLIdle, out, ortn = -1);
255
256 do {
257 ortn = SSLHandshake(ctx);
258 require_noerr(SSLGetSessionState(ctx, &ssl_state), out);
259
260 if (ortn == errSSLWouldBlock) {
261 require_action(ssl_state == kSSLHandshake, out, ortn = -1);
262 }
263 } while (ortn == errSSLWouldBlock);
264
265 require_noerr_quiet(ortn, out);
266
267 require_action(ssl_state == kSSLConnected, out, ortn = -1);
268
269 out:
270 SSLClose(ssl->st);
271 close(ssl->comm);
272 pthread_exit((void *)(intptr_t)ortn);
273 return NULL;
274 }
275
276
277
278 static
279 unsigned client_dhe_sizes[] = {
280 0, // default, don't set.
281 256, // will resolve to 512.
282 512,
283 768,
284 1024,
285 2048,
286 4096, // will resolve to 2048.
287 };
288
289
290 static const unsigned n_client_dhe_sizes = sizeof(client_dhe_sizes)/sizeof(client_dhe_sizes[0]);
291
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
297 };
298
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
306 };
307
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
318 };
319
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
333 };
334
335
336 static
337 struct {
338 const void *dhParams;
339 size_t dhParamsLen;
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
346 };
347
348 static const unsigned n_server_dhe_params = sizeof(server_dhe_params)/sizeof(server_dhe_params[0]);
349
350 static
351 int expected_client_error[n_server_dhe_params][n_client_dhe_sizes] = {
352 //Client:
353 // (default)
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)
360 };
361
362 -(void)testDHE
363 {
364 pthread_t client_thread, server_thread;
365 CFArrayRef server_certs = server_chain();
366 CFArrayRef trusted_ca = trusted_roots();
367
368 XCTAssert(server_certs, "got server certs");
369 XCTAssert(trusted_ca, "got trusted roots");
370
371 int i, j;
372
373 for (i = 0; i < (int)n_server_dhe_params; i++) {
374 for (j = 0; j < (int)n_client_dhe_sizes; j++) {
375
376 int sp[2];
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);
380
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);
384
385
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);
389
390 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
391 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
392
393 intptr_t server_err, client_err;
394
395 pthread_join(client_thread, (void*)&client_err);
396 pthread_join(server_thread, (void*)&server_err);
397
398
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);
400
401 ssl_server_handle_destroy(server);
402 ssl_client_handle_destroy(client);
403 }
404 }
405
406 CFReleaseSafe(server_certs);
407 CFReleaseSafe(trusted_ca);
408 }
409
410 @end
411
412 #pragma clang diagnostic pop