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