]>
Commit | Line | Data |
---|---|---|
427c49bc A |
1 | /* |
2 | * Copyright (c) 1999-2001,2005-2011 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 | * cipherSpecs.c - SSLCipherSpec declarations | |
26 | */ | |
27 | ||
28 | #include "sslBuildFlags.h" | |
29 | #include "CipherSuite.h" | |
30 | #include "sslContext.h" | |
31 | #include "sslCipherSpecs.h" | |
32 | #include "sslDebug.h" | |
33 | #include "sslMemory.h" | |
34 | #include "sslDebug.h" | |
35 | #include "sslUtils.h" | |
36 | #include "sslPriv.h" | |
37 | #include "sslCrypto.h" | |
38 | ||
39 | #include <string.h> | |
40 | #include <assert.h> | |
41 | #include <Security/SecBase.h> | |
42 | #include <utilities/array_size.h> | |
43 | ||
44 | #include <TargetConditionals.h> | |
45 | ||
46 | ||
47 | #define ENABLE_RSA_DES_SHA_NONEXPORT ENABLE_DES | |
48 | #define ENABLE_RSA_DES_MD5_NONEXPORT ENABLE_DES | |
49 | #define ENABLE_RSA_DES_SHA_EXPORT ENABLE_DES | |
50 | #define ENABLE_RSA_RC4_MD5_EXPORT ENABLE_RC4 /* the most common one */ | |
51 | #define ENABLE_RSA_RC4_MD5_NONEXPORT ENABLE_RC4 | |
52 | #define ENABLE_RSA_RC4_SHA_NONEXPORT ENABLE_RC4 | |
53 | #define ENABLE_RSA_RC2_MD5_EXPORT ENABLE_RC2 | |
54 | #define ENABLE_RSA_RC2_MD5_NONEXPORT ENABLE_RC2 | |
55 | #define ENABLE_RSA_3DES_SHA ENABLE_3DES | |
56 | #define ENABLE_RSA_3DES_MD5 ENABLE_3DES | |
57 | ||
58 | #define ENABLE_ECDH 1 | |
59 | #define ENABLE_AES_GCM 0 | |
60 | ||
61 | #define ENABLE_PSK 1 | |
62 | ||
63 | #if APPLE_DH | |
64 | #define ENABLE_DH_ANON 1 | |
65 | #define ENABLE_DH_EPHEM_RSA 1 | |
66 | #if USE_CDSA_CRYPTO | |
67 | #define ENABLE_DH_EPHEM_DSA 1 | |
68 | #else | |
69 | #define ENABLE_DH_EPHEM_DSA 0 | |
70 | #endif | |
71 | #else | |
72 | #define ENABLE_DH_ANON 0 | |
73 | #define ENABLE_DH_EPHEM_RSA 0 | |
74 | #define ENABLE_DH_EPHEM_DSA 0 | |
75 | #endif /* APPLE_DH */ | |
76 | ||
77 | /* | |
78 | * List of all CipherSpecs we implement. Depending on a context's | |
79 | * exportable flag, not all of these might be available for use. | |
80 | */ | |
81 | /* Order by preference, domestic first */ | |
82 | static const SSLCipherSuite KnownCipherSuites[] = { | |
83 | #if ENABLE_AES_GCM | |
84 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, | |
85 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, | |
86 | #endif | |
87 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, | |
88 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, | |
89 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, | |
90 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, | |
91 | TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, | |
92 | TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, | |
93 | #if ENABLE_AES_GCM | |
94 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, | |
95 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, | |
96 | #endif | |
97 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, | |
98 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, | |
99 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, | |
100 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, | |
101 | TLS_ECDHE_RSA_WITH_RC4_128_SHA, | |
102 | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, | |
103 | #if ENABLE_ECDH | |
104 | #if ENABLE_AES_GCM | |
105 | TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, | |
106 | TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, | |
107 | #endif | |
108 | TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, | |
109 | TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, | |
110 | #if ENABLE_AES_GCM | |
111 | TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, | |
112 | TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, | |
113 | #endif | |
114 | TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, | |
115 | TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, | |
116 | TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, | |
117 | TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, | |
118 | TLS_ECDH_ECDSA_WITH_RC4_128_SHA, | |
119 | TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, | |
120 | TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, | |
121 | TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, | |
122 | TLS_ECDH_RSA_WITH_RC4_128_SHA, | |
123 | TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, | |
124 | #endif | |
125 | #if ENABLE_AES_GCM | |
126 | TLS_RSA_WITH_AES_256_GCM_SHA384, | |
127 | TLS_RSA_WITH_AES_128_GCM_SHA256, | |
128 | #endif | |
129 | TLS_RSA_WITH_AES_256_CBC_SHA256, | |
130 | TLS_RSA_WITH_AES_128_CBC_SHA256, | |
131 | TLS_RSA_WITH_AES_128_CBC_SHA, | |
132 | SSL_RSA_WITH_RC4_128_SHA, | |
133 | SSL_RSA_WITH_RC4_128_MD5, | |
134 | TLS_RSA_WITH_AES_256_CBC_SHA, | |
135 | SSL_RSA_WITH_3DES_EDE_CBC_SHA, | |
136 | #if ENABLE_SSLV2 | |
137 | SSL_RSA_WITH_3DES_EDE_CBC_MD5, | |
138 | #endif | |
139 | #if ENABLE_DES | |
140 | SSL_RSA_WITH_DES_CBC_SHA, | |
141 | #endif | |
142 | #if ENABLE_SSLV2 | |
143 | SSL_RSA_WITH_DES_CBC_MD5, | |
144 | #endif | |
145 | #if ENABLE_RC2 | |
146 | SSL_RSA_WITH_RC2_CBC_MD5, | |
147 | #endif | |
148 | #if ENABLE_AES_GCM | |
149 | # if ENABLE_DH_EPHEM_DSA | |
150 | TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, | |
151 | # endif // ENABLE_DH_EPHEM_DSA | |
152 | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, | |
153 | # if ENABLE_DH_EPHEM_DSA | |
154 | TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, | |
155 | # endif // ENABLE_DH_EPHEM_DSA | |
156 | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, | |
157 | #endif // ENABLE_AES_GCM | |
158 | #if ENABLE_DH_EPHEM_DSA | |
159 | TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, | |
160 | #endif | |
161 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, | |
162 | #if ENABLE_DH_EPHEM_DSA | |
163 | TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, | |
164 | #endif | |
165 | TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, | |
166 | #if ENABLE_DH_EPHEM_DSA | |
167 | TLS_DHE_DSS_WITH_AES_128_CBC_SHA, | |
168 | #endif | |
169 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA, | |
170 | #if ENABLE_DH_EPHEM_DSA | |
171 | TLS_DHE_DSS_WITH_AES_256_CBC_SHA, | |
172 | #endif | |
173 | TLS_DHE_RSA_WITH_AES_256_CBC_SHA, | |
174 | SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, | |
175 | #if ENABLE_DES | |
176 | SSL_DHE_RSA_WITH_DES_CBC_SHA, | |
177 | #endif | |
178 | #if ENABLE_DH_EPHEM_DSA | |
179 | SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, | |
180 | #if ENABLE_DES | |
181 | SSL_DHE_DSS_WITH_DES_CBC_SHA, | |
182 | #endif | |
183 | #endif | |
184 | #if ENABLE_AES_GCM | |
185 | TLS_DH_anon_WITH_AES_256_GCM_SHA384, | |
186 | TLS_DH_anon_WITH_AES_128_GCM_SHA256, | |
187 | #endif | |
188 | TLS_DH_anon_WITH_AES_128_CBC_SHA256, | |
189 | TLS_DH_anon_WITH_AES_256_CBC_SHA256, | |
190 | TLS_DH_anon_WITH_AES_128_CBC_SHA, | |
191 | TLS_DH_anon_WITH_AES_256_CBC_SHA, | |
192 | SSL_DH_anon_WITH_RC4_128_MD5, | |
193 | SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, | |
194 | #if ENABLE_DES | |
195 | SSL_DH_anon_WITH_DES_CBC_SHA, | |
196 | #endif | |
197 | TLS_ECDHE_ECDSA_WITH_NULL_SHA, | |
198 | TLS_ECDHE_RSA_WITH_NULL_SHA, | |
199 | #if ENABLE_ECDH | |
200 | TLS_ECDH_ECDSA_WITH_NULL_SHA, | |
201 | TLS_ECDH_RSA_WITH_NULL_SHA, | |
202 | #endif | |
203 | ||
204 | #if ENABLE_PSK | |
205 | TLS_PSK_WITH_AES_256_CBC_SHA384, | |
206 | TLS_PSK_WITH_AES_128_CBC_SHA256, | |
207 | TLS_PSK_WITH_AES_256_CBC_SHA, | |
208 | TLS_PSK_WITH_AES_128_CBC_SHA, | |
209 | TLS_PSK_WITH_RC4_128_SHA, | |
210 | TLS_PSK_WITH_3DES_EDE_CBC_SHA, | |
211 | TLS_PSK_WITH_NULL_SHA384, | |
212 | TLS_PSK_WITH_NULL_SHA256, | |
213 | TLS_PSK_WITH_NULL_SHA, | |
214 | #endif | |
215 | ||
216 | TLS_RSA_WITH_NULL_SHA256, | |
217 | SSL_RSA_WITH_NULL_SHA, | |
218 | SSL_RSA_WITH_NULL_MD5 | |
219 | ||
220 | #if 0 | |
221 | /* We don't support these yet. */ | |
222 | TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, | |
223 | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, | |
224 | TLS_RSA_WITH_RC4_128_SHA, | |
225 | TLS_RSA_WITH_3DES_EDE_CBC_SHA, | |
226 | TLS_RSA_WITH_RC4_128_MD5, | |
227 | TLS_DH_DSS_WITH_AES_256_GCM_SHA384, | |
228 | TLS_DH_DSS_WITH_AES_128_GCM_SHA256, | |
229 | TLS_DH_RSA_WITH_AES_256_GCM_SHA384, | |
230 | TLS_DH_RSA_WITH_AES_128_GCM_SHA256, | |
231 | TLS_DH_DSS_WITH_AES_256_CBC_SHA256, | |
232 | TLS_DH_RSA_WITH_AES_256_CBC_SHA256, | |
233 | TLS_DH_DSS_WITH_AES_128_CBC_SHA256, | |
234 | TLS_DH_RSA_WITH_AES_128_CBC_SHA256, | |
235 | TLS_DH_DSS_WITH_AES_256_CBC_SHA, | |
236 | TLS_DH_RSA_WITH_AES_256_CBC_SHA, | |
237 | TLS_DH_DSS_WITH_AES_128_CBC_SHA, | |
238 | TLS_DH_RSA_WITH_AES_128_CBC_SHA, | |
239 | TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, | |
240 | TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, | |
241 | TLS_ECDH_anon_WITH_AES_256_CBC_SHA, | |
242 | TLS_ECDH_anon_WITH_AES_128_CBC_SHA, | |
243 | TLS_ECDH_anon_WITH_RC4_128_SHA, | |
244 | TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, | |
245 | TLS_ECDH_anon_WITH_NULL_SHA, | |
246 | #endif | |
247 | }; | |
248 | ||
249 | static const unsigned CipherSuiteCount = array_size(KnownCipherSuites); | |
250 | ||
251 | ||
252 | /* | |
253 | * Given a valid ctx->validCipherSpecs array, calculate how many of those | |
254 | * cipherSpecs are *not* SSLv2 only, storing result in | |
255 | * ctx->numValidNonSSLv2Specs. ClientHello routines need this to set | |
256 | * up outgoing cipherSpecs arrays correctly. | |
257 | * | |
258 | * Also determines if any ECDSA/ECDH ciphers are enabled; we need to know | |
259 | * that when creating a hello message. | |
260 | */ | |
261 | static void sslAnalyzeCipherSpecs(SSLContext *ctx) | |
262 | { | |
263 | unsigned dex; | |
264 | const SSLCipherSuite *cipherSuite; | |
265 | ||
266 | #if ENABLE_SSLV2 | |
267 | ctx->numValidNonSSLv2Suites = 0; | |
268 | #endif | |
269 | cipherSuite = &ctx->validCipherSuites[0]; | |
270 | ctx->ecdsaEnable = false; | |
271 | for(dex=0; dex<ctx->numValidCipherSuites; dex++, cipherSuite++) { | |
272 | #if ENABLE_SSLV2 | |
273 | if(!CIPHER_SPEC_IS_SSLv2(*cipherSuite)) { | |
274 | ctx->numValidNonSSLv2Suites++; | |
275 | } | |
276 | #endif | |
277 | switch(sslCipherSuiteGetKeyExchangeMethod(*cipherSuite)) { | |
278 | case SSL_ECDH_ECDSA: | |
279 | case SSL_ECDHE_ECDSA: | |
280 | case SSL_ECDH_RSA: | |
281 | case SSL_ECDHE_RSA: | |
282 | case SSL_ECDH_anon: | |
283 | ctx->ecdsaEnable = true; | |
284 | break; | |
285 | default: | |
286 | break; | |
287 | } | |
288 | } | |
289 | } | |
290 | ||
291 | /* | |
292 | * Build ctx->validCipherSpecs as a copy of KnownCipherSpecs, assuming that | |
293 | * validCipherSpecs is currently not valid (i.e., SSLSetEnabledCiphers() has | |
294 | * not been called). | |
295 | */ | |
296 | OSStatus sslBuildCipherSuiteArray(SSLContext *ctx) | |
297 | { | |
298 | size_t size; | |
299 | unsigned dex; | |
300 | ||
301 | assert(ctx != NULL); | |
302 | assert(ctx->validCipherSuites == NULL); | |
303 | ||
304 | ctx->numValidCipherSuites = CipherSuiteCount; | |
305 | size = CipherSuiteCount * sizeof(SSLCipherSuite); | |
306 | ctx->validCipherSuites = (SSLCipherSuite *)sslMalloc(size); | |
307 | if(ctx->validCipherSuites == NULL) { | |
308 | ctx->numValidCipherSuites = 0; | |
309 | return errSecAllocate; | |
310 | } | |
311 | ||
312 | /* | |
313 | * Trim out inappropriate ciphers: | |
314 | * -- trim anonymous ciphers if !ctx->anonCipherEnable | |
315 | * -- trim ECDSA ciphers for server side if appropriate | |
316 | * -- trim ECDSA ciphers if TLSv1 disable or SSLv2 enabled (since | |
317 | * we MUST do the Client Hello extensions to make these ciphers | |
318 | * work reliably) | |
319 | * -- trim Stream ciphers if DTLSv1 enable | |
320 | */ | |
321 | SSLCipherSuite *dst = ctx->validCipherSuites; | |
322 | const SSLCipherSuite *src = KnownCipherSuites; | |
323 | ||
324 | bool trimECDSA = false; | |
325 | if((ctx->protocolSide == kSSLServerSide) && !SSL_ECDSA_SERVER) { | |
326 | trimECDSA = true; | |
327 | } | |
328 | if(ctx->minProtocolVersion == SSL_Version_2_0 | |
329 | || ctx->maxProtocolVersion == SSL_Version_3_0) { | |
330 | /* We trim ECDSA cipher suites if SSL2 is enabled or | |
331 | The maximum allowed protocol is SSL3. Note that this | |
332 | won't trim ECDSA cipherspecs for DTLS which should be | |
333 | the right thing to do here. */ | |
334 | trimECDSA = true; | |
335 | } | |
336 | ||
337 | /* trim Stream Ciphers for DTLS */ | |
338 | bool trimRC4 = ctx->isDTLS; | |
339 | ||
340 | bool trimDHE = (ctx->protocolSide == kSSLServerSide) && | |
341 | !ctx->dhParamsEncoded.length; | |
342 | ||
343 | for(dex=0; dex<CipherSuiteCount; dex++) { | |
344 | KeyExchangeMethod kem = sslCipherSuiteGetKeyExchangeMethod(*src); | |
345 | uint8_t keySize = sslCipherSuiteGetSymmetricCipherKeySize(*src); | |
346 | HMAC_Algs mac = sslCipherSuiteGetMacAlgorithm(*src); | |
347 | SSL_CipherAlgorithm cipher = sslCipherSuiteGetSymmetricCipherAlgorithm(*src); | |
348 | /* First skip ECDSA ciphers as appropriate */ | |
349 | switch(kem) { | |
350 | case SSL_ECDH_ECDSA: | |
351 | case SSL_ECDHE_ECDSA: | |
352 | case SSL_ECDH_RSA: | |
353 | case SSL_ECDHE_RSA: | |
354 | case SSL_ECDH_anon: | |
355 | if(trimECDSA) { | |
356 | /* Skip this one */ | |
357 | ctx->numValidCipherSuites--; | |
358 | src++; | |
359 | continue; | |
360 | } | |
361 | else { | |
362 | break; | |
363 | } | |
364 | default: | |
365 | break; | |
366 | } | |
367 | if(!ctx->anonCipherEnable) { | |
368 | /* trim out the anonymous (and null-auth-cipher) ciphers */ | |
369 | if(mac == HA_Null) { | |
370 | /* skip this one */ | |
371 | ctx->numValidCipherSuites--; | |
372 | src++; | |
373 | continue; | |
374 | } | |
375 | switch(kem) { | |
376 | case SSL_DH_anon: | |
377 | case SSL_DH_anon_EXPORT: | |
378 | case SSL_ECDH_anon: | |
379 | /* skip this one */ | |
380 | ctx->numValidCipherSuites--; | |
381 | src++; | |
382 | continue; | |
383 | default: | |
384 | break; | |
385 | } | |
386 | } | |
387 | if(ctx->falseStartEnabled) { | |
388 | switch(kem){ | |
389 | case SSL_ECDHE_ECDSA: | |
390 | case SSL_ECDHE_RSA: | |
391 | case SSL_DHE_RSA: | |
392 | case SSL_DHE_DSS: | |
393 | /* Ok for false start */ | |
394 | break; | |
395 | default: | |
396 | /* Not ok, skip */ | |
397 | ctx->numValidCipherSuites--; | |
398 | src++; | |
399 | continue; | |
400 | } | |
401 | switch(cipher) { | |
402 | case SSL_CipherAlgorithmAES_128_CBC: | |
403 | case SSL_CipherAlgorithmAES_128_GCM: | |
404 | case SSL_CipherAlgorithmAES_256_CBC: | |
405 | case SSL_CipherAlgorithmAES_256_GCM: | |
406 | case SSL_CipherAlgorithmRC4_128: | |
407 | /* Ok for false start */ | |
408 | break; | |
409 | default: | |
410 | /* Not ok, skip*/ | |
411 | ctx->numValidCipherSuites--; | |
412 | src++; | |
413 | continue; | |
414 | } | |
415 | } | |
416 | ||
417 | /* This will skip the simple DES cipher suites, but not the NULL cipher ones */ | |
418 | if (keySize == 8) | |
419 | { | |
420 | /* skip this one */ | |
421 | ctx->numValidCipherSuites--; | |
422 | src++; | |
423 | continue; | |
424 | } | |
425 | ||
426 | /* Trim PSK ciphersuites, they need to be enabled explicitely */ | |
427 | if (kem==TLS_PSK) { | |
428 | ctx->numValidCipherSuites--; | |
429 | src++; | |
430 | continue; | |
431 | } | |
432 | ||
433 | if (trimDHE) { | |
434 | switch(kem) { | |
435 | case SSL_DHE_DSS: | |
436 | case SSL_DHE_DSS_EXPORT: | |
437 | case SSL_DHE_RSA: | |
438 | case SSL_DHE_RSA_EXPORT: | |
439 | /* skip this one */ | |
440 | ctx->numValidCipherSuites--; | |
441 | src++; | |
442 | continue; | |
443 | default: | |
444 | break; | |
445 | } | |
446 | } | |
447 | ||
448 | if (trimRC4 && (cipher==SSL_CipherAlgorithmRC4_128)) { | |
449 | ctx->numValidCipherSuites--; | |
450 | src++; | |
451 | continue; | |
452 | } | |
453 | ||
454 | if(cipher==SSL_CipherAlgorithmNull) { | |
455 | ctx->numValidCipherSuites--; | |
456 | src++; | |
457 | continue; | |
458 | } | |
459 | ||
460 | /* This one is good to go */ | |
461 | *dst++ = *src++; | |
462 | } | |
463 | sslAnalyzeCipherSpecs(ctx); | |
464 | return errSecSuccess; | |
465 | } | |
466 | ||
467 | /* | |
468 | * Convert an array of SSLCipherSuites (which is always KnownCipherSpecs) | |
469 | * to an array of SSLCipherSuites. | |
470 | */ | |
471 | static OSStatus | |
472 | cipherSuitesToCipherSuites( | |
473 | size_t numCipherSuites, | |
474 | const SSLCipherSuite *cipherSuites, | |
475 | SSLCipherSuite *ciphers, /* RETURNED */ | |
476 | size_t *numCiphers) /* IN/OUT */ | |
477 | { | |
478 | if(*numCiphers < numCipherSuites) { | |
479 | return errSSLBufferOverflow; | |
480 | } | |
481 | memcpy(ciphers, cipherSuites, numCipherSuites * sizeof(SSLCipherSuite)); | |
482 | *numCiphers = numCipherSuites; | |
483 | return errSecSuccess; | |
484 | } | |
485 | ||
486 | /*** | |
487 | *** Publically exported functions declared in SecureTransport.h | |
488 | ***/ | |
489 | ||
490 | /* | |
491 | * Determine number and values of all of the SSLCipherSuites we support. | |
492 | * Caller allocates output buffer for SSLGetSupportedCiphers() and passes in | |
493 | * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow | |
494 | * will be returned. | |
495 | */ | |
496 | OSStatus | |
497 | SSLGetNumberSupportedCiphers (SSLContextRef ctx, | |
498 | size_t *numCiphers) | |
499 | { | |
500 | if((ctx == NULL) || (numCiphers == NULL)) { | |
501 | return errSecParam; | |
502 | } | |
503 | *numCiphers = CipherSuiteCount; | |
504 | return errSecSuccess; | |
505 | } | |
506 | ||
507 | OSStatus | |
508 | SSLGetSupportedCiphers (SSLContextRef ctx, | |
509 | SSLCipherSuite *ciphers, /* RETURNED */ | |
510 | size_t *numCiphers) /* IN/OUT */ | |
511 | { | |
512 | if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) { | |
513 | return errSecParam; | |
514 | } | |
515 | return cipherSuitesToCipherSuites(CipherSuiteCount, | |
516 | KnownCipherSuites, | |
517 | ciphers, | |
518 | numCiphers); | |
519 | } | |
520 | ||
521 | /* | |
522 | * Specify a (typically) restricted set of SSLCipherSuites to be enabled by | |
523 | * the current SSLContext. Can only be called when no session is active. Default | |
524 | * set of enabled SSLCipherSuites is NOT the same as the complete set of supported | |
525 | * SSLCipherSuites as obtained by SSLGetSupportedCiphers(). | |
526 | */ | |
527 | OSStatus | |
528 | SSLSetEnabledCiphers (SSLContextRef ctx, | |
529 | const SSLCipherSuite *ciphers, | |
530 | size_t numCiphers) | |
531 | { | |
532 | size_t size; | |
533 | size_t foundCiphers=0; | |
534 | unsigned callerDex; | |
535 | unsigned tableDex; | |
536 | ||
537 | if((ctx == NULL) || (ciphers == NULL) || (numCiphers == 0)) { | |
538 | return errSecParam; | |
539 | } | |
540 | if(sslIsSessionActive(ctx)) { | |
541 | /* can't do this with an active session */ | |
542 | return errSecBadReq; | |
543 | } | |
544 | size = numCiphers * sizeof(SSLCipherSuite); | |
545 | ctx->validCipherSuites = (SSLCipherSuite *)sslMalloc(size); | |
546 | if(ctx->validCipherSuites == NULL) { | |
547 | ctx->numValidCipherSuites = 0; | |
548 | return errSecAllocate; | |
549 | } | |
550 | ||
551 | /* | |
552 | * Run thru caller's specs, keep only the supported ones. | |
553 | */ | |
554 | for(callerDex=0; callerDex<numCiphers; callerDex++) { | |
555 | /* find matching CipherSpec in our known table */ | |
556 | for(tableDex=0; tableDex<CipherSuiteCount; tableDex++) { | |
557 | if(ciphers[callerDex] == KnownCipherSuites[tableDex]) { | |
558 | ctx->validCipherSuites[foundCiphers] = KnownCipherSuites[tableDex]; | |
559 | foundCiphers++; | |
560 | break; | |
561 | } | |
562 | } | |
563 | } | |
564 | ||
565 | if(foundCiphers==0) { | |
566 | /* caller specified only unsupported ciphersuites */ | |
567 | sslFree(ctx->validCipherSuites); | |
568 | ctx->validCipherSuites = NULL; | |
569 | return errSSLBadCipherSuite; | |
570 | } | |
571 | ||
572 | /* success */ | |
573 | ctx->numValidCipherSuites = foundCiphers; | |
574 | sslAnalyzeCipherSpecs(ctx); | |
575 | return errSecSuccess; | |
576 | } | |
577 | ||
578 | /* | |
579 | * Determine number and values of all of the SSLCipherSuites currently enabled. | |
580 | * Caller allocates output buffer for SSLGetEnabledCiphers() and passes in | |
581 | * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow | |
582 | * will be returned. | |
583 | */ | |
584 | OSStatus | |
585 | SSLGetNumberEnabledCiphers (SSLContextRef ctx, | |
586 | size_t *numCiphers) | |
587 | { | |
588 | if((ctx == NULL) || (numCiphers == NULL)) { | |
589 | return errSecParam; | |
590 | } | |
591 | if(ctx->validCipherSuites == NULL) { | |
592 | /* hasn't been set; use default */ | |
593 | *numCiphers = CipherSuiteCount; | |
594 | } | |
595 | else { | |
596 | /* caller set via SSLSetEnabledCiphers */ | |
597 | *numCiphers = ctx->numValidCipherSuites; | |
598 | } | |
599 | return errSecSuccess; | |
600 | } | |
601 | ||
602 | OSStatus | |
603 | SSLGetEnabledCiphers (SSLContextRef ctx, | |
604 | SSLCipherSuite *ciphers, /* RETURNED */ | |
605 | size_t *numCiphers) /* IN/OUT */ | |
606 | { | |
607 | if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) { | |
608 | return errSecParam; | |
609 | } | |
610 | if(ctx->validCipherSuites == NULL) { | |
611 | /* hasn't been set; use default */ | |
612 | return cipherSuitesToCipherSuites(CipherSuiteCount, | |
613 | KnownCipherSuites, | |
614 | ciphers, | |
615 | numCiphers); | |
616 | } | |
617 | else { | |
618 | /* use the ones specified in SSLSetEnabledCiphers() */ | |
619 | return cipherSuitesToCipherSuites(ctx->numValidCipherSuites, | |
620 | ctx->validCipherSuites, | |
621 | ciphers, | |
622 | numCiphers); | |
623 | } | |
624 | } | |
625 | ||
626 | /*** | |
627 | *** End of publically exported functions declared in SecureTransport.h | |
628 | ***/ | |
629 | ||
630 | void InitCipherSpecParams(SSLContext *ctx) | |
631 | { | |
632 | SSLCipherSpecParams *dst = &ctx->selectedCipherSpecParams; | |
633 | dst->cipherSpec = ctx->selectedCipher; | |
634 | dst->macSize = sslCipherSuiteGetMacSize(ctx->selectedCipher); | |
635 | dst->macAlg = sslCipherSuiteGetMacAlgorithm(ctx->selectedCipher); | |
636 | dst->keySize = sslCipherSuiteGetSymmetricCipherKeySize(ctx->selectedCipher); | |
637 | dst->blockSize = sslCipherSuiteGetSymmetricCipherBlockIvSize(ctx->selectedCipher); | |
638 | dst->ivSize = dst->blockSize; | |
639 | dst->keyExchangeMethod = sslCipherSuiteGetKeyExchangeMethod(ctx->selectedCipher); | |
640 | }; | |
641 | ||
642 | ||
643 | OSStatus | |
644 | FindCipherSpec(SSLContext *ctx) | |
645 | { | |
646 | unsigned i; | |
647 | ||
648 | assert(ctx != NULL); | |
649 | assert(ctx->validCipherSuites != NULL); | |
650 | ||
651 | for (i=0; i<ctx->numValidCipherSuites; i++) | |
652 | { | |
653 | if (ctx->validCipherSuites[i] == ctx->selectedCipher) { | |
654 | InitCipherSpecParams(ctx); | |
655 | /* Make sure we're configured to handle this cipherSuite. */ | |
656 | return sslVerifySelectedCipher(ctx); | |
657 | } | |
658 | } | |
659 | /* Not found */ | |
660 | return errSSLNegotiation; | |
661 | } |