2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
22 Contains: SSLCipherSpec declarations
24 Written by: Doug Mitchell
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
30 #include "sslContext.h"
31 #include "cryptType.h"
32 #include "symCipher.h"
33 #include "cipherSpecs.h"
35 #include "sslMemory.h"
39 #include "appleCdsa.h"
41 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
43 #define ENABLE_3DES 1 /* normally enabled */
44 #define ENABLE_RC4 1 /* normally enabled, our first preference */
45 #define ENABLE_DES 1 /* normally enabled */
46 #define ENABLE_RC2 1 /* normally enabled */
48 #define ENABLE_RSA_DES_SHA_NONEXPORT ENABLE_DES
49 #define ENABLE_RSA_DES_MD5_NONEXPORT ENABLE_DES
50 #define ENABLE_RSA_DES_SHA_EXPORT ENABLE_DES
51 #define ENABLE_RSA_RC4_MD5_EXPORT ENABLE_RC4 /* the most common one */
52 #define ENABLE_RSA_RC4_MD5_NONEXPORT ENABLE_RC4
53 #define ENABLE_RSA_RC4_SHA_NONEXPORT ENABLE_RC4
54 #define ENABLE_RSA_RC2_MD5_EXPORT ENABLE_RC2
55 #define ENABLE_RSA_RC2_MD5_NONEXPORT ENABLE_RC2
56 #define ENABLE_RSA_3DES_SHA ENABLE_3DES
57 #define ENABLE_RSA_3DES_MD5 ENABLE_3DES
60 #define ENABLE_DH_ANON 1
61 #define ENABLE_DH_EPHEM_RSA 1
62 #define ENABLE_DH_EPHEM_DSA 1
64 #define ENABLE_DH_ANON 0
65 #define ENABLE_DH_EPHEM_RSA 0
66 #define ENABLE_DH_EPHEM_DSA 0
70 extern const SSLSymmetricCipher SSLCipherNull
; /* in sslNullCipher.cpp */
74 * The symmetric ciphers currently supported (in addition to the
75 * NULL cipher in nullciph.c).
78 static const SSLSymmetricCipher SSLCipherDES_CBC
= {
79 8, /* Key size in bytes */
80 8, /* Secret key size = 64 bits */
85 /* Note we don't want CSSM_ALGMODE_CBCPadIV8; our clients do that
95 static const SSLSymmetricCipher SSLCipherDES40_CBC
= {
96 8, /* Key size in bytes */
97 5, /* Secret key size = 40 bits */
102 CSSM_ALGMODE_CBC_IV8
,
109 #endif /* ENABLE_DES */
112 static const SSLSymmetricCipher SSLCipher3DES_CBC
= {
113 24, /* Key size in bytes */
114 24, /* Secret key size = 192 bits */
117 CSSM_ALGID_3DES_3KEY
, // key gen
118 CSSM_ALGID_3DES_3KEY_EDE
, // encryption
119 /* Note we don't want CSSM_ALGMODE_CBCPadIV8; our clients do that
121 CSSM_ALGMODE_CBC_IV8
,
128 #endif /* ENABLE_3DES */
131 static const SSLSymmetricCipher SSLCipherRC4_40
= {
132 16, /* Key size in bytes */
133 5, /* Secret key size = 40 bits */
146 static const SSLSymmetricCipher SSLCipherRC4_128
= {
147 16, /* Key size in bytes */
148 16, /* Secret key size = 128 bits */
160 #endif /* ENABLE_RC4 */
163 static const SSLSymmetricCipher SSLCipherRC2_40
= {
164 16, /* Key size in bytes */
165 5, /* Secret key size = 40 bits */
170 CSSM_ALGMODE_CBC_IV8
,
178 static const SSLSymmetricCipher SSLCipherRC2_128
= {
179 16, /* Key size in bytes */
180 16, /* Secret key size = 40 bits */
185 CSSM_ALGMODE_CBC_IV8
,
193 #endif /* ENABLE_RC2*/
196 /* Even if we don't support NULL_WITH_NULL_NULL for transport,
197 * we need a reference for startup */
198 const SSLCipherSpec SSL_NULL_WITH_NULL_NULL_CipherSpec
=
199 { SSL_NULL_WITH_NULL_NULL
,
207 * List of all CipherSpecs we implement. Depending on a context's
208 * exportable flag, not all of these might be available for use.
210 * FIXME - I'm not sure the distinction between e.g. SSL_RSA and SSL_RSA_EXPORT
211 * makes any sense here. See comments for the definition of
212 * KeyExchangeMethod in cryptType.h.
214 /* Order by preference, domestic first */
215 static const SSLCipherSpec KnownCipherSpecs
[] =
217 /*** domestic only ***/
218 #if ENABLE_RSA_RC4_SHA_NONEXPORT
220 SSL_RSA_WITH_RC4_128_SHA
,
227 #if ENABLE_RSA_RC4_MD5_NONEXPORT
229 SSL_RSA_WITH_RC4_128_MD5
,
236 #if ENABLE_RSA_3DES_SHA
238 SSL_RSA_WITH_3DES_EDE_CBC_SHA
,
245 #if ENABLE_RSA_3DES_MD5
247 SSL_RSA_WITH_3DES_EDE_CBC_MD5
,
254 #if ENABLE_RSA_DES_SHA_NONEXPORT
256 SSL_RSA_WITH_DES_CBC_SHA
,
263 #if ENABLE_RSA_DES_MD5_NONEXPORT
265 SSL_RSA_WITH_DES_CBC_MD5
,
273 #if ENABLE_RSA_RC4_MD5_EXPORT
275 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
282 #if ENABLE_RSA_DES_SHA_EXPORT
284 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
292 #if ENABLE_RSA_RC2_MD5_EXPORT
294 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
301 #if ENABLE_RSA_RC2_MD5_NONEXPORT
303 SSL_RSA_WITH_RC2_CBC_MD5
,
311 SSL_RSA_WITH_NULL_MD5
,
317 #if ENABLE_DH_EPHEM_RSA
319 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
326 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
333 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
340 #endif /* ENABLE_DH_EPHEM_RSA */
341 #if ENABLE_DH_EPHEM_DSA
343 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
350 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
357 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
364 #endif /* ENABLE_DH_EPHEM_DSA */
367 SSL_DH_anon_WITH_RC4_128_MD5
,
374 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
381 SSL_DH_anon_WITH_DES_CBC_SHA
,
388 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
395 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
401 #endif /* APPLE_DH */
404 static const unsigned CipherSpecCount
= sizeof(KnownCipherSpecs
) / sizeof(SSLCipherSpec
);
407 * Build ctx->validCipherSpecs as a copy of KnownCipherSpecs, assuming that
408 * validCipherSpecs is currently not valid (i.e., SSLSetEnabledCiphers() has
411 OSStatus
sslBuildCipherSpecArray(SSLContext
*ctx
)
416 assert(ctx
->validCipherSpecs
== NULL
);
418 ctx
->numValidCipherSpecs
= CipherSpecCount
;
419 size
= CipherSpecCount
* sizeof(SSLCipherSpec
);
420 ctx
->validCipherSpecs
= (SSLCipherSpec
*)sslMalloc(size
);
421 if(ctx
->validCipherSpecs
== NULL
) {
422 ctx
->numValidCipherSpecs
= 0;
425 memmove(ctx
->validCipherSpecs
, KnownCipherSpecs
, size
);
430 * Convert an array of SSLCipherSpecs (which is either KnownCipherSpecs or
431 * ctx->validCipherSpecs) to an array of SSLCipherSuites.
434 cipherSpecsToCipherSuites(
435 UInt32 numCipherSpecs
, /* size of cipherSpecs */
436 const SSLCipherSpec
*cipherSpecs
,
437 SSLCipherSuite
*ciphers
, /* RETURNED */
438 UInt32
*numCiphers
) /* IN/OUT */
442 if(*numCiphers
< numCipherSpecs
) {
443 return errSSLBufferOverflow
;
445 for(dex
=0; dex
<numCipherSpecs
; dex
++) {
446 ciphers
[dex
] = cipherSpecs
[dex
].cipherSpec
;
448 *numCiphers
= numCipherSpecs
;
453 *** Publically exported functions declared in SecureTransport.h
457 * Determine number and values of all of the SSLCipherSuites we support.
458 * Caller allocates output buffer for SSLGetSupportedCiphers() and passes in
459 * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow
463 SSLGetNumberSupportedCiphers (SSLContextRef ctx
,
466 if((ctx
== NULL
) || (numCiphers
== NULL
)) {
469 *numCiphers
= CipherSpecCount
;
474 SSLGetSupportedCiphers (SSLContextRef ctx
,
475 SSLCipherSuite
*ciphers
, /* RETURNED */
476 UInt32
*numCiphers
) /* IN/OUT */
478 if((ctx
== NULL
) || (ciphers
== NULL
) || (numCiphers
== NULL
)) {
481 return cipherSpecsToCipherSuites(CipherSpecCount
,
488 * Specify a (typically) restricted set of SSLCipherSuites to be enabled by
489 * the current SSLContext. Can only be called when no session is active. Default
490 * set of enabled SSLCipherSuites is the same as the complete set of supported
491 * SSLCipherSuites as obtained by SSLGetSupportedCiphers().
494 SSLSetEnabledCiphers (SSLContextRef ctx
,
495 const SSLCipherSuite
*ciphers
,
502 if((ctx
== NULL
) || (ciphers
== NULL
) || (numCiphers
== 0)) {
505 if(sslIsSessionActive(ctx
)) {
506 /* can't do this with an active session */
509 size
= numCiphers
* sizeof(SSLCipherSpec
);
510 ctx
->validCipherSpecs
= (SSLCipherSpec
*)sslMalloc(size
);
511 if(ctx
->validCipherSpecs
== NULL
) {
512 ctx
->numValidCipherSpecs
= 0;
517 * Run thru caller's specs, finding a matching SSLCipherSpec for each one.
518 * If caller specifies one we don't know about, abort.
520 for(callerDex
=0; callerDex
<numCiphers
; callerDex
++) {
521 /* find matching CipherSpec in our known table */
523 for(tableDex
=0; tableDex
<CipherSpecCount
; tableDex
++) {
524 if(ciphers
[callerDex
] == KnownCipherSpecs
[tableDex
].cipherSpec
) {
525 ctx
->validCipherSpecs
[callerDex
] = KnownCipherSpecs
[tableDex
];
531 /* caller specified one we don't implement */
532 sslFree(ctx
->validCipherSpecs
);
533 ctx
->validCipherSpecs
= NULL
;
534 return errSSLBadCipherSuite
;
539 ctx
->numValidCipherSpecs
= numCiphers
;
544 * Determine number and values of all of the SSLCipherSuites currently enabled.
545 * Caller allocates output buffer for SSLGetEnabledCiphers() and passes in
546 * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow
550 SSLGetNumberEnabledCiphers (SSLContextRef ctx
,
553 if((ctx
== NULL
) || (numCiphers
== NULL
)) {
556 if(ctx
->validCipherSpecs
== NULL
) {
557 /* hasn't been set; use default */
558 *numCiphers
= CipherSpecCount
;
561 /* caller set via SSLSetEnabledCiphers */
562 *numCiphers
= ctx
->numValidCipherSpecs
;
568 SSLGetEnabledCiphers (SSLContextRef ctx
,
569 SSLCipherSuite
*ciphers
, /* RETURNED */
570 UInt32
*numCiphers
) /* IN/OUT */
572 if((ctx
== NULL
) || (ciphers
== NULL
) || (numCiphers
== NULL
)) {
575 if(ctx
->validCipherSpecs
== NULL
) {
576 /* hasn't been set; use default */
577 return cipherSpecsToCipherSuites(CipherSpecCount
,
583 /* use the ones specified in SSLSetEnabledCiphers() */
584 return cipherSpecsToCipherSuites(ctx
->numValidCipherSpecs
,
585 ctx
->validCipherSpecs
,
592 *** End of publically exported functions declared in SecureTransport.h
596 * Given a valid ctx->selectedCipher and ctx->validCipherSpecs, set
597 * ctx->selectedCipherSpec as appropriate.
600 FindCipherSpec(SSLContext
*ctx
)
606 assert(ctx
->validCipherSpecs
!= NULL
);
608 ctx
->selectedCipherSpec
= NULL
;
609 for (i
=0; i
<ctx
->numValidCipherSpecs
; i
++)
610 { if (ctx
->validCipherSpecs
[i
].cipherSpec
== ctx
->selectedCipher
) {
611 ctx
->selectedCipherSpec
= &ctx
->validCipherSpecs
[i
];
615 if (ctx
->selectedCipherSpec
== NULL
) /* Not found */
616 return errSSLNegotiation
;
618 /* make sure we're configured to handle this one */
619 return sslVerifyNegotiatedCipher(ctx
);