]> git.saurik.com Git - apple/security.git/blame - AppleCSP/AES/aescsp.cpp
Security-163.tar.gz
[apple/security.git] / AppleCSP / AES / aescsp.cpp
CommitLineData
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
bac41a7b
A
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 */
37void 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 */
62AESContext::~AESContext()
63{
64 deleteKey();
65 memset(mRawKey, 0, MAX_AES_KEY_BITS / 8);
66 mInitFlag = false;
67}
68
69void 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
87void 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 */
101void 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;
29654253 140#if !GLADMAN_AES_128_ENABLE
bac41a7b
A
141 if((mBlockSize == (MIN_AES_BLOCK_BITS/8)) &&
142 (keyLen == (MIN_AES_KEY_BITS/8)) &&
143 doAES128) {
144 opt128 = 1;
145 }
29654253 146#endif /* !GLADMAN_AES_128_ENABLE */
bac41a7b
A
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
29654253 169#if !GLADMAN_AES_128_ENABLE
bac41a7b
A
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 }
29654253
A
180#else
181 /* common standard path */
182 mEncryptFcn = rijndaelBlockEncrypt;
183 mDecryptFcn = rijndaelBlockDecrypt;
df0e469f 184#endif /* !GLADMAN_AES_128_ENABLE */
bac41a7b
A
185
186 /* Finally, have BlockCryptor do its setup */
187 setup(mBlockSize, context);
188 mInitFlag = true;
189}
190
191/*
192 * Functions called by BlockCryptor
193 */
194void 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
216void 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