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