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, based on Netscape RSARef 3.0
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
31 #include "cryptType.h"
32 #include "symCipher.h"
33 #include "cipherSpecs.h"
39 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
41 /* FIXME - domestic suites do not work in server side in level 3 */
43 #define ENABLE_3DES 1 /* normally enabled, our first preference */
44 #define ENABLE_RC4 1 /* normally enabled, the most common one */
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
59 extern SSLSymmetricCipher SSLCipherNull
; /* in nullciph.c */
62 * The symmetric ciphers currently supported (in addition to the
63 * NULL cipher in nullciph.c).
66 static const SSLSymmetricCipher SSLCipherDES_CBC
= {
67 8, /* Key size in bytes */
68 8, /* Secret key size = 64 bits */
73 /* Note we don't want CSSM_ALGMODE_CBCPadIV8; our clients do that
83 static const SSLSymmetricCipher SSLCipherDES40_CBC
= {
84 8, /* Key size in bytes */
85 5, /* Secret key size = 40 bits */
97 #endif /* ENABLE_DES */
100 static const SSLSymmetricCipher SSLCipher3DES_CBC
= {
101 24, /* Key size in bytes */
102 24, /* Secret key size = 192 bits */
105 CSSM_ALGID_3DES_3KEY
, // key gen
106 CSSM_ALGID_3DES_3KEY_EDE
, // encryption
107 /* Note we don't want CSSM_ALGMODE_CBCPadIV8; our clients do that
109 CSSM_ALGMODE_CBC_IV8
,
116 #endif /* ENABLE_3DES */
119 static const SSLSymmetricCipher SSLCipherRC4_40
= {
120 16, /* Key size in bytes */
121 5, /* Secret key size = 40 bits */
134 static const SSLSymmetricCipher SSLCipherRC4_128
= {
135 16, /* Key size in bytes */
136 16, /* Secret key size = 128 bits */
148 #endif /* ENABLE_RC4 */
151 static const SSLSymmetricCipher SSLCipherRC2_40
= {
152 16, /* Key size in bytes */
153 5, /* Secret key size = 40 bits */
158 CSSM_ALGMODE_CBC_IV8
,
166 static const SSLSymmetricCipher SSLCipherRC2_128
= {
167 16, /* Key size in bytes */
168 16, /* Secret key size = 40 bits */
173 CSSM_ALGMODE_CBC_IV8
,
181 #endif /* ENABLE_RC2*/
184 /* Even if we don't support NULL_WITH_NULL_NULL for transport,
185 * we need a reference for startup */
186 const SSLCipherSpec SSL_NULL_WITH_NULL_NULL_CipherSpec
=
187 { SSL_NULL_WITH_NULL_NULL
,
195 * List of all CipherSpecs we implement. Depending on a context's
196 * exportable flag, not all of these might be available for use.
198 * FIXME - I'm not sure the distinction between e.g. SSL_RSA and SSL_RSA_EXPORT
199 * makes any sense here. See comments for the definition of
200 * KeyExchangeMethod in cryptType.h.
202 /* Order by preference, domestic first */
203 static const SSLCipherSpec KnownCipherSpecs
[] =
205 /*** domestic only ***/
206 #if ENABLE_RSA_3DES_SHA
208 SSL_RSA_WITH_3DES_EDE_CBC_SHA
,
215 #if ENABLE_RSA_3DES_MD5
217 SSL_RSA_WITH_3DES_EDE_CBC_MD5
,
224 #if ENABLE_RSA_RC4_SHA_NONEXPORT
226 SSL_RSA_WITH_RC4_128_SHA
,
233 #if ENABLE_RSA_RC4_MD5_NONEXPORT
235 SSL_RSA_WITH_RC4_128_MD5
,
242 #if ENABLE_RSA_DES_SHA_NONEXPORT
244 SSL_RSA_WITH_DES_CBC_SHA
,
251 #if ENABLE_RSA_DES_MD5_NONEXPORT
253 SSL_RSA_WITH_DES_CBC_MD5
,
261 #if ENABLE_RSA_RC4_MD5_EXPORT
263 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
271 /* Apple CSP doesn't support D-H yet */
273 SSL_DH_anon_WITH_RC4_128_MD5
,
280 #if ENABLE_RSA_DES_SHA_EXPORT
282 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
290 #if ENABLE_RSA_RC2_MD5_EXPORT
292 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
299 #if ENABLE_RSA_RC2_MD5_NONEXPORT
301 SSL_RSA_WITH_RC2_CBC_MD5
,
309 SSL_RSA_WITH_NULL_MD5
,
317 static const int CipherSpecCount
= sizeof(KnownCipherSpecs
) / sizeof(SSLCipherSpec
);
320 * Build ctx->validCipherSpecs as a copy of KnownCipherSpecs, assuming that
321 * validCipherSpecs is currently not valid (i.e., SSLSetEnabledCiphers() has
324 SSLErr
sslBuildCipherSpecArray(SSLContext
*ctx
)
328 CASSERT(ctx
!= NULL
);
329 CASSERT(ctx
->validCipherSpecs
== NULL
);
331 ctx
->numValidCipherSpecs
= CipherSpecCount
;
332 size
= CipherSpecCount
* sizeof(SSLCipherSpec
);
333 ctx
->validCipherSpecs
= sslMalloc(size
);
334 if(ctx
->validCipherSpecs
== NULL
) {
335 ctx
->numValidCipherSpecs
= 0;
338 memmove(ctx
->validCipherSpecs
, KnownCipherSpecs
, size
);
343 * Convert an array of SSLCipherSpecs (which is either KnownCipherSpecs or
344 * ctx->validCipherSpecs) to an array of SSLCipherSuites.
347 cipherSpecsToCipherSuites(
348 UInt32 numCipherSpecs
, /* size of cipherSpecs */
349 const SSLCipherSpec
*cipherSpecs
,
350 SSLCipherSuite
*ciphers
, /* RETURNED */
351 UInt32
*numCiphers
) /* IN/OUT */
355 if(*numCiphers
< numCipherSpecs
) {
356 return errSSLBufferOverflow
;
358 for(dex
=0; dex
<numCipherSpecs
; dex
++) {
359 ciphers
[dex
] = cipherSpecs
[dex
].cipherSpec
;
361 *numCiphers
= numCipherSpecs
;
366 *** Publically exported functions declared in SecureTransport.h
370 * Determine number and values of all of the SSLCipherSuites we support.
371 * Caller allocates output buffer for SSLGetSupportedCiphers() and passes in
372 * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow
376 SSLGetNumberSupportedCiphers (SSLContextRef ctx
,
379 if((ctx
== NULL
) || (numCiphers
== NULL
)) {
382 *numCiphers
= CipherSpecCount
;
387 SSLGetSupportedCiphers (SSLContextRef ctx
,
388 SSLCipherSuite
*ciphers
, /* RETURNED */
389 UInt32
*numCiphers
) /* IN/OUT */
391 if((ctx
== NULL
) || (ciphers
== NULL
) || (numCiphers
== NULL
)) {
394 return cipherSpecsToCipherSuites(CipherSpecCount
,
401 * Specify a (typlically) restricted set of SSLCipherSuites to be enabled by
402 * the current SSLContext. Can only be called when no session is active. Default
403 * set of enabled SSLCipherSuites is the same as the complete set of supported
404 * SSLCipherSuites as obtained by SSLGetSupportedCiphers().
407 SSLSetEnabledCiphers (SSLContextRef ctx
,
408 const SSLCipherSuite
*ciphers
,
415 if((ctx
== NULL
) || (ciphers
== NULL
) || (numCiphers
== 0)) {
418 if(sslIsSessionActive(ctx
)) {
419 /* can't do this with an active session */
422 size
= numCiphers
* sizeof(SSLCipherSpec
);
423 ctx
->validCipherSpecs
= sslMalloc(size
);
424 if(ctx
->validCipherSpecs
== NULL
) {
425 ctx
->numValidCipherSpecs
= 0;
430 * Run thru caller's specs, finding a matching SSLCipherSpec for each one.
431 * If caller specifies one we don't know about, abort.
433 for(callerDex
=0; callerDex
<numCiphers
; callerDex
++) {
434 /* find matching CipherSpec in our known table */
436 for(tableDex
=0; tableDex
<CipherSpecCount
; tableDex
++) {
437 if(ciphers
[callerDex
] == KnownCipherSpecs
[tableDex
].cipherSpec
) {
438 ctx
->validCipherSpecs
[callerDex
] = KnownCipherSpecs
[tableDex
];
444 /* caller specified one we don't implement */
445 sslFree(ctx
->validCipherSpecs
);
446 ctx
->validCipherSpecs
= NULL
;
447 return errSSLBadCipherSuite
;
452 ctx
->numValidCipherSpecs
= numCiphers
;
457 * Determine number and values of all of the SSLCipherSuites currently enabled.
458 * Caller allocates output buffer for SSLGetEnabledCiphers() and passes in
459 * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow
463 SSLGetNumberEnabledCiphers (SSLContextRef ctx
,
466 if((ctx
== NULL
) || (numCiphers
== NULL
)) {
469 if(ctx
->validCipherSpecs
== NULL
) {
470 /* hasn't been set; use default */
471 *numCiphers
= CipherSpecCount
;
474 /* caller set via SSLSetEnabledCiphers */
475 *numCiphers
= ctx
->numValidCipherSpecs
;
481 SSLGetEnabledCiphers (SSLContextRef ctx
,
482 SSLCipherSuite
*ciphers
, /* RETURNED */
483 UInt32
*numCiphers
) /* IN/OUT */
485 if((ctx
== NULL
) || (ciphers
== NULL
) || (numCiphers
== NULL
)) {
488 if(ctx
->validCipherSpecs
== NULL
) {
489 /* hasn't been set; use default */
490 return cipherSpecsToCipherSuites(CipherSpecCount
,
496 /* use the ones specified in SSLSetEnabledCiphers() */
497 return cipherSpecsToCipherSuites(ctx
->numValidCipherSpecs
,
498 ctx
->validCipherSpecs
,
505 *** End of publically exported functions declared in SecureTransport.h
509 * Given a valid ctx->selectedCipher and ctx->validCipherSpecs, set
510 * ctx->selectedCipherSpec as appropriate.
513 FindCipherSpec(SSLContext
*ctx
)
518 CASSERT(ctx
!= NULL
);
519 CASSERT(ctx
->validCipherSpecs
!= NULL
);
521 ctx
->selectedCipherSpec
= NULL
;
522 for (i
=0; i
<ctx
->numValidCipherSpecs
; i
++)
523 { if (ctx
->validCipherSpecs
[i
].cipherSpec
== ctx
->selectedCipher
) {
524 ctx
->selectedCipherSpec
= &ctx
->validCipherSpecs
[i
];
528 if (ctx
->selectedCipherSpec
== NULL
) /* Not found */
529 return SSLNegotiationErr
;