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