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_regressions.h"
36 #include "ssl-utils.h"
39 SSL Session Cache tests:
41 Test both the client and server side.
44 - Make sure that resumption fails after session cache TTL.
47 - handshake pass or fail
52 static OSStatus
SocketWrite(SSLConnectionRef conn
, const void *data
, size_t *length
)
55 uint8_t *ptr
= (uint8_t *)data
;
60 ret
= write((int)conn
, ptr
, len
);
61 } while ((ret
< 0) && (errno
== EAGAIN
|| errno
== EINTR
));
70 *length
= *length
- len
;
74 static OSStatus
SocketRead(SSLConnectionRef conn
, void *data
, size_t *length
)
77 uint8_t *ptr
= (uint8_t *)data
;
82 ret
= read((int)conn
, ptr
, len
);
83 } while ((ret
< 0) && (errno
== EINPROGRESS
|| errno
== EAGAIN
|| errno
== EINTR
));
88 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn
, ret
, errno
);
93 *length
= *length
- len
;
103 static ssl_client_handle
*
104 ssl_client_handle_create(int comm
, bool anyRoot
, CFArrayRef trustedCA
, bool trustedCAOnly
, CFArrayRef trustedLeafs
, uint32_t cache_ttl
, uintptr_t peerID
)
106 ssl_client_handle
*handle
= calloc(1, sizeof(ssl_client_handle
));
107 SSLContextRef ctx
= SSLCreateContext(kCFAllocatorDefault
, kSSLClientSide
, kSSLStreamType
);
109 require(handle
, out
);
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
);
119 require_noerr(SSLSetAllowsAnyRoot(ctx
, anyRoot
), out
);
120 require_noerr(SSLSetTrustedRoots(ctx
, trustedCA
, trustedCAOnly
), out
);
121 #if !TARGET_OS_IPHONE
122 require_noerr(SSLSetTrustedLeafCertificates(ctx
, trustedLeafs
), out
);
125 require_noerr(SSLSetSessionCacheTimeout(ctx
, cache_ttl
), out
);
127 require_noerr(SSLSetPeerID(ctx
, &peerID
, sizeof(peerID
)), out
);
144 ssl_client_handle_destroy(ssl_client_handle
*handle
)
147 SSLClose(handle
->st
);
148 CFRelease(handle
->st
);
153 static void *securetransport_ssl_client_thread(void *arg
)
156 ssl_client_handle
* ssl
= (ssl_client_handle
*)arg
;
157 SSLContextRef ctx
= ssl
->st
;
158 SSLSessionState ssl_state
;
160 pthread_setname_np("client thread");
162 require_noerr(ortn
=SSLGetSessionState(ctx
,&ssl_state
), out
);
163 require_action(ssl_state
==kSSLIdle
, out
, ortn
= -1);
166 ortn
= SSLHandshake(ctx
);
167 require_noerr(SSLGetSessionState(ctx
,&ssl_state
), out
);
169 if (ortn
== errSSLWouldBlock
) {
170 require_string(ssl_state
==kSSLHandshake
, out
, "Wrong client handshake state after errSSLWouldBlock");
172 } while (ortn
== errSSLWouldBlock
);
177 pthread_exit((void *)(intptr_t)ortn
);
189 static ssl_server_handle
*
190 ssl_server_handle_create(int comm
, CFArrayRef certs
, uint32_t cache_ttl
)
192 ssl_server_handle
*handle
= calloc(1, sizeof(ssl_server_handle
));
193 SSLContextRef ctx
= SSLCreateContext(kCFAllocatorDefault
, kSSLServerSide
, kSSLStreamType
);
194 SSLCipherSuite cipher
= TLS_RSA_WITH_AES_256_CBC_SHA256
;
195 uintptr_t peerID
= 0xdeadbeef;
197 require(handle
, out
);
200 require_noerr(SSLSetIOFuncs(ctx
,
201 (SSLReadFunc
)SocketRead
, (SSLWriteFunc
)SocketWrite
), out
);
202 require_noerr(SSLSetConnection(ctx
, (SSLConnectionRef
)(intptr_t)comm
), out
);
204 require_noerr(SSLSetCertificate(ctx
, certs
), out
);
206 require_noerr(SSLSetEnabledCiphers(ctx
, &cipher
, 1), out
);
208 require_noerr(SSLSetSessionCacheTimeout(ctx
, cache_ttl
), out
);
210 require_noerr(SSLSetPeerID(ctx
, &peerID
, sizeof(peerID
)), out
);
213 handle
->certs
= certs
;
228 ssl_server_handle_destroy(ssl_server_handle
*handle
)
231 SSLClose(handle
->st
);
232 CFRelease(handle
->st
);
237 static void *securetransport_ssl_server_thread(void *arg
)
240 ssl_server_handle
* ssl
= (ssl_server_handle
*)arg
;
241 SSLContextRef ctx
= ssl
->st
;
242 SSLSessionState ssl_state
;
244 pthread_setname_np("server thread");
246 require_noerr(ortn
=SSLGetSessionState(ctx
,&ssl_state
), out
);
247 require_action(ssl_state
==kSSLIdle
, out
, ortn
= -1);
250 ortn
= SSLHandshake(ctx
);
251 require_noerr(SSLGetSessionState(ctx
,&ssl_state
), out
);
253 if (ortn
== errSSLWouldBlock
) {
254 require_action(ssl_state
==kSSLHandshake
, out
, ortn
= -1);
256 } while (ortn
== errSSLWouldBlock
);
258 require_noerr_quiet(ortn
, out
);
260 require_action(ssl_state
==kSSLConnected
, out
, ortn
= -1);
265 pthread_exit((void *)(intptr_t)ortn
);
271 tests_cache_ttl(void)
273 pthread_t client_thread
, server_thread
;
274 CFArrayRef server_certs
= server_chain();
275 CFArrayRef trusted_ca
= trusted_roots();
277 ok(server_certs
, "ttl: got server certs");
278 ok(trusted_ca
, "ttl: got trusted roots");
282 for (i
=0; i
<2; i
++) { // client cache TTL
283 for (j
=0; j
<2; j
++) { // Server cache TTL
284 for (k
=0; k
<2; k
++) {
285 ssl_client_handle
*client
= NULL
;
286 ssl_server_handle
*server
= NULL
;
289 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, sp
)) exit(errno
);
290 fcntl(sp
[0], F_SETNOSIGPIPE
, 1);
291 fcntl(sp
[1], F_SETNOSIGPIPE
, 1);
293 client
= ssl_client_handle_create(sp
[0], false, trusted_ca
, true, NULL
, i
, (i
<<8)|(j
+1));
294 ok(client
!=NULL
, "ttl: could not create client handle (%d:%d:%d)", i
, j
, k
);
295 require(client
, errOut
);
297 server
= ssl_server_handle_create(sp
[1], server_certs
, j
);
298 ok(server
!=NULL
, "ttl: could not create server handle (%d:%d:%d)", i
, j
, k
);
299 require(server
, errOut
);
300 pthread_create(&client_thread
, NULL
, securetransport_ssl_client_thread
, client
);
301 pthread_create(&server_thread
, NULL
, securetransport_ssl_server_thread
, server
);
303 intptr_t server_err
, client_err
;
305 pthread_join(client_thread
, (void*)&client_err
);
306 pthread_join(server_thread
, (void*)&server_err
);
309 unsigned char sessionID
[32];
310 size_t sessionIDLength
= sizeof(sessionID
);
312 ok(client_err
==0, "ttl: unexpected error %ld (client %d:%d:%d)", client_err
, i
, j
, k
);
313 ok(server_err
==0, "ttl: unexpected error %ld (server %d:%d:%d)", server_err
, i
, j
, k
);
314 ok_status(SSLGetResumableSessionInfo(client
->st
, &resumed
, sessionID
, &sessionIDLength
), "SSLGetResumableSessionInfo");
316 ok((bool)resumed
== (bool)(k
&& (!i
) && (!j
)), "ttl: Unexpected resumption state=%d (%d:%d:%d)", resumed
, i
, j
, k
);
319 ssl_server_handle_destroy(server
);
320 ssl_client_handle_destroy(client
);
322 /* Sleep two seconds so that Session cache TTL can expire */
328 CFReleaseSafe(server_certs
);
329 CFReleaseSafe(trusted_ca
);
333 tests_cache_trust(void)
335 pthread_t client_thread
, server_thread
;
336 CFArrayRef server_certs
= server_chain();
337 CFArrayRef trusted_ca
= trusted_roots();
338 CFMutableArrayRef trusted_ca2
= CFArrayCreateMutableCopy(kCFAllocatorDefault
, 0, trusted_ca
);
339 CFArrayAppendArray(trusted_ca2
, trusted_ca
, CFRangeMake(0, CFArrayGetCount(trusted_ca
)));
341 ok(server_certs
, "trust: got server certs");
342 ok(trusted_ca
, "trust: got trusted roots");
343 ok(trusted_ca2
, "trust: got trusted roots extra");
345 int any
, ca
, caonly
, leaf
, k
;
347 // Test cache and trust options:
350 for (any
=0; any
<2; any
++) // any root ?
351 for (ca
=0; ca
<2; ca
++) // trustedCA ?
352 for (caonly
=0; caonly
<2; caonly
++) // leaf>
357 for (leaf
=0; leaf
<2; leaf
++)
360 // attempt initial connection, then resumed connection, but all with same peer id (0xdeadbeef)
361 for (k
=0; k
<2; k
++) {
362 ssl_client_handle
*client
= NULL
;
363 ssl_server_handle
*server
= NULL
;
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);
370 client
= ssl_client_handle_create(sp
[0], any
, ca
?trusted_ca
:trusted_ca2
, caonly
, leaf
?NULL
:trusted_ca
, 300, 0xdeadbeef);
371 ok(client
!=NULL
, "trust: could not create client handle (%d:%d:%d:%d:%d)", any
, ca
, caonly
, leaf
, k
);
372 require(client
, errOut
);
374 server
= ssl_server_handle_create(sp
[1], server_certs
, 300);
375 ok(server
!=NULL
, "trust: could not create server handle (%d:%d:%d:%d:%d)", any
, ca
, caonly
, leaf
, k
);
376 require(server
, errOut
);
378 pthread_create(&client_thread
, NULL
, securetransport_ssl_client_thread
, client
);
379 pthread_create(&server_thread
, NULL
, securetransport_ssl_server_thread
, server
);
381 intptr_t server_err
, client_err
;
383 pthread_join(client_thread
, (void*)&client_err
);
384 pthread_join(server_thread
, (void*)&server_err
);
387 unsigned char sessionID
[32];
388 size_t sessionIDLength
= sizeof(sessionID
);
390 ok(client_err
==0, "trust: unexpected error %ld (client %d:%d:%d:%d:%d)", client_err
, any
, ca
, caonly
, leaf
, k
);
391 ok(server_err
==0, "trust: unexpected error %ld (server %d:%d:%d:%d:%d)", server_err
, any
, ca
, caonly
, leaf
, k
);
392 ok_status(SSLGetResumableSessionInfo(client
->st
, &resumed
, sessionID
, &sessionIDLength
), "SSLGetResumableSessionInfo");
394 ok((bool)resumed
== (bool)(k
), "trust: Unexpected resumption state=%d (%d:%d:%d:%d:%d)", resumed
, any
, ca
, caonly
, leaf
, k
);
397 ssl_server_handle_destroy(server
);
398 ssl_client_handle_destroy(client
);
403 CFReleaseSafe(server_certs
);
404 CFReleaseSafe(trusted_ca
);
407 int ssl_55_sessioncache(int argc
, char *const *argv
)
411 #define N_TRUST_TESTS 8
413 #define N_TRUST_TESTS 16
416 plan_tests(/*ttl :*/ 6 * 8 + 2 + /* trust:*/ N_TRUST_TESTS
*6*2 + 3);