1/*
2 * Copyright (c) 2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * CommonCryptor.c - common crypto context.
26 *
27 */
28
29// #define COMMON_CRYPTOR_FUNCTIONS
30
31#include "ccGlobals.h"
32#include "ccMemory.h"
33#include "ccdebug.h"
34#include "CommonCryptor.h"
35#include "CommonCryptorSPI.h"
36#include "CommonCryptorPriv.h"
37#include <dispatch/dispatch.h>
38#include <dispatch/queue.h>
39
40#ifdef DEBUG
41#include <stdio.h>
42#include "CommonRandomSPI.h"
43#endif
44
45/*
46 * CommonCryptor's portion of a CCCryptorRef.
47 */
48
49static inline uint32_t ccGetCipherBlockSize(CCCryptor *ref) {
50    switch(ref->cipher) {
51        case kCCAlgorithmAES128:    return kCCBlockSizeAES128;
52        case kCCAlgorithmDES:       return kCCBlockSizeDES;
53        case kCCAlgorithm3DES:      return kCCBlockSize3DES;
54        case kCCAlgorithmCAST:      return kCCBlockSizeCAST;
55        case kCCAlgorithmRC4:       return 1;
56        case kCCAlgorithmRC2:       return kCCBlockSizeRC2;
57        case kCCAlgorithmBlowfish:  return kCCBlockSizeBlowfish;
58        default: return kCCBlockSizeAES128;
59    }
60}
61
62const corecryptoMode getCipherMode(CCAlgorithm cipher, CCMode mode, CCOperation direction)
63{
64    cc_globals_t globals = _cc_globals();
65    for(int i = 0; i<2; i++) {
66        dispatch_once(&(globals->cipherModeTab[cipher][i].init), ^{
67            globals->cipherModeTab[cipher][i].ecb = ccmodeList[cipher][i].ecb();
68            globals->cipherModeTab[cipher][i].cbc = ccmodeList[cipher][i].cbc();
69            globals->cipherModeTab[cipher][i].cfb = ccmodeList[cipher][i].cfb();
70            globals->cipherModeTab[cipher][i].cfb8 = ccmodeList[cipher][i].cfb8();
71            globals->cipherModeTab[cipher][i].ctr = ccmodeList[cipher][i].ctr();
72            globals->cipherModeTab[cipher][i].ofb = ccmodeList[cipher][i].ofb();
73            globals->cipherModeTab[cipher][i].xts = ccmodeList[cipher][i].xts();
74            globals->cipherModeTab[cipher][i].gcm = ccmodeList[cipher][i].gcm();
75            globals->cipherModeTab[cipher][i].ccm = ccmodeList[cipher][i].ccm();
76        });
77    }
78
79    switch(mode) {
80        case kCCModeECB: return (corecryptoMode) globals->cipherModeTab[cipher][direction].ecb;
81        case kCCModeCBC: return (corecryptoMode) globals->cipherModeTab[cipher][direction].cbc;
82        case kCCModeCFB: return (corecryptoMode) globals->cipherModeTab[cipher][direction].cfb;
83        case kCCModeCFB8: return (corecryptoMode) globals->cipherModeTab[cipher][direction].cfb8;
84        case kCCModeCTR: return (corecryptoMode) globals->cipherModeTab[cipher][direction].ctr;
85        case kCCModeOFB: return (corecryptoMode) globals->cipherModeTab[cipher][direction].ofb;
86        case kCCModeXTS: return (corecryptoMode) globals->cipherModeTab[cipher][direction].xts;
87        case kCCModeGCM: return (corecryptoMode) globals->cipherModeTab[cipher][direction].gcm;
88        case kCCModeCCM: return (corecryptoMode) globals->cipherModeTab[cipher][direction].ccm;
89    }
90    return (corecryptoMode) (const struct ccmode_ecb*) NULL;
91}
92
93static inline CCCryptorStatus setCryptorCipherMode(CCCryptor *ref, CCAlgorithm cipher, CCMode mode, CCOperation direction) {
94    switch(mode) {
95        case kCCModeECB: if((ref->symMode[direction].ecb = getCipherMode(cipher, mode, direction).ecb) == NULL) return kCCUnimplemented;
96            ref->modeDesc = &ccecb_mode; break;
97        case kCCModeCBC: if((ref->symMode[direction].cbc = getCipherMode(cipher, mode, direction).cbc) == NULL) return kCCUnimplemented;
98            ref->modeDesc = &cccbc_mode; break;
99        case kCCModeCFB: if((ref->symMode[direction].cfb = getCipherMode(cipher, mode, direction).cfb) == NULL) return kCCUnimplemented;
100            ref->modeDesc = &cccfb_mode; break;
101        case kCCModeCFB8: if((ref->symMode[direction].cfb8 = getCipherMode(cipher, mode, direction).cfb8) == NULL) return kCCUnimplemented;
102            ref->modeDesc = &cccfb8_mode; break;
103        case kCCModeCTR: if((ref->symMode[direction].ctr = getCipherMode(cipher, mode, direction).ctr) == NULL) return kCCUnimplemented;
104            ref->modeDesc = &ccctr_mode; break;
105        case kCCModeOFB: if((ref->symMode[direction].ofb = getCipherMode(cipher, mode, direction).ofb) == NULL) return kCCUnimplemented;
106            ref->modeDesc = &ccofb_mode; break;
107        case kCCModeXTS: if((ref->symMode[direction].xts = getCipherMode(cipher, mode, direction).xts) == NULL) return kCCUnimplemented;
108            ref->modeDesc = &ccxts_mode; break;
109        case kCCModeGCM: if((ref->symMode[direction].gcm = getCipherMode(cipher, mode, direction).gcm) == NULL) return kCCUnimplemented;
110            ref->modeDesc = &ccgcm_mode; break;
111        case kCCModeCCM: if((ref->symMode[direction].ccm = getCipherMode(cipher, mode, direction).ccm) == NULL) return kCCUnimplemented;
112            ref->modeDesc = &ccccm_mode; break;
113        default: return kCCParamError;
114    }
115    return kCCSuccess;
116
117}
118
119
120static inline CCCryptorStatus ccSetupCryptor(CCCryptor *ref, CCAlgorithm cipher, CCMode mode, CCOperation direction, CCPadding padding) {
121    CCCryptorStatus retval;
122
123    if(cipher > 6) return kCCParamError;
124    if(direction > kCCBoth) return kCCParamError;
125    if(cipher == kCCAlgorithmRC4) mode = kCCModeOFB;
126
127    ref->mode = mode;
128    CCOperation op = direction;
129    if(ref->mode == kCCModeXTS || ref->mode == kCCModeECB || ref->mode == kCCModeCBC) op = kCCBoth;
130
131    // printf("Cryptor setup - cipher %d mode %d direction %d padding %d\n", cipher, mode, direction, padding);
132    switch(op) {
133        case kCCEncrypt:
134        case kCCDecrypt:
135            if((retval = setCryptorCipherMode(ref, cipher, mode, op)) != kCCSuccess) return retval;
136            if((ref->ctx[op].data = CC_XMALLOC(ref->modeDesc->mode_get_ctx_size(ref->symMode[op]))) == NULL) return kCCMemoryFailure;
137            break;
138        case kCCBoth:
139            if((retval = setCryptorCipherMode(ref, cipher, mode, kCCEncrypt)) != kCCSuccess) return retval;
140            if((ref->ctx[kCCEncrypt].data = CC_XMALLOC(ref->modeDesc->mode_get_ctx_size(ref->symMode[kCCEncrypt]))) == NULL) return kCCMemoryFailure;
141            if((retval = setCryptorCipherMode(ref, cipher, mode, kCCDecrypt)) != kCCSuccess) return retval;
142            if((ref->ctx[kCCDecrypt].data = CC_XMALLOC(ref->modeDesc->mode_get_ctx_size(ref->symMode[kCCDecrypt]))) == NULL) return kCCMemoryFailure;
143            break;
144    }
145
146    switch(padding) {
147        case ccNoPadding:
148            ref->padptr = &ccnopad_pad;
149            break;
150        case ccPKCS7Padding:
151            if(mode == kCCModeCBC)
152                ref->padptr = &ccpkcs7_pad;
153            else
154                ref->padptr = &ccpkcs7_ecb_pad;
155            break;
156        case ccCBCCTS1:
157            ref->padptr = &cccts1_pad;
158            break;
159        case ccCBCCTS2:
160            ref->padptr = &cccts2_pad;
161            break;
162        case ccCBCCTS3:
163            ref->padptr = &cccts3_pad;
164            break;
165        default:
166            ref->padptr = &ccnopad_pad;
167    }
168    ref->cipher = cipher;
169    ref->cipherBlocksize = ccGetCipherBlockSize(ref);
170    ref->op = direction;
171    ref->bufferPos = 0;
172    ref->bytesProcessed = 0;
173    return kCCSuccess;
174}
175
176#define OP4INFO(X) (((X)->op == 3) ? 0: (X)->op)
177
178#if 0
179static inline size_t ccGetBlockSize(CCCryptor *ref) {
180    return ref->modeDesc->mode_get_block_size(ref->symMode[OP4INFO(ref)]);
181}
182#endif
183
184static inline bool ccIsStreaming(CCCryptor *ref) {
185    return ref->modeDesc->mode_get_block_size(ref->symMode[ref->op]) == 1;
186}
187
188static inline CCCryptorStatus ccInitCryptor(CCCryptor *ref, const void *key, unsigned long key_len, const void *tweak_key, const void *iv) {
189    size_t blocksize = ccGetCipherBlockSize(ref);
190    uint8_t defaultIV[blocksize];
191
192    if(iv == NULL) {
193        CC_XZEROMEM(defaultIV, blocksize);
194        iv = defaultIV;
195    }
196
197    CCOperation op = ref->op;
198
199    // This will create both sides of the context/mode pairs for now.
200    if(ref->mode == kCCModeXTS || ref->mode == kCCModeECB || ref->mode == kCCModeCBC) op = kCCBoth;
201
202    switch(op) {
203        case kCCEncrypt:
204        case kCCDecrypt:
205            ref->modeDesc->mode_setup(ref->symMode[ref->op], iv, key, key_len, tweak_key, 0, 0, ref->ctx[ref->op]);
206            break;
207        case kCCBoth:
208            ref->modeDesc->mode_setup(ref->symMode[kCCEncrypt], iv, key, key_len, tweak_key, 0, 0, ref->ctx[kCCEncrypt]);
209            ref->modeDesc->mode_setup(ref->symMode[kCCDecrypt], iv, key, key_len, tweak_key, 0, 0, ref->ctx[kCCDecrypt]);
210            break;
211    }
212    return kCCSuccess;
213}
214
215static inline CCCryptorStatus ccDoEnCrypt(CCCryptor *ref, const void *dataIn, size_t dataInLength, void *dataOut) {
216    if(!ref->modeDesc->mode_encrypt) return kCCParamError;
217    ref->modeDesc->mode_encrypt(ref->symMode[kCCEncrypt], dataIn, dataOut, dataInLength, ref->ctx[kCCEncrypt]);
218    return kCCSuccess;
219}
220
221static inline CCCryptorStatus ccDoDeCrypt(CCCryptor *ref, const void *dataIn, size_t dataInLength, void *dataOut) {
222    if(!ref->modeDesc->mode_decrypt) return kCCParamError;
223    ref->modeDesc->mode_decrypt(ref->symMode[kCCDecrypt], dataIn, dataOut, dataInLength, ref->ctx[kCCDecrypt]);
224    return kCCSuccess;
225}
226
227static inline CCCryptorStatus ccDoEnCryptTweaked(CCCryptor *ref, const void *dataIn, size_t dataInLength, void *dataOut, const void *tweak) {
228    if(!ref->modeDesc->mode_encrypt_tweaked) return kCCParamError;
229    ref->modeDesc->mode_encrypt_tweaked(ref->symMode[kCCEncrypt], dataIn, dataInLength, dataOut, tweak, ref->ctx[kCCEncrypt]);
230    return kCCSuccess;
231}
232
233static inline CCCryptorStatus ccDoDeCryptTweaked(CCCryptor *ref, const void *dataIn, size_t dataInLength, void *dataOut, const void *tweak) {
234    if(!ref->modeDesc->mode_decrypt_tweaked) return kCCParamError;
235    ref->modeDesc->mode_decrypt_tweaked(ref->symMode[kCCDecrypt], dataIn, dataInLength, dataOut, tweak, ref->ctx[kCCDecrypt]);
236    return kCCSuccess;
237}
238
239static inline CCCryptorStatus ccGetIV(CCCryptor *ref, void *iv, size_t *ivLen) {
240    if(ref->modeDesc->mode_getiv == NULL) return kCCParamError;
241    uint32_t tmp = (uint32_t) *ivLen;
242    if(ref->modeDesc->mode_getiv(ref->symMode[OP4INFO(ref)], iv, &tmp, ref->ctx[OP4INFO(ref)]) != 0) return kCCMemoryFailure;
243    *ivLen = tmp;
244    return kCCSuccess;
245}
246
247static inline CCCryptorStatus ccSetIV(CCCryptor *ref, const void *iv, size_t ivLen) {
248    if(ref->modeDesc->mode_setiv == NULL) return kCCParamError;
249    if(ref->modeDesc->mode_setiv(ref->symMode[OP4INFO(ref)], iv, (uint32_t ) ivLen, ref->ctx[OP4INFO(ref)]) != 0) return kCCMemoryFailure;
250    return kCCSuccess;
251}
252
253static inline void ccClearCryptor(CCCryptor *ref) {
254    CC_XZEROMEM(ref->buffptr, sizeof(ref->buffptr));
255    CCOperation op = ref->op;
256
257    // This will clear both sides of the context/mode pairs for now.
258    if(ref->mode == kCCModeXTS || ref->mode == kCCModeECB || ref->mode == kCCModeCBC) op = kCCBoth;
259    switch(op) {
260        case kCCEncrypt:
261        case kCCDecrypt:
262            CC_XZEROMEM(ref->ctx[ref->op].data, ref->modeDesc->mode_get_ctx_size(ref->symMode[ref->op]));
263            CC_XFREE(ref->ctx[ref->op].data, ref->modeDesc->mode_get_ctx_size(ref->symMode[ref->op]));
264            break;
265        case kCCBoth:
266            for(int i = 0; i<2; i++) {
267                CC_XZEROMEM(ref->ctx[i].data, ref->modeDesc->mode_get_ctx_size(ref->symMode[i]));
268                CC_XFREE(ref->ctx[i].data, ref->modeDesc->mode_get_ctx_size(ref->symMode[i]));
269            }
270            break;
271    }
272    ref->cipher = 0;
273    ref->mode = 0;
274    ref->op = 0;
275    ref->bufferPos = 0;
276    ref->bytesProcessed = 0;
277}
278
279static inline void returnLengthIfPossible(size_t length, size_t *returnPtr) {
280    if(returnPtr) *returnPtr = length;
281}
282
283static inline CCCryptorStatus ccEncryptPad(CCCryptor *cryptor, void *buf, size_t *moved) {
284    if(cryptor->padptr->encrypt_pad(cryptor->ctx[cryptor->op], cryptor->modeDesc, cryptor->symMode[cryptor->op], cryptor->buffptr, cryptor->bufferPos, buf, moved)) return kCCAlignmentError;
285    return kCCSuccess;
286}
287
288static inline CCCryptorStatus ccDecryptPad(CCCryptor *cryptor, void *buf, size_t *moved) {
289    if(cryptor->padptr->decrypt_pad(cryptor->ctx[cryptor->op], cryptor->modeDesc, cryptor->symMode[cryptor->op], cryptor->buffptr, cryptor->bufferPos, buf, moved)) return kCCAlignmentError;
290    return kCCSuccess;
291}
292
293static inline size_t ccGetReserve(CCCryptor *cryptor) {
294    return cryptor->padptr->padreserve(cryptor->op == kCCEncrypt, cryptor->modeDesc, cryptor->symMode[cryptor->op]);
295}
296
297static inline size_t ccGetPadOutputlen(CCCryptor *cryptor, size_t inputLength, bool final) {
298    size_t totalLen = cryptor->bufferPos + inputLength;
299    return cryptor->padptr->padlen(cryptor->op == kCCEncrypt, cryptor->modeDesc, cryptor->symMode[cryptor->op], totalLen, final);
300}
301
302
303static inline CCCryptor *
304ccCreateCompatCryptorFromData(const void *data, size_t dataLength, size_t *dataUsed) {
305    uintptr_t startptr = (uintptr_t) data;
306	uintptr_t retval = (uintptr_t) data;
307    if((retval & 0x07) ) retval = ((startptr / 8) * 8 + 8);
308    size_t usedLen = retval - startptr + CC_COMPAT_SIZE;
309    returnLengthIfPossible(usedLen, dataUsed);
310    if(usedLen > dataLength) return NULL;
311	return (CCCryptor *) retval;
312}
313
314static inline int ccAddBuff(CCCryptor *cryptor, const void *dataIn, size_t dataInLength) {
315    CC_XMEMCPY((char *) cryptor->buffptr + cryptor->bufferPos, dataIn, dataInLength);
316    cryptor->bufferPos += dataInLength;
317    return (int) dataInLength;
318}
319
320
321CCCryptorStatus CCCryptorCreateFromData(
322    CCOperation op,             /* kCCEncrypt, etc. */
323    CCAlgorithm alg,            /* kCCAlgorithmDES, etc. */
324    CCOptions options,          /* kCCOptionPKCS7Padding, etc. */
325    const void *key,            /* raw key material */
326    size_t keyLength,
327    const void *iv,             /* optional initialization vector */
328    const void *data,			/* caller-supplied memory */
329    size_t dataLength,			/* length of data in bytes */
330    CCCryptorRef *cryptorRef,   /* RETURNED */
331    size_t *dataUsed)			/* optional, RETURNED */
332
333{
334    CCCryptor *cryptor = ccCreateCompatCryptorFromData(data, dataLength, dataUsed);
335    if(!cryptor) return kCCBufferTooSmall;
336    CCCryptorStatus err = CCCryptorCreate(op, alg, options, key,  keyLength, iv, &cryptor->compat);
337    if(err == kCCSuccess) *cryptorRef = cryptor;
338    return err;
339}
340
341CCCryptorStatus CCCryptorCreate(
342	CCOperation op,             /* kCCEncrypt, etc. */
343	CCAlgorithm alg,            /* kCCAlgorithmDES, etc. */
344	CCOptions options,          /* kCCOptionPKCS7Padding, etc. */
345	const void *key,            /* raw key material */
346	size_t keyLength,
347	const void *iv,             /* optional initialization vector */
348	CCCryptorRef *cryptorRef)  /* RETURNED */
349{
350	CCMode			mode;
351    CCPadding		padding;
352	const void 		*tweak;
353	size_t 			tweakLength;
354	int				numRounds;
355	CCModeOptions 	modeOptions;
356
357    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
358	/* Determine mode from options - old call only supported ECB and CBC
359       we treat RC4 as a "mode" in that it's the only streaming cipher
360       currently supported
361    */
362    if(alg == kCCAlgorithmRC4) mode = kCCModeRC4;
363    else if(options & kCCOptionECBMode) mode = kCCModeECB;
364	else mode = kCCModeCBC;
365
366	/* Determine padding from options - only PKCS7 was available */
367    padding = ccNoPadding;
368	if(options & kCCOptionPKCS7Padding) padding = ccPKCS7Padding;
369
370	/* No tweak was ever used */
371   	tweak = NULL;
372    tweakLength = 0;
373
374	/* default rounds */
375    numRounds = 0;
376
377	/* No mode options needed */
378    modeOptions = 0;
379
380	return CCCryptorCreateWithMode(op, mode, alg, padding, iv, key, keyLength, tweak, tweakLength, numRounds, modeOptions, cryptorRef);
381}
382
383/* This version mallocs the CCCryptorRef */
384
385CCCryptorStatus CCCryptorCreateFromDataWithMode(
386    CCOperation 	op,				/* kCCEncrypt, kCCEncrypt, kCCBoth (default for BlockMode) */
387    CCMode			mode,
388    CCAlgorithm		alg,
389    CCPadding		padding,
390    const void 		*iv,			/* optional initialization vector */
391    const void 		*key,			/* raw key material */
392    size_t 			keyLength,
393    const void 		*tweak,			/* raw tweak material */
394    size_t 			tweakLength,
395    int				numRounds,
396    CCModeOptions 	options,
397    const void		*data,			/* caller-supplied memory */
398    size_t			dataLength,		/* length of data in bytes */
399    CCCryptorRef	*cryptorRef,	/* RETURNED */
400    size_t			*dataUsed)		/* optional, RETURNED */
401{
402    CCCryptor *cryptor = ccCreateCompatCryptorFromData(data, dataLength, dataUsed);
403    if(!cryptor) return kCCBufferTooSmall;
404    CCCryptorStatus err = CCCryptorCreateWithMode(op, mode, alg, padding, iv, key,  keyLength, tweak, tweakLength, numRounds, options, &cryptor->compat);
405    if(err == kCCSuccess) *cryptorRef = cryptor;
406    return err;
407}
408
409#define KEYALIGNMENT (sizeof(int)-1)
410CCCryptorStatus CCCryptorCreateWithMode(
411	CCOperation 	op,				/* kCCEncrypt, kCCEncrypt, kCCBoth (default for BlockMode) */
412	CCMode			mode,
413	CCAlgorithm		alg,
414	CCPadding		padding,
415	const void 		*iv,			/* optional initialization vector */
416	const void 		*key,			/* raw key material */
417	size_t 			keyLength,
418	const void 		*tweak,			/* raw tweak material */
419	size_t 			tweakLength,
420	int				numRounds,		/* 0 == default */
421	CCModeOptions 	options,
422	CCCryptorRef	*cryptorRef)	/* RETURNED */
423{
424	CCCryptorStatus retval = kCCSuccess;
425	CCCryptor *cryptor = NULL;
426    uint8_t *alignedKey = NULL;
427
428    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering Op: %d Mode: %d Cipher: %d Padding: %d\n", op, mode, alg, padding);
429
430    // For now we're mapping these two AES selectors to the stock one.
431    if(alg == kCCAlgorithmAES128NoHardware || alg == kCCAlgorithmAES128WithHardware)
432        alg = kCCAlgorithmAES128;
433
434    /* corecrypto only implements CTR_BE.  No use of CTR_LE was found so we're marking
435       this as unimplemented for now.  Also in Lion this was defined in reverse order.
436       See <rdar://problem/10306112> */
437
438    if(mode == kCCModeCTR && options != kCCModeOptionCTR_BE) {
439        CC_DEBUG_LOG(ASL_LEVEL_ERR, "Mode is CTR, but options isn't BE\n", op, mode, alg, padding);
440        return kCCUnimplemented;
441    }
442
443    // validate pointers
444	if((cryptorRef == NULL) || (key == NULL)) {
445		CC_DEBUG_LOG(ASL_LEVEL_ERR, "bad arguments\n", 0);
446		return kCCParamError;
447	}
448
449    /*
450     * Some implementations are sensitive to keys not being 4 byte aligned.
451     * We'll move the key into an aligned buffer for the call to setup
452     * the key schedule.
453     */
454
455    if((intptr_t) key & KEYALIGNMENT) {
456        if((alignedKey = CC_XMALLOC(keyLength)) == NULL) {
457            return kCCMemoryFailure;
458        }
459        CC_XMEMCPY(alignedKey, key, keyLength);
460        key = alignedKey;
461    }
462
463    if((cryptor = (CCCryptor *)CC_XMALLOC(DEFAULT_CRYPTOR_MALLOC)) == NULL) {
464        retval = kCCMemoryFailure;
465        goto out;
466    }
467
468    cryptor->compat = NULL;
469
470    if((retval = ccSetupCryptor(cryptor, alg, mode, op, padding)) != kCCSuccess) {
471        goto out;
472    }
473
474    if((retval = ccInitCryptor(cryptor, key, keyLength, tweak, iv)) != kCCSuccess) {
475        goto out;
476    }
477
478	*cryptorRef = cryptor;
479#ifdef DEBUG
480    cryptor->active = ACTIVE;
481    CCRandomCopyBytes(kCCRandomDefault, &cryptor->cryptorID, sizeof(cryptor->cryptorID));
482#endif
483
484out:
485    // Things to destroy if setup failed
486    if(retval) {
487        *cryptorRef = NULL;
488        if(cryptor) {
489            CC_XZEROMEM(cryptor, DEFAULT_CRYPTOR_MALLOC);
490            CC_XFREE(cryptor, DEFAULT_CRYPTOR_MALLOC);
491        }
492    } else {
493        // printf("Blocksize = %d mode = %d pad = %d\n", ccGetBlockSize(cryptor), cryptor->mode, padding);
494    }
495
496    // Things to destroy all the time
497    if(alignedKey) {
498        CC_XZEROMEM(alignedKey, keyLength);
499        CC_XFREE(alignedKey, keyLength);
500    }
501
502    return retval;
503}
504
505
506CCCryptorStatus CCCryptorRelease(
507	CCCryptorRef cryptorRef)
508{
509    CCCryptor *cryptor = getRealCryptor(cryptorRef, 0);
510
511    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
512    if(cryptor) {
513        ccClearCryptor(cryptor);
514        CC_XMEMSET(cryptor, 0, CCCRYPTOR_SIZE);
515        CC_XFREE(cryptor, DEFAULT_CRYPTOR_MALLOC);
516    }
517	return kCCSuccess;
518}
519
520#define FULLBLOCKSIZE(X,BLOCKSIZE) (((X)/(BLOCKSIZE))*BLOCKSIZE)
521#define FULLBLOCKREMAINDER(X,BLOCKSIZE) ((X)%(BLOCKSIZE))
522
523static CCCryptorStatus ccSimpleUpdate(CCCryptor *cryptor, const void *dataIn, size_t dataInLength, void **dataOut, size_t *dataOutAvailable, size_t *dataOutMoved)
524{
525	CCCryptorStatus	retval;
526    if(cryptor->op == kCCEncrypt) {
527        if((retval = ccDoEnCrypt(cryptor, dataIn, dataInLength, *dataOut)) != kCCSuccess) return retval;
528    } else {
529        if((retval = ccDoDeCrypt(cryptor, dataIn, dataInLength, *dataOut)) != kCCSuccess) return retval;
530    }
531    if(dataOutMoved) *dataOutMoved += dataInLength;
532    if(*dataOutAvailable < dataInLength) return kCCBufferTooSmall;
533    cryptor->bytesProcessed += dataInLength;
534    *dataOut += dataInLength;
535    *dataOutAvailable -= dataInLength;
536    return kCCSuccess;
537}
538
539static CCCryptorStatus ccBlockUpdate(CCCryptor *cryptor, const void *dataIn, size_t dataInLength, void *dataOut, size_t *dataOutAvailable, size_t *dataOutMoved)
540{
541    CCCryptorStatus retval;
542    size_t dataCount = cryptor->bufferPos + dataInLength;
543    size_t reserve = ccGetReserve(cryptor);
544    size_t blocksize = ccGetCipherBlockSize(cryptor);
545    size_t buffsize = (reserve) ? reserve: blocksize; /* minimum buffering is a block */
546    size_t dataCountToHold, dataCountToProcess;
547    size_t remainder, movecnt;
548
549    /* This is a simple optimization */
550    if(reserve == 0 && cryptor->bufferPos == 0 && (dataInLength % blocksize) == 0) { // No Padding, not buffering, even blocks
551        // printf("simple processing\n");
552    	return ccSimpleUpdate(cryptor, dataIn, dataInLength, &dataOut, dataOutAvailable, dataOutMoved);
553    }
554
555    /* From this point on we're dealing with a Block Cipher with Block oriented I/O
556
557     We always fallback to buffering once we're processing non-block aligned data.
558     If the data inputs result in data becoming block aligned once again we can
559     move back to block aligned I/O - even if it's only for partial processing
560     of the data supplied to this routine.
561
562     */
563
564    if(dataCount <= reserve) {
565    	dataCountToHold = dataCount;
566    } else {
567    	remainder = FULLBLOCKREMAINDER(dataCount, blocksize);
568		dataCountToHold = buffsize - blocksize + remainder;
569        dataCountToHold = (remainder) ? dataCountToHold: reserve;
570    }
571
572    dataCountToProcess = dataCount - dataCountToHold;
573    // printf("DataCount %d Processing %d Holding %d\n", dataCount, dataCountToProcess, dataCountToHold);
574
575    if(dataCountToProcess > 0) {
576    	if(cryptor->bufferPos == 0) {
577        	// printf("CCCryptorUpdate checkpoint 0\n");
578        	/* nothing to do yet */
579    	} else if(cryptor->bufferPos < dataCountToProcess) {
580        	// printf("CCCryptorUpdate checkpoint 1\n");
581            movecnt = blocksize - (cryptor->bufferPos % blocksize);
582            ccAddBuff(cryptor, dataIn, movecnt);
583            dataIn += movecnt; dataInLength -= movecnt;
584
585         	// printf("CCCryptorUpdate checkpoint 1.1 bufpos = %d\n", (int) cryptor->bufferPos);
586           	if((retval = ccSimpleUpdate(cryptor, cryptor->buffptr, cryptor->bufferPos, &dataOut, dataOutAvailable, dataOutMoved)) != kCCSuccess) {
587                return retval;
588        	}
589			// printf("CCCryptorUpdate checkpoint 1.2\n");
590
591			dataCountToProcess -= cryptor->bufferPos;
592        	cryptor->bufferPos = 0;
593        } else if(cryptor->bufferPos == dataCountToProcess) {
594        	// printf("CCCryptorUpdate checkpoint 2\n");
595			if((retval = ccSimpleUpdate(cryptor, cryptor->buffptr, cryptor->bufferPos, &dataOut, dataOutAvailable, dataOutMoved)) != kCCSuccess) {
596                return retval;
597        	}
598			dataCountToProcess -= cryptor->bufferPos;
599        	cryptor->bufferPos = 0;
600        } else /* (cryptor->bufferPos > dataCountToProcess) */ {
601         	// printf("CCCryptorUpdate checkpoint 3\n");
602       		if(dataCountToHold) {
603            	// printf("CCCryptorUpdate bad calculation 1\n");
604                return kCCDecodeError;
605            }
606			if((retval = ccSimpleUpdate(cryptor, cryptor->buffptr, dataCountToProcess, &dataOut, dataOutAvailable, dataOutMoved)) != kCCSuccess) {
607                return retval;
608        	}
609            cryptor->bufferPos = (uint32_t) (reserve - dataCountToProcess);
610            memmove(cryptor->buffptr, ((uint8_t *) cryptor->buffptr)+ dataCountToProcess, cryptor->bufferPos);
611            return kCCSuccess;
612        }
613
614        if(dataCountToProcess > 0) {
615         	// printf("CCCryptorUpdate checkpoint 4\n");
616   			movecnt = FULLBLOCKREMAINDER(dataCountToProcess, blocksize);
617            if(movecnt) {
618            	// printf("CCCryptorUpdate bad calculation 2\n");
619                return kCCDecodeError;
620            }
621        	if((retval = ccSimpleUpdate(cryptor, dataIn, dataCountToProcess, &dataOut, dataOutAvailable, dataOutMoved)) != kCCSuccess) return retval;
622        	dataIn += dataCountToProcess; dataInLength -= dataCountToProcess;
623        }
624    }
625
626    if(dataCountToHold) {
627		// printf("CCCryptorUpdate checkpoint 1\n");
628    	movecnt = dataCountToHold - cryptor->bufferPos;
629        if(movecnt) {
630        	if(movecnt != dataInLength) {
631            	// printf("CCCryptorUpdate bad calculation 3\n");
632                return kCCDecodeError;
633            }
634            ccAddBuff(cryptor, dataIn, movecnt);
635        	dataInLength -= movecnt;
636        }
637    }
638
639    if(dataInLength) {
640        // printf("CCCryptorUpdate bad calculation 4\n");
641        return kCCDecodeError;
642    }
643    return kCCSuccess;
644}
645
646static inline size_t ccGetOutputLength(CCCryptor *cryptor, size_t inputLength, bool final) {
647    if(ccIsStreaming(cryptor)) return inputLength;
648    return ccGetPadOutputlen(cryptor, inputLength, final);
649}
650
651size_t CCCryptorGetOutputLength(
652    CCCryptorRef cryptorRef,
653    size_t inputLength,
654    bool final)
655{
656    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
657    CCCryptor *cryptor = getRealCryptor(cryptorRef, 1);
658    if(cryptor == NULL) return kCCParamError;
659    return ccGetOutputLength(cryptor, inputLength, final);
660}
661
662CCCryptorStatus CCCryptorUpdate(
663    CCCryptorRef cryptorRef,
664    const void *dataIn,
665    size_t dataInLength,
666    void *dataOut,
667    size_t dataOutAvailable,
668    size_t *dataOutMoved)
669{
670    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
671	CCCryptorStatus	retval;
672    CCCryptor *cryptor = getRealCryptor(cryptorRef, 1);
673    if(!cryptor) return kCCParamError;
674	if(dataOutMoved) *dataOutMoved = 0;
675    if(0 == dataInLength) return kCCSuccess;
676
677    size_t needed = ccGetOutputLength(cryptor, dataInLength, false);
678    if(needed > dataOutAvailable) {
679        if(dataOutMoved) *dataOutMoved = needed;
680        return kCCBufferTooSmall;
681    }
682
683
684	if(ccIsStreaming(cryptor))
685        retval = ccSimpleUpdate(cryptor, dataIn, dataInLength, &dataOut, &dataOutAvailable, dataOutMoved);
686    else
687        retval = ccBlockUpdate(cryptor, dataIn, dataInLength, dataOut, &dataOutAvailable, dataOutMoved);
688
689    return retval;
690}
691
692
693
694CCCryptorStatus CCCryptorFinal(
695	CCCryptorRef cryptorRef,
696	void *dataOut,					/* data RETURNED here */
697	size_t dataOutAvailable,
698	size_t *dataOutMoved)		/* number of bytes written */
699{
700    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
701    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 0);
702    // Some old behavior .. CDSA? has zapped the Cryptor.
703    if(cryptor == NULL) return kCCSuccess;
704
705
706	CCCryptorStatus	retval;
707    int encrypting = (cryptor->op == kCCEncrypt);
708	uint32_t blocksize = ccGetCipherBlockSize(cryptor);
709
710    size_t moved;
711	char tmpbuf[blocksize*2];
712
713	if(dataOutMoved) *dataOutMoved = 0;
714
715    if(ccIsStreaming(cryptor)) {
716        if(cryptor->modeDesc->mode_done) {
717            cryptor->modeDesc->mode_done(cryptor->symMode[cryptor->op], cryptor->ctx[cryptor->op]);
718        }
719        return kCCSuccess;
720    }
721
722	if(encrypting) {
723        retval = ccEncryptPad(cryptor, tmpbuf, &moved);
724        if(retval != kCCSuccess) return retval;
725		if(dataOutAvailable < moved) {
726            return kCCBufferTooSmall;
727        }
728        if(dataOut) {
729            CC_XMEMCPY(dataOut, tmpbuf, moved);
730            if(dataOutMoved) *dataOutMoved = moved;
731        }
732		cryptor->bufferPos = 0;
733	} else {
734        retval = ccDecryptPad(cryptor, tmpbuf, &moved);
735        if(retval != kCCSuccess) return retval;
736        if(dataOutAvailable < moved) {
737            return kCCBufferTooSmall;
738        }
739        if(dataOut) {
740            CC_XMEMCPY(dataOut, tmpbuf, moved);
741            if(dataOutMoved) *dataOutMoved = moved;
742        }
743        cryptor->bytesProcessed += moved;
744        cryptor->bufferPos = 0;
745	}
746    cryptor->bufferPos = 0;
747#ifdef DEBUG
748    cryptor->active = RELEASED;
749#endif
750	return kCCSuccess;
751}
752
753CCCryptorStatus CCCryptorReset(
754	CCCryptorRef cryptorRef,
755	const void *iv)
756{
757    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
758    CCCryptor *cryptor = getRealCryptor(cryptorRef, 1);
759    if(!cryptor) return kCCParamError;
760    CCCryptorStatus retval;
761
762    /*
763    	This routine resets all buffering and sets or clears the IV.  It is
764    	documented to throw away any in-flight buffer data.
765    */
766
767    cryptor->bytesProcessed = cryptor->bufferPos = 0;
768
769    /*
770    	Call the common routine to reset the IV - this will copy in the new
771       	value. There is now always space for an IV in the cryptor.
772    */
773
774    if(iv) {
775        retval = ccSetIV(cryptor, iv, ccGetCipherBlockSize(cryptor));
776    } else {
777        uint8_t ivzero[ccGetCipherBlockSize(cryptor)];
778        CC_XZEROMEM(ivzero, ccGetCipherBlockSize(cryptor));
779        retval = ccSetIV(cryptor, ivzero, ccGetCipherBlockSize(cryptor));
780    }
781    if(retval == kCCParamError) return kCCSuccess;
782    return retval;
783}
784
785CCCryptorStatus
786CCCryptorGetIV(CCCryptorRef cryptorRef, void *iv)
787{
788    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 1);
789    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
790    if(!cryptor) return kCCParamError;
791
792    if(ccIsStreaming(cryptor)) return kCCParamError;
793    size_t blocksize = ccGetCipherBlockSize(cryptor);
794    return ccGetIV(cryptor, iv, &blocksize);
795}
796
797
798
799/*
800 * One-shot is mostly service provider independent, except for the
801 * dataOutLength check.
802 */
803CCCryptorStatus CCCrypt(
804	CCOperation op,			/* kCCEncrypt, etc. */
805	CCAlgorithm alg,		/* kCCAlgorithmAES128, etc. */
806	CCOptions options,		/* kCCOptionPKCS7Padding, etc. */
807	const void *key,
808	size_t keyLength,
809	const void *iv,			/* optional initialization vector */
810	const void *dataIn,		/* optional per op and alg */
811	size_t dataInLength,
812	void *dataOut,			/* data RETURNED here */
813	size_t dataOutAvailable,
814	size_t *dataOutMoved)
815{
816    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
817	CCCryptorRef cryptor = NULL;
818	CCCryptorStatus retval;
819	size_t updateLen, finalLen;
820
821	if(kCCSuccess != (retval = CCCryptorCreate(op, alg, options, key, keyLength, iv, &cryptor))) return retval;
822    size_t needed = CCCryptorGetOutputLength(cryptor, dataInLength, true);
823    if(dataOutMoved != NULL) *dataOutMoved = needed;
824    if(needed > dataOutAvailable) {
825        retval = kCCBufferTooSmall;
826        goto out;
827    }
828
829	if(kCCSuccess != (retval = CCCryptorUpdate(cryptor, dataIn, dataInLength, dataOut, dataOutAvailable, &updateLen))) {
830        goto out;
831    }
832    dataOut += updateLen; dataOutAvailable -= updateLen;
833    retval = CCCryptorFinal(cryptor, dataOut, dataOutAvailable, &finalLen);
834    if(dataOutMoved != NULL) *dataOutMoved = updateLen + finalLen;
835out:
836	CCCryptorRelease(cryptor);
837	return retval;
838}
839
840CCCryptorStatus CCCryptorEncryptDataBlock(
841	CCCryptorRef cryptorRef,
842	const void *iv,
843	const void *dataIn,
844	size_t dataInLength,
845	void *dataOut)
846{
847    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
848    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 1);
849    if(!cryptor) return kCCParamError;
850    if(ccIsStreaming(cryptor)) return kCCParamError;
851    if(!iv) return ccDoEnCrypt(cryptor, dataIn, dataInLength, dataOut);
852    return ccDoEnCryptTweaked(cryptor, dataIn, dataInLength, dataOut, iv);
853}
854
855
856CCCryptorStatus CCCryptorDecryptDataBlock(
857	CCCryptorRef cryptorRef,
858	const void *iv,
859	const void *dataIn,
860	size_t dataInLength,
861	void *dataOut)
862{
863    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
864    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 1);
865    if(!cryptor) return kCCParamError;
866    if(ccIsStreaming(cryptor)) return kCCParamError;
867    if(!iv) return ccDoDeCrypt(cryptor, dataIn, dataInLength, dataOut);
868    return ccDoDeCryptTweaked(cryptor, dataIn, dataInLength, dataOut, iv);
869}
870
871#include <corecrypto/ccmode_factory.h>
872
873static bool ccm_ready(modeCtx ctx) {
874// FIX THESE NOW XXX
875    if(ctx.ccm->mac_size == (size_t) 0xffffffffffffffff ||
876       ctx.ccm->nonce_size == (size_t) 0xffffffffffffffff ||
877       ctx.ccm->total_len == (size_t) 0xffffffffffffffff) return false;
878    return true;
879}
880
881CCCryptorStatus CCCryptorAddParameter(
882    CCCryptorRef cryptorRef,
883    CCParameter parameter,
884    const void *data,
885    size_t dataSize)
886{
887    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
888    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 1);
889    if(!cryptor) return kCCParamError;
890
891    switch(parameter) {
892    case kCCParameterIV:
893        // GCM version
894        if(cryptor->mode == kCCModeGCM) {
895            ccmode_gcm_set_iv(cryptor->ctx[cryptor->op].gcm, dataSize, data);
896        } else if(cryptor->mode == kCCModeCCM) {
897            ccm_nonce_ctx *ccm = cryptor->ctx[cryptor->op].ccm;
898            ccm->nonce_size = dataSize;
899            CC_XMEMCPY(ccm->nonce_buf, data, dataSize);
900        } else return kCCUnimplemented;
901        break;
902
903    case kCCParameterAuthData:
904        // GCM version
905        if(cryptor->mode == kCCModeGCM) {
906            ccmode_gcm_gmac(cryptor->ctx[cryptor->op].gcm, dataSize, data);
907        } else if(cryptor->mode == kCCModeCCM) {
908            if(!ccm_ready(cryptor->ctx[cryptor->op])) return kCCParamError;
909            ccm_nonce_ctx *ccm = cryptor->ctx[cryptor->op].ccm;
910            const struct ccmode_ccm *mode = cryptor->symMode[cryptor->op].ccm;
911            ccm->ad_len = dataSize;
912            mode->set_iv(&ccm->ccm, (ccccm_nonce *) &ccm->nonce,
913                    ccm->nonce_size, ccm->nonce_buf, ccm->mac_size, ccm->ad_len, ccm->total_len);
914            mode->cbcmac(&ccm->ccm, (ccccm_nonce *) &ccm->nonce,
915                    ccm->ad_len, data);
916        } else return kCCUnimplemented;
917        break;
918
919    case kCCMacSize:
920        if(cryptor->mode == kCCModeCCM) {
921            cryptor->ctx[cryptor->op].ccm->mac_size = dataSize;
922        } else return kCCUnimplemented;
923        break;
924
925    case kCCDataSize:
926        if(cryptor->mode == kCCModeCCM) {
927            cryptor->ctx[cryptor->op].ccm->total_len = dataSize;
928        } else return kCCUnimplemented;
929        break;
930
931    default:
932        return kCCParamError;
933    }
934    return kCCSuccess;
935}
936
937CCCryptorStatus CCCryptorGetParameter(
938    CCCryptorRef cryptorRef,
939    CCParameter parameter,
940    void *data,
941    size_t *dataSize)
942{
943    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
944    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 1);
945    if(!cryptor) return kCCParamError;
946
947    switch(parameter) {
948    case kCCParameterAuthTag:
949        // GCM version
950        if(cryptor->mode == kCCModeGCM) {
951            return kCCUnimplemented;
952        } else if(cryptor->mode == kCCModeCCM) {
953            ccm_nonce_ctx *ccm = cryptor->ctx[cryptor->op].ccm;
954            CC_XMEMCPY(data, ccm->mac, ccm->mac_size);
955            *dataSize = ccm->mac_size;
956        } else return kCCUnimplemented;
957        break;
958    default:
959        return kCCParamError;
960    }
961    return kCCSuccess;
962}
963
964
965