]>
Commit | Line | Data |
---|---|---|
bac41a7b A |
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 | ||
5a719ac8 | 24 | Written by: Doug Mitchell |
bac41a7b A |
25 | |
26 | Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved. | |
27 | ||
28 | */ | |
bac41a7b | 29 | |
5a719ac8 | 30 | #include "sslContext.h" |
bac41a7b A |
31 | #include "cryptType.h" |
32 | #include "sslDebug.h" | |
5a719ac8 | 33 | #include "sslMemory.h" |
bac41a7b A |
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 | { | |
5a719ac8 | 45 | assert(cipherCtx != NULL); |
bac41a7b | 46 | if(cipherCtx->symKey != NULL) { |
5a719ac8 | 47 | assert(cipherCtx->cspHand != 0); |
bac41a7b A |
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 | ||
5a719ac8 | 59 | OSStatus CDSASymmInit( |
bac41a7b A |
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 | ||
5a719ac8 | 80 | OSStatus serr = errSSLInternal; |
bac41a7b A |
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; | |
bac41a7b A |
87 | char *op; |
88 | ||
5a719ac8 A |
89 | assert(cipherCtx != NULL); |
90 | assert(cipherCtx->symCipher != NULL); | |
91 | assert(ctx != NULL); | |
bac41a7b | 92 | if(ctx->cspHand == 0) { |
5a719ac8 A |
93 | sslErrorLog("CDSASymmInit: NULL cspHand!\n"); |
94 | return errSSLInternal; | |
bac41a7b A |
95 | } |
96 | ||
97 | /* clean up cipherCtx */ | |
98 | disposeCipherCtx(cipherCtx); | |
99 | ||
100 | /* cook up a raw key */ | |
5a719ac8 | 101 | symKey = (CSSM_KEY_PTR)sslMalloc(sizeof(CSSM_KEY)); |
bac41a7b | 102 | if(symKey == NULL) { |
5a719ac8 | 103 | return memFullErr; |
bac41a7b | 104 | } |
29654253 A |
105 | serr = sslSetUpSymmKey(symKey, cipherCtx->symCipher->keyAlg, |
106 | CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, CSSM_TRUE, | |
107 | key, cipherCtx->symCipher->keySize); | |
bac41a7b A |
108 | if(serr) { |
109 | sslFree(symKey); | |
110 | return serr; | |
111 | } | |
bac41a7b A |
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); | |
5a719ac8 | 133 | serr = errSSLCrypto; |
bac41a7b A |
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); | |
5a719ac8 | 149 | serr = errSSLCrypto; |
bac41a7b A |
150 | goto errOut; |
151 | } | |
152 | ||
153 | /* success */ | |
154 | cipherCtx->cspHand = ctx->cspHand; | |
5a719ac8 | 155 | serr = noErr; |
bac41a7b A |
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 | ||
5a719ac8 | 194 | OSStatus CDSASymmEncrypt( |
bac41a7b A |
195 | SSLBuffer src, |
196 | SSLBuffer dest, | |
197 | CipherContext *cipherCtx, | |
198 | SSLContext *ctx) | |
199 | { | |
200 | CSSM_RETURN crtn; | |
201 | CSSM_DATA ptextData; | |
29654253 | 202 | CSSM_DATA ctextData; |
bac41a7b | 203 | uint32 bytesEncrypted; |
5a719ac8 | 204 | OSStatus serr = errSSLInternal; |
29654253 | 205 | uint32 origLen = dest.length; |
bac41a7b A |
206 | |
207 | /* | |
208 | * Valid on entry: | |
209 | * cipherCtx->ccHand | |
210 | * cipherCtx->cspHand | |
211 | */ | |
5a719ac8 A |
212 | assert(ctx != NULL); |
213 | assert(cipherCtx != NULL); | |
bac41a7b A |
214 | logSymmData("Symm encrypt ptext", &src, 48); |
215 | ||
29654253 | 216 | /* this requirement allows us to avoid a malloc and copy */ |
5a719ac8 | 217 | assert(dest.length >= src.length); |
29654253 | 218 | |
bac41a7b A |
219 | #if SSL_DEBUG |
220 | { | |
221 | unsigned blockSize = cipherCtx->symCipher->blockSize; | |
222 | if(blockSize) { | |
223 | if(!IS_ALIGNED(src.length, blockSize)) { | |
5a719ac8 | 224 | sslErrorLog("CDSASymmEncrypt: unaligned ptext (len %ld bs %d)\n", |
bac41a7b | 225 | src.length, blockSize); |
5a719ac8 | 226 | return errSSLInternal; |
bac41a7b A |
227 | } |
228 | if(!IS_ALIGNED(dest.length, blockSize)) { | |
5a719ac8 | 229 | sslErrorLog("CDSASymmEncrypt: unaligned ctext (len %ld bs %d)\n", |
bac41a7b | 230 | dest.length, blockSize); |
5a719ac8 | 231 | return errSSLInternal; |
bac41a7b A |
232 | } |
233 | } | |
234 | } | |
235 | #endif | |
236 | ||
237 | if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) { | |
5a719ac8 A |
238 | sslErrorLog("CDSASymmEncrypt: null args\n"); |
239 | return errSSLInternal; | |
bac41a7b A |
240 | } |
241 | SSLBUF_TO_CSSM(&src, &ptextData); | |
29654253 | 242 | SSLBUF_TO_CSSM(&dest, &ctextData); |
bac41a7b A |
243 | crtn = CSSM_EncryptDataUpdate(cipherCtx->ccHand, |
244 | &ptextData, | |
245 | 1, | |
246 | &ctextData, | |
247 | 1, | |
248 | &bytesEncrypted); | |
249 | if(crtn) { | |
250 | stPrintCdsaError("CSSM_EncryptDataUpdate", crtn); | |
5a719ac8 | 251 | serr = errSSLCrypto; |
bac41a7b A |
252 | goto errOut; |
253 | } | |
254 | ||
29654253 A |
255 | if(bytesEncrypted > origLen) { |
256 | /* should never happen, callers always give us block-aligned | |
257 | * plaintext and CSP padding is disabled. */ | |
5a719ac8 | 258 | sslErrorLog("Symmetric encrypt overflow: bytesEncrypted %ld destLen %ld\n", |
bac41a7b | 259 | bytesEncrypted, dest.length); |
5a719ac8 | 260 | serr = errSSLCrypto; |
bac41a7b A |
261 | goto errOut; |
262 | } | |
bac41a7b | 263 | dest.length = bytesEncrypted; |
bac41a7b | 264 | logSymmData("Symm encrypt ctext", &dest, 48); |
5a719ac8 | 265 | serr = noErr; |
bac41a7b A |
266 | |
267 | errOut: | |
268 | return serr; | |
269 | } | |
270 | ||
5a719ac8 | 271 | OSStatus CDSASymmDecrypt( |
bac41a7b A |
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; | |
5a719ac8 | 281 | OSStatus serr = errSSLInternal; |
29654253 A |
282 | uint32 origLen = dest.length; |
283 | ||
bac41a7b A |
284 | /* |
285 | * Valid on entry: | |
286 | * cipherCtx->cspHand | |
287 | * cipherCtx->ccHand | |
288 | */ | |
5a719ac8 A |
289 | assert(ctx != NULL); |
290 | assert(cipherCtx != NULL); | |
bac41a7b | 291 | if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) { |
5a719ac8 A |
292 | sslErrorLog("CDSASymmDecrypt: null args\n"); |
293 | return errSSLInternal; | |
bac41a7b | 294 | } |
29654253 | 295 | /* this requirement allows us to avoid a malloc and copy */ |
5a719ac8 | 296 | assert(dest.length >= src.length); |
bac41a7b A |
297 | |
298 | #if SSL_DEBUG | |
299 | { | |
300 | unsigned blockSize = cipherCtx->symCipher->blockSize; | |
301 | if(blockSize) { | |
302 | if(!IS_ALIGNED(src.length, blockSize)) { | |
5a719ac8 | 303 | sslErrorLog("CDSASymmDecrypt: unaligned ctext (len %ld bs %d)\n", |
bac41a7b | 304 | src.length, blockSize); |
5a719ac8 | 305 | return errSSLInternal; |
bac41a7b A |
306 | } |
307 | if(!IS_ALIGNED(dest.length, blockSize)) { | |
5a719ac8 | 308 | sslErrorLog("CDSASymmDecrypt: unaligned ptext (len %ld bs %d)\n", |
bac41a7b | 309 | dest.length, blockSize); |
5a719ac8 | 310 | return errSSLInternal; |
bac41a7b A |
311 | } |
312 | } | |
313 | } | |
314 | #endif | |
315 | ||
316 | SSLBUF_TO_CSSM(&src, &ctextData); | |
29654253 | 317 | SSLBUF_TO_CSSM(&dest, &ptextData); |
bac41a7b A |
318 | crtn = CSSM_DecryptDataUpdate(cipherCtx->ccHand, |
319 | &ctextData, | |
320 | 1, | |
321 | &ptextData, | |
322 | 1, | |
323 | &bytesDecrypted); | |
324 | if(crtn) { | |
325 | stPrintCdsaError("CSSM_DecryptDataUpdate", crtn); | |
5a719ac8 | 326 | serr = errSSLCrypto; |
bac41a7b A |
327 | goto errOut; |
328 | } | |
329 | ||
29654253 | 330 | if(bytesDecrypted > origLen) { |
bac41a7b | 331 | /* FIXME - can this happen? Should we remalloc? */ |
5a719ac8 | 332 | sslErrorLog("Symmetric decrypt overflow: bytesDecrypted %ld destLen %ld\n", |
bac41a7b | 333 | bytesDecrypted, dest.length); |
5a719ac8 | 334 | serr = errSSLCrypto; |
bac41a7b A |
335 | goto errOut; |
336 | } | |
bac41a7b | 337 | dest.length = bytesDecrypted; |
5a719ac8 | 338 | serr = noErr; |
bac41a7b A |
339 | logSymmData("Symm decrypt ptext(1)", &dest, 48); |
340 | errOut: | |
341 | return serr; | |
342 | } | |
343 | ||
5a719ac8 | 344 | OSStatus CDSASymmFinish( |
bac41a7b A |
345 | CipherContext *cipherCtx, |
346 | SSLContext *ctx) | |
347 | { | |
348 | /* dispose of cipherCtx->{symKey,cspHand,ccHand} */ | |
349 | disposeCipherCtx(cipherCtx); | |
5a719ac8 | 350 | return noErr; |
bac41a7b A |
351 | } |
352 |