]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sni.m
Security-59306.41.2.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / SecureTransportTests / STLegacyTests+sni.m
1 #include <stdbool.h>
2 #include <pthread.h>
3 #include <fcntl.h>
4 #include <sys/mman.h>
5 #include <unistd.h>
6
7 #include <CoreFoundation/CoreFoundation.h>
8
9 #include <AssertMacros.h>
10 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
11 #include <Security/SecureTransport.h>
12 #include <Security/SecPolicy.h>
13 #include <Security/SecTrust.h>
14 #include <Security/SecIdentity.h>
15 #include <Security/SecIdentityPriv.h>
16 #include <Security/SecCertificatePriv.h>
17 #include <Security/SecKeyPriv.h>
18 #include <Security/SecItem.h>
19 #include <Security/SecRandom.h>
20
21 #include <utilities/SecCFRelease.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <mach/mach_time.h>
28
29 #if TARGET_OS_IPHONE
30 #include <Security/SecRSAKey.h>
31 #endif
32
33 #include "ssl-utils.h"
34 #import "STLegacyTests.h"
35
36 #define serverSelectedProtocol "baz"
37 #define serverAdvertisedProtocols "\x03""baz"
38
39 #pragma clang diagnostic push
40 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
41
42 @implementation STLegacyTests (sni)
43
44 typedef struct {
45 SSLContextRef handle;
46 uint32_t session_id;
47 bool is_server;
48 int comm;
49 } ssl_test_handle;
50
51
52 #pragma mark -
53 #pragma mark SecureTransport support
54
55 #if SECTRANS_VERBOSE_DEBUG
56 static void hexdump(const uint8_t *bytes, size_t len) {
57 size_t ix;
58 printf("socket write(%p, %lu)\n", bytes, len);
59 for (ix = 0; ix < len; ++ix) {
60 if (!(ix % 16))
61 printf("\n");
62 printf("%02X ", bytes[ix]);
63 }
64 printf("\n");
65 }
66 #else
67 #define hexdump(bytes, len)
68 #endif
69
70
71 static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length)
72 {
73 size_t len = *length;
74 uint8_t *ptr = (uint8_t *)data;
75
76 do {
77 ssize_t ret;
78 do {
79 hexdump(ptr, len);
80 ret = write((int)h, ptr, len);
81 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
82 if (ret > 0) {
83 len -= ret;
84 ptr += ret;
85 }
86 else
87 return -36;
88 } while (len > 0);
89
90 *length = *length - len;
91 return errSecSuccess;
92 }
93
94 static OSStatus SocketRead(SSLConnectionRef h, void *data, size_t *length)
95 {
96 size_t len = *length;
97 uint8_t *ptr = (uint8_t *)data;
98
99 do {
100 ssize_t ret;
101 do {
102 ret = read((int)h, ptr, len);
103 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
104 if (ret > 0) {
105 len -= ret;
106 ptr += ret;
107 } else {
108 printf("read error(%d): ret=%zd, errno=%d\n", (int)h, ret, errno);
109 return -errno;
110 }
111 } while (len > 0);
112
113 *length = *length - len;
114 return errSecSuccess;
115 }
116
117 static char peername[] = "localhost";
118
119 static void *securetransport_server_thread(void *arg)
120 {
121 OSStatus ortn;
122 ssl_test_handle * ssl = (ssl_test_handle *)arg;
123 SSLContextRef ctx = ssl->handle;
124 CFArrayRef server_certs = server_chain();
125
126 do {
127 ortn = SSLHandshake(ctx);
128 } while (ortn == errSSLWouldBlock);
129
130 if (ortn == errSSLClientHelloReceived) {
131 char *sni = NULL;
132 size_t length = 0;
133 SSLCopyRequestedPeerNameLength(ctx, &length);
134 if (length > 0) {
135 sni = malloc(length);
136 SSLCopyRequestedPeerName(ctx, sni, &length);
137 }
138
139 SSLProtocol version = 0;
140 require_noerr(SSLGetProtocolVersionMax(ctx, &version), out);
141 if (version == kSSLProtocol3) {
142 require_string(sni == NULL, out, "Unexpected SNI");
143 } else {
144 require_string(sni != NULL &&
145 length == sizeof(peername) &&
146 (memcmp(sni, peername, sizeof(peername))==0), out,
147 "SNI does not match");
148 }
149 require_noerr(SSLSetCertificate(ctx, server_certs), out);
150 free(sni);
151
152 tls_buffer alpnData;
153 alpnData.length = strlen(serverSelectedProtocol);
154 alpnData.data = malloc(alpnData.length);
155 memcpy(alpnData.data, serverSelectedProtocol, alpnData.length);
156 require_noerr_string(SSLSetALPNData(ctx, alpnData.data, alpnData.length), out, "Error setting alpn data");
157 free(alpnData.data);
158
159 tls_buffer npnData;
160 npnData.length = strlen(serverAdvertisedProtocols);
161 npnData.data = malloc(npnData.length);
162 memcpy(npnData.data, serverAdvertisedProtocols, npnData.length);
163 require_noerr_string(SSLSetNPNData(ctx, npnData.data, npnData.length), out, "Error setting npn data");
164 free(npnData.data);
165
166 }
167
168 out:
169 SSLClose(ctx);
170 CFReleaseNull(ctx);
171 close(ssl->comm);
172 CFReleaseSafe(server_certs);
173
174 pthread_exit((void *)(intptr_t)ortn);
175 return NULL;
176 }
177
178 static void *securetransport_client_thread(void *arg)
179 {
180 OSStatus ortn;
181 ssl_test_handle * ssl = (ssl_test_handle *)arg;
182 SSLContextRef ctx = ssl->handle;
183
184 do {
185 ortn = SSLHandshake(ctx);
186 } while (ortn == errSSLWouldBlock || ortn != errSSLClosedGraceful);
187
188 size_t length = 0;
189 uint8_t *alpnData = NULL;
190 alpnData = (uint8_t*)SSLGetALPNData(ctx, &length);
191 if (alpnData != NULL) {
192 require_noerr(memcmp(alpnData, serverSelectedProtocol, strlen(serverSelectedProtocol)), out);
193 }
194
195 length = 0;
196 uint8_t *npnData = NULL;
197 npnData = (uint8_t*)SSLGetNPNData(ctx, &length);
198 if (npnData != NULL) {
199 require_noerr_string(memcmp(npnData, serverAdvertisedProtocols, strlen(serverAdvertisedProtocols)),
200 out, "npn Data received does not match");
201 }
202 out:
203 SSLClose(ctx);
204 CFReleaseNull(ctx);
205 close(ssl->comm);
206
207 pthread_exit((void *)(intptr_t)ortn);
208 return NULL;
209 }
210
211 static SSLCipherSuite ciphers[] = {
212 TLS_RSA_WITH_AES_128_CBC_SHA,
213 };
214
215 static ssl_test_handle *
216 ssl_test_handle_create(uint32_t session_id, bool server, int comm)
217 {
218 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
219 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType);
220
221 require(handle, out);
222 require(ctx, out);
223
224 require_noerr(SSLSetIOFuncs(ctx,
225 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
226 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
227
228 if (server)
229 require_noerr(SSLSetSessionOption(ctx,
230 kSSLSessionOptionBreakOnClientHello, true), out);
231 else
232 require_noerr(SSLSetSessionOption(ctx,
233 kSSLSessionOptionBreakOnServerAuth, true), out);
234
235 handle->handle = ctx;
236 handle->is_server = server;
237 handle->session_id = session_id;
238 handle->comm = comm;
239
240 return handle;
241
242 out:
243 if (handle) free(handle);
244 if (ctx) CFRelease(ctx);
245 return NULL;
246 }
247
248 static SSLProtocol versions[] = {
249 kSSLProtocol3,
250 kTLSProtocol1,
251 kTLSProtocol11,
252 kTLSProtocol12,
253 };
254 static int nversions = sizeof(versions)/sizeof(versions[0]);
255
256 -(void)testSNI
257 {
258 int j;
259 pthread_t client_thread, server_thread;
260
261 for(j = 0; j < nversions; j++)
262 {
263 int sp[2];
264 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
265
266 ssl_test_handle *server, *client;
267
268 uint32_t session_id = (j+1) << 16 | 1 << 8;
269 server = ssl_test_handle_create(session_id, true /*server*/, sp[0]);
270 client = ssl_test_handle_create(session_id, false/*client*/, sp[1]);
271
272 XCTAssertEqual(errSecSuccess, SSLSetPeerID(server->handle, &session_id, sizeof(session_id)));
273 XCTAssertEqual(errSecSuccess, SSLSetPeerID(client->handle, &session_id, sizeof(session_id)));
274 const void *inputPeerId = NULL;
275 size_t inputPeerIdLen;
276 XCTAssertEqual(errSecSuccess, SSLGetPeerID(client->handle, &inputPeerId, &inputPeerIdLen));
277
278 /* set fixed cipher on client and server */
279 XCTAssertEqual(errSecSuccess, SSLSetEnabledCiphers(client->handle, &ciphers[0], 1));
280 XCTAssertEqual(errSecSuccess, SSLSetEnabledCiphers(server->handle, &ciphers[0], 1));
281
282 XCTAssertEqual(errSecSuccess, SSLSetProtocolVersionMax(client->handle, versions[j]));
283 XCTAssertEqual(errSecSuccess, SSLSetPeerDomainName(client->handle, peername, sizeof(peername)));
284
285 XCTAssertEqual(errSecSuccess, SSLSetProtocolVersionMax(server->handle, versions[j]));
286
287 pthread_create(&client_thread, NULL, securetransport_client_thread, client);
288 pthread_create(&server_thread, NULL, securetransport_server_thread, server);
289
290 intptr_t server_err, client_err;
291 pthread_join(client_thread, (void*)&client_err);
292 pthread_join(server_thread, (void*)&server_err);
293
294 free(client);
295 free(server);
296
297 }
298 }
299
300 @end
301
302 #pragma clang diagnostic pop