]> git.saurik.com Git - apple/security.git/blame - AppleCSP/AES/aescsp.cpp
Security-28.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
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 */
53void 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 */
78AESContext::~AESContext()
79{
80 deleteKey();
81 memset(mRawKey, 0, MAX_AES_KEY_BITS / 8);
82 mInitFlag = false;
83}
84
85void 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
103void 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 */
117void 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 */
202void 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
224void 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