]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
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, | |
427c49bc A |
165 | (int)keyLen * 8, |
166 | mBlockSize * 8, | |
b1ab9ed8 A |
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); | |
427c49bc | 175 | mRawKeySize = (uint32)keyLen; |
b1ab9ed8 A |
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 |