]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/ssl-54-dhe.c
Security-57336.10.29.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / ssl-54-dhe.c
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_regressions.h"
35 #include "ssl-utils.h"
36
37 /*
38 SSL DHE tests:
39
40 Test both the client and server side.
41
42 Test Goal:
43 - Make sure that handshake fail when dh param size is too small.
44
45 Behavior to verify:
46 - handshake pass or fail
47
48 */
49
50
51 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
52 {
53 size_t len = *length;
54 uint8_t *ptr = (uint8_t *)data;
55
56 do {
57 ssize_t ret;
58 do {
59 ret = write((int)conn, ptr, len);
60 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
61 if (ret > 0) {
62 len -= ret;
63 ptr += ret;
64 }
65 else
66 return -36;
67 } while (len > 0);
68
69 *length = *length - len;
70 return errSecSuccess;
71 }
72
73 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
74 {
75 size_t len = *length;
76 uint8_t *ptr = (uint8_t *)data;
77
78 do {
79 ssize_t ret;
80 do {
81 ret = read((int)conn, ptr, len);
82 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
83 if (ret > 0) {
84 len -= ret;
85 ptr += ret;
86 } else {
87 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
88 return -errno;
89 }
90 } while (len > 0);
91
92 *length = *length - len;
93 return errSecSuccess;
94 }
95
96 typedef struct {
97 SSLContextRef st;
98 int comm;
99 unsigned dhe_size;
100 } ssl_client_handle;
101
102 static ssl_client_handle *
103 ssl_client_handle_create(int comm, CFArrayRef trustedCA, unsigned dhe_size)
104 {
105 ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle));
106 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
107
108 require(handle, out);
109 require(ctx, out);
110
111 require_noerr(SSLSetIOFuncs(ctx,
112 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
113 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
114 static const char *peer_domain_name = "localhost";
115 require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name,
116 strlen(peer_domain_name)), out);
117
118 require_noerr(SSLSetTrustedRoots(ctx, trustedCA, true), out);
119
120 require_noerr(SSLSetDHEEnabled(ctx, true), out);
121
122 if(dhe_size)
123 require_noerr(SSLSetMinimumDHGroupSize(ctx, dhe_size), out);
124
125 handle->comm = comm;
126 handle->st = ctx;
127 handle->dhe_size = dhe_size;
128
129 return handle;
130
131 out:
132 if (ctx)
133 CFRelease(ctx);
134 if (handle)
135 free(handle);
136
137 return NULL;
138 }
139
140 static void
141 ssl_client_handle_destroy(ssl_client_handle *handle)
142 {
143 if(handle) {
144 SSLClose(handle->st);
145 CFRelease(handle->st);
146 free(handle);
147 }
148 }
149
150 static void *securetransport_ssl_client_thread(void *arg)
151 {
152 OSStatus ortn;
153 ssl_client_handle * ssl = (ssl_client_handle *)arg;
154 SSLContextRef ctx = ssl->st;
155 SSLSessionState ssl_state;
156
157 pthread_setname_np("client thread");
158
159 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
160 require_action(ssl_state==kSSLIdle, out, ortn = -1);
161
162 do {
163 ortn = SSLHandshake(ctx);
164 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
165
166 if (ortn == errSSLWouldBlock) {
167 require_string(ssl_state==kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
168 }
169 } while (ortn == errSSLWouldBlock);
170
171 out:
172 SSLClose(ssl->st);
173 close(ssl->comm);
174 pthread_exit((void *)(intptr_t)ortn);
175 return NULL;
176 }
177
178
179 typedef struct {
180 SSLContextRef st;
181 int comm;
182 CFArrayRef certs;
183
184 } ssl_server_handle;
185
186 static ssl_server_handle *
187 ssl_server_handle_create(int comm, CFArrayRef certs, const void *dhParams, size_t dhParamsLen)
188 {
189 ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle));
190 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
191 SSLCipherSuite cipher = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
192
193 require(handle, out);
194 require(ctx, out);
195
196 require_noerr(SSLSetIOFuncs(ctx,
197 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
198 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
199
200 require_noerr(SSLSetCertificate(ctx, certs), out);
201
202 require_noerr(SSLSetEnabledCiphers(ctx, &cipher, 1), out);
203
204 if(dhParams)
205 require_noerr(SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen), out);
206
207 handle->comm = comm;
208 handle->certs = certs;
209 handle->st = ctx;
210
211 return handle;
212
213 out:
214 if (ctx)
215 CFRelease(ctx);
216 if (handle)
217 free(handle);
218
219 return NULL;
220 }
221
222 static void
223 ssl_server_handle_destroy(ssl_server_handle *handle)
224 {
225 if(handle) {
226 SSLClose(handle->st);
227 CFRelease(handle->st);
228 free(handle);
229 }
230 }
231
232 static void *securetransport_ssl_server_thread(void *arg)
233 {
234 OSStatus ortn;
235 ssl_server_handle * ssl = (ssl_server_handle *)arg;
236 SSLContextRef ctx = ssl->st;
237 SSLSessionState ssl_state;
238
239 pthread_setname_np("server thread");
240
241 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
242 require_action(ssl_state==kSSLIdle, out, ortn = -1);
243
244 do {
245 ortn = SSLHandshake(ctx);
246 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
247
248 if (ortn == errSSLWouldBlock) {
249 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
250 }
251 } while (ortn == errSSLWouldBlock);
252
253 require_noerr_quiet(ortn, out);
254
255 require_action(ssl_state==kSSLConnected, out, ortn = -1);
256
257 out:
258 SSLClose(ssl->st);
259 close(ssl->comm);
260 pthread_exit((void *)(intptr_t)ortn);
261 return NULL;
262 }
263
264
265
266 static
267 unsigned client_dhe_sizes[] = {
268 0, // default, don't set.
269 256, // will resolve to 512.
270 512,
271 768,
272 1024,
273 2048,
274 4096, // will resolve to 2048.
275 };
276
277
278 static const unsigned n_client_dhe_sizes = sizeof(client_dhe_sizes)/sizeof(client_dhe_sizes[0]);
279
280 static uint8_t dh_parameters_256_data[] = {
281 0x30, 0x26, 0x02, 0x21, 0x00, 0xd8, 0x23, 0xeb, 0xcb, 0x41, 0xd0, 0x3a,
282 0xc4, 0x9a, 0x2a, 0x2a, 0x4f, 0x35, 0xf7, 0x4f, 0xd9, 0xc5, 0x2e, 0xf8,
283 0x44, 0xa7, 0x74, 0xe3, 0x84, 0x98, 0x9f, 0xad, 0x58, 0xd5, 0x15, 0xb4,
284 0xf3, 0x02, 0x01, 0x02
285 };
286
287 static uint8_t dh_parameters_512_data[] = {
288 0x30, 0x46, 0x02, 0x41, 0x00, 0x85, 0xcd, 0xc1, 0x7e, 0x26, 0xeb, 0x37,
289 0x84, 0x13, 0xd0, 0x3b, 0x07, 0xc1, 0x57, 0x7d, 0xf3, 0x55, 0x8d, 0xa0,
290 0xc4, 0xa5, 0x03, 0xc4, 0x2c, 0xc6, 0xd5, 0xa6, 0x31, 0xcb, 0x68, 0xdf,
291 0x5d, 0x96, 0x20, 0x1a, 0x15, 0x57, 0x49, 0x7d, 0xd7, 0x51, 0x65, 0x6e,
292 0x37, 0xa8, 0xe3, 0xe9, 0xe1, 0x59, 0x2e, 0xd4, 0x57, 0x4a, 0xf0, 0xcb,
293 0x0e, 0x85, 0x07, 0xdd, 0x35, 0xa7, 0xe3, 0xc6, 0xbb, 0x02, 0x01, 0x02
294 };
295
296 static uint8_t dh_parameters_768_data[] = {
297 0x30, 0x66, 0x02, 0x61, 0x00, 0xe1, 0xa2, 0x50, 0xab, 0xb0, 0xdc, 0xef,
298 0xe1, 0x2f, 0xd9, 0xde, 0x59, 0x86, 0x24, 0x43, 0x3b, 0xf3, 0x40, 0x9d,
299 0x02, 0xcc, 0xe2, 0x70, 0x63, 0x46, 0x8d, 0x0f, 0xf3, 0x8a, 0xc6, 0xa0,
300 0x1d, 0x7b, 0x30, 0x83, 0x10, 0x48, 0x40, 0x28, 0xa4, 0x3e, 0xbe, 0x4d,
301 0xb6, 0xea, 0x90, 0x02, 0xae, 0x25, 0x93, 0xc0, 0xe8, 0x36, 0x5c, 0xc8,
302 0xc8, 0x0b, 0x04, 0xd5, 0x05, 0xac, 0x67, 0x24, 0x4b, 0xa9, 0x42, 0x5a,
303 0x03, 0x65, 0x4d, 0xd0, 0xc0, 0xbd, 0x78, 0x32, 0xd0, 0x8c, 0x0a, 0xf4,
304 0xbf, 0xd1, 0x61, 0x86, 0x13, 0x13, 0x3b, 0x83, 0xce, 0xbf, 0x3b, 0xbc,
305 0x8f, 0xf9, 0x4e, 0x50, 0xe3, 0x02, 0x01, 0x02
306 };
307
308 static uint8_t dh_parameters_1024_data[] = {
309 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xd5, 0x06, 0x69, 0xc6, 0xd4,
310 0x98, 0x2b, 0xe3, 0x49, 0xe2, 0xa1, 0x9b, 0x82, 0xaf, 0x3f, 0xaa, 0xc3,
311 0x86, 0x2a, 0x7a, 0xfa, 0x62, 0x12, 0x33, 0x45, 0x9f, 0x34, 0x57, 0xc6,
312 0x6c, 0x88, 0x81, 0xa6, 0x5d, 0xa3, 0x43, 0xe5, 0x4d, 0x87, 0x4f, 0x69,
313 0x3d, 0x2b, 0xc8, 0x18, 0xb6, 0xd7, 0x29, 0x53, 0x94, 0x0d, 0x73, 0x9b,
314 0x08, 0x22, 0x73, 0x84, 0x7b, 0x5a, 0x03, 0x2e, 0xfc, 0x10, 0x9b, 0x35,
315 0xc6, 0xa1, 0xca, 0x36, 0xd0, 0xcc, 0x3e, 0xa2, 0x04, 0x3a, 0x8a, 0xe8,
316 0x87, 0xe8, 0x60, 0x72, 0xee, 0x99, 0xf3, 0x04, 0x0a, 0xd8, 0x1a, 0xe6,
317 0xfc, 0xbc, 0xe1, 0xc5, 0x9d, 0x3a, 0xca, 0xf9, 0xfd, 0xbf, 0x58, 0xd3,
318 0x4d, 0xde, 0x8b, 0x4a, 0xb5, 0x37, 0x1e, 0x6d, 0xf4, 0x22, 0x0f, 0xb7,
319 0x48, 0x0a, 0xda, 0x82, 0x40, 0xc9, 0x55, 0x20, 0x01, 0x3b, 0x35, 0xb2,
320 0x94, 0x68, 0xab, 0x02, 0x01, 0x02
321 };
322
323
324 static
325 struct {
326 const void *dhParams;
327 size_t dhParamsLen;
328 } server_dhe_params[] = {
329 {dh_parameters_256_data, sizeof(dh_parameters_256_data)},
330 {dh_parameters_512_data, sizeof(dh_parameters_512_data)},
331 {dh_parameters_768_data, sizeof(dh_parameters_768_data)},
332 {dh_parameters_1024_data, sizeof(dh_parameters_1024_data)},
333 {NULL, 0}, // default is a 2048
334 };
335
336 static const unsigned n_server_dhe_params = sizeof(server_dhe_params)/sizeof(server_dhe_params[0]);
337
338 static
339 int expected_client_error[n_server_dhe_params][n_client_dhe_sizes] = {
340 //Client:
341 // (default)
342 // 1024, 512, 512, 768, 1024, 2048, 2048 // Server:
343 { -9850, -9850, -9850, -9850, -9850, -9850, -9850}, // 256
344 { -9850, 0, 0, -9850, -9850, -9850, -9850}, // 512
345 { -9850, 0, 0, 0, -9850, -9850, -9850}, // 768
346 { 0, 0, 0, 0, 0, -9850, -9850}, // 1024
347 { 0, 0, 0, 0, 0, 0, 0}, // default(2048)
348 };
349
350 static void
351 tests(void)
352 {
353 pthread_t client_thread, server_thread;
354 CFArrayRef server_certs = server_chain();
355 CFArrayRef trusted_ca = trusted_roots();
356
357 ok(server_certs, "got server certs");
358 ok(trusted_ca, "got trusted roots");
359
360 int i, j;
361
362 for (i=0; i<n_server_dhe_params; i++) {
363 for (j=0; j<n_client_dhe_sizes; j++) {
364
365 int sp[2];
366 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
367 fcntl(sp[0], F_SETNOSIGPIPE, 1);
368 fcntl(sp[1], F_SETNOSIGPIPE, 1);
369
370 ssl_client_handle *client;
371 client = ssl_client_handle_create(sp[0], trusted_ca, client_dhe_sizes[j]);
372 ok(client!=NULL, "could not create client handle (%d:%d)", i, j);
373
374
375 ssl_server_handle *server;
376 server = ssl_server_handle_create(sp[1], server_certs, server_dhe_params[i].dhParams, server_dhe_params[i].dhParamsLen);
377 ok(server!=NULL, "could not create server handle (%d:%d)", i, j);
378
379 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
380 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
381
382 intptr_t server_err, client_err;
383
384 pthread_join(client_thread, (void*)&client_err);
385 pthread_join(server_thread, (void*)&server_err);
386
387
388 ok(client_err==expected_client_error[i][j], "unexpected error %d!=%d (client %d:%d)", (int)client_err, expected_client_error[i][j], i, j);
389
390 ssl_server_handle_destroy(server);
391 ssl_client_handle_destroy(client);
392 close(sp[0]);
393 close(sp[1]);
394
395 }
396 }
397
398 CFReleaseSafe(server_certs);
399 CFReleaseSafe(trusted_ca);
400 }
401
402 int ssl_54_dhe(int argc, char *const *argv)
403 {
404
405 plan_tests(n_server_dhe_params * n_client_dhe_sizes * 3 + 2 /*cert*/);
406
407
408 tests();
409
410 return 0;
411 }