]> git.saurik.com Git - apple/security.git/blob - SecureTransport/symCipher.c
Security-29.tar.gz
[apple/security.git] / SecureTransport / symCipher.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 /*
20 File: symCipher.c
21
22 Contains: CDSA-based symmetric cipher module
23
24 Written by: Doug Mitchell, based on Netscape RSARef 3.0
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29 /* *********************************************************************
30 File: ciphers.c
31
32 SSLRef 3.0 Final -- 11/19/96
33
34 Copyright (c)1996 by Netscape Communications Corp.
35
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.
39
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/>.
43
44 *********************************************************************
45
46 File: ciphers.c Data structures for handling supported ciphers
47
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.
51
52 ****************************************************************** */
53
54 #include "sslctx.h"
55 #include "cryptType.h"
56 #include "sslDebug.h"
57 #include "sslalloc.h"
58 #include "appleCdsa.h"
59 #include "symCipher.h"
60
61 #include <Security/cssm.h>
62
63 #include <string.h>
64
65 /* dispose of dynamically allocated resources in a CipherContext */
66 static void disposeCipherCtx(
67 CipherContext *cipherCtx)
68 {
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;
75 }
76 cipherCtx->cspHand = 0;
77 if(cipherCtx->ccHand != 0) {
78 CSSM_DeleteContext(cipherCtx->ccHand);
79 cipherCtx->ccHand = 0;
80 }
81 }
82
83 SSLErr CDSASymmInit(
84 uint8 *key,
85 uint8* iv,
86 CipherContext *cipherCtx,
87 SSLContext *ctx)
88 {
89 /*
90 * Cook up a symmetric key and a CCSM_CC_HANDLE. Assumes:
91 * cipherCtx->symCipher.keyAlg
92 * ctx->cspHand
93 * key (raw key bytes)
94 * On successful exit:
95 * Resulting CSSM_KEY_PTR --> cipherCtx->symKey
96 * Resulting CSSM_CC_HANDLE --> cipherCtx->ccHand
97 * (Currently) a copy of ctx->cspHand --> cipherCtx->cspHand
98 *
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.
102 */
103
104 SSLErr serr = SSLInternalError;
105 CSSM_RETURN crtn;
106 const SSLSymmetricCipher *symCipher;
107 CSSM_DATA ivData;
108 CSSM_DATA_PTR ivDataPtr = NULL;
109 CSSM_KEY_PTR symKey = NULL;
110 CSSM_CC_HANDLE ccHand = 0;
111 CSSM_KEYHEADER_PTR hdr;
112 char *op;
113
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;
120 }
121
122 /* clean up cipherCtx */
123 disposeCipherCtx(cipherCtx);
124
125 /* cook up a raw key */
126 symKey = sslMalloc(sizeof(CSSM_KEY));
127 if(symKey == NULL) {
128 return SSLMemoryErr;
129 }
130 memset(symKey, 0, sizeof(CSSM_KEY));
131 serr = stSetUpCssmData(&symKey->KeyData, cipherCtx->symCipher->keySize);
132 if(serr) {
133 sslFree(symKey);
134 return serr;
135 }
136 memmove(symKey->KeyData.Data, key, cipherCtx->symCipher->keySize);
137
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;
148
149 cipherCtx->symKey = symKey;
150
151 /* now the crypt handle */
152 symCipher = cipherCtx->symCipher;
153 if(symCipher->ivSize != 0) {
154 ivData.Data = iv;
155 ivData.Length = symCipher->ivSize;
156 ivDataPtr = &ivData;
157 }
158 crtn = CSSM_CSP_CreateSymmetricContext(ctx->cspHand,
159 symCipher->encrAlg,
160 symCipher->encrMode,
161 NULL,
162 symKey,
163 ivDataPtr,
164 symCipher->encrPad,
165 0, // Params
166 &ccHand);
167 if(crtn) {
168 stPrintCdsaError("CSSM_CSP_CreateSymmetricContext", crtn);
169 serr = SSLCryptoError;
170 goto errOut;
171 }
172 cipherCtx->ccHand = ccHand;
173
174 /* after this, each en/decrypt is merely an update */
175 if(cipherCtx->encrypting) {
176 crtn = CSSM_EncryptDataInit(ccHand);
177 op = "CSSM_EncryptDataInit";
178 }
179 else {
180 crtn = CSSM_DecryptDataInit(ccHand);
181 op = "CSSM_DecryptDataInit";
182 }
183 if(crtn) {
184 stPrintCdsaError("CSSM_CSP_EncryptDataInit", crtn);
185 serr = SSLCryptoError;
186 goto errOut;
187 }
188
189 /* success */
190 cipherCtx->cspHand = ctx->cspHand;
191 serr = SSLNoErr;
192
193 errOut:
194 if(serr) {
195 /* dispose of the stuff we created */
196 disposeCipherCtx(cipherCtx);
197 }
198 return serr;
199 }
200
201 #define REDECRYPT_DATA 0
202
203 #define LOG_SYMM_DATA 0
204 #if LOG_SYMM_DATA
205 static void logSymmData(
206 char *field,
207 SSLBuffer *data,
208 int maxLen)
209 {
210 int i;
211
212 printf("%s: ", field);
213 for(i=0; i<data->length; i++) {
214 if(i == maxLen) {
215 break;
216 }
217 printf("%02X", data->data[i]);
218 if((i % 4) == 3) {
219 printf(" ");
220 }
221 }
222 printf("\n");
223 }
224 #else /* LOG_SYMM_DATA */
225 #define logSymmData(f, d, l)
226 #endif /* LOG_SYMM_DATA */
227
228 #define IS_ALIGNED(count, blockSize) ((count % blockSize) == 0)
229
230 SSLErr CDSASymmEncrypt(
231 SSLBuffer src,
232 SSLBuffer dest,
233 CipherContext *cipherCtx,
234 SSLContext *ctx)
235 {
236 CSSM_RETURN crtn;
237 CSSM_DATA ptextData;
238 CSSM_DATA ctextData = {0, NULL};
239 uint32 bytesEncrypted;
240 SSLErr serr = SSLInternalError;
241
242 /*
243 * Valid on entry:
244 * cipherCtx->ccHand
245 * cipherCtx->cspHand
246 */
247 CASSERT(ctx != NULL);
248 CASSERT(cipherCtx != NULL);
249 logSymmData("Symm encrypt ptext", &src, 48);
250
251 #if SSL_DEBUG
252 {
253 unsigned blockSize = cipherCtx->symCipher->blockSize;
254 if(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;
259 }
260 if(!IS_ALIGNED(dest.length, blockSize)) {
261 errorLog2("CDSASymmEncrypt: unaligned ctext (len %ld bs %d)\n",
262 dest.length, blockSize);
263 return SSLInternalError;
264 }
265 }
266 }
267 #endif
268
269 if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) {
270 errorLog0("CDSASymmEncrypt: null args\n");
271 return SSLInternalError;
272 }
273 SSLBUF_TO_CSSM(&src, &ptextData);
274 crtn = CSSM_EncryptDataUpdate(cipherCtx->ccHand,
275 &ptextData,
276 1,
277 &ctextData,
278 1,
279 &bytesEncrypted);
280 if(crtn) {
281 stPrintCdsaError("CSSM_EncryptDataUpdate", crtn);
282 serr = SSLCryptoError;
283 goto errOut;
284 }
285
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;
291 goto errOut;
292 }
293 if(bytesEncrypted) {
294 memmove(dest.data, ctextData.Data, bytesEncrypted);
295 }
296 dest.length = bytesEncrypted;
297
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);
302
303 /* FIXME - sure we don't need to do Final()? */
304
305 logSymmData("Symm encrypt ctext", &dest, 48);
306 serr = SSLNoErr;
307
308 errOut:
309 return serr;
310 }
311
312 SSLErr CDSASymmDecrypt(
313 SSLBuffer src,
314 SSLBuffer dest,
315 CipherContext *cipherCtx,
316 SSLContext *ctx)
317 {
318 CSSM_RETURN crtn;
319 CSSM_DATA ptextData = {0, NULL};
320 CSSM_DATA ctextData;
321 uint32 bytesDecrypted;
322 SSLErr serr = SSLInternalError;
323
324 /*
325 * Valid on entry:
326 * cipherCtx->cspHand
327 * cipherCtx->ccHand
328 */
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;
334 }
335
336 #if SSL_DEBUG
337 {
338 unsigned blockSize = cipherCtx->symCipher->blockSize;
339 if(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;
344 }
345 if(!IS_ALIGNED(dest.length, blockSize)) {
346 errorLog2("CDSASymmDecrypt: unaligned ptext (len %ld bs %d)\n",
347 dest.length, blockSize);
348 return SSLInternalError;
349 }
350 }
351 }
352 #endif
353
354 SSLBUF_TO_CSSM(&src, &ctextData);
355 crtn = CSSM_DecryptDataUpdate(cipherCtx->ccHand,
356 &ctextData,
357 1,
358 &ptextData,
359 1,
360 &bytesDecrypted);
361 if(crtn) {
362 stPrintCdsaError("CSSM_DecryptDataUpdate", crtn);
363 serr = SSLCryptoError;
364 goto errOut;
365 }
366
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;
372 goto errOut;
373 }
374
375 if(bytesDecrypted) {
376 memmove(dest.data, ptextData.Data, bytesDecrypted);
377 }
378
379 /* CSP mallocd ptext, remData */
380 stFreeCssmData(&ptextData, CSSM_FALSE);
381
382 dest.length = bytesDecrypted;
383 serr = SSLNoErr;
384 logSymmData("Symm decrypt ptext(1)", &dest, 48);
385 errOut:
386 return serr;
387 }
388
389 SSLErr CDSASymmFinish(
390 CipherContext *cipherCtx,
391 SSLContext *ctx)
392 {
393 /* dispose of cipherCtx->{symKey,cspHand,ccHand} */
394 disposeCipherCtx(cipherCtx);
395 return SSLNoErr;
396 }
397