8 #include <CoreFoundation/CoreFoundation.h>
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>
22 #include <utilities/array_size.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
28 #include <mach/mach_time.h>
31 #include <Security/SecRSAKey.h>
34 #include "ssl-utils.h"
35 #import "STLegacyTests.h"
37 @implementation STLegacyTests (renegotiation)
40 SSL Renegotiation tests:
42 Test both the client and server side.
45 - Make sure that renegotiation works on both client and server.
48 - handshake pass or fail
53 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
56 uint8_t *ptr = (uint8_t *)data;
61 ret = write((int)conn, ptr, len);
62 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
71 *length = *length - len;
75 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
78 uint8_t *ptr = (uint8_t *)data;
83 ret = read((int)conn, ptr, len);
84 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
89 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
94 *length = *length - len;
105 static ssl_client_handle *
106 ssl_client_handle_create(int comm, bool renegotiate)
108 ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle));
109 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
111 require(handle, out);
114 require_noerr(SSLSetIOFuncs(ctx,
115 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
116 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
117 static const char *peer_domain_name = "localhost";
118 require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name,
119 strlen(peer_domain_name)), out);
121 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, TRUE), out);
123 require_noerr(SSLSetAllowsAnyRoot(ctx, TRUE), out);
128 handle->renegotiate = renegotiate;
142 ssl_client_handle_destroy(ssl_client_handle *handle)
145 SSLClose(handle->st);
146 CFRelease(handle->st);
151 static void *securetransport_ssl_client_thread(void *arg)
154 ssl_client_handle * ssl = (ssl_client_handle *)arg;
155 SSLContextRef ctx = ssl->st;
156 SSLSessionState ssl_state;
157 bool peer_auth_received = false;
159 pthread_setname_np("client thread");
161 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
162 require_action(ssl_state==kSSLIdle, out, ortn = -1);
165 ortn = SSLHandshake(ctx);
166 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
168 if (ortn == errSSLPeerAuthCompleted) {
169 require_action(!peer_auth_received, out, ortn = -1);
170 peer_auth_received = true;
172 if (ortn == errSSLWouldBlock) {
173 require_string(ssl_state==kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
175 } while (ortn == errSSLWouldBlock || ortn == errSSLPeerAuthCompleted);
177 require_noerr(ortn, out);
178 require_action(ssl_state==kSSLConnected, out, ortn = -1);
179 require_action(peer_auth_received, out, ortn = -1);
181 if(ssl->renegotiate) {
182 // Renegotiate then write
183 require_noerr(SSLReHandshake(ctx), out);
185 peer_auth_received = false;
188 ortn = SSLHandshake(ctx);
189 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
190 if (ortn == errSSLPeerAuthCompleted) {
191 require_action(!peer_auth_received, out, ortn = -1);
192 peer_auth_received = true;
194 if (ortn == errSSLWouldBlock) {
195 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
197 } while (ortn == errSSLWouldBlock || ortn == errSSLPeerAuthCompleted);
199 require_noerr(ortn, out);
200 require_action(ssl_state==kSSLConnected, out, ortn = -1);
201 require_action(peer_auth_received, out, ortn = -1);
203 unsigned char obuf[100];
205 size_t len = sizeof(obuf);
207 unsigned char *p = obuf;
209 require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, len, p), out, ortn = -1);
212 require_noerr(ortn = SSLWrite(ctx, p, len, &olen), out);
218 unsigned char ibuf[100];
220 peer_auth_received = false;
222 size_t len = sizeof(ibuf);
224 unsigned char *p = ibuf;
226 ortn = SSLRead(ctx, p, len, &olen);
228 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
230 if (ortn == errSSLPeerAuthCompleted) {
231 require_action(!peer_auth_received, out, ortn = -1);
232 peer_auth_received = true;
234 require_noerr(ortn, out);
237 /* If we get data, we should have renegotiated */
239 require_noerr(ortn, out);
240 require_action(ssl_state==kSSLConnected, out, ortn = -1);
241 require_action(peer_auth_received, out, ortn = -1);
252 pthread_exit((void *)(intptr_t)ortn);
264 static ssl_server_handle *
265 ssl_server_handle_create(int comm, CFArrayRef certs, bool renegotiate)
267 ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle));
268 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
269 SSLCipherSuite cipher = TLS_RSA_WITH_AES_256_CBC_SHA256;
271 require(handle, out);
274 require_noerr(SSLSetIOFuncs(ctx,
275 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
276 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
278 require_noerr(SSLSetCertificate(ctx, certs), out);
280 require_noerr(SSLSetEnabledCiphers(ctx, &cipher, 1), out);
282 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnClientHello, TRUE), out);
283 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionAllowRenegotiation, TRUE), out);
286 handle->certs = certs;
288 handle->renegotiate = renegotiate;
302 ssl_server_handle_destroy(ssl_server_handle *handle)
305 SSLClose(handle->st);
306 CFRelease(handle->st);
311 static void *securetransport_ssl_server_thread(void *arg)
314 ssl_server_handle * ssl = (ssl_server_handle *)arg;
315 SSLContextRef ctx = ssl->st;
316 SSLSessionState ssl_state;
317 bool client_hello_received = false;
319 pthread_setname_np("server thread");
321 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
322 require_action(ssl_state==kSSLIdle, out, ortn = -1);
325 ortn = SSLHandshake(ctx);
326 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
327 if (ortn == errSSLClientHelloReceived) {
328 require_action(!client_hello_received, out, ortn = -1);
329 client_hello_received = true;
331 if (ortn == errSSLWouldBlock) {
332 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
334 } while (ortn == errSSLWouldBlock || ortn == errSSLClientHelloReceived);
336 require_noerr(ortn, out);
337 require_action(ssl_state==kSSLConnected, out, ortn = -1);
338 require_action(client_hello_received, out, ortn = -1);
340 if(ssl->renegotiate) {
341 // Renegotiate then write
342 require_noerr(SSLReHandshake(ctx), out);
344 client_hello_received = false;
347 ortn = SSLHandshake(ctx);
348 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
349 if (ortn == errSSLClientHelloReceived) {
350 require_action(!client_hello_received, out, ortn = -1);
351 client_hello_received = true;
353 if (ortn == errSSLWouldBlock) {
354 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
356 } while (ortn == errSSLWouldBlock || ortn == errSSLClientHelloReceived);
358 require_noerr(ortn, out);
359 require_action(ssl_state==kSSLConnected, out, ortn = -1);
360 require_action(client_hello_received, out, ortn = -1);
362 unsigned char obuf[100];
364 size_t len = sizeof(obuf);
366 unsigned char *p = obuf;
368 require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, len, p), out, ortn = -1);
371 require_noerr(ortn = SSLWrite(ctx, p, len, &olen), out);
377 unsigned char ibuf[100];
379 client_hello_received = false;
381 size_t len = sizeof(ibuf);
383 unsigned char *p = ibuf;
385 ortn = SSLRead(ctx, p, len, &olen);
387 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
389 if (ortn == errSSLClientHelloReceived) {
390 require_action(!client_hello_received, out, ortn = -1);
391 client_hello_received = true;
393 require_noerr(ortn, out);
396 /* If we get data, we should have renegotiated */
398 require_noerr(ortn, out);
399 require_action(ssl_state==kSSLConnected, out, ortn = -1);
400 require_action(client_hello_received, out, ortn = -1);
411 pthread_exit((void *)(intptr_t)ortn);
416 -(void) test_renego: (bool) client_renego
418 pthread_t client_thread, server_thread;
419 CFArrayRef server_certs = server_chain();
421 XCTAssert(server_certs, "renego: got server certs");
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);
429 ssl_client_handle *client;
430 client = ssl_client_handle_create(sp[0], client_renego);
431 XCTAssert(client!=NULL, "renego: could not create client handle");
434 ssl_server_handle *server;
435 server = ssl_server_handle_create(sp[1], server_certs, !client_renego);
436 XCTAssert(server!=NULL, "renego: could not create server handle");
438 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
439 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
441 intptr_t server_err, client_err;
443 pthread_join(client_thread, (void*)&client_err);
444 pthread_join(server_thread, (void*)&server_err);
446 XCTAssert(client_err==0, "renego: unexpected error %ld (client)", client_err);
447 XCTAssert(server_err==0, "renego: unexpected error %ld (server)", server_err);
449 ssl_server_handle_destroy(server);
450 ssl_client_handle_destroy(client);
453 CFReleaseSafe(server_certs);
457 -(void) testRenegotiation
460 [self test_renego:false]; // server side trigger renego.
461 [self test_renego:true]; // client side trigger renego.