]> git.saurik.com Git - apple/security.git/blob - SecureTransport/symCipher.cpp
Security-54.1.3.tar.gz
[apple/security.git] / SecureTransport / symCipher.cpp
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
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29
30 #include "sslContext.h"
31 #include "cryptType.h"
32 #include "sslDebug.h"
33 #include "sslMemory.h"
34 #include "appleCdsa.h"
35 #include "symCipher.h"
36
37 #include <Security/cssm.h>
38
39 #include <string.h>
40
41 /* dispose of dynamically allocated resources in a CipherContext */
42 static void disposeCipherCtx(
43 CipherContext *cipherCtx)
44 {
45 assert(cipherCtx != NULL);
46 if(cipherCtx->symKey != NULL) {
47 assert(cipherCtx->cspHand != 0);
48 CSSM_FreeKey(cipherCtx->cspHand, NULL, cipherCtx->symKey, CSSM_FALSE);
49 sslFree(cipherCtx->symKey);
50 cipherCtx->symKey = NULL;
51 }
52 cipherCtx->cspHand = 0;
53 if(cipherCtx->ccHand != 0) {
54 CSSM_DeleteContext(cipherCtx->ccHand);
55 cipherCtx->ccHand = 0;
56 }
57 }
58
59 OSStatus CDSASymmInit(
60 uint8 *key,
61 uint8* iv,
62 CipherContext *cipherCtx,
63 SSLContext *ctx)
64 {
65 /*
66 * Cook up a symmetric key and a CCSM_CC_HANDLE. Assumes:
67 * cipherCtx->symCipher.keyAlg
68 * ctx->cspHand
69 * key (raw key bytes)
70 * On successful exit:
71 * Resulting CSSM_KEY_PTR --> cipherCtx->symKey
72 * Resulting CSSM_CC_HANDLE --> cipherCtx->ccHand
73 * (Currently) a copy of ctx->cspHand --> cipherCtx->cspHand
74 *
75 * FIXME - for now we assume that ctx->cspHand is capable of
76 * using the specified algorithm, keysize, and mode. This
77 * may need revisiting.
78 */
79
80 OSStatus serr = errSSLInternal;
81 CSSM_RETURN crtn;
82 const SSLSymmetricCipher *symCipher;
83 CSSM_DATA ivData;
84 CSSM_DATA_PTR ivDataPtr = NULL;
85 CSSM_KEY_PTR symKey = NULL;
86 CSSM_CC_HANDLE ccHand = 0;
87 char *op;
88
89 assert(cipherCtx != NULL);
90 assert(cipherCtx->symCipher != NULL);
91 assert(ctx != NULL);
92 if(ctx->cspHand == 0) {
93 sslErrorLog("CDSASymmInit: NULL cspHand!\n");
94 return errSSLInternal;
95 }
96
97 /* clean up cipherCtx */
98 disposeCipherCtx(cipherCtx);
99
100 /* cook up a raw key */
101 symKey = (CSSM_KEY_PTR)sslMalloc(sizeof(CSSM_KEY));
102 if(symKey == NULL) {
103 return memFullErr;
104 }
105 serr = sslSetUpSymmKey(symKey, cipherCtx->symCipher->keyAlg,
106 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, CSSM_TRUE,
107 key, cipherCtx->symCipher->keySize);
108 if(serr) {
109 sslFree(symKey);
110 return serr;
111 }
112
113 cipherCtx->symKey = symKey;
114
115 /* now the crypt handle */
116 symCipher = cipherCtx->symCipher;
117 if(symCipher->ivSize != 0) {
118 ivData.Data = iv;
119 ivData.Length = symCipher->ivSize;
120 ivDataPtr = &ivData;
121 }
122 crtn = CSSM_CSP_CreateSymmetricContext(ctx->cspHand,
123 symCipher->encrAlg,
124 symCipher->encrMode,
125 NULL,
126 symKey,
127 ivDataPtr,
128 symCipher->encrPad,
129 0, // Params
130 &ccHand);
131 if(crtn) {
132 stPrintCdsaError("CSSM_CSP_CreateSymmetricContext", crtn);
133 serr = errSSLCrypto;
134 goto errOut;
135 }
136 cipherCtx->ccHand = ccHand;
137
138 /* after this, each en/decrypt is merely an update */
139 if(cipherCtx->encrypting) {
140 crtn = CSSM_EncryptDataInit(ccHand);
141 op = "CSSM_EncryptDataInit";
142 }
143 else {
144 crtn = CSSM_DecryptDataInit(ccHand);
145 op = "CSSM_DecryptDataInit";
146 }
147 if(crtn) {
148 stPrintCdsaError("CSSM_CSP_EncryptDataInit", crtn);
149 serr = errSSLCrypto;
150 goto errOut;
151 }
152
153 /* success */
154 cipherCtx->cspHand = ctx->cspHand;
155 serr = noErr;
156
157 errOut:
158 if(serr) {
159 /* dispose of the stuff we created */
160 disposeCipherCtx(cipherCtx);
161 }
162 return serr;
163 }
164
165 #define REDECRYPT_DATA 0
166
167 #define LOG_SYMM_DATA 0
168 #if LOG_SYMM_DATA
169 static void logSymmData(
170 char *field,
171 SSLBuffer *data,
172 int maxLen)
173 {
174 int i;
175
176 printf("%s: ", field);
177 for(i=0; i<data->length; i++) {
178 if(i == maxLen) {
179 break;
180 }
181 printf("%02X", data->data[i]);
182 if((i % 4) == 3) {
183 printf(" ");
184 }
185 }
186 printf("\n");
187 }
188 #else /* LOG_SYMM_DATA */
189 #define logSymmData(f, d, l)
190 #endif /* LOG_SYMM_DATA */
191
192 #define IS_ALIGNED(count, blockSize) ((count % blockSize) == 0)
193
194 OSStatus CDSASymmEncrypt(
195 SSLBuffer src,
196 SSLBuffer dest,
197 CipherContext *cipherCtx,
198 SSLContext *ctx)
199 {
200 CSSM_RETURN crtn;
201 CSSM_DATA ptextData;
202 CSSM_DATA ctextData;
203 uint32 bytesEncrypted;
204 OSStatus serr = errSSLInternal;
205 uint32 origLen = dest.length;
206
207 /*
208 * Valid on entry:
209 * cipherCtx->ccHand
210 * cipherCtx->cspHand
211 */
212 assert(ctx != NULL);
213 assert(cipherCtx != NULL);
214 logSymmData("Symm encrypt ptext", &src, 48);
215
216 /* this requirement allows us to avoid a malloc and copy */
217 assert(dest.length >= src.length);
218
219 #if SSL_DEBUG
220 {
221 unsigned blockSize = cipherCtx->symCipher->blockSize;
222 if(blockSize) {
223 if(!IS_ALIGNED(src.length, blockSize)) {
224 sslErrorLog("CDSASymmEncrypt: unaligned ptext (len %ld bs %d)\n",
225 src.length, blockSize);
226 return errSSLInternal;
227 }
228 if(!IS_ALIGNED(dest.length, blockSize)) {
229 sslErrorLog("CDSASymmEncrypt: unaligned ctext (len %ld bs %d)\n",
230 dest.length, blockSize);
231 return errSSLInternal;
232 }
233 }
234 }
235 #endif
236
237 if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) {
238 sslErrorLog("CDSASymmEncrypt: null args\n");
239 return errSSLInternal;
240 }
241 SSLBUF_TO_CSSM(&src, &ptextData);
242 SSLBUF_TO_CSSM(&dest, &ctextData);
243 crtn = CSSM_EncryptDataUpdate(cipherCtx->ccHand,
244 &ptextData,
245 1,
246 &ctextData,
247 1,
248 &bytesEncrypted);
249 if(crtn) {
250 stPrintCdsaError("CSSM_EncryptDataUpdate", crtn);
251 serr = errSSLCrypto;
252 goto errOut;
253 }
254
255 if(bytesEncrypted > origLen) {
256 /* should never happen, callers always give us block-aligned
257 * plaintext and CSP padding is disabled. */
258 sslErrorLog("Symmetric encrypt overflow: bytesEncrypted %ld destLen %ld\n",
259 bytesEncrypted, dest.length);
260 serr = errSSLCrypto;
261 goto errOut;
262 }
263 dest.length = bytesEncrypted;
264 logSymmData("Symm encrypt ctext", &dest, 48);
265 serr = noErr;
266
267 errOut:
268 return serr;
269 }
270
271 OSStatus CDSASymmDecrypt(
272 SSLBuffer src,
273 SSLBuffer dest,
274 CipherContext *cipherCtx,
275 SSLContext *ctx)
276 {
277 CSSM_RETURN crtn;
278 CSSM_DATA ptextData = {0, NULL};
279 CSSM_DATA ctextData;
280 uint32 bytesDecrypted;
281 OSStatus serr = errSSLInternal;
282 uint32 origLen = dest.length;
283
284 /*
285 * Valid on entry:
286 * cipherCtx->cspHand
287 * cipherCtx->ccHand
288 */
289 assert(ctx != NULL);
290 assert(cipherCtx != NULL);
291 if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) {
292 sslErrorLog("CDSASymmDecrypt: null args\n");
293 return errSSLInternal;
294 }
295 /* this requirement allows us to avoid a malloc and copy */
296 assert(dest.length >= src.length);
297
298 #if SSL_DEBUG
299 {
300 unsigned blockSize = cipherCtx->symCipher->blockSize;
301 if(blockSize) {
302 if(!IS_ALIGNED(src.length, blockSize)) {
303 sslErrorLog("CDSASymmDecrypt: unaligned ctext (len %ld bs %d)\n",
304 src.length, blockSize);
305 return errSSLInternal;
306 }
307 if(!IS_ALIGNED(dest.length, blockSize)) {
308 sslErrorLog("CDSASymmDecrypt: unaligned ptext (len %ld bs %d)\n",
309 dest.length, blockSize);
310 return errSSLInternal;
311 }
312 }
313 }
314 #endif
315
316 SSLBUF_TO_CSSM(&src, &ctextData);
317 SSLBUF_TO_CSSM(&dest, &ptextData);
318 crtn = CSSM_DecryptDataUpdate(cipherCtx->ccHand,
319 &ctextData,
320 1,
321 &ptextData,
322 1,
323 &bytesDecrypted);
324 if(crtn) {
325 stPrintCdsaError("CSSM_DecryptDataUpdate", crtn);
326 serr = errSSLCrypto;
327 goto errOut;
328 }
329
330 if(bytesDecrypted > origLen) {
331 /* FIXME - can this happen? Should we remalloc? */
332 sslErrorLog("Symmetric decrypt overflow: bytesDecrypted %ld destLen %ld\n",
333 bytesDecrypted, dest.length);
334 serr = errSSLCrypto;
335 goto errOut;
336 }
337 dest.length = bytesDecrypted;
338 serr = noErr;
339 logSymmData("Symm decrypt ptext(1)", &dest, 48);
340 errOut:
341 return serr;
342 }
343
344 OSStatus CDSASymmFinish(
345 CipherContext *cipherCtx,
346 SSLContext *ctx)
347 {
348 /* dispose of cipherCtx->{symKey,cspHand,ccHand} */
349 disposeCipherCtx(cipherCtx);
350 return noErr;
351 }
352