1/* 2 * Copyright (c) 1999-2001,2005-2008,2010-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 * symCipher.c - CommonCrypto-based symmetric cipher module 26 */ 27 28/* THIS FILE CONTAINS KERNEL CODE */ 29 30#include "sslBuildFlags.h" 31#include "sslDebug.h" 32#include "sslMemory.h" 33#include "symCipher.h" 34#include "cipherSpecs.h" 35#include "SSLRecordInternal.h" 36 37#ifdef KERNEL 38 39#include <corecrypto/ccaes.h> 40#include <corecrypto/ccdes.h> 41#include <corecrypto/ccmode.h> 42 43#include <AssertMacros.h> 44 45struct SymCipherContext { 46 const struct ccmode_cbc *cbc; 47 cccbc_ctx u[]; /* this will have the key and iv */ 48}; 49 50/* Macros for accessing the content of a SymCipherContext */ 51 52/* 53 SymCipherContext looks like this in memory: 54 55 { 56 const struct ccmode_cbc *cbc; 57 cccbc_ctx key[n]; 58 cccbc_iv iv[m]; 59 } 60 61 cccbc_ctx and cccbc_iv are typedef-ined as aligned opaque struct, the actual contexts are arrays 62 of those types normally declared with a cc_ctx_decl macro. 63 The cc_ctx_n macros gives the number of elements in those arrays that are needed to store the 64 contexts. 65 The size of the context depends on the actual cbc implementation used. 66*/ 67 68 69/* CTX_SIZE: Total size of the SymCipherContext struct for a cbc implementation */ 70static inline 71size_t CTX_SIZE(const struct ccmode_cbc *cbc) 72{ 73#ifdef __CC_HAS_FIX_FOR_11468135__ 74 return (sizeof(SymCipherContext) + (sizeof(cccbc_ctx) * (cc_ctx_n(cccbc_ctx, cbc->size) + cc_ctx_n(cccbc_iv, cbc->block_size)))); 75#else 76 /* This is approximate, but will work in that case, this code will go away after we transition */ 77 return (sizeof(SymCipherContext) + sizeof(cccbc_ctx) + cbc->size); 78#endif 79} 80 81/* CTX_KEY: Address of the key context in the SymCipherContext struct */ 82static inline 83cccbc_ctx *CTX_KEY(struct SymCipherContext *ctx) 84{ 85 return &ctx->u[0]; 86} 87 88 89/* CTX_IV: Address of the iv context in the SymCipherContext struct */ 90#ifdef __CC_HAS_FIX_FOR_11468135__ 91static inline 92cccbc_iv *CTX_IV(struct SymCipherContext *ctx) 93{ 94 return (cccbc_iv *)&ctx->u[cc_ctx_n(cccbc_ctx, ctx->cbc->size)]; 95} 96#endif 97 98static 99const void *ccmode(SSL_CipherAlgorithm alg, int enc) 100{ 101 switch(alg) { 102 case SSL_CipherAlgorithmAES_128_CBC: 103 case SSL_CipherAlgorithmAES_256_CBC: 104 return enc?ccaes_cbc_encrypt_mode():ccaes_cbc_decrypt_mode(); 105 case SSL_CipherAlgorithm3DES_CBC: 106 return enc?ccdes3_cbc_encrypt_mode():ccdes3_cbc_decrypt_mode(); 107 case SSL_CipherAlgorithmAES_128_GCM: 108 case SSL_CipherAlgorithmAES_256_GCM: 109 case SSL_CipherAlgorithmRC4_128: 110 /* TODO: we should do RC4 for TLS, but we dont need it for DTLS */ 111 default: 112 check(0); 113 return NULL; /* This will cause CCCryptorCreate to return an error */ 114 } 115} 116 117static 118int CCSymmInit( 119 const SSLSymmetricCipherParams *params, 120 int encrypting, 121 uint8_t *key, 122 uint8_t* iv, 123 SymCipherContext *cipherCtx) 124{ 125 check(cipherCtx!=NULL); 126 check(params); 127 SymCipherContext ctx = *cipherCtx; 128 129 /* 130 * Cook up a cccbx_ctx object. Assumes: 131 * cipherCtx->symCipher.keyAlg 132 * cipherCtx->encrypting 133 * key (raw key bytes) 134 * iv (raw bytes) 135 * On successful exit: 136 * Resulting ccmode --> cipherCtx 137 */ 138 139 /* FIXME: this should not be needed as long as CCSymFinish is called */ 140 if(ctx) { 141 sslFree(ctx); 142 ctx = NULL; 143 } 144 145 const struct ccmode_cbc *cbc = ccmode(params->keyAlg, encrypting); 146 147 ctx = sslMalloc(CTX_SIZE(cbc)); 148 149 if(ctx==NULL) { 150 sslErrorLog("CCSymmInit: Can't allocate context\n"); 151 return errSSLRecordInternal; 152 } 153 154 ctx->cbc = cbc; 155 156#ifdef __CC_HAS_FIX_FOR_11468135__ 157 cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key); 158 cccbc_set_iv(cbc, CTX_IV(ctx), iv); 159#else 160 cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key, iv); 161#endif 162 163 *cipherCtx = ctx; 164 return 0; 165} 166 167/* same for en/decrypt */ 168static 169int CCSymmEncryptDecrypt( 170 const uint8_t *src, 171 uint8_t *dest, 172 size_t len, 173 SymCipherContext cipherCtx) 174{ 175 176 ASSERT(cipherCtx != NULL); 177 ASSERT(cipherCtx->cbc != NULL); 178 179 if(cipherCtx == NULL || cipherCtx->cbc == NULL) { 180 sslErrorLog("CCSymmEncryptDecrypt: NULL cipherCtx\n"); 181 return errSSLRecordInternal; 182 } 183 184 ASSERT((len%cipherCtx->cbc->block_size)==0); 185 186 if(len%cipherCtx->cbc->block_size) { 187 sslErrorLog("CCSymmEncryptDecrypt: Invalid size\n"); 188 return errSSLRecordInternal; 189 } 190 191 unsigned long nblocks = len/cipherCtx->cbc->block_size; 192 193#ifdef __CC_HAS_FIX_FOR_11468135__ 194 cccbc_update(cipherCtx->cbc, CTX_KEY(cipherCtx), CTX_IV(cipherCtx), nblocks, src, dest); 195#else 196 cipherCtx->cbc->cbc(CTX_KEY(cipherCtx), nblocks, src, dest); 197#endif 198 return 0; 199} 200 201static 202int CCSymmFinish( 203 SymCipherContext cipherCtx) 204{ 205 if(cipherCtx) { 206 sslFree(cipherCtx); 207 } 208 return 0; 209} 210 211 212#else 213 214#define ENABLE_RC4 1 215#define ENABLE_3DES 1 216#define ENABLE_AES 1 217#define ENABLE_AES256 1 218 219/* 220 * CommonCrypto-based symmetric cipher callouts 221 */ 222#include <CommonCrypto/CommonCryptor.h> 223#include <CommonCrypto/CommonCryptorSPI.h> 224#include <assert.h> 225 226static 227CCAlgorithm CCAlg(SSL_CipherAlgorithm alg) 228{ 229 switch(alg) { 230 case SSL_CipherAlgorithmAES_128_CBC: 231 case SSL_CipherAlgorithmAES_256_CBC: 232 case SSL_CipherAlgorithmAES_128_GCM: 233 case SSL_CipherAlgorithmAES_256_GCM: 234 return kCCAlgorithmAES128; /* AES128 here means 128bit block size, not key size */ 235 case SSL_CipherAlgorithm3DES_CBC: 236 return kCCAlgorithm3DES; 237 case SSL_CipherAlgorithmDES_CBC: 238 return kCCAlgorithmDES; 239 case SSL_CipherAlgorithmRC4_128: 240 return kCCAlgorithmRC4; 241 case SSL_CipherAlgorithmRC2_128: 242 return kCCAlgorithmRC2; 243 default: 244 assert(0); 245 return (CCAlgorithm)(-1); /* This will cause CCCryptorCreate to return an error */ 246 } 247} 248 249static CCOptions CCOpt(CipherType cipherType) 250{ 251#if 0 252 if(cipherType==aeadCipherType) return kCCModeGCM; 253#endif 254 return 0; 255} 256 257static 258int CCSymmInit( 259 const SSLSymmetricCipherParams *params, 260 int encrypting, 261 uint8_t *key, 262 uint8_t* iv, 263 SymCipherContext *cipherCtx) 264{ 265 assert(cipherCtx!=NULL); 266 267 /* 268 * Cook up a CCCryptorRef. Assumes: 269 * cipherCtx->symCipher.keyAlg 270 * cipherCtx->encrypting 271 * key (raw key bytes) 272 * iv (raw bytes) 273 * On successful exit: 274 * Resulting CCCryptorRef --> cipherCtx->cryptorRef 275 */ 276 CCCryptorStatus ccrtn; 277 CCOperation op = encrypting ? kCCEncrypt : kCCDecrypt; 278 CCCryptorRef cryptorRef = (CCCryptorRef)*cipherCtx; 279 280 /* FIXME: this should not be needed as long as CCSymFinish is called */ 281 if(cryptorRef) { 282 CCCryptorRelease(cryptorRef); 283 cryptorRef = NULL; 284 } 285 286 ccrtn = CCCryptorCreate(op, CCAlg(params->keyAlg), 287 /* options - gcm or no padding, default CBC */ 288 CCOpt(params->cipherType), 289 key, params->keySize, 290 iv, 291 &cryptorRef); 292 if(ccrtn) { 293 sslErrorLog("CCCryptorCreate returned %d\n", (int)ccrtn); 294 return errSSLRecordInternal; 295 } 296 *cipherCtx = (SymCipherContext)cryptorRef; 297 return 0; 298} 299 300/* same for en/decrypt */ 301static 302int CCSymmEncryptDecrypt( 303 const uint8_t *src, 304 uint8_t *dest, 305 size_t len, 306 SymCipherContext cipherCtx) 307{ 308 CCCryptorStatus ccrtn; 309 CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; 310 ASSERT(cryptorRef != NULL); 311 if(cryptorRef == NULL) { 312 sslErrorLog("CCSymmEncryptDecrypt: NULL cryptorRef\n"); 313 return errSSLRecordInternal; 314 } 315 size_t data_moved; 316 ccrtn = CCCryptorUpdate(cryptorRef, src, len, 317 dest, len, &data_moved); 318 assert(data_moved == len); 319#if SSL_DEBUG 320 if(ccrtn) { 321 sslErrorLog("CCSymmEncryptDecrypt: returned %d\n", (int)ccrtn); 322 return errSSLRecordInternal; 323 } 324#endif 325 return 0; 326} 327 328#if ENABLE_AES_GCM 329 330/* same for en/decrypt */ 331static 332int CCSymmAEADSetIV( 333 const uint8_t *iv, 334 size_t len, 335 SymCipherContext cipherCtx) 336{ 337 CCCryptorStatus ccrtn; 338 CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; 339 340 ASSERT(cryptorRef != NULL); 341 if(cryptorRef == NULL) { 342 sslErrorLog("CCSymmAEADAddIV: NULL cryptorRef\n"); 343 return errSecInternalComponent; 344 } 345 ccrtn = CCCryptorGCMAddIV(cryptorRef, iv, len); 346#if SSL_DEBUG 347 if(ccrtn) { 348 sslErrorLog("CCSymmAEADAddIV: returned %d\n", (int)ccrtn); 349 return errSSLRecordInternal; 350 } 351#endif 352 return 0; 353} 354 355/* same for en/decrypt */ 356static 357int CCSymmAddADD( 358 const uint8_t *src, 359 size_t len, 360 SymCipherContext cipherCtx) 361{ 362 CCCryptorStatus ccrtn; 363 CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; 364 365 ASSERT(cryptorRef != NULL); 366 if(cryptorRef == NULL) { 367 sslErrorLog("CCSymmAddADD: NULL cryptorRef\n"); 368 return errSSLRecordInternal; 369 } 370 ccrtn = CCCryptorGCMAddADD(cryptorRef, src, len); 371#if SSL_DEBUG 372 if(ccrtn) { 373 sslErrorLog("CCSymmAddADD: returned %d\n", (int)ccrtn); 374 return errSSLRecordInternal; 375 } 376#endif 377 return 0; 378} 379 380static 381int CCSymmAEADEncrypt( 382 const uint8_t *src, 383 uint8_t *dest, 384 size_t len, 385 SymCipherContext cipherCtx) 386{ 387 CCCryptorStatus ccrtn; 388 CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; 389 390 ASSERT(cryptorRef != NULL); 391 if(cryptorRef == NULL) { 392 sslErrorLog("CCSymmAEADEncrypt: NULL cryptorRef\n"); 393 return errSSLRecordInternal; 394 } 395 ccrtn = CCCryptorGCMEncrypt(cryptorRef, src, len, dest); 396#if SSL_DEBUG 397 if(ccrtn) { 398 sslErrorLog("CCSymmAEADEncrypt: returned %d\n", (int)ccrtn); 399 return errSSLRecordInternal; 400 } 401#endif 402 return 0; 403} 404 405 406static 407int CCSymmAEADDecrypt( 408 const uint8_t *src, 409 uint8_t *dest, 410 size_t len, 411 SymCipherContext cipherCtx) 412{ 413 CCCryptorStatus ccrtn; 414 CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; 415 416 ASSERT(cipherCtx != NULL); 417 ASSERT(cipherCtx->cryptorRef != NULL); 418 if(cipherCtx->cryptorRef == NULL) { 419 sslErrorLog("CCSymmAEADDecrypt: NULL cryptorRef\n"); 420 return errSSLRecordInternal; 421 } 422 ccrtn = CCCryptorGCMDecrypt(cryptorRef, src, len, dest); 423#if SSL_DEBUG 424 if(ccrtn) { 425 sslErrorLog("CCSymmAEADDecrypt: returned %d\n", (int)ccrtn); 426 return errSSLRecordInternal; 427 } 428#endif 429 return 0; 430} 431 432 433static 434int CCSymmAEADDone( 435 uint8_t *mac, 436 size_t *macLen, 437 SymCipherContext cipherCtx) 438{ 439 CCCryptorStatus ccrtn; 440 CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; 441 442 ASSERT(cipherCtx != NULL); 443 ASSERT(cipherCtx->cryptorRef != NULL); 444 if(cipherCtx->cryptorRef == NULL) { 445 sslErrorLog("CCSymmAEADDone: NULL cryptorRef\n"); 446 return errSSLRecordInternal; 447 } 448 ccrtn = CCCryptorGCMFinal(cipherCtx->cryptorRef, mac, macLen); 449 CCCryptorStatus ccrtn2 = CCCryptorGCMReset(cipherCtx->cryptorRef); 450 if (ccrtn == kCCSuccess) 451 ccrtn = ccrtn2; 452#if SSL_DEBUG 453 if(ccrtn) { 454 sslErrorLog("CCSymmAEADDone: returned %d\n", (int)ccrtn); 455 return errSSLRecordInternal; 456 } 457#endif 458 return 0; 459} 460#endif 461 462static 463int CCSymmFinish( 464 SymCipherContext cipherCtx) 465{ 466 CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; 467 468 if(cryptorRef) { 469 CCCryptorRelease(cryptorRef); 470 } 471 return 0; 472} 473 474#endif /* KERNEL */ 475 476#if ENABLE_DES 477const SSLSymmetricCipher SSLCipherDES_CBC = { 478 .params = &SSLCipherDES_CBCParams, 479 .c.cipher = { 480 .initialize = CCSymmInit, 481 .encrypt = CCSymmEncryptDecrypt, 482 .decrypt = CCSymmEncryptDecrypt 483 }, 484 .finish = CCSymmFinish 485}; 486#endif /* ENABLE_DES */ 487 488#if ENABLE_3DES 489const SSLSymmetricCipher SSLCipher3DES_CBC = { 490 .params = &SSLCipher3DES_CBCParams, 491 .c.cipher = { 492 .initialize = CCSymmInit, 493 .encrypt = CCSymmEncryptDecrypt, 494 .decrypt = CCSymmEncryptDecrypt 495 }, 496 .finish = CCSymmFinish 497}; 498#endif /* ENABLE_3DES */ 499 500#if ENABLE_RC4 501const SSLSymmetricCipher SSLCipherRC4_128 = { 502 .params = &SSLCipherRC4_128Params, 503 .c.cipher = { 504 .initialize = CCSymmInit, 505 .encrypt = CCSymmEncryptDecrypt, 506 .decrypt = CCSymmEncryptDecrypt 507 }, 508 .finish = CCSymmFinish 509}; 510#endif /* ENABLE_RC4 */ 511 512#if ENABLE_RC2 513const SSLSymmetricCipher SSLCipherRC2_128 = { 514 .params = &SSLCipherRC2_128Params, 515 .c.cipher = { 516 .initialize = CCSymmInit, 517 .encrypt = CCSymmEncryptDecrypt, 518 .decrypt = CCSymmEncryptDecrypt 519 }, 520 .finish = CCSymmFinish 521}; 522#endif /* ENABLE_RC2*/ 523 524#if ENABLE_AES 525const SSLSymmetricCipher SSLCipherAES_128_CBC = { 526 .params = &SSLCipherAES_128_CBCParams, 527 .c.cipher = { 528 .initialize = CCSymmInit, 529 .encrypt = CCSymmEncryptDecrypt, 530 .decrypt = CCSymmEncryptDecrypt 531 }, 532 .finish = CCSymmFinish 533}; 534#endif /* ENABLE_AES */ 535 536#if ENABLE_AES256 537const SSLSymmetricCipher SSLCipherAES_256_CBC = { 538 .params = &SSLCipherAES_256_CBCParams, 539 .c.cipher = { 540 .initialize = CCSymmInit, 541 .encrypt = CCSymmEncryptDecrypt, 542 .decrypt = CCSymmEncryptDecrypt 543 }, 544 .finish = CCSymmFinish 545}; 546#endif /* ENABLE_AES256 */ 547 548#if ENABLE_AES_GCM 549const SSLSymmetricCipher SSLCipherAES_128_GCM = { 550 .params = &SSLCipherAES_128_GCMParams, 551 .c.aead = { 552 .initialize = CCSymmInit, 553 .setIV = CCSymmAEADSetIV, 554 .update = CCSymmAddADD, 555 .encrypt = CCSymmAEADEncrypt, 556 .decrypt = CCSymmAEADDecrypt, 557 .done = CCSymmAEADDone 558 }, 559 .finish = CCSymmFinish 560}; 561 562const SSLSymmetricCipher SSLCipherAES_256_GCM = { 563 .params = &SSLCipherAES_256_GCMParams, 564 .c.aead = { 565 .initialize = CCSymmInit, 566 .setIV = CCSymmAEADSetIV, 567 .update = CCSymmAddADD, 568 .encrypt = CCSymmAEADEncrypt, 569 .decrypt = CCSymmAEADDecrypt, 570 .done = CCSymmAEADDone 571 }, 572 .finish = CCSymmFinish 573}; 574#endif /* ENABLE_AES_GCM */ 575