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_regressions.h"
35 #include "ssl-utils.h"
38 SSL Session Cache tests:
40 Test both the client and server side.
43 - Make sure that resumption fails after session cache TTL.
46 - handshake pass or fail
51 static OSStatus
SocketWrite(SSLConnectionRef conn
, const void *data
, size_t *length
)
54 uint8_t *ptr
= (uint8_t *)data
;
59 ret
= write((int)conn
, ptr
, len
);
60 } while ((ret
< 0) && (errno
== EAGAIN
|| errno
== EINTR
));
69 *length
= *length
- len
;
73 static OSStatus
SocketRead(SSLConnectionRef conn
, void *data
, size_t *length
)
76 uint8_t *ptr
= (uint8_t *)data
;
81 ret
= read((int)conn
, ptr
, len
);
82 } while ((ret
< 0) && (errno
== EINPROGRESS
|| errno
== EAGAIN
|| errno
== EINTR
));
87 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn
, ret
, errno
);
92 *length
= *length
- len
;
102 static ssl_client_handle
*
103 ssl_client_handle_create(int comm
, bool anyRoot
, CFArrayRef trustedCA
, bool trustedCAOnly
, CFArrayRef trustedLeafs
, uint32_t cache_ttl
, uintptr_t peerID
)
105 ssl_client_handle
*handle
= calloc(1, sizeof(ssl_client_handle
));
106 SSLContextRef ctx
= SSLCreateContext(kCFAllocatorDefault
, kSSLClientSide
, kSSLStreamType
);
108 require(handle
, out
);
111 require_noerr(SSLSetIOFuncs(ctx
,
112 (SSLReadFunc
)SocketRead
, (SSLWriteFunc
)SocketWrite
), out
);
113 require_noerr(SSLSetConnection(ctx
, (SSLConnectionRef
)(intptr_t)comm
), out
);
114 static const char *peer_domain_name
= "localhost";
115 require_noerr(SSLSetPeerDomainName(ctx
, peer_domain_name
,
116 strlen(peer_domain_name
)), out
);
118 require_noerr(SSLSetAllowsAnyRoot(ctx
, anyRoot
), out
);
119 require_noerr(SSLSetTrustedRoots(ctx
, trustedCA
, trustedCAOnly
), out
);
120 #if !TARGET_OS_IPHONE
121 require_noerr(SSLSetTrustedLeafCertificates(ctx
, trustedLeafs
), out
);
124 require_noerr(SSLSetSessionCacheTimeout(ctx
, cache_ttl
), out
);
126 require_noerr(SSLSetPeerID(ctx
, &peerID
, sizeof(peerID
)), out
);
143 ssl_client_handle_destroy(ssl_client_handle
*handle
)
146 SSLClose(handle
->st
);
147 CFRelease(handle
->st
);
152 static void *securetransport_ssl_client_thread(void *arg
)
155 ssl_client_handle
* ssl
= (ssl_client_handle
*)arg
;
156 SSLContextRef ctx
= ssl
->st
;
157 SSLSessionState ssl_state
;
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
== errSSLWouldBlock
) {
169 require_string(ssl_state
==kSSLHandshake
, out
, "Wrong client handshake state after errSSLWouldBlock");
171 } while (ortn
== errSSLWouldBlock
);
176 pthread_exit((void *)(intptr_t)ortn
);
188 static ssl_server_handle
*
189 ssl_server_handle_create(int comm
, CFArrayRef certs
, uint32_t cache_ttl
)
191 ssl_server_handle
*handle
= calloc(1, sizeof(ssl_server_handle
));
192 SSLContextRef ctx
= SSLCreateContext(kCFAllocatorDefault
, kSSLServerSide
, kSSLStreamType
);
193 SSLCipherSuite cipher
= TLS_RSA_WITH_AES_256_CBC_SHA256
;
194 uintptr_t peerID
= 0xdeadbeef;
196 require(handle
, out
);
199 require_noerr(SSLSetIOFuncs(ctx
,
200 (SSLReadFunc
)SocketRead
, (SSLWriteFunc
)SocketWrite
), out
);
201 require_noerr(SSLSetConnection(ctx
, (SSLConnectionRef
)(intptr_t)comm
), out
);
203 require_noerr(SSLSetCertificate(ctx
, certs
), out
);
205 require_noerr(SSLSetEnabledCiphers(ctx
, &cipher
, 1), out
);
207 require_noerr(SSLSetSessionCacheTimeout(ctx
, cache_ttl
), out
);
209 require_noerr(SSLSetPeerID(ctx
, &peerID
, sizeof(peerID
)), out
);
212 handle
->certs
= certs
;
227 ssl_server_handle_destroy(ssl_server_handle
*handle
)
230 SSLClose(handle
->st
);
231 CFRelease(handle
->st
);
236 static void *securetransport_ssl_server_thread(void *arg
)
239 ssl_server_handle
* ssl
= (ssl_server_handle
*)arg
;
240 SSLContextRef ctx
= ssl
->st
;
241 SSLSessionState ssl_state
;
243 pthread_setname_np("server thread");
245 require_noerr(ortn
=SSLGetSessionState(ctx
,&ssl_state
), out
);
246 require_action(ssl_state
==kSSLIdle
, out
, ortn
= -1);
249 ortn
= SSLHandshake(ctx
);
250 require_noerr(SSLGetSessionState(ctx
,&ssl_state
), out
);
252 if (ortn
== errSSLWouldBlock
) {
253 require_action(ssl_state
==kSSLHandshake
, out
, ortn
= -1);
255 } while (ortn
== errSSLWouldBlock
);
257 require_noerr_quiet(ortn
, out
);
259 require_action(ssl_state
==kSSLConnected
, out
, ortn
= -1);
264 pthread_exit((void *)(intptr_t)ortn
);
270 tests_cache_ttl(void)
272 pthread_t client_thread
, server_thread
;
273 CFArrayRef server_certs
= server_chain();
274 CFArrayRef trusted_ca
= trusted_roots();
276 ok(server_certs
, "ttl: got server certs");
277 ok(trusted_ca
, "ttl: got trusted roots");
281 for (i
=0; i
<2; i
++) { // client cache TTL
282 for (j
=0; j
<2; j
++) { // Server cache TTL
283 for (k
=0; k
<2; k
++) {
284 ssl_client_handle
*client
= NULL
;
285 ssl_server_handle
*server
= NULL
;
288 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, sp
)) exit(errno
);
289 fcntl(sp
[0], F_SETNOSIGPIPE
, 1);
290 fcntl(sp
[1], F_SETNOSIGPIPE
, 1);
292 client
= ssl_client_handle_create(sp
[0], false, trusted_ca
, true, NULL
, i
, (i
<<8)|(j
+1));
293 ok(client
!=NULL
, "ttl: could not create client handle (%d:%d:%d)", i
, j
, k
);
294 require(client
, errOut
);
296 server
= ssl_server_handle_create(sp
[1], server_certs
, j
);
297 ok(server
!=NULL
, "ttl: could not create server handle (%d:%d:%d)", i
, j
, k
);
298 require(server
, errOut
);
299 pthread_create(&client_thread
, NULL
, securetransport_ssl_client_thread
, client
);
300 pthread_create(&server_thread
, NULL
, securetransport_ssl_server_thread
, server
);
302 intptr_t server_err
, client_err
;
304 pthread_join(client_thread
, (void*)&client_err
);
305 pthread_join(server_thread
, (void*)&server_err
);
308 unsigned char sessionID
[32];
309 size_t sessionIDLength
= sizeof(sessionID
);
311 ok(client_err
==0, "ttl: unexpected error %ld (client %d:%d:%d)", client_err
, i
, j
, k
);
312 ok(server_err
==0, "ttl: unexpected error %ld (server %d:%d:%d)", server_err
, i
, j
, k
);
313 ok_status(SSLGetResumableSessionInfo(client
->st
, &resumed
, sessionID
, &sessionIDLength
), "SSLGetResumableSessionInfo");
315 ok((bool)resumed
== (bool)(k
&& (!i
) && (!j
)), "ttl: Unexpected resumption state=%d (%d:%d:%d)", resumed
, i
, j
, k
);
318 ssl_server_handle_destroy(server
);
319 ssl_client_handle_destroy(client
);
321 /* Sleep two seconds so that Session cache TTL can expire */
327 CFReleaseSafe(server_certs
);
328 CFReleaseSafe(trusted_ca
);
332 tests_cache_trust(void)
334 pthread_t client_thread
, server_thread
;
335 CFArrayRef server_certs
= server_chain();
336 CFArrayRef trusted_ca
= trusted_roots();
337 CFMutableArrayRef trusted_ca2
= CFArrayCreateMutableCopy(kCFAllocatorDefault
, 0, trusted_ca
);
338 CFArrayAppendArray(trusted_ca2
, trusted_ca
, CFRangeMake(0, CFArrayGetCount(trusted_ca
)));
340 ok(server_certs
, "trust: got server certs");
341 ok(trusted_ca
, "trust: got trusted roots");
342 ok(trusted_ca2
, "trust: got trusted roots extra");
344 int any
, ca
, caonly
, leaf
, k
;
346 // Test cache and trust options:
349 for (any
=0; any
<2; any
++) // any root ?
350 for (ca
=0; ca
<2; ca
++) // trustedCA ?
351 for (caonly
=0; caonly
<2; caonly
++) // leaf>
356 for (leaf
=0; leaf
<2; leaf
++)
359 // attempt initial connection, then resumed connection, but all with same peer id (0xdeadbeef)
360 for (k
=0; k
<2; k
++) {
361 ssl_client_handle
*client
= NULL
;
362 ssl_server_handle
*server
= NULL
;
365 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, sp
)) exit(errno
);
366 fcntl(sp
[0], F_SETNOSIGPIPE
, 1);
367 fcntl(sp
[1], F_SETNOSIGPIPE
, 1);
369 client
= ssl_client_handle_create(sp
[0], any
, ca
?trusted_ca
:trusted_ca2
, caonly
, leaf
?NULL
:trusted_ca
, 300, 0xdeadbeef);
370 ok(client
!=NULL
, "trust: could not create client handle (%d:%d:%d:%d:%d)", any
, ca
, caonly
, leaf
, k
);
371 require(client
, errOut
);
373 server
= ssl_server_handle_create(sp
[1], server_certs
, 300);
374 ok(server
!=NULL
, "trust: could not create server handle (%d:%d:%d:%d:%d)", any
, ca
, caonly
, leaf
, k
);
375 require(server
, errOut
);
377 pthread_create(&client_thread
, NULL
, securetransport_ssl_client_thread
, client
);
378 pthread_create(&server_thread
, NULL
, securetransport_ssl_server_thread
, server
);
380 intptr_t server_err
, client_err
;
382 pthread_join(client_thread
, (void*)&client_err
);
383 pthread_join(server_thread
, (void*)&server_err
);
386 unsigned char sessionID
[32];
387 size_t sessionIDLength
= sizeof(sessionID
);
389 ok(client_err
==0, "trust: unexpected error %ld (client %d:%d:%d:%d:%d)", client_err
, any
, ca
, caonly
, leaf
, k
);
390 ok(server_err
==0, "trust: unexpected error %ld (server %d:%d:%d:%d:%d)", server_err
, any
, ca
, caonly
, leaf
, k
);
391 ok_status(SSLGetResumableSessionInfo(client
->st
, &resumed
, sessionID
, &sessionIDLength
), "SSLGetResumableSessionInfo");
393 ok((bool)resumed
== (bool)(k
), "trust: Unexpected resumption state=%d (%d:%d:%d:%d:%d)", resumed
, any
, ca
, caonly
, leaf
, k
);
396 ssl_server_handle_destroy(server
);
397 ssl_client_handle_destroy(client
);
402 CFReleaseSafe(server_certs
);
403 CFReleaseSafe(trusted_ca
);
406 int ssl_55_sessioncache(int argc
, char *const *argv
)
410 #define N_TRUST_TESTS 8
412 #define N_TRUST_TESTS 16
415 plan_tests(/*ttl :*/ 6 * 8 + 2 + /* trust:*/ N_TRUST_TESTS
*6*2 + 3);