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