]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_csp/lib/aescsp.cpp
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / libsecurity_apple_csp / lib / aescsp.cpp
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 * aescsp.cpp - glue between BlockCryptor and AES implementation
21 */
22
23 #include "aescspi.h"
24 #include "rijndaelApi.h"
25 #include "rijndael-alg-ref.h"
26 #include "cspdebugging.h"
27
28 #define DEFAULT_BLOCK_SIZE (MIN_AES_BLOCK_BITS / 8)
29
30 /*
31 * AES symmetric key generation.
32 * This algorithm has key size restrictions which don't fit with the
33 * standard AppleSymmKeyGenContext model so we have to do some addditional
34 * checking.
35 */
36 void AESKeyGenContext::generate(
37 const Context &context,
38 CssmKey &symKey,
39 CssmKey &dummyKey)
40 {
41 uint32 reqKeySize = context.getInt(
42 CSSM_ATTRIBUTE_KEY_LENGTH,
43 CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
44 switch(reqKeySize) {
45 case MIN_AES_KEY_BITS:
46 case MID_AES_KEY_BITS:
47 case MAX_AES_KEY_BITS:
48 break;
49 default:
50 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
51 }
52 AppleSymmKeyGenContext::generateSymKey(
53 context,
54 session(),
55 symKey);
56 }
57
58 /*
59 * AES encrypt/decrypt.
60 */
61 AESContext::~AESContext()
62 {
63 deleteKey();
64 memset(mRawKey, 0, MAX_AES_KEY_BITS / 8);
65 mInitFlag = false;
66 }
67
68 void AESContext::aesError(
69 int artn,
70 const char *errStr)
71 {
72 CSSM_RETURN crtn;
73 errorLog2("AESContext: %s : %d\n", errStr, artn);
74 switch(artn) {
75 case BAD_KEY_INSTANCE:
76 default:
77 crtn = CSSMERR_CSP_INTERNAL_ERROR;
78 break;
79 case BAD_KEY_MAT:
80 crtn = CSSMERR_CSP_INVALID_KEY;
81 break;
82 }
83 CssmError::throwMe(crtn);
84 }
85
86 void AESContext::deleteKey()
87 {
88 if(mAesKey) {
89 memset(mAesKey, 0, sizeof(keyInstance));
90 session().free(mAesKey);
91 mAesKey = NULL;
92 }
93 }
94
95 /*
96 * Standard CSPContext init, called from CSPFullPluginSession::init().
97 * Reusable, e.g., query followed by en/decrypt. Even reusable after context
98 * changed (i.e., new IV in Encrypted File System).
99 */
100 void AESContext::init(
101 const Context &context,
102 bool encrypting)
103 {
104 if(mInitFlag && !opStarted()) {
105 return;
106 }
107
108 CSSM_SIZE keyLen;
109 uint8 *keyData = NULL;
110 unsigned lastBlockSize = mBlockSize; // may be 0 (first time thru)
111 bool sameKeyAndBlockSizes = false;
112
113 /* obtain key from context */
114 symmetricKeyBits(context, session(), CSSM_ALGID_AES,
115 encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
116 keyData, keyLen);
117
118 switch(keyLen) {
119 case MIN_AES_KEY_BITS / 8:
120 case MID_AES_KEY_BITS / 8:
121 case MAX_AES_KEY_BITS / 8:
122 break;
123 default:
124 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
125 }
126
127 /*
128 * Validate context
129 * block size is optional
130 */
131 mBlockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE);
132 if(mBlockSize == 0) {
133 mBlockSize = DEFAULT_BLOCK_SIZE;
134 }
135
136
137 /*
138 * Delete existing key if key size or block size changed
139 */
140 if((lastBlockSize == mBlockSize) && (mRawKeySize == keyLen)) {
141 sameKeyAndBlockSizes = true;
142 }
143 if((mAesKey != NULL) && !sameKeyAndBlockSizes) {
144 deleteKey();
145 }
146
147 int opt128 = 0;
148 #if !GLADMAN_AES_128_ENABLE
149 if((mBlockSize == (MIN_AES_BLOCK_BITS/8)) &&
150 (keyLen == (MIN_AES_KEY_BITS/8)) &&
151 doAES128) {
152 opt128 = 1;
153 }
154 #endif /* !GLADMAN_AES_128_ENABLE */
155
156 /* create new key if needed */
157 if(mAesKey == NULL) {
158 mAesKey = (keyInstance *)session().malloc(sizeof(keyInstance));
159 }
160
161 /* init key only if key size, block size, or key bits have changed */
162 if(!sameKeyAndBlockSizes || memcmp(mRawKey, keyData, mRawKeySize)) {
163 int artn = makeKey((keyInstance *)mAesKey,
164 (int)keyLen * 8,
165 mBlockSize * 8,
166 (word8 *)keyData,
167 opt128);
168 if(artn < 0) {
169 aesError(artn, "makeKey");
170 }
171
172 /* save this raw key data */
173 memmove(mRawKey, keyData, mRawKeySize);
174 mRawKeySize = (uint32)keyLen;
175 }
176
177 #if !GLADMAN_AES_128_ENABLE
178 if(opt128) {
179 /* optimized path */
180 mEncryptFcn = rijndaelBlockEncrypt128;
181 mDecryptFcn = rijndaelBlockDecrypt128;
182 }
183 else {
184 /* common standard path */
185 mEncryptFcn = rijndaelBlockEncrypt;
186 mDecryptFcn = rijndaelBlockDecrypt;
187 }
188 #else
189 /* common standard path */
190 mEncryptFcn = rijndaelBlockEncrypt;
191 mDecryptFcn = rijndaelBlockDecrypt;
192 #endif /* !GLADMAN_AES_128_ENABLE */
193
194 /* Finally, have BlockCryptor do its setup */
195 setup(mBlockSize, context);
196 mInitFlag = true;
197 }
198
199 /*
200 * Functions called by BlockCryptor
201 */
202 void AESContext::encryptBlock(
203 const void *plainText, // length implied (one block)
204 size_t plainTextLen,
205 void *cipherText,
206 size_t &cipherTextLen, // in/out, throws on overflow
207 bool final) // ignored
208 {
209 if(plainTextLen != mBlockSize) {
210 CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
211 }
212 if(cipherTextLen < mBlockSize) {
213 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
214 }
215 int artn = mEncryptFcn(mAesKey,
216 (word8 *)plainText,
217 (word8 *)cipherText);
218 if(artn < 0) {
219 aesError(artn, "rijndaelBlockEncrypt");
220 }
221 cipherTextLen = mBlockSize;
222 }
223
224 void AESContext::decryptBlock(
225 const void *cipherText, // length implied (one cipher block)
226 size_t cipherTextLen,
227 void *plainText,
228 size_t &plainTextLen, // in/out, throws on overflow
229 bool final) // ignored
230 {
231 if(plainTextLen < mBlockSize) {
232 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
233 }
234 int artn = mDecryptFcn(mAesKey,
235 (word8 *)cipherText,
236 (word8 *)plainText);
237 if(artn < 0) {
238 aesError(artn, "rijndaelBlockDecrypt");
239 }
240 plainTextLen = mBlockSize;
241 }
242