]> git.saurik.com Git - apple/security.git/blob - AppleCSP/AES/rijndaelApi.c
Security-29.tar.gz
[apple/security.git] / AppleCSP / AES / rijndaelApi.c
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 * rijndaelApi.c - AES API layer
21 *
22 * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto
23 * and Vincent Rijmen
24 */
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "rijndael-alg-ref.h"
29 #include "rijndaelApi.h"
30
31 #ifdef ALTIVEC_ENABLE
32 /* this goes somewhere else and gets init'd by the plugin object.... */
33 /* as of 4/11/2001, the vectorized routines do NOT work */
34 int gHasAltivec = 0;
35 #endif
36
37 int doAES128 = 1;
38
39 #define CBC_DEBUG 0
40 #if CBC_DEBUG
41 static void dumpChainBuf(cipherInstance *cipher, char *op)
42 {
43 int t,j;
44 int columns = cipher->blockLen / 32;
45
46 printf("chainBuf %s: ", op);
47 for (j = 0; j < columns; j++) {
48 for(t = 0; t < 4; t++) {
49 printf("%02x ", cipher->chainBlock[t][j]);
50 }
51 }
52 printf("\n");
53 }
54 #else
55 #define dumpChainBuf(c, o)
56 #endif
57
58 int makeKey(
59 keyInstance *key,
60 int keyLen, // in BITS
61 int blockLen, // in BITS
62 word8 *keyMaterial,
63 int enable128Opt)
64 {
65 unsigned keyBytes;
66 unsigned i;
67
68 if (key == NULL) {
69 return BAD_KEY_INSTANCE;
70 }
71 if(keyMaterial == NULL) {
72 return BAD_KEY_MAT;
73 }
74 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
75 key->keyLen = keyLen;
76 } else {
77 return BAD_KEY_MAT;
78 }
79 key->blockLen = blockLen;
80 key->columns = blockLen / 32;
81
82 /* initialize key schedule */
83 if(enable128Opt &&
84 (keyLen == MIN_AES_KEY_BITS) &&
85 (blockLen == MIN_AES_BLOCK_BITS)) {
86 /* optimized, 128 bit key and block size */
87 word8 k[4][KC_128_OPT] __attribute__((aligned(4)));
88
89 for(i = 0; i < (MIN_AES_KEY_BITS/8); i++) {
90 /* speed this up */
91 k[i % 4][i / 4] = keyMaterial[i];
92 }
93 rijndaelKeySched128 (k, key->keySched);
94 memset(k, 0, 4 * KC_128_OPT);
95 }
96 else {
97 /* general case */
98 word8 k[4][MAXKC];
99
100 keyBytes = keyLen / 8;
101 for(i = 0; i < keyBytes; i++) {
102 k[i % 4][i / 4] = keyMaterial[i];
103 }
104 rijndaelKeySched (k, key->keyLen, key->blockLen, key->keySched);
105 memset(k, 0, 4 * MAXKC);
106 }
107 return TRUE;
108 }
109
110 /*
111 * Simplified single-block encrypt/decrypt.
112 */
113 #define AES_CONSISTENCY_CHECK 1
114
115 int rijndaelBlockEncrypt(
116 keyInstance *key,
117 word8 *input,
118 word8 *outBuffer)
119 {
120 int j, t;
121 word8 localBlock[4][MAXBC]; // working memory: encrypt/decrypt in place here
122
123 #if AES_CONSISTENCY_CHECK
124 if (key == NULL ||
125 (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256) ||
126 (key->blockLen != 128 && key->blockLen != 192 && key->blockLen != 256)) {
127 return BAD_KEY_INSTANCE;
128 }
129 #endif /* AES_CONSISTENCY_CHECK */
130
131 #if defined(__ppc__) && defined(ALTIVEC_ENABLE)
132 if(gHasAltivec && (key->blockLen == 128)) {
133 vBlockEncrypt128(key, input, outBuffer);
134 return 128;
135 }
136 #endif
137
138 for (j = 0; j < key->columns; j++) {
139 for(t = 0; t < 4; t++)
140 /* parse input stream into rectangular array */
141 localBlock[t][j] = input[4*j+t];
142 }
143 rijndaelEncrypt (localBlock, key->keyLen, key->blockLen, key->keySched);
144 for (j = 0; j < key->columns; j++) {
145 /* parse rectangular array into output ciphertext bytes */
146 for(t = 0; t < 4; t++)
147 outBuffer[4*j+t] = (word8) localBlock[t][j];
148 }
149 memset(localBlock, 0, 4 * MAXBC);
150 return key->blockLen;
151 }
152
153 int rijndaelBlockDecrypt(
154 keyInstance *key,
155 word8 *input,
156 word8 *outBuffer)
157 {
158 int j, t;
159 word8 localBlock[4][MAXBC]; // working memory: encrypt/decrypt in place here
160
161 #if AES_CONSISTENCY_CHECK
162 if (key == NULL ||
163 (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256) ||
164 (key->blockLen != 128 && key->blockLen != 192 && key->blockLen != 256)) {
165 return BAD_KEY_INSTANCE;
166 }
167 #endif /* AES_CONSISTENCY_CHECK */
168
169 #if defined(__ppc__) && defined(ALTIVEC_ENABLE)
170 if(gHasAltivec && (cipher->blockLen == 128)) {
171 vBlockDecrypt128(key, input, outBuffer);
172 return 128;
173 }
174 #endif
175
176 for (j = 0; j < key->columns; j++) {
177 for(t = 0; t < 4; t++)
178 /* parse input stream into rectangular array */
179 localBlock[t][j] = input[4*j+t];
180 }
181 rijndaelDecrypt (localBlock, key->keyLen, key->blockLen, key->keySched);
182 for (j = 0; j < key->columns; j++) {
183 /* parse rectangular array into output ciphertext bytes */
184 for(t = 0; t < 4; t++)
185 outBuffer[4*j+t] = (word8) localBlock[t][j];
186 }
187 memset(localBlock, 0, 4 * MAXBC);
188 return key->blockLen;
189 }
190
191 /*
192 * Optimized routines for 128 bit block and 128 bit key.
193 */
194 int rijndaelBlockEncrypt128(
195 keyInstance *key,
196 word8 *input,
197 word8 *outBuffer)
198 {
199 int j;
200 word8 localBlock[4][BC_128_OPT] __attribute__((aligned(4)));
201 word8 *row0 = localBlock[0];
202 word8 *row1 = localBlock[1];
203 word8 *row2 = localBlock[2];
204 word8 *row3 = localBlock[3];
205
206 /* parse input stream into rectangular array */
207 for (j = 0; j < BC_128_OPT; j++) {
208 *row0++ = *input++;
209 *row1++ = *input++;
210 *row2++ = *input++;
211 *row3++ = *input++;
212 }
213 rijndaelEncrypt128 (localBlock, key->keySched);
214
215 /* parse rectangular array into output ciphertext bytes */
216 row0 = localBlock[0];
217 row1 = localBlock[1];
218 row2 = localBlock[2];
219 row3 = localBlock[3];
220
221 for (j = 0; j < BC_128_OPT; j++) {
222 *outBuffer++ = *row0++;
223 *outBuffer++ = *row1++;
224 *outBuffer++ = *row2++;
225 *outBuffer++ = *row3++;
226 }
227 memset(localBlock, 0, 4*BC_128_OPT);
228 return MIN_AES_BLOCK_BITS;
229 }
230
231 int rijndaelBlockDecrypt128(
232 keyInstance *key,
233 word8 *input,
234 word8 *outBuffer)
235 {
236 int j;
237 word8 localBlock[4][BC_128_OPT] __attribute__((aligned(4)));
238 word8 *row0 = localBlock[0];
239 word8 *row1 = localBlock[1];
240 word8 *row2 = localBlock[2];
241 word8 *row3 = localBlock[3];
242
243 /* parse input stream into rectangular array */
244 for (j = 0; j < BC_128_OPT; j++) {
245 *row0++ = *input++;
246 *row1++ = *input++;
247 *row2++ = *input++;
248 *row3++ = *input++;
249 }
250
251 rijndaelDecrypt128 (localBlock, key->keySched);
252
253 /* parse rectangular array into output ciphertext bytes */
254 row0 = localBlock[0];
255 row1 = localBlock[1];
256 row2 = localBlock[2];
257 row3 = localBlock[3];
258
259 for (j = 0; j < BC_128_OPT; j++) {
260 *outBuffer++ = *row0++;
261 *outBuffer++ = *row1++;
262 *outBuffer++ = *row2++;
263 *outBuffer++ = *row3++;
264 }
265 memset(localBlock, 0, 4*BC_128_OPT);
266 return MIN_AES_BLOCK_BITS;
267 }
268