1/* 2 * Copyright (c) 2000-2001,2011-2012,2014 Apple 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 * gladmanContext.cpp - glue between BlockCryptor and Gladman AES implementation 21 */ 22 23#include "gladmanContext.h" 24#include "cspdebugging.h" 25#include <CommonCrypto/CommonCryptor.h> 26 27/* 28 * AES encrypt/decrypt. 29 */ 30GAESContext::GAESContext(AppleCSPSession &session) : 31 BlockCryptor(session), 32 mAesKey(NULL), 33 mInitFlag(false), 34 mRawKeySize(0), 35 mWasEncrypting(false) 36{ 37 cbcCapable(false); 38 multiBlockCapable(false); 39} 40 41GAESContext::~GAESContext() 42{ 43 if(mAesKey) { 44 CCCryptorFinal(mAesKey,NULL,0,NULL); 45 CCCryptorRelease(mAesKey); 46 mAesKey = NULL; 47 } 48 49 deleteKey(); 50 memset(mRawKey, 0, MAX_AES_KEY_BITS / 8); 51 mInitFlag = false; 52} 53 54void GAESContext::deleteKey() 55{ 56 mRawKeySize = 0; 57} 58 59/* 60 * Standard CSPContext init, called from CSPFullPluginSession::init(). 61 * Reusable, e.g., query followed by en/decrypt. Even reusable after context 62 * changed (i.e., new IV in Encrypted File System). 63 */ 64void GAESContext::init( 65 const Context &context, 66 bool encrypting) 67{ 68 if(mInitFlag && !opStarted()) { 69 return; 70 } 71 72 CSSM_SIZE keyLen; 73 uint8 *keyData = NULL; 74 bool sameKeySize = false; 75 76 /* obtain key from context */ 77 symmetricKeyBits(context, session(), CSSM_ALGID_AES, 78 encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, 79 keyData, keyLen); 80 81 switch(keyLen) { 82 case kCCKeySizeAES128: 83 case kCCKeySizeAES192: 84 case kCCKeySizeAES256: 85 break; 86 default: 87 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); 88 } 89 90 /* 91 * Delete existing key if key size changed 92 */ 93 if(mRawKeySize == keyLen) { 94 sameKeySize = true; 95 } 96 else { 97 deleteKey(); 98 } 99 100 /* 101 * Init key only if key size or key bits have changed, or 102 * we're doing a different operation than the previous key 103 * was scheduled for. 104 */ 105 if(!sameKeySize || (mWasEncrypting != encrypting) || 106 memcmp(mRawKey, keyData, mRawKeySize)) { 107 (void) CCCryptorCreateWithMode(0, kCCModeECB, kCCAlgorithmAES128, ccDefaultPadding, NULL, keyData, keyLen, NULL, 0, 0, 0, &mAesKey); 108 109 /* save this raw key data */ 110 memmove(mRawKey, keyData, keyLen); 111 mRawKeySize = (uint32)keyLen; 112 mWasEncrypting = encrypting; 113 } 114 115 /* we handle CBC, and hence the IV, ourselves */ 116 CSSM_ENCRYPT_MODE cssmMode = context.getInt(CSSM_ATTRIBUTE_MODE); 117 switch (cssmMode) { 118 /* no mode attr --> 0 == CSSM_ALGMODE_NONE, not currently supported */ 119 case CSSM_ALGMODE_CBCPadIV8: 120 case CSSM_ALGMODE_CBC_IV8: 121 { 122 CssmData *iv = context.get<CssmData>(CSSM_ATTRIBUTE_INIT_VECTOR); 123 if(iv == NULL) { 124 CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); 125 } 126 if(iv->Length != kCCBlockSizeAES128) { 127 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR); 128 } 129 } 130 break; 131 default: 132 break; 133 } 134 135 /* Finally, have BlockCryptor do its setup */ 136 setup(GLADMAN_BLOCK_SIZE_BYTES, context); 137 mInitFlag = true; 138} 139 140/* 141 * Functions called by BlockCryptor 142 * FIXME make this multi-block capabl3e 143 */ 144void GAESContext::encryptBlock( 145 const void *plainText, // length implied (one block) 146 size_t plainTextLen, 147 void *cipherText, 148 size_t &cipherTextLen, // in/out, throws on overflow 149 bool final) // ignored 150{ 151 if(cipherTextLen < plainTextLen) { 152 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); 153 } 154 (void) CCCryptorEncryptDataBlock(mAesKey, NULL, plainText, plainTextLen, cipherText); 155 156 cipherTextLen = plainTextLen; 157} 158 159void GAESContext::decryptBlock( 160 const void *cipherText, // length implied (one cipher block) 161 size_t cipherTextLen, 162 void *plainText, 163 size_t &plainTextLen, // in/out, throws on overflow 164 bool final) // ignored 165{ 166 if(plainTextLen < cipherTextLen) { 167 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); 168 } 169 (void) CCCryptorDecryptDataBlock(mAesKey, NULL, cipherText, cipherTextLen, plainText); 170 plainTextLen = cipherTextLen; 171} 172 173