]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_ssl/regressions/ssl-54-dhe.c
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / ssl-54-dhe.c
CommitLineData
5c19dc3a
A
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
51static 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
73static 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
96typedef struct {
97 SSLContextRef st;
98 int comm;
99 unsigned dhe_size;
100} ssl_client_handle;
101
102static ssl_client_handle *
103ssl_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
131out:
132 if (ctx)
133 CFRelease(ctx);
134 if (handle)
135 free(handle);
136
137 return NULL;
138}
139
140static void
141ssl_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
150static 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
171out:
172 SSLClose(ssl->st);
173 close(ssl->comm);
174 pthread_exit((void *)(intptr_t)ortn);
175 return NULL;
176}
177
178
179typedef struct {
180 SSLContextRef st;
181 int comm;
182 CFArrayRef certs;
183
184} ssl_server_handle;
185
186static ssl_server_handle *
187ssl_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
213out:
214 if (ctx)
215 CFRelease(ctx);
216 if (handle)
217 free(handle);
218
219 return NULL;
220}
221
222static void
223ssl_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
232static 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
257out:
258 SSLClose(ssl->st);
259 close(ssl->comm);
260 pthread_exit((void *)(intptr_t)ortn);
261 return NULL;
262}
263
264
265
266static
267unsigned 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
278static const unsigned n_client_dhe_sizes = sizeof(client_dhe_sizes)/sizeof(client_dhe_sizes[0]);
279
280static 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
287static 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
296static 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
308static 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
324static
325struct {
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
336static const unsigned n_server_dhe_params = sizeof(server_dhe_params)/sizeof(server_dhe_params[0]);
337
338static
339int 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
350static void
351tests(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
402int 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}