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>
23 #include <utilities/SecCFRelease.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
29 #include <mach/mach_time.h>
32 #include <Security/SecRSAKey.h>
35 #include "ssl-utils.h"
36 #import "STLegacyTests.h"
38 #pragma clang diagnostic push
39 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
41 @implementation STLegacyTests (renegotiation)
44 SSL Renegotiation tests:
46 Test both the client and server side.
49 - Make sure that renegotiation works on both client and server.
52 - handshake pass or fail
57 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
60 uint8_t *ptr = (uint8_t *)data;
65 ret = write((int)conn, ptr, len);
66 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
75 *length = *length - len;
79 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
82 uint8_t *ptr = (uint8_t *)data;
87 ret = read((int)conn, ptr, len);
88 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
93 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
98 *length = *length - len;
109 static ssl_client_handle *
110 ssl_client_handle_create(int comm, bool renegotiate)
112 ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle));
113 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
115 require(handle, out);
118 require_noerr(SSLSetIOFuncs(ctx,
119 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
120 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
121 static const char *peer_domain_name = "localhost";
122 require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name,
123 strlen(peer_domain_name)), out);
125 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, TRUE), out);
127 require_noerr(SSLSetAllowsAnyRoot(ctx, TRUE), out);
132 handle->renegotiate = renegotiate;
146 ssl_client_handle_destroy(ssl_client_handle *handle)
149 SSLClose(handle->st);
150 CFRelease(handle->st);
155 static void *securetransport_ssl_client_thread(void *arg)
158 ssl_client_handle * ssl = (ssl_client_handle *)arg;
159 SSLContextRef ctx = ssl->st;
160 SSLSessionState ssl_state;
161 bool peer_auth_received = false;
163 pthread_setname_np("client thread");
165 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
166 require_action(ssl_state==kSSLIdle, out, ortn = -1);
169 ortn = SSLHandshake(ctx);
170 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
172 if (ortn == errSSLPeerAuthCompleted) {
173 require_action(!peer_auth_received, out, ortn = -1);
174 peer_auth_received = true;
176 if (ortn == errSSLWouldBlock) {
177 require_string(ssl_state==kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
179 } while (ortn == errSSLWouldBlock || ortn == errSSLPeerAuthCompleted);
181 require_noerr(ortn, out);
182 require_action(ssl_state==kSSLConnected, out, ortn = -1);
183 require_action(peer_auth_received, out, ortn = -1);
185 if(ssl->renegotiate) {
186 // Renegotiate then write
187 require_noerr(SSLReHandshake(ctx), out);
189 peer_auth_received = false;
192 ortn = SSLHandshake(ctx);
193 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
194 if (ortn == errSSLPeerAuthCompleted) {
195 require_action(!peer_auth_received, out, ortn = -1);
196 peer_auth_received = true;
198 if (ortn == errSSLWouldBlock) {
199 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
201 } while (ortn == errSSLWouldBlock || ortn == errSSLPeerAuthCompleted);
203 require_noerr(ortn, out);
204 require_action(ssl_state==kSSLConnected, out, ortn = -1);
205 require_action(peer_auth_received, out, ortn = -1);
207 unsigned char obuf[100];
209 size_t len = sizeof(obuf);
211 unsigned char *p = obuf;
213 require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, len, p), out, ortn = -1);
216 require_noerr(ortn = SSLWrite(ctx, p, len, &olen), out);
222 unsigned char ibuf[100];
224 peer_auth_received = false;
226 size_t len = sizeof(ibuf);
228 unsigned char *p = ibuf;
230 ortn = SSLRead(ctx, p, len, &olen);
232 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
234 if (ortn == errSSLPeerAuthCompleted) {
235 require_action(!peer_auth_received, out, ortn = -1);
236 peer_auth_received = true;
238 require_noerr(ortn, out);
241 /* If we get data, we should have renegotiated */
243 require_noerr(ortn, out);
244 require_action(ssl_state==kSSLConnected, out, ortn = -1);
245 require_action(peer_auth_received, out, ortn = -1);
256 pthread_exit((void *)(intptr_t)ortn);
268 static ssl_server_handle *
269 ssl_server_handle_create(int comm, CFArrayRef certs, bool renegotiate)
271 ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle));
272 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
273 SSLCipherSuite cipher = TLS_RSA_WITH_AES_256_CBC_SHA256;
275 require(handle, out);
278 require_noerr(SSLSetIOFuncs(ctx,
279 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
280 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
282 require_noerr(SSLSetCertificate(ctx, certs), out);
284 require_noerr(SSLSetEnabledCiphers(ctx, &cipher, 1), out);
286 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnClientHello, TRUE), out);
287 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionAllowRenegotiation, TRUE), out);
290 handle->certs = certs;
292 handle->renegotiate = renegotiate;
306 ssl_server_handle_destroy(ssl_server_handle *handle)
309 SSLClose(handle->st);
310 CFRelease(handle->st);
315 static void *securetransport_ssl_server_thread(void *arg)
318 ssl_server_handle * ssl = (ssl_server_handle *)arg;
319 SSLContextRef ctx = ssl->st;
320 SSLSessionState ssl_state;
321 bool client_hello_received = false;
323 pthread_setname_np("server thread");
325 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
326 require_action(ssl_state==kSSLIdle, out, ortn = -1);
329 ortn = SSLHandshake(ctx);
330 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
331 if (ortn == errSSLClientHelloReceived) {
332 require_action(!client_hello_received, out, ortn = -1);
333 client_hello_received = true;
335 if (ortn == errSSLWouldBlock) {
336 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
338 } while (ortn == errSSLWouldBlock || ortn == errSSLClientHelloReceived);
340 require_noerr(ortn, out);
341 require_action(ssl_state==kSSLConnected, out, ortn = -1);
342 require_action(client_hello_received, out, ortn = -1);
344 if(ssl->renegotiate) {
345 // Renegotiate then write
346 require_noerr(SSLReHandshake(ctx), out);
348 client_hello_received = false;
351 ortn = SSLHandshake(ctx);
352 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
353 if (ortn == errSSLClientHelloReceived) {
354 require_action(!client_hello_received, out, ortn = -1);
355 client_hello_received = true;
357 if (ortn == errSSLWouldBlock) {
358 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
360 } while (ortn == errSSLWouldBlock || ortn == errSSLClientHelloReceived);
362 require_noerr(ortn, out);
363 require_action(ssl_state==kSSLConnected, out, ortn = -1);
364 require_action(client_hello_received, out, ortn = -1);
366 unsigned char obuf[100];
368 size_t len = sizeof(obuf);
370 unsigned char *p = obuf;
372 require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, len, p), out, ortn = -1);
375 require_noerr(ortn = SSLWrite(ctx, p, len, &olen), out);
381 unsigned char ibuf[100];
383 client_hello_received = false;
385 size_t len = sizeof(ibuf);
387 unsigned char *p = ibuf;
389 ortn = SSLRead(ctx, p, len, &olen);
391 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
393 if (ortn == errSSLClientHelloReceived) {
394 require_action(!client_hello_received, out, ortn = -1);
395 client_hello_received = true;
397 require_noerr(ortn, out);
400 /* If we get data, we should have renegotiated */
402 require_noerr(ortn, out);
403 require_action(ssl_state==kSSLConnected, out, ortn = -1);
404 require_action(client_hello_received, out, ortn = -1);
415 pthread_exit((void *)(intptr_t)ortn);
420 -(void) test_renego: (bool) client_renego
422 pthread_t client_thread, server_thread;
423 CFArrayRef server_certs = server_chain();
425 XCTAssert(server_certs, "renego: got server certs");
429 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
430 fcntl(sp[0], F_SETNOSIGPIPE, 1);
431 fcntl(sp[1], F_SETNOSIGPIPE, 1);
433 ssl_client_handle *client;
434 client = ssl_client_handle_create(sp[0], client_renego);
435 XCTAssert(client!=NULL, "renego: could not create client handle");
438 ssl_server_handle *server;
439 server = ssl_server_handle_create(sp[1], server_certs, !client_renego);
440 XCTAssert(server!=NULL, "renego: could not create server handle");
442 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
443 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
445 intptr_t server_err, client_err;
447 pthread_join(client_thread, (void*)&client_err);
448 pthread_join(server_thread, (void*)&server_err);
450 XCTAssert(client_err==0, "renego: unexpected error %ld (client)", client_err);
451 XCTAssert(server_err==0, "renego: unexpected error %ld (server)", server_err);
453 ssl_server_handle_destroy(server);
454 ssl_client_handle_destroy(client);
457 CFReleaseSafe(server_certs);
461 -(void) testRenegotiation
464 [self test_renego:false]; // server side trigger renego.
465 [self test_renego:true]; // client side trigger renego.
470 #pragma clang diagnostic pop