]> git.saurik.com Git - apple/xnu.git/blob - bsd/crypto/aes/i386/aesxts.c
xnu-1699.22.73.tar.gz
[apple/xnu.git] / bsd / crypto / aes / i386 / aesxts.c
1 /*
2 * Copyright (c) 2010 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include "aesxts.h"
25 #include <sys/types.h>
26 #include <string.h>
27 #include <libkern/libkern.h>
28
29 int
30 aes_encrypt_key(const uint8_t *key, int key_len, aesedp_encrypt_ctx cx[1]);
31
32 int
33 aes_decrypt_key(const uint8_t *key, int key_len, aesedp_decrypt_ctx cx[1]);
34
35 int
36 aes_encrypt(const uint8_t *Plaintext, uint8_t *Ciphertext, aesedp_encrypt_ctx *ctx);
37
38 int
39 aes_decrypt(const uint8_t *Ciphertext, uint8_t *Plaintext, aesedp_decrypt_ctx *ctx);
40
41
42 /* error codes [will be expanded in future releases] */
43 enum {
44 CRYPT_OK=0, /* Result OK */
45 CRYPT_ERROR=1, /* Generic Error */
46 CRYPT_INVALID_KEYSIZE=3, /* Invalid key size given */
47 CRYPT_INVALID_ARG=16, /* Generic invalid argument */
48 };
49
50 static int
51 aesedp_keysize(int *keysize)
52 {
53 switch (*keysize) {
54 case 16:
55 case 24:
56 case 32:
57 return CRYPT_OK;
58 default:
59 return CRYPT_INVALID_KEYSIZE;
60 }
61 }
62
63 static int
64 aesedp_setup(const uint8_t *key, int keylen, int num_rounds __unused, aesedp_ctx *skey)
65 {
66 aesedp_ctx *ctx = (aesedp_ctx *) skey;
67 int retval;
68
69 if((retval = aesedp_keysize(&keylen)) != CRYPT_OK) return retval;
70 if((retval = aes_encrypt_key(key, keylen, &ctx->encrypt)) != CRYPT_OK) return CRYPT_ERROR;
71 if((retval = aes_decrypt_key(key, keylen, &ctx->decrypt)) != CRYPT_OK) return CRYPT_ERROR;
72 return CRYPT_OK;
73 }
74
75 #ifdef ZZZNEVER
76 static int
77 aesedp_ecb_encrypt(const uint8_t *pt, uint8_t *ct, aesedp_ctx *skey)
78 {
79 aesedp_ctx *ctx = (aesedp_ctx *) skey;
80 return aes_encrypt(pt, ct, &ctx->encrypt);
81 }
82
83
84
85 static int
86 aesedp_ecb_decrypt(const uint8_t *ct, uint8_t *pt, aesedp_ctx *skey)
87 {
88 return aes_decrypt(ct, pt, &skey->decrypt);
89 }
90 #endif
91
92
93 static void
94 aesedp_done(aesedp_ctx *skey __unused)
95 {
96 }
97
98 /** Start XTS mode
99 @param cipher The index of the cipher to use
100 @param key1 The encrypt key
101 @param key2 The tweak encrypt key
102 @param keylen The length of the keys (each) in octets
103 @param num_rounds The number of rounds for the cipher (0 == default)
104 @param xts [out] XTS structure
105 Returns CRYPT_OK upon success.
106 */
107
108 uint32_t
109 xts_start(uint32_t cipher, // ignored - we're doing this for xts-aes only
110 const uint8_t *IV __unused, // ignored
111 const uint8_t *key1, int keylen,
112 const uint8_t *key2, int tweaklen __unused, // both keys are the same size for xts
113 uint32_t num_rounds, // ignored
114 uint32_t options __unused, // ignored
115 symmetric_xts *xts)
116 {
117 uint32_t err;
118
119 /* check inputs */
120 if((key1 == NULL)|| (key2 == NULL) || (xts == NULL)) return CRYPT_INVALID_ARG;
121
122 /* schedule the two ciphers */
123 if ((err = aesedp_setup(key1, keylen, num_rounds, &xts->key1)) != 0) {
124 return err;
125 }
126 if ((err = aesedp_setup(key2, keylen, num_rounds, &xts->key2)) != 0) {
127 return err;
128 }
129 xts->cipher = cipher;
130
131 return err;
132 }
133
134
135
136
137 /** multiply by x
138 @param I The value to multiply by x (LFSR shift)
139 */
140 #if defined __x86_64__ || defined __i386__
141 extern void xts_mult_x(uint8_t *I);
142 #else
143 static void xts_mult_x(uint8_t *I)
144 {
145 uint32_t x;
146 uint8_t t, tt;
147
148 for (x = t = 0; x < 16; x++) {
149 tt = I[x] >> 7;
150 I[x] = ((I[x] << 1) | t) & 0xFF;
151 t = tt;
152 }
153 if (tt) {
154 I[0] ^= 0x87;
155 }
156 }
157 #endif
158
159 #if defined __x86_64__ || defined __i386__
160 extern int tweak_crypt(const uint8_t *P, uint8_t *C, uint8_t *T, aesedp_encrypt_ctx *ctx);
161 extern int tweak_crypt_group(const uint8_t *P, uint8_t *C, uint8_t *T, aesedp_encrypt_ctx *ctx, uint32_t lim);
162 #else
163 static int tweak_crypt(const uint8_t *P, uint8_t *C, uint8_t *T, aesedp_encrypt_ctx *ctx)
164 {
165 uint32_t x;
166 uint32_t err;
167
168 /* tweak encrypt block i */
169 for (x = 0; x < 16; x += sizeof(uint64_t)) {
170 *((uint64_t*)&C[x]) = *((uint64_t*)&P[x]) ^ *((uint64_t*)&T[x]);
171 }
172
173 if ((err = aes_encrypt(C, C, ctx)) != CRYPT_OK) {
174 return CRYPT_INVALID_KEYSIZE;
175 }
176
177 for (x = 0; x < 16; x += sizeof(uint64_t)) {
178 *((uint64_t*)&C[x]) ^= *((uint64_t*)&T[x]);
179 }
180
181 /* LFSR the tweak */
182 xts_mult_x(T);
183
184 return CRYPT_OK;
185 }
186 #endif
187
188 /** XTS Encryption
189 @param pt [in] Plaintext
190 @param ptlen Length of plaintext (and ciphertext)
191 @param ct [out] Ciphertext
192 @param tweak [in] The 128--bit encryption tweak (e.g. sector number)
193 @param xts The XTS structure
194 Returns CRYPT_OK upon success
195 */
196 int xts_encrypt(
197 const uint8_t *pt, unsigned long ptlen,
198 uint8_t *ct,
199 const uint8_t *tweak,
200 symmetric_xts *xts)
201 {
202 aesedp_encrypt_ctx *encrypt_ctx = &xts->key1.encrypt;
203 uint8_t PP[16], CC[16], T[16];
204 uint32_t i, m, mo, lim;
205 uint32_t err;
206
207 /* check inputs */
208 if((pt == NULL) || (ct == NULL)|| (tweak == NULL) || (xts == NULL)) return 1;
209
210 /* get number of blocks */
211 m = ptlen >> 4;
212 mo = ptlen & 15;
213
214 /* must have at least one full block */
215 if (m == 0) {
216 return CRYPT_INVALID_ARG;
217 }
218
219 /* encrypt the tweak */
220 if ((err = aes_encrypt(tweak, T, &xts->key2.encrypt)) != 0) {
221 return CRYPT_INVALID_KEYSIZE;
222 }
223
224 /* for i = 0 to m-2 do */
225 if (mo == 0) {
226 lim = m;
227 } else {
228 lim = m - 1;
229 }
230
231 #if defined __x86_64__ || defined __i386__
232 if (lim>0) {
233 err = tweak_crypt_group(pt, ct, T, encrypt_ctx, lim);
234 ct += (lim<<4);
235 pt += (lim<<4);
236 }
237 #else
238 for (i = 0; i < lim; i++) {
239 err = tweak_crypt(pt, ct, T, encrypt_ctx);
240 ct += 16;
241 pt += 16;
242 }
243 #endif
244
245 /* if ptlen not divide 16 then */
246 if (mo > 0) {
247 /* CC = tweak encrypt block m-1 */
248 if ((err = tweak_crypt(pt, CC, T, encrypt_ctx)) != 0) {
249 return err;
250 }
251
252 /* Cm = first ptlen % 16 bytes of CC */
253 for (i = 0; i < mo; i++) {
254 PP[i] = pt[16+i];
255 ct[16+i] = CC[i];
256 }
257
258 for (; i < 16; i++) {
259 PP[i] = CC[i];
260 }
261
262 /* Cm-1 = Tweak encrypt PP */
263 if ((err = tweak_crypt(PP, ct, T, encrypt_ctx)) != 0) {
264 return err;
265 }
266 }
267
268 return err;
269 }
270
271 #if defined __x86_64__ || defined __i386__
272 extern int tweak_uncrypt(const uint8_t *C, uint8_t *P, uint8_t *T, aesedp_decrypt_ctx *ctx);
273 extern int tweak_uncrypt_group(const uint8_t *C, uint8_t *P, uint8_t *T, aesedp_decrypt_ctx *ctx, uint32_t lim);
274 #else
275 static int tweak_uncrypt(const uint8_t *C, uint8_t *P, uint8_t *T, aesedp_decrypt_ctx *ctx)
276 {
277 uint32_t x;
278 uint32_t err;
279
280 /* tweak encrypt block i */
281 for (x = 0; x < 16; x += sizeof(uint64_t)) {
282 *((uint64_t*)&P[x]) = *((uint64_t*)&C[x]) ^ *((uint64_t*)&T[x]);
283 }
284
285 err = aes_decrypt(P, P, ctx);
286
287 for (x = 0; x < 16; x += sizeof(uint64_t)) {
288 *((uint64_t*)&P[x]) ^= *((uint64_t*)&T[x]);
289 }
290
291 /* LFSR the tweak */
292 xts_mult_x(T);
293
294 return err;
295 }
296 #endif
297
298 /** XTS Decryption
299 @param ct [in] Ciphertext
300 @param ptlen Length of plaintext (and ciphertext)
301 @param pt [out] Plaintext
302 @param tweak [in] The 128--bit encryption tweak (e.g. sector number)
303 @param xts The XTS structure
304 Returns CRYPT_OK upon success
305 */
306
307 int xts_decrypt(
308 const uint8_t *ct, unsigned long ptlen,
309 uint8_t *pt,
310 const uint8_t *tweak,
311 symmetric_xts *xts)
312 {
313 aesedp_decrypt_ctx *decrypt_ctx = &xts->key1.decrypt;
314 uint8_t PP[16], CC[16], T[16];
315 uint32_t i, m, mo, lim;
316 uint32_t err;
317
318 /* check inputs */
319 if((pt == NULL) || (ct == NULL)|| (tweak == NULL) || (xts == NULL)) return 1;
320
321 /* get number of blocks */
322 m = ptlen >> 4;
323 mo = ptlen & 15;
324
325 /* must have at least one full block */
326 if (m == 0) {
327 return CRYPT_INVALID_ARG;
328 }
329
330 /* encrypt the tweak , yes - encrypt */
331 if ((err = aes_encrypt(tweak, T, &xts->key2.encrypt)) != 0) {
332 return CRYPT_INVALID_KEYSIZE;
333 }
334
335 /* for i = 0 to m-2 do */
336 if (mo == 0) {
337 lim = m;
338 } else {
339 lim = m - 1;
340 }
341
342 #if defined __x86_64__ || defined __i386__
343 if (lim>0) {
344 err = tweak_uncrypt_group(ct, pt, T, decrypt_ctx, lim);
345 ct += (lim<<4);
346 pt += (lim<<4);
347 }
348 #else
349 for (i = 0; i < lim; i++) {
350 err = tweak_uncrypt(ct, pt, T, decrypt_ctx);
351 ct += 16;
352 pt += 16;
353 }
354 #endif
355
356 /* if ptlen not divide 16 then */
357 if (mo > 0) {
358 memcpy(CC, T, 16);
359 xts_mult_x(CC);
360
361 /* PP = tweak decrypt block m-1 */
362 if ((err = tweak_uncrypt(ct, PP, CC, decrypt_ctx)) != CRYPT_OK) {
363 return err;
364 }
365
366 /* Pm = first ptlen % 16 bytes of PP */
367 for (i = 0; i < mo; i++) {
368 CC[i] = ct[16+i];
369 pt[16+i] = PP[i];
370 }
371 for (; i < 16; i++) {
372 CC[i] = PP[i];
373 }
374
375 /* Pm-1 = Tweak uncrypt CC */
376 if ((err = tweak_uncrypt(CC, pt, T, decrypt_ctx)) != CRYPT_OK) {
377 return err;
378 }
379 }
380
381 return CRYPT_OK;
382 }
383
384
385
386 void xts_done(symmetric_xts *xts)
387 {
388 if(xts == NULL) return;
389 aesedp_done(&xts->key1);
390 aesedp_done(&xts->key2);
391 }
392