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: CDSA-based symmetric cipher module
24 Written by: Doug Mitchell, based on Netscape RSARef 3.0
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
29 /* *********************************************************************
32 SSLRef 3.0 Final -- 11/19/96
34 Copyright (c)1996 by Netscape Communications Corp.
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
44 *********************************************************************
46 File: ciphers.c Data structures for handling supported ciphers
48 Contains a table mapping cipherSuite values to the ciphers, MAC
49 algorithms, key exchange procedures and so on that are used for that
50 algorithm, in order of preference.
52 ****************************************************************** */
55 #include "cryptType.h"
58 #include "appleCdsa.h"
59 #include "symCipher.h"
61 #include <Security/cssm.h>
65 /* dispose of dynamically allocated resources in a CipherContext */
66 static void disposeCipherCtx(
67 CipherContext
*cipherCtx
)
69 CASSERT(cipherCtx
!= NULL
);
70 if(cipherCtx
->symKey
!= NULL
) {
71 CASSERT(cipherCtx
->cspHand
!= 0);
72 CSSM_FreeKey(cipherCtx
->cspHand
, NULL
, cipherCtx
->symKey
, CSSM_FALSE
);
73 sslFree(cipherCtx
->symKey
);
74 cipherCtx
->symKey
= NULL
;
76 cipherCtx
->cspHand
= 0;
77 if(cipherCtx
->ccHand
!= 0) {
78 CSSM_DeleteContext(cipherCtx
->ccHand
);
79 cipherCtx
->ccHand
= 0;
86 CipherContext
*cipherCtx
,
90 * Cook up a symmetric key and a CCSM_CC_HANDLE. Assumes:
91 * cipherCtx->symCipher.keyAlg
95 * Resulting CSSM_KEY_PTR --> cipherCtx->symKey
96 * Resulting CSSM_CC_HANDLE --> cipherCtx->ccHand
97 * (Currently) a copy of ctx->cspHand --> cipherCtx->cspHand
99 * FIXME - for now we assume that ctx->cspHand is capable of
100 * using the specified algorithm, keysize, and mode. This
101 * may need revisiting.
104 SSLErr serr
= SSLInternalError
;
106 const SSLSymmetricCipher
*symCipher
;
108 CSSM_DATA_PTR ivDataPtr
= NULL
;
109 CSSM_KEY_PTR symKey
= NULL
;
110 CSSM_CC_HANDLE ccHand
= 0;
111 CSSM_KEYHEADER_PTR hdr
;
114 CASSERT(cipherCtx
!= NULL
);
115 CASSERT(cipherCtx
->symCipher
!= NULL
);
116 CASSERT(ctx
!= NULL
);
117 if(ctx
->cspHand
== 0) {
118 errorLog0("CDSASymmInit: NULL cspHand!\n");
119 return SSLInternalError
;
122 /* clean up cipherCtx */
123 disposeCipherCtx(cipherCtx
);
125 /* cook up a raw key */
126 symKey
= sslMalloc(sizeof(CSSM_KEY
));
130 memset(symKey
, 0, sizeof(CSSM_KEY
));
131 serr
= stSetUpCssmData(&symKey
->KeyData
, cipherCtx
->symCipher
->keySize
);
136 memmove(symKey
->KeyData
.Data
, key
, cipherCtx
->symCipher
->keySize
);
138 /* set up the header */
139 hdr
= &symKey
->KeyHeader
;
140 hdr
->BlobType
= CSSM_KEYBLOB_RAW
;
141 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
142 hdr
->AlgorithmId
= cipherCtx
->symCipher
->keyAlg
;
143 hdr
->KeyClass
= CSSM_KEYCLASS_SESSION_KEY
;
144 hdr
->LogicalKeySizeInBits
= cipherCtx
->symCipher
->keySize
* 8;
145 hdr
->KeyAttr
= CSSM_KEYATTR_MODIFIABLE
| CSSM_KEYATTR_EXTRACTABLE
;
146 hdr
->KeyUsage
= CSSM_KEYUSE_ENCRYPT
| CSSM_KEYUSE_DECRYPT
;
147 hdr
->WrapAlgorithmId
= CSSM_ALGID_NONE
;
149 cipherCtx
->symKey
= symKey
;
151 /* now the crypt handle */
152 symCipher
= cipherCtx
->symCipher
;
153 if(symCipher
->ivSize
!= 0) {
155 ivData
.Length
= symCipher
->ivSize
;
158 crtn
= CSSM_CSP_CreateSymmetricContext(ctx
->cspHand
,
168 stPrintCdsaError("CSSM_CSP_CreateSymmetricContext", crtn
);
169 serr
= SSLCryptoError
;
172 cipherCtx
->ccHand
= ccHand
;
174 /* after this, each en/decrypt is merely an update */
175 if(cipherCtx
->encrypting
) {
176 crtn
= CSSM_EncryptDataInit(ccHand
);
177 op
= "CSSM_EncryptDataInit";
180 crtn
= CSSM_DecryptDataInit(ccHand
);
181 op
= "CSSM_DecryptDataInit";
184 stPrintCdsaError("CSSM_CSP_EncryptDataInit", crtn
);
185 serr
= SSLCryptoError
;
190 cipherCtx
->cspHand
= ctx
->cspHand
;
195 /* dispose of the stuff we created */
196 disposeCipherCtx(cipherCtx
);
201 #define REDECRYPT_DATA 0
203 #define LOG_SYMM_DATA 0
205 static void logSymmData(
212 printf("%s: ", field
);
213 for(i
=0; i
<data
->length
; i
++) {
217 printf("%02X", data
->data
[i
]);
224 #else /* LOG_SYMM_DATA */
225 #define logSymmData(f, d, l)
226 #endif /* LOG_SYMM_DATA */
228 #define IS_ALIGNED(count, blockSize) ((count % blockSize) == 0)
230 SSLErr
CDSASymmEncrypt(
233 CipherContext
*cipherCtx
,
238 CSSM_DATA ctextData
= {0, NULL
};
239 uint32 bytesEncrypted
;
240 SSLErr serr
= SSLInternalError
;
247 CASSERT(ctx
!= NULL
);
248 CASSERT(cipherCtx
!= NULL
);
249 logSymmData("Symm encrypt ptext", &src
, 48);
253 unsigned blockSize
= cipherCtx
->symCipher
->blockSize
;
255 if(!IS_ALIGNED(src
.length
, blockSize
)) {
256 errorLog2("CDSASymmEncrypt: unaligned ptext (len %ld bs %d)\n",
257 src
.length
, blockSize
);
258 return SSLInternalError
;
260 if(!IS_ALIGNED(dest
.length
, blockSize
)) {
261 errorLog2("CDSASymmEncrypt: unaligned ctext (len %ld bs %d)\n",
262 dest
.length
, blockSize
);
263 return SSLInternalError
;
269 if((cipherCtx
->ccHand
== 0) || (cipherCtx
->cspHand
== 0)) {
270 errorLog0("CDSASymmEncrypt: null args\n");
271 return SSLInternalError
;
273 SSLBUF_TO_CSSM(&src
, &ptextData
);
274 crtn
= CSSM_EncryptDataUpdate(cipherCtx
->ccHand
,
281 stPrintCdsaError("CSSM_EncryptDataUpdate", crtn
);
282 serr
= SSLCryptoError
;
286 if(bytesEncrypted
> dest
.length
) {
287 /* FIXME - can this happen? Should we remalloc? */
288 errorLog2("Symmetric encrypt overflow: bytesEncrypted %ld destLen %ld\n",
289 bytesEncrypted
, dest
.length
);
290 serr
= SSLDataOverflow
;
294 memmove(dest
.data
, ctextData
.Data
, bytesEncrypted
);
296 dest
.length
= bytesEncrypted
;
298 /* CSP mallocd ctext */
299 /* FIXME - once we're really sure that the caller always mallocs
300 * dest.data, we should avoid this malloc/copy */
301 stFreeCssmData(&ctextData
, CSSM_FALSE
);
303 /* FIXME - sure we don't need to do Final()? */
305 logSymmData("Symm encrypt ctext", &dest
, 48);
312 SSLErr
CDSASymmDecrypt(
315 CipherContext
*cipherCtx
,
319 CSSM_DATA ptextData
= {0, NULL
};
321 uint32 bytesDecrypted
;
322 SSLErr serr
= SSLInternalError
;
329 CASSERT(ctx
!= NULL
);
330 CASSERT(cipherCtx
!= NULL
);
331 if((cipherCtx
->ccHand
== 0) || (cipherCtx
->cspHand
== 0)) {
332 errorLog0("CDSASymmDecrypt: null args\n");
333 return SSLInternalError
;
338 unsigned blockSize
= cipherCtx
->symCipher
->blockSize
;
340 if(!IS_ALIGNED(src
.length
, blockSize
)) {
341 errorLog2("CDSASymmDecrypt: unaligned ctext (len %ld bs %d)\n",
342 src
.length
, blockSize
);
343 return SSLInternalError
;
345 if(!IS_ALIGNED(dest
.length
, blockSize
)) {
346 errorLog2("CDSASymmDecrypt: unaligned ptext (len %ld bs %d)\n",
347 dest
.length
, blockSize
);
348 return SSLInternalError
;
354 SSLBUF_TO_CSSM(&src
, &ctextData
);
355 crtn
= CSSM_DecryptDataUpdate(cipherCtx
->ccHand
,
362 stPrintCdsaError("CSSM_DecryptDataUpdate", crtn
);
363 serr
= SSLCryptoError
;
367 if(bytesDecrypted
> dest
.length
) {
368 /* FIXME - can this happen? Should we remalloc? */
369 errorLog2("Symmetric decrypt overflow: bytesDecrypted %ld destLen %ld\n",
370 bytesDecrypted
, dest
.length
);
371 serr
= SSLDataOverflow
;
376 memmove(dest
.data
, ptextData
.Data
, bytesDecrypted
);
379 /* CSP mallocd ptext, remData */
380 stFreeCssmData(&ptextData
, CSSM_FALSE
);
382 dest
.length
= bytesDecrypted
;
384 logSymmData("Symm decrypt ptext(1)", &dest
, 48);
389 SSLErr
CDSASymmFinish(
390 CipherContext
*cipherCtx
,
393 /* dispose of cipherCtx->{symKey,cspHand,ccHand} */
394 disposeCipherCtx(cipherCtx
);