]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_ssl/regressions/ssl-45-tls12.c
Security-57031.30.12.tar.gz
[apple/security.git] / Security / libsecurity_ssl / regressions / ssl-45-tls12.c
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
49 #include <string.h>
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <mach/mach_time.h>
55
56 #include "ssl_regressions.h"
57
58 typedef struct {
59 uint32_t session_id;
60 bool is_session_resume;
61 SSLContextRef st;
62 bool is_server;
63 bool client_side_auth;
64 bool dh_anonymous;
65 int comm;
66 CFArrayRef certs;
67 } ssl_test_handle;
68
69
70
71 #if 0
72 static void hexdump(const uint8_t *bytes, size_t len) {
73 size_t ix;
74 printf("socket write(%p, %lu)\n", bytes, len);
75 for (ix = 0; ix < len; ++ix) {
76 if (!(ix % 16))
77 printf("\n");
78 printf("%02X ", bytes[ix]);
79 }
80 printf("\n");
81 }
82 #else
83 #define hexdump(bytes, len)
84 #endif
85
86 static int SocketConnect(const char *hostName, int port)
87 {
88 struct sockaddr_in addr;
89 struct in_addr host;
90 int sock;
91 int err;
92 struct hostent *ent;
93
94 if (hostName[0] >= '0' && hostName[0] <= '9')
95 {
96 host.s_addr = inet_addr(hostName);
97 }
98 else {
99 unsigned dex;
100 #define GETHOST_RETRIES 5
101 /* seeing a lot of soft failures here that I really don't want to track down */
102 for(dex=0; dex<GETHOST_RETRIES; dex++) {
103 if(dex != 0) {
104 printf("\n...retrying gethostbyname(%s)", hostName);
105 }
106 ent = gethostbyname(hostName);
107 if(ent != NULL) {
108 break;
109 }
110 }
111 if(ent == NULL) {
112 printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno));
113 return -1;
114 }
115 memcpy(&host, ent->h_addr, sizeof(struct in_addr));
116 }
117
118
119 sock = socket(AF_INET, SOCK_STREAM, 0);
120 addr.sin_addr = host;
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 {
128 perror("connect failed");
129 return err;
130 }
131
132 return sock;
133 }
134
135
136 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
137 {
138 size_t len = *length;
139 uint8_t *ptr = (uint8_t *)data;
140
141 do {
142 ssize_t ret;
143 do {
144 hexdump(ptr, len);
145 ret = write((int)conn, ptr, len);
146 if (ret < 0)
147 perror("send");
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 } while (len > 0);
156
157 *length = *length - len;
158 return errSecSuccess;
159 }
160
161 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
162 {
163 size_t len = *length;
164 uint8_t *ptr = (uint8_t *)data;
165
166 do {
167 ssize_t ret;
168 do {
169 ret = read((int)conn, ptr, len);
170 if (ret < 0)
171 perror("send");
172 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
173 if (ret > 0) {
174 len -= ret;
175 ptr += ret;
176 }
177 else
178 return -36;
179 } while (len > 0);
180
181 *length = *length - len;
182 return errSecSuccess;
183 }
184
185 static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot)
186 {
187 SSLContextRef ctx = NULL;
188
189 require_noerr(SSLNewContext(false, &ctx), out);
190 require_noerr(SSLSetIOFuncs(ctx,
191 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
192 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
193
194 require_noerr(SSLSetSessionOption(ctx,
195 kSSLSessionOptionBreakOnServerAuth, true), out);
196
197 require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out);
198 /* Tell SecureTransport to not check certs itself: it will break out of the
199 handshake to let us take care of it instead. */
200 require_noerr(SSLSetEnableCertVerify(ctx, false), out);
201
202 return ctx;
203 out:
204 if (ctx)
205 SSLDisposeContext(ctx);
206 return NULL;
207 }
208
209 static OSStatus securetransport(ssl_test_handle * ssl)
210 {
211 OSStatus ortn;
212 SSLContextRef ctx = ssl->st;
213 SecTrustRef trust = NULL;
214 bool got_server_auth = false, got_client_cert_req = false;
215
216 //uint64_t start = mach_absolute_time();
217 do {
218 ortn = SSLHandshake(ctx);
219
220 if (ortn == errSSLServerAuthCompleted)
221 {
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
232 } } while (ortn == errSSLWouldBlock
233 || ortn == errSSLServerAuthCompleted);
234 require_noerr_action_quiet(ortn, out,
235 fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn));
236
237 require_string(got_server_auth, out, "never got server auth");
238
239 //uint64_t elapsed = mach_absolute_time() - start;
240 //fprintf(stderr, "setr elapsed: %lld\n", elapsed);
241
242 /*
243 SSLProtocol proto = kSSLProtocolUnknown;
244 require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out); */
245
246 SSLCipherSuite cipherSuite;
247 require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out);
248 //fprintf(stderr, "st negotiated %02x\n", cipherSuite);
249
250
251 out:
252 SSLClose(ctx);
253 SSLDisposeContext(ctx);
254 if (trust) CFRelease(trust);
255
256 return ortn;
257 }
258
259
260
261 static ssl_test_handle *
262 ssl_test_handle_create(int comm, SSLProtocol maxprot)
263 {
264 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
265 if (handle) {
266 handle->comm = comm;
267 handle->st = make_ssl_ref(comm, maxprot);
268 }
269 return handle;
270 }
271
272 struct s_server {
273 char *host;
274 int port;
275 SSLProtocol maxprot;
276 } servers[] = {
277 /* Good tls 1.2 servers */
278 {"encrypted.google.com", 443, kTLSProtocol12 },
279 {"www.amazon.com",443, kTLSProtocol12 },
280 //{"www.mikestoolbox.org",443, kTLSProtocol12 },
281 /* servers with issues */
282 {"vpp.visa.co.uk", 443, kTLSProtocol12 }, // Doesnt like SSL 3.0 in initial record layer version
283 {"imap.softbank.jp",993, kTLSProtocol1 }, // 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).
284 {"mobile.charter.net",993, kTLSProtocol1 }, // Support 1.2 but fail to negotiate properly
285 {"mybill.vodafone.com.au", 443, kTLSProtocol1 }, /* 2056 bit server key */
286 };
287
288 #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0]))
289 #define NLOOPS 1
290
291 static void
292 tests(void)
293 {
294 int p;
295
296 for(p=0; p<NSERVERS;p++) {
297 for(int loops=0; loops<NLOOPS; loops++) {
298
299 ssl_test_handle *client;
300
301 int s;
302 OSStatus r;
303
304 s=SocketConnect(servers[p].host, servers[p].port);
305 if(s<0) {
306 fail("connect failed with err=%d - %s:%d (try %d)", s, servers[p].host, servers[p].port, loops);
307 break;
308 }
309
310 client = ssl_test_handle_create(s, servers[p].maxprot);
311
312 r=securetransport(client);
313 ok(!r, "handshake failed with err=%ld - %s:%d (try %d)", (long)r, servers[p].host, servers[p].port, loops);
314
315 free(client);
316 close(s);
317 } }
318 }
319
320 int ssl_45_tls12(int argc, char *const *argv)
321 {
322 plan_tests(NSERVERS*NLOOPS);
323
324 tests();
325
326 return 0;
327 }