]> git.saurik.com Git - apple/security.git/blame - SecureTransport/symCipher.cpp
Security-176.tar.gz
[apple/security.git] / SecureTransport / symCipher.cpp
CommitLineData
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 */
42static 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 59OSStatus 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
157errOut:
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
169static 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 194OSStatus 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
267errOut:
268 return serr;
269}
270
5a719ac8 271OSStatus 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);
340errOut:
341 return serr;
342}
343
5a719ac8 344OSStatus 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