]>
Commit | Line | Data |
---|---|---|
bac41a7b 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 | #define DEBUG_ED 0 /* general encrypt/decrypt debug */ | |
32 | #if DEBUG_ED | |
33 | #define dprint(s) printf s | |
34 | #else | |
35 | #define dprint(s) | |
36 | #endif | |
37 | ||
38 | #define DEBUG_SIZES 0 | |
39 | #if DEBUG_SIZES | |
40 | #define logSize(s, final, encr, ibs, in, out) \ | |
41 | printf("%s final %d encr %d inbufsz %d inSize %d outSize %d\n", \ | |
42 | s, final, encr, ibs, in, out) | |
43 | #else | |
44 | #define logSize(s, final, encr, ibs, in, out) | |
45 | #endif | |
46 | ||
47 | /* | |
48 | * AES symmetric key generation. | |
49 | * This algorithm has key size restrictions which don't fit with the | |
50 | * standard AppleSymmKeyGenContext model so we have to do some addditional | |
51 | * checking. | |
52 | */ | |
53 | void AESKeyGenContext::generate( | |
54 | const Context &context, | |
55 | CssmKey &symKey, | |
56 | CssmKey &dummyKey) | |
57 | { | |
58 | uint32 reqKeySize = context.getInt( | |
59 | CSSM_ATTRIBUTE_KEY_LENGTH, | |
60 | CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); | |
61 | switch(reqKeySize) { | |
62 | case MIN_AES_KEY_BITS: | |
63 | case MID_AES_KEY_BITS: | |
64 | case MAX_AES_KEY_BITS: | |
65 | break; | |
66 | default: | |
67 | CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); | |
68 | } | |
69 | AppleSymmKeyGenContext::generateSymKey( | |
70 | context, | |
71 | session(), | |
72 | symKey); | |
73 | } | |
74 | ||
75 | /* | |
76 | * AES encrypt/decrypt. | |
77 | */ | |
78 | AESContext::~AESContext() | |
79 | { | |
80 | deleteKey(); | |
81 | memset(mRawKey, 0, MAX_AES_KEY_BITS / 8); | |
82 | mInitFlag = false; | |
83 | } | |
84 | ||
85 | void AESContext::aesError( | |
86 | int artn, | |
87 | const char *errStr) | |
88 | { | |
89 | CSSM_RETURN crtn; | |
90 | errorLog2("AESContext: %s : %d\n", errStr, artn); | |
91 | switch(artn) { | |
92 | case BAD_KEY_INSTANCE: | |
93 | default: | |
94 | crtn = CSSMERR_CSP_INTERNAL_ERROR; | |
95 | break; | |
96 | case BAD_KEY_MAT: | |
97 | crtn = CSSMERR_CSP_INVALID_KEY; | |
98 | break; | |
99 | } | |
100 | CssmError::throwMe(crtn); | |
101 | } | |
102 | ||
103 | void AESContext::deleteKey() | |
104 | { | |
105 | if(mAesKey) { | |
106 | memset(mAesKey, 0, sizeof(keyInstance)); | |
107 | session().free(mAesKey); | |
108 | mAesKey = NULL; | |
109 | } | |
110 | } | |
111 | ||
112 | /* | |
113 | * Standard CSPContext init, called from CSPFullPluginSession::init(). | |
114 | * Reusable, e.g., query followed by en/decrypt. Even reusable after context | |
115 | * changed (i.e., new IV in Encrypted File System). | |
116 | */ | |
117 | void AESContext::init( | |
118 | const Context &context, | |
119 | bool encrypting) | |
120 | { | |
121 | if(mInitFlag && !opStarted()) { | |
122 | return; | |
123 | } | |
124 | ||
125 | UInt32 keyLen; | |
126 | UInt8 *keyData = NULL; | |
127 | unsigned lastBlockSize = mBlockSize; // may be 0 (first time thru) | |
128 | bool sameKeyAndBlockSizes = false; | |
129 | ||
130 | /* obtain key from context */ | |
131 | symmetricKeyBits(context, CSSM_ALGID_AES, | |
132 | encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, | |
133 | keyData, keyLen); | |
134 | ||
135 | /* | |
136 | * Validate context | |
137 | * block size is optional | |
138 | */ | |
139 | mBlockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE); | |
140 | if(mBlockSize == 0) { | |
141 | mBlockSize = DEFAULT_BLOCK_SIZE; | |
142 | } | |
143 | ||
144 | ||
145 | /* | |
146 | * Delete existing key if key size or block size changed | |
147 | */ | |
148 | if((lastBlockSize == mBlockSize) && (mRawKeySize == keyLen)) { | |
149 | sameKeyAndBlockSizes = true; | |
150 | } | |
151 | if((mAesKey != NULL) && !sameKeyAndBlockSizes) { | |
152 | deleteKey(); | |
153 | } | |
154 | ||
155 | int opt128 = 0; | |
156 | if((mBlockSize == (MIN_AES_BLOCK_BITS/8)) && | |
157 | (keyLen == (MIN_AES_KEY_BITS/8)) && | |
158 | doAES128) { | |
159 | opt128 = 1; | |
160 | } | |
161 | ||
162 | /* create new key if needed */ | |
163 | if(mAesKey == NULL) { | |
164 | mAesKey = (keyInstance *)session().malloc(sizeof(keyInstance)); | |
165 | } | |
166 | ||
167 | /* init key only if key size, block size, or key bits have changed */ | |
168 | if(!sameKeyAndBlockSizes || memcmp(mRawKey, keyData, mRawKeySize)) { | |
169 | int artn = makeKey((keyInstance *)mAesKey, | |
170 | keyLen * 8, | |
171 | mBlockSize * 8, | |
172 | (word8 *)keyData, | |
173 | opt128); | |
174 | if(artn < 0) { | |
175 | aesError(artn, "makeKey"); | |
176 | } | |
177 | ||
178 | /* save this raw key data */ | |
179 | memmove(mRawKey, keyData, mRawKeySize); | |
180 | mRawKeySize = keyLen; | |
181 | } | |
182 | ||
183 | if(opt128) { | |
184 | /* optimized path */ | |
185 | mEncryptFcn = rijndaelBlockEncrypt128; | |
186 | mDecryptFcn = rijndaelBlockDecrypt128; | |
187 | } | |
188 | else { | |
189 | /* common standard path */ | |
190 | mEncryptFcn = rijndaelBlockEncrypt; | |
191 | mDecryptFcn = rijndaelBlockDecrypt; | |
192 | } | |
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 | void *plainText, | |
227 | size_t &plainTextLen, // in/out, throws on overflow | |
228 | bool final) // ignored | |
229 | { | |
230 | if(plainTextLen < mBlockSize) { | |
231 | CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); | |
232 | } | |
233 | int artn = mDecryptFcn(mAesKey, | |
234 | (word8 *)cipherText, | |
235 | (word8 *)plainText); | |
236 | if(artn < 0) { | |
237 | aesError(artn, "rijndaelBlockDecrypt"); | |
238 | } | |
239 | plainTextLen = mBlockSize; | |
240 | } | |
241 |