]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+dhe.m
Security-58286.240.4.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
30 #if TARGET_OS_IPHONE
31 #include <Security/SecRSAKey.h>
32 #endif
33
34 #include "ssl-utils.h"
35 #import "STLegacyTests.h"
36
37 @implementation STLegacyTests (dhe)
38
39 /*
40 SSL DHE tests:
41
42 Test both the client and server side.
43
44 Test Goal:
45 - Make sure that handshake fail when dh param size is too small.
46
47 Behavior to verify:
48 - handshake pass or fail
49
50 */
51
52
53 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
54 {
55 size_t len = *length;
56 uint8_t *ptr = (uint8_t *)data;
57
58 do {
59 ssize_t ret;
60 do {
61 ret = write((int)conn, ptr, len);
62 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
63 if (ret > 0) {
64 len -= ret;
65 ptr += ret;
66 }
67 else
68 return -36;
69 } while (len > 0);
70
71 *length = *length - len;
72 return errSecSuccess;
73 }
74
75 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
76 {
77 size_t len = *length;
78 uint8_t *ptr = (uint8_t *)data;
79
80 do {
81 ssize_t ret;
82 do {
83 ret = read((int)conn, ptr, len);
84 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
85 if (ret > 0) {
86 len -= ret;
87 ptr += ret;
88 } else {
89 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
90 return -errno;
91 }
92 } while (len > 0);
93
94 *length = *length - len;
95 return errSecSuccess;
96 }
97
98 typedef struct {
99 SSLContextRef st;
100 int comm;
101 unsigned dhe_size;
102 } ssl_client_handle;
103
104 static ssl_client_handle *
105 ssl_client_handle_create(int comm, CFArrayRef trustedCA, unsigned dhe_size)
106 {
107 ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle));
108 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
109
110 require(handle, out);
111 require(ctx, out);
112
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);
119
120 require_noerr(SSLSetTrustedRoots(ctx, trustedCA, true), out);
121
122 require_noerr(SSLSetDHEEnabled(ctx, true), out);
123
124 if(dhe_size)
125 require_noerr(SSLSetMinimumDHGroupSize(ctx, dhe_size), out);
126
127 handle->comm = comm;
128 handle->st = ctx;
129 handle->dhe_size = dhe_size;
130
131 return handle;
132
133 out:
134 if (ctx)
135 CFRelease(ctx);
136 if (handle)
137 free(handle);
138
139 return NULL;
140 }
141
142 static void
143 ssl_client_handle_destroy(ssl_client_handle *handle)
144 {
145 if(handle) {
146 SSLClose(handle->st);
147 CFRelease(handle->st);
148 free(handle);
149 }
150 }
151
152 static void *securetransport_ssl_client_thread(void *arg)
153 {
154 OSStatus ortn;
155 ssl_client_handle * ssl = (ssl_client_handle *)arg;
156 SSLContextRef ctx = ssl->st;
157 SSLSessionState ssl_state;
158
159 pthread_setname_np("client thread");
160
161 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
162 require_action(ssl_state==kSSLIdle, out, ortn = -1);
163
164 do {
165 ortn = SSLHandshake(ctx);
166 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
167
168 if (ortn == errSSLWouldBlock) {
169 require_string(ssl_state==kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
170 }
171 } while (ortn == errSSLWouldBlock);
172
173 out:
174 SSLClose(ssl->st);
175 close(ssl->comm);
176 pthread_exit((void *)(intptr_t)ortn);
177 return NULL;
178 }
179
180
181 typedef struct {
182 SSLContextRef st;
183 int comm;
184 CFArrayRef certs;
185
186 } ssl_server_handle;
187
188 static ssl_server_handle *
189 ssl_server_handle_create(int comm, CFArrayRef certs, const void *dhParams, size_t dhParamsLen)
190 {
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;
194
195 require(handle, out);
196 require(ctx, out);
197
198 require_noerr(SSLSetIOFuncs(ctx,
199 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
200 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
201
202 require_noerr(SSLSetCertificate(ctx, certs), out);
203
204 require_noerr(SSLSetEnabledCiphers(ctx, &cipher, 1), out);
205
206 if(dhParams)
207 require_noerr(SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen), out);
208
209 handle->comm = comm;
210 handle->certs = certs;
211 handle->st = ctx;
212
213 return handle;
214
215 out:
216 if (ctx)
217 CFRelease(ctx);
218 if (handle)
219 free(handle);
220
221 return NULL;
222 }
223
224 static void
225 ssl_server_handle_destroy(ssl_server_handle *handle)
226 {
227 if(handle) {
228 SSLClose(handle->st);
229 CFRelease(handle->st);
230 free(handle);
231 }
232 }
233
234 static void *securetransport_ssl_server_thread(void *arg)
235 {
236 OSStatus ortn;
237 ssl_server_handle * ssl = (ssl_server_handle *)arg;
238 SSLContextRef ctx = ssl->st;
239 SSLSessionState ssl_state;
240
241 pthread_setname_np("server thread");
242
243 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
244 require_action(ssl_state==kSSLIdle, out, ortn = -1);
245
246 do {
247 ortn = SSLHandshake(ctx);
248 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
249
250 if (ortn == errSSLWouldBlock) {
251 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
252 }
253 } while (ortn == errSSLWouldBlock);
254
255 require_noerr_quiet(ortn, out);
256
257 require_action(ssl_state==kSSLConnected, out, ortn = -1);
258
259 out:
260 SSLClose(ssl->st);
261 close(ssl->comm);
262 pthread_exit((void *)(intptr_t)ortn);
263 return NULL;
264 }
265
266
267
268 static
269 unsigned client_dhe_sizes[] = {
270 0, // default, don't set.
271 256, // will resolve to 512.
272 512,
273 768,
274 1024,
275 2048,
276 4096, // will resolve to 2048.
277 };
278
279
280 static const unsigned n_client_dhe_sizes = sizeof(client_dhe_sizes)/sizeof(client_dhe_sizes[0]);
281
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
287 };
288
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
296 };
297
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
308 };
309
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
323 };
324
325
326 static
327 struct {
328 const void *dhParams;
329 size_t dhParamsLen;
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
336 };
337
338 static const unsigned n_server_dhe_params = sizeof(server_dhe_params)/sizeof(server_dhe_params[0]);
339
340 static
341 int expected_client_error[n_server_dhe_params][n_client_dhe_sizes] = {
342 //Client:
343 // (default)
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)
350 };
351
352 -(void)testDHE
353 {
354 pthread_t client_thread, server_thread;
355 CFArrayRef server_certs = server_chain();
356 CFArrayRef trusted_ca = trusted_roots();
357
358 XCTAssert(server_certs, "got server certs");
359 XCTAssert(trusted_ca, "got trusted roots");
360
361 int i, j;
362
363 for (i=0; i<n_server_dhe_params; i++) {
364 for (j=0; j<n_client_dhe_sizes; j++) {
365
366 int sp[2];
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);
370
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);
374
375
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);
379
380 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
381 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
382
383 intptr_t server_err, client_err;
384
385 pthread_join(client_thread, (void*)&client_err);
386 pthread_join(server_thread, (void*)&server_err);
387
388
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);
390
391 ssl_server_handle_destroy(server);
392 ssl_client_handle_destroy(client);
393 }
394 }
395
396 CFReleaseSafe(server_certs);
397 CFReleaseSafe(trusted_ca);
398 }
399
400 @end