]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / SecureTransportTests / STLegacyTests+tls12.m
1 /*
2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include <stdbool.h>
26 #include <pthread.h>
27 #include <fcntl.h>
28 #include <sys/mman.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <netinet/in.h>
32 #include <sys/socket.h>
33 #include <netdb.h>
34 #include <arpa/inet.h>
35 #include <CoreFoundation/CoreFoundation.h>
36
37 #include <AssertMacros.h>
38 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
39 #include <Security/SecureTransport.h>
40 #include <Security/SecPolicy.h>
41 #include <Security/SecTrust.h>
42 #include <Security/SecIdentity.h>
43 #include <Security/SecIdentityPriv.h>
44 #include <Security/SecCertificatePriv.h>
45 #include <Security/SecKeyPriv.h>
46 #include <Security/SecItem.h>
47 #include <Security/SecRandom.h>
48 #include <utilities/SecCFRelease.h>
49
50 #include <string.h>
51 #include <sys/types.h>
52 #include <sys/socket.h>
53 #include <errno.h>
54 #include <stdlib.h>
55 #include <mach/mach_time.h>
56
57 #include "STLegacyTests.h"
58
59 @implementation STLegacyTests (tls12)
60
61 struct s_server {
62 char *host;
63 int port;
64 SSLProtocol maxprot;
65 };
66
67 typedef struct {
68 struct s_server *server;
69 uint32_t session_id;
70 bool is_session_resume;
71 SSLContextRef st;
72 bool client_side_auth;
73 bool dh_anonymous;
74 int comm;
75 CFArrayRef certs;
76 } ssl_test_handle;
77
78 #pragma clang diagnostic push
79 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
80
81 #if SECTRANS_VERBOSE_DEBUG
82 static void hexdump(const uint8_t *bytes, size_t len) {
83 size_t ix;
84 printf("socket write(%p, %lu)\n", bytes, len);
85 for (ix = 0; ix < len; ++ix) {
86 if (!(ix % 16))
87 printf("\n");
88 printf("%02X ", bytes[ix]);
89 }
90 printf("\n");
91 }
92 #else
93 #define hexdump(bytes, len)
94 #endif
95
96 static int SocketConnect(const char *hostName, int port)
97 {
98 struct sockaddr_in addr;
99 struct in_addr host;
100 int sock;
101 int err;
102 struct hostent *ent;
103 char **h_addr_list = NULL;
104
105 if (hostName[0] >= '0' && hostName[0] <= '9') {
106 host.s_addr = inet_addr(hostName);
107 } else {
108 ent = gethostbyname(hostName);
109 if(ent == NULL) {
110 printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno));
111 return -2;
112 }
113 h_addr_list = malloc(sizeof(char *));
114 memcpy(h_addr_list, ent->h_addr_list, sizeof(char *));
115 memcpy(&host, h_addr_list[0], sizeof(struct in_addr));
116 }
117
118 sock = socket(AF_INET, SOCK_STREAM, 0);
119 addr.sin_addr.s_addr = host.s_addr;
120 free(h_addr_list);
121 addr.sin_port = htons((u_short)port);
122
123 addr.sin_family = AF_INET;
124 err = connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
125
126 if (err!=0) {
127 perror("connect failed");
128 return -1;
129 }
130
131 return sock;
132 }
133
134
135 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
136 {
137 size_t len = *length;
138 uint8_t *ptr = (uint8_t *)data;
139
140 do {
141 ssize_t ret;
142 do {
143 hexdump(ptr, len);
144 ret = write((int)conn, ptr, len);
145 if (ret < 0) {
146 perror("send");
147 }
148 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
149 if (ret > 0) {
150 len -= ret;
151 ptr += ret;
152 }
153 else {
154 return -36;
155 }
156 } while (len > 0);
157
158 *length = *length - len;
159 return errSecSuccess;
160 }
161
162 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
163 {
164 size_t len = *length;
165 uint8_t *ptr = (uint8_t *)data;
166
167 do {
168 ssize_t ret;
169 do {
170 ret = read((int)conn, ptr, len);
171 if (ret < 0)
172 perror("send");
173 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
174 if (ret > 0) {
175 len -= ret;
176 ptr += ret;
177 }
178 else {
179 return -36;
180 }
181 } while (len > 0);
182
183 *length = *length - len;
184 return errSecSuccess;
185 }
186
187 static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot, const char *peerName)
188 {
189 SSLContextRef ctx = NULL;
190 require((ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType)), out);
191 require_noerr(SSLSetIOFuncs(ctx,
192 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
193 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
194
195 require_noerr(SSLSetSessionOption(ctx,
196 kSSLSessionOptionBreakOnServerAuth, true), out);
197
198 require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out);
199
200 require_noerr(SSLSetPeerDomainName(ctx, peerName, strlen(peerName)), out);
201 /* Tell SecureTransport to not check certs itself: it will break out of the
202 handshake to let us take care of it instead. */
203 require_noerr(SSLSetEnableCertVerify(ctx, false), out);
204
205 return ctx;
206 out:
207 CFReleaseNull(ctx);
208 return NULL;
209 }
210
211 static OSStatus securetransport(ssl_test_handle * ssl)
212 {
213 OSStatus ortn;
214 SSLContextRef ctx = ssl->st;
215 SecTrustRef trust = NULL;
216 bool got_server_auth = false, got_client_cert_req = false;
217
218 do {
219 ortn = SSLHandshake(ctx);
220
221 if (ortn == errSSLServerAuthCompleted) {
222 require_string(!got_server_auth, out, "second server auth");
223 require_string(!got_client_cert_req, out, "got client cert req before server auth");
224 got_server_auth = true;
225 require_string(!trust, out, "Got errSSLServerAuthCompleted twice?");
226 /* verify peer cert chain */
227 require_noerr(SSLCopyPeerTrust(ctx, &trust), out);
228 SecTrustResultType trust_result = 0;
229 /* this won't verify without setting up a trusted anchor */
230 require_noerr(SecTrustEvaluate(trust, &trust_result), out);
231 require((trust_result == kSecTrustResultUnspecified || trust_result == kSecTrustResultProceed), out);
232
233 }
234 } while (ortn == errSSLWouldBlock
235 || ortn == errSSLServerAuthCompleted);
236 require_noerr_action_quiet(ortn, out,
237 fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn));
238
239 require_string(got_server_auth, out, "never got server auth");
240
241 SSLProtocol proto = kSSLProtocolUnknown;
242 require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out);
243
244 SSLCipherSuite cipherSuite;
245 require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out);
246
247
248 out:
249 SSLClose(ctx);
250 CFReleaseNull(ctx);
251 CFReleaseNull(trust);
252
253 return ortn;
254 }
255
256
257
258 #define CONNECT_TRIES 3
259
260 -(ssl_test_handle *)ssl_test_handle_create:(struct s_server *)server
261 {
262 int comm = -1;
263
264 for (int try = 0; comm < 0 && try < CONNECT_TRIES; try++) {
265 comm = SocketConnect(server->host, server->port);
266 }
267
268 if (comm < 0) {
269 return NULL;
270 }
271
272 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
273 if (handle) {
274 handle->comm = comm;
275 handle->st = make_ssl_ref(comm, server->maxprot, server->host);
276 handle->server = server;
277 }
278 return handle;
279 }
280
281 static void
282 ssl_test_handle_destroy(ssl_test_handle *handle)
283 {
284 close(handle->comm);
285 free(handle);
286 }
287
288
289 struct s_server servers[] = {
290 #if !TARGET_OS_IPHONE //This test run on AppleWifi on iPhone, so we can't connect to internal servers.
291 {"nod.apple.com", 636, kTLSProtocol12 }, // This one has only the server eku, not the client one.
292 #endif
293 {"gsa.apple.com", 443, kTLSProtocol12 }, // This one has only the server eku, not the client one.
294 /* Good tls 1.2 servers */
295 {"sslanalyzer.comodoca.com", 443, kTLSProtocol12 }, // This one has a stapled OCSP response with SCTs.
296 {"encrypted.google.com", 443, kTLSProtocol12 },
297 {"www.amazon.com",443, kTLSProtocol12 },
298 //{"www.mikestoolbox.org",443, kTLSProtocol12 },
299 /* servers with issues */
300 // This server went offline as of May 2016 -- {"vpp.visa.co.uk", 443, kTLSProtocol12 }, // Doesnt like SSL 3.0 in initial record layer version
301 {"imap.softbank.jp",993, kTLSProtocol12 }, // softbank imap server, there are multiple servers behind this, one of them is not able to handle downgrading to TLS 1.2 properly (126.240.66.17).
302 {"mobile.charter.net",993, kTLSProtocol12 }, // Support 1.2 but fail to negotiate properly
303 {"mybill.vodafone.com.au", 443, kTLSProtocol1 }, /* 2056 bit server key */
304 };
305
306 #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0]))
307 #define NLOOPS 1
308
309 -(void)testTls12
310 {
311 int p;
312 OSStatus r;
313
314 for (p = 0; p < NSERVERS; p++) {
315 for (int loops = 0; loops < NLOOPS; loops++) {
316 ssl_test_handle *client;
317
318 SKIP: {
319 if (!(client = [self ssl_test_handle_create:&servers[p]]))
320 continue;
321 r = securetransport(client);
322 XCTAssert(r == errSecSuccess, "handshake failed with err=%ld - %s:%d (try %d)", (long)r, servers[p].host, servers[p].port, loops);
323
324 ssl_test_handle_destroy(client);
325 }
326 }
327 }
328 }
329
330 @end
331
332 #pragma clang diagnostic pop