]> git.saurik.com Git - apple/security.git/blob - SecureTransport/symCipher.c
a70b1d90e44f63bdaf1d31076031d3ff0ac3daa2
[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 SSLRef 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 char *op;
112
113 CASSERT(cipherCtx != NULL);
114 CASSERT(cipherCtx->symCipher != NULL);
115 CASSERT(ctx != NULL);
116 if(ctx->cspHand == 0) {
117 errorLog0("CDSASymmInit: NULL cspHand!\n");
118 return SSLInternalError;
119 }
120
121 /* clean up cipherCtx */
122 disposeCipherCtx(cipherCtx);
123
124 /* cook up a raw key */
125 symKey = sslMalloc(sizeof(CSSM_KEY));
126 if(symKey == NULL) {
127 return SSLMemoryErr;
128 }
129 serr = sslSetUpSymmKey(symKey, cipherCtx->symCipher->keyAlg,
130 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, CSSM_TRUE,
131 key, cipherCtx->symCipher->keySize);
132 if(serr) {
133 sslFree(symKey);
134 return serr;
135 }
136
137 cipherCtx->symKey = symKey;
138
139 /* now the crypt handle */
140 symCipher = cipherCtx->symCipher;
141 if(symCipher->ivSize != 0) {
142 ivData.Data = iv;
143 ivData.Length = symCipher->ivSize;
144 ivDataPtr = &ivData;
145 }
146 crtn = CSSM_CSP_CreateSymmetricContext(ctx->cspHand,
147 symCipher->encrAlg,
148 symCipher->encrMode,
149 NULL,
150 symKey,
151 ivDataPtr,
152 symCipher->encrPad,
153 0, // Params
154 &ccHand);
155 if(crtn) {
156 stPrintCdsaError("CSSM_CSP_CreateSymmetricContext", crtn);
157 serr = SSLCryptoError;
158 goto errOut;
159 }
160 cipherCtx->ccHand = ccHand;
161
162 /* after this, each en/decrypt is merely an update */
163 if(cipherCtx->encrypting) {
164 crtn = CSSM_EncryptDataInit(ccHand);
165 op = "CSSM_EncryptDataInit";
166 }
167 else {
168 crtn = CSSM_DecryptDataInit(ccHand);
169 op = "CSSM_DecryptDataInit";
170 }
171 if(crtn) {
172 stPrintCdsaError("CSSM_CSP_EncryptDataInit", crtn);
173 serr = SSLCryptoError;
174 goto errOut;
175 }
176
177 /* success */
178 cipherCtx->cspHand = ctx->cspHand;
179 serr = SSLNoErr;
180
181 errOut:
182 if(serr) {
183 /* dispose of the stuff we created */
184 disposeCipherCtx(cipherCtx);
185 }
186 return serr;
187 }
188
189 #define REDECRYPT_DATA 0
190
191 #define LOG_SYMM_DATA 0
192 #if LOG_SYMM_DATA
193 static void logSymmData(
194 char *field,
195 SSLBuffer *data,
196 int maxLen)
197 {
198 int i;
199
200 printf("%s: ", field);
201 for(i=0; i<data->length; i++) {
202 if(i == maxLen) {
203 break;
204 }
205 printf("%02X", data->data[i]);
206 if((i % 4) == 3) {
207 printf(" ");
208 }
209 }
210 printf("\n");
211 }
212 #else /* LOG_SYMM_DATA */
213 #define logSymmData(f, d, l)
214 #endif /* LOG_SYMM_DATA */
215
216 #define IS_ALIGNED(count, blockSize) ((count % blockSize) == 0)
217
218 SSLErr CDSASymmEncrypt(
219 SSLBuffer src,
220 SSLBuffer dest,
221 CipherContext *cipherCtx,
222 SSLContext *ctx)
223 {
224 CSSM_RETURN crtn;
225 CSSM_DATA ptextData;
226 CSSM_DATA ctextData;
227 uint32 bytesEncrypted;
228 SSLErr serr = SSLInternalError;
229 uint32 origLen = dest.length;
230
231 /*
232 * Valid on entry:
233 * cipherCtx->ccHand
234 * cipherCtx->cspHand
235 */
236 CASSERT(ctx != NULL);
237 CASSERT(cipherCtx != NULL);
238 logSymmData("Symm encrypt ptext", &src, 48);
239
240 /* this requirement allows us to avoid a malloc and copy */
241 CASSERT(dest.length >= src.length);
242
243 #if SSL_DEBUG
244 {
245 unsigned blockSize = cipherCtx->symCipher->blockSize;
246 if(blockSize) {
247 if(!IS_ALIGNED(src.length, blockSize)) {
248 errorLog2("CDSASymmEncrypt: unaligned ptext (len %ld bs %d)\n",
249 src.length, blockSize);
250 return SSLInternalError;
251 }
252 if(!IS_ALIGNED(dest.length, blockSize)) {
253 errorLog2("CDSASymmEncrypt: unaligned ctext (len %ld bs %d)\n",
254 dest.length, blockSize);
255 return SSLInternalError;
256 }
257 }
258 }
259 #endif
260
261 if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) {
262 errorLog0("CDSASymmEncrypt: null args\n");
263 return SSLInternalError;
264 }
265 SSLBUF_TO_CSSM(&src, &ptextData);
266 SSLBUF_TO_CSSM(&dest, &ctextData);
267 crtn = CSSM_EncryptDataUpdate(cipherCtx->ccHand,
268 &ptextData,
269 1,
270 &ctextData,
271 1,
272 &bytesEncrypted);
273 if(crtn) {
274 stPrintCdsaError("CSSM_EncryptDataUpdate", crtn);
275 serr = SSLCryptoError;
276 goto errOut;
277 }
278
279 if(bytesEncrypted > origLen) {
280 /* should never happen, callers always give us block-aligned
281 * plaintext and CSP padding is disabled. */
282 errorLog2("Symmetric encrypt overflow: bytesEncrypted %ld destLen %ld\n",
283 bytesEncrypted, dest.length);
284 serr = SSLDataOverflow;
285 goto errOut;
286 }
287 dest.length = bytesEncrypted;
288 logSymmData("Symm encrypt ctext", &dest, 48);
289 serr = SSLNoErr;
290
291 errOut:
292 return serr;
293 }
294
295 SSLErr CDSASymmDecrypt(
296 SSLBuffer src,
297 SSLBuffer dest,
298 CipherContext *cipherCtx,
299 SSLContext *ctx)
300 {
301 CSSM_RETURN crtn;
302 CSSM_DATA ptextData = {0, NULL};
303 CSSM_DATA ctextData;
304 uint32 bytesDecrypted;
305 SSLErr serr = SSLInternalError;
306 uint32 origLen = dest.length;
307
308 /*
309 * Valid on entry:
310 * cipherCtx->cspHand
311 * cipherCtx->ccHand
312 */
313 CASSERT(ctx != NULL);
314 CASSERT(cipherCtx != NULL);
315 if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) {
316 errorLog0("CDSASymmDecrypt: null args\n");
317 return SSLInternalError;
318 }
319 /* this requirement allows us to avoid a malloc and copy */
320 CASSERT(dest.length >= src.length);
321
322 #if SSL_DEBUG
323 {
324 unsigned blockSize = cipherCtx->symCipher->blockSize;
325 if(blockSize) {
326 if(!IS_ALIGNED(src.length, blockSize)) {
327 errorLog2("CDSASymmDecrypt: unaligned ctext (len %ld bs %d)\n",
328 src.length, blockSize);
329 return SSLInternalError;
330 }
331 if(!IS_ALIGNED(dest.length, blockSize)) {
332 errorLog2("CDSASymmDecrypt: unaligned ptext (len %ld bs %d)\n",
333 dest.length, blockSize);
334 return SSLInternalError;
335 }
336 }
337 }
338 #endif
339
340 SSLBUF_TO_CSSM(&src, &ctextData);
341 SSLBUF_TO_CSSM(&dest, &ptextData);
342 crtn = CSSM_DecryptDataUpdate(cipherCtx->ccHand,
343 &ctextData,
344 1,
345 &ptextData,
346 1,
347 &bytesDecrypted);
348 if(crtn) {
349 stPrintCdsaError("CSSM_DecryptDataUpdate", crtn);
350 serr = SSLCryptoError;
351 goto errOut;
352 }
353
354 if(bytesDecrypted > origLen) {
355 /* FIXME - can this happen? Should we remalloc? */
356 errorLog2("Symmetric decrypt overflow: bytesDecrypted %ld destLen %ld\n",
357 bytesDecrypted, dest.length);
358 serr = SSLDataOverflow;
359 goto errOut;
360 }
361 dest.length = bytesDecrypted;
362 serr = SSLNoErr;
363 logSymmData("Symm decrypt ptext(1)", &dest, 48);
364 errOut:
365 return serr;
366 }
367
368 SSLErr CDSASymmFinish(
369 CipherContext *cipherCtx,
370 SSLContext *ctx)
371 {
372 /* dispose of cipherCtx->{symKey,cspHand,ccHand} */
373 disposeCipherCtx(cipherCtx);
374 return SSLNoErr;
375 }
376