]> git.saurik.com Git - apple/security.git/blob - libsecurity_apple_csp/lib/aescsp.cpp
Security-55471.tar.gz
[apple/security.git] / libsecurity_apple_csp / lib / 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 CSSM_SIZE 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, session(), CSSM_ALGID_AES,
116 encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
117 keyData, keyLen);
118
119 switch(keyLen) {
120 case MIN_AES_KEY_BITS / 8:
121 case MID_AES_KEY_BITS / 8:
122 case MAX_AES_KEY_BITS / 8:
123 break;
124 default:
125 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
126 }
127
128 /*
129 * Validate context
130 * block size is optional
131 */
132 mBlockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE);
133 if(mBlockSize == 0) {
134 mBlockSize = DEFAULT_BLOCK_SIZE;
135 }
136
137
138 /*
139 * Delete existing key if key size or block size changed
140 */
141 if((lastBlockSize == mBlockSize) && (mRawKeySize == keyLen)) {
142 sameKeyAndBlockSizes = true;
143 }
144 if((mAesKey != NULL) && !sameKeyAndBlockSizes) {
145 deleteKey();
146 }
147
148 int opt128 = 0;
149 #if !GLADMAN_AES_128_ENABLE
150 if((mBlockSize == (MIN_AES_BLOCK_BITS/8)) &&
151 (keyLen == (MIN_AES_KEY_BITS/8)) &&
152 doAES128) {
153 opt128 = 1;
154 }
155 #endif /* !GLADMAN_AES_128_ENABLE */
156
157 /* create new key if needed */
158 if(mAesKey == NULL) {
159 mAesKey = (keyInstance *)session().malloc(sizeof(keyInstance));
160 }
161
162 /* init key only if key size, block size, or key bits have changed */
163 if(!sameKeyAndBlockSizes || memcmp(mRawKey, keyData, mRawKeySize)) {
164 int artn = makeKey((keyInstance *)mAesKey,
165 (int)keyLen * 8,
166 mBlockSize * 8,
167 (word8 *)keyData,
168 opt128);
169 if(artn < 0) {
170 aesError(artn, "makeKey");
171 }
172
173 /* save this raw key data */
174 memmove(mRawKey, keyData, mRawKeySize);
175 mRawKeySize = (uint32)keyLen;
176 }
177
178 #if !GLADMAN_AES_128_ENABLE
179 if(opt128) {
180 /* optimized path */
181 mEncryptFcn = rijndaelBlockEncrypt128;
182 mDecryptFcn = rijndaelBlockDecrypt128;
183 }
184 else {
185 /* common standard path */
186 mEncryptFcn = rijndaelBlockEncrypt;
187 mDecryptFcn = rijndaelBlockDecrypt;
188 }
189 #else
190 /* common standard path */
191 mEncryptFcn = rijndaelBlockEncrypt;
192 mDecryptFcn = rijndaelBlockDecrypt;
193 #endif /* !GLADMAN_AES_128_ENABLE */
194
195 /* Finally, have BlockCryptor do its setup */
196 setup(mBlockSize, context);
197 mInitFlag = true;
198 }
199
200 /*
201 * Functions called by BlockCryptor
202 */
203 void AESContext::encryptBlock(
204 const void *plainText, // length implied (one block)
205 size_t plainTextLen,
206 void *cipherText,
207 size_t &cipherTextLen, // in/out, throws on overflow
208 bool final) // ignored
209 {
210 if(plainTextLen != mBlockSize) {
211 CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
212 }
213 if(cipherTextLen < mBlockSize) {
214 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
215 }
216 int artn = mEncryptFcn(mAesKey,
217 (word8 *)plainText,
218 (word8 *)cipherText);
219 if(artn < 0) {
220 aesError(artn, "rijndaelBlockEncrypt");
221 }
222 cipherTextLen = mBlockSize;
223 }
224
225 void AESContext::decryptBlock(
226 const void *cipherText, // length implied (one cipher block)
227 size_t cipherTextLen,
228 void *plainText,
229 size_t &plainTextLen, // in/out, throws on overflow
230 bool final) // ignored
231 {
232 if(plainTextLen < mBlockSize) {
233 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
234 }
235 int artn = mDecryptFcn(mAesKey,
236 (word8 *)cipherText,
237 (word8 *)plainText);
238 if(artn < 0) {
239 aesError(artn, "rijndaelBlockDecrypt");
240 }
241 plainTextLen = mBlockSize;
242 }
243