]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/ssl-56-renegotiate.c
Security-58286.51.6.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / ssl-56-renegotiate.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 Renegotiation tests:
39
40 Test both the client and server side.
41
42 Test Goal:
43 - Make sure that renegotiation works on both client and server.
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 bool renegotiate;
101 } ssl_client_handle;
102
103 static ssl_client_handle *
104 ssl_client_handle_create(int comm, bool renegotiate)
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(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, TRUE), out);
120
121 require_noerr(SSLSetAllowsAnyRoot(ctx, TRUE), out);
122
123
124 handle->comm = comm;
125 handle->st = ctx;
126 handle->renegotiate = renegotiate;
127
128 return handle;
129
130 out:
131 if (ctx)
132 CFRelease(ctx);
133 if (handle)
134 free(handle);
135
136 return NULL;
137 }
138
139 static void
140 ssl_client_handle_destroy(ssl_client_handle *handle)
141 {
142 if(handle) {
143 SSLClose(handle->st);
144 CFRelease(handle->st);
145 free(handle);
146 }
147 }
148
149 static void *securetransport_ssl_client_thread(void *arg)
150 {
151 OSStatus ortn;
152 ssl_client_handle * ssl = (ssl_client_handle *)arg;
153 SSLContextRef ctx = ssl->st;
154 SSLSessionState ssl_state;
155 bool peer_auth_received = false;
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 == errSSLPeerAuthCompleted) {
167 require_action(!peer_auth_received, out, ortn = -1);
168 peer_auth_received = true;
169 }
170 if (ortn == errSSLWouldBlock) {
171 require_string(ssl_state==kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
172 }
173 } while (ortn == errSSLWouldBlock || ortn == errSSLPeerAuthCompleted);
174
175 require_noerr(ortn, out);
176 require_action(ssl_state==kSSLConnected, out, ortn = -1);
177 require_action(peer_auth_received, out, ortn = -1);
178
179 if(ssl->renegotiate) {
180 // Renegotiate then write
181 require_noerr(SSLReHandshake(ctx), out);
182
183 peer_auth_received = false;
184
185 do {
186 ortn = SSLHandshake(ctx);
187 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
188 if (ortn == errSSLPeerAuthCompleted) {
189 require_action(!peer_auth_received, out, ortn = -1);
190 peer_auth_received = true;
191 }
192 if (ortn == errSSLWouldBlock) {
193 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
194 }
195 } while (ortn == errSSLWouldBlock || ortn == errSSLPeerAuthCompleted);
196
197 require_noerr(ortn, out);
198 require_action(ssl_state==kSSLConnected, out, ortn = -1);
199 require_action(peer_auth_received, out, ortn = -1);
200
201 unsigned char obuf[100];
202
203 size_t len = sizeof(obuf);
204 size_t olen;
205 unsigned char *p = obuf;
206
207 require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, len, p), out, ortn = -1);
208
209 while (len) {
210 require_noerr(ortn = SSLWrite(ctx, p, len, &olen), out);
211 len -= olen;
212 p += olen;
213 }
214 } else {
215 // just read.
216 unsigned char ibuf[100];
217
218 peer_auth_received = false;
219
220 size_t len = sizeof(ibuf);
221 size_t olen;
222 unsigned char *p = ibuf;
223 while (len) {
224 ortn = SSLRead(ctx, p, len, &olen);
225
226 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
227
228 if (ortn == errSSLPeerAuthCompleted) {
229 require_action(!peer_auth_received, out, ortn = -1);
230 peer_auth_received = true;
231 } else {
232 require_noerr(ortn, out);
233 }
234
235 /* If we get data, we should have renegotiated */
236 if(olen) {
237 require_noerr(ortn, out);
238 require_action(ssl_state==kSSLConnected, out, ortn = -1);
239 require_action(peer_auth_received, out, ortn = -1);
240 }
241
242 len -= olen;
243 p += olen;
244 }
245 }
246
247 out:
248 SSLClose(ssl->st);
249 close(ssl->comm);
250 pthread_exit((void *)(intptr_t)ortn);
251 return NULL;
252 }
253
254
255 typedef struct {
256 SSLContextRef st;
257 int comm;
258 CFArrayRef certs;
259 bool renegotiate;
260 } ssl_server_handle;
261
262 static ssl_server_handle *
263 ssl_server_handle_create(int comm, CFArrayRef certs, bool renegotiate)
264 {
265 ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle));
266 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
267 SSLCipherSuite cipher = TLS_RSA_WITH_AES_256_CBC_SHA256;
268
269 require(handle, out);
270 require(ctx, out);
271
272 require_noerr(SSLSetIOFuncs(ctx,
273 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
274 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
275
276 require_noerr(SSLSetCertificate(ctx, certs), out);
277
278 require_noerr(SSLSetEnabledCiphers(ctx, &cipher, 1), out);
279
280 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnClientHello, TRUE), out);
281 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionAllowRenegotiation, TRUE), out);
282
283 handle->comm = comm;
284 handle->certs = certs;
285 handle->st = ctx;
286 handle->renegotiate = renegotiate;
287
288 return handle;
289
290 out:
291 if (ctx)
292 CFRelease(ctx);
293 if (handle)
294 free(handle);
295
296 return NULL;
297 }
298
299 static void
300 ssl_server_handle_destroy(ssl_server_handle *handle)
301 {
302 if(handle) {
303 SSLClose(handle->st);
304 CFRelease(handle->st);
305 free(handle);
306 }
307 }
308
309 static void *securetransport_ssl_server_thread(void *arg)
310 {
311 OSStatus ortn;
312 ssl_server_handle * ssl = (ssl_server_handle *)arg;
313 SSLContextRef ctx = ssl->st;
314 SSLSessionState ssl_state;
315 bool client_hello_received = false;
316
317 pthread_setname_np("server thread");
318
319 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
320 require_action(ssl_state==kSSLIdle, out, ortn = -1);
321
322 do {
323 ortn = SSLHandshake(ctx);
324 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
325 if (ortn == errSSLClientHelloReceived) {
326 require_action(!client_hello_received, out, ortn = -1);
327 client_hello_received = true;
328 }
329 if (ortn == errSSLWouldBlock) {
330 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
331 }
332 } while (ortn == errSSLWouldBlock || ortn == errSSLClientHelloReceived);
333
334 require_noerr(ortn, out);
335 require_action(ssl_state==kSSLConnected, out, ortn = -1);
336 require_action(client_hello_received, out, ortn = -1);
337
338 if(ssl->renegotiate) {
339 // Renegotiate then write
340 require_noerr(SSLReHandshake(ctx), out);
341
342 client_hello_received = false;
343
344 do {
345 ortn = SSLHandshake(ctx);
346 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
347 if (ortn == errSSLClientHelloReceived) {
348 require_action(!client_hello_received, out, ortn = -1);
349 client_hello_received = true;
350 }
351 if (ortn == errSSLWouldBlock) {
352 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
353 }
354 } while (ortn == errSSLWouldBlock || ortn == errSSLClientHelloReceived);
355
356 require_noerr(ortn, out);
357 require_action(ssl_state==kSSLConnected, out, ortn = -1);
358 require_action(client_hello_received, out, ortn = -1);
359
360 unsigned char obuf[100];
361
362 size_t len = sizeof(obuf);
363 size_t olen;
364 unsigned char *p = obuf;
365
366 require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, len, p), out, ortn = -1);
367
368 while (len) {
369 require_noerr(ortn = SSLWrite(ctx, p, len, &olen), out);
370 len -= olen;
371 p += olen;
372 }
373 } else {
374 // just read
375 unsigned char ibuf[100];
376
377 client_hello_received = false;
378
379 size_t len = sizeof(ibuf);
380 size_t olen;
381 unsigned char *p = ibuf;
382 while (len) {
383 ortn = SSLRead(ctx, p, len, &olen);
384
385 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
386
387 if (ortn == errSSLClientHelloReceived) {
388 require_action(!client_hello_received, out, ortn = -1);
389 client_hello_received = true;
390 } else {
391 require_noerr(ortn, out);
392 }
393
394 /* If we get data, we should have renegotiated */
395 if(olen) {
396 require_noerr(ortn, out);
397 require_action(ssl_state==kSSLConnected, out, ortn = -1);
398 require_action(client_hello_received, out, ortn = -1);
399 }
400
401 len -= olen;
402 p += olen;
403 }
404 }
405
406 out:
407 SSLClose(ssl->st);
408 close(ssl->comm);
409 pthread_exit((void *)(intptr_t)ortn);
410 return NULL;
411 }
412
413
414 static void
415 test_renego(bool client_renego)
416 {
417 pthread_t client_thread, server_thread;
418 CFArrayRef server_certs = server_chain();
419
420 ok(server_certs, "renego: got server certs");
421
422
423 int sp[2];
424 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
425 fcntl(sp[0], F_SETNOSIGPIPE, 1);
426 fcntl(sp[1], F_SETNOSIGPIPE, 1);
427
428 ssl_client_handle *client;
429 client = ssl_client_handle_create(sp[0], client_renego);
430 ok(client!=NULL, "renego: could not create client handle");
431
432
433 ssl_server_handle *server;
434 server = ssl_server_handle_create(sp[1], server_certs, !client_renego);
435 ok(server!=NULL, "renego: could not create server handle");
436
437 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
438 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
439
440 intptr_t server_err, client_err;
441
442 pthread_join(client_thread, (void*)&client_err);
443 pthread_join(server_thread, (void*)&server_err);
444
445 ok(client_err==0, "renego: unexpected error %ld (client)", client_err);
446 ok(server_err==0, "renego: unexpected error %ld (server)", server_err);
447
448 ssl_server_handle_destroy(server);
449 ssl_client_handle_destroy(client);
450
451
452 CFReleaseSafe(server_certs);
453 }
454
455
456 int ssl_56_renegotiate(int argc, char *const *argv)
457 {
458 plan_tests(10);
459
460 test_renego(false); // server side trigger renego.
461 test_renego(true); // client side trigger renego.
462
463 return 0;
464 }