]>
git.saurik.com Git - apple/xnu.git/blob - bsd/crypto/aes/i386/aesxts.c
2 * Copyright (c) 2010 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <sys/types.h>
27 #include <libkern/libkern.h>
30 aes_encrypt_key(const uint8_t *key
, int key_len
, aesedp_encrypt_ctx cx
[1]);
33 aes_decrypt_key(const uint8_t *key
, int key_len
, aesedp_decrypt_ctx cx
[1]);
36 aes_encrypt(const uint8_t *Plaintext
, uint8_t *Ciphertext
, aesedp_encrypt_ctx
*ctx
);
39 aes_decrypt(const uint8_t *Ciphertext
, uint8_t *Plaintext
, aesedp_decrypt_ctx
*ctx
);
42 /* error codes [will be expanded in future releases] */
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 */
51 aesedp_keysize(int *keysize
)
59 return CRYPT_INVALID_KEYSIZE
;
64 aesedp_setup(const uint8_t *key
, int keylen
, int num_rounds __unused
, aesedp_ctx
*skey
)
66 aesedp_ctx
*ctx
= (aesedp_ctx
*) skey
;
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
;
77 aesedp_ecb_encrypt(const uint8_t *pt
, uint8_t *ct
, aesedp_ctx
*skey
)
79 aesedp_ctx
*ctx
= (aesedp_ctx
*) skey
;
80 return aes_encrypt(pt
, ct
, &ctx
->encrypt
);
86 aesedp_ecb_decrypt(const uint8_t *ct
, uint8_t *pt
, aesedp_ctx
*skey
)
88 return aes_decrypt(ct
, pt
, &skey
->decrypt
);
94 aesedp_done(aesedp_ctx
*skey __unused
)
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.
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
120 if((key1
== NULL
)|| (key2
== NULL
) || (xts
== NULL
)) return CRYPT_INVALID_ARG
;
122 /* schedule the two ciphers */
123 if ((err
= aesedp_setup(key1
, keylen
, num_rounds
, &xts
->key1
)) != 0) {
126 if ((err
= aesedp_setup(key2
, keylen
, num_rounds
, &xts
->key2
)) != 0) {
129 xts
->cipher
= cipher
;
138 @param I The value to multiply by x (LFSR shift)
140 #if defined __x86_64__ || defined __i386__
141 extern void xts_mult_x(uint8_t *I
);
143 static void xts_mult_x(uint8_t *I
)
148 for (x
= t
= 0; x
< 16; x
++) {
150 I
[x
] = ((I
[x
] << 1) | t
) & 0xFF;
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
);
163 static int tweak_crypt(const uint8_t *P
, uint8_t *C
, uint8_t *T
, aesedp_encrypt_ctx
*ctx
)
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
]);
173 if ((err
= aes_encrypt(C
, C
, ctx
)) != CRYPT_OK
) {
174 return CRYPT_INVALID_KEYSIZE
;
177 for (x
= 0; x
< 16; x
+= sizeof(uint64_t)) {
178 *((uint64_t*)&C
[x
]) ^= *((uint64_t*)&T
[x
]);
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
197 const uint8_t *pt
, unsigned long ptlen
,
199 const uint8_t *tweak
,
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
;
208 if((pt
== NULL
) || (ct
== NULL
)|| (tweak
== NULL
) || (xts
== NULL
)) return 1;
210 /* get number of blocks */
214 /* must have at least one full block */
216 return CRYPT_INVALID_ARG
;
219 /* encrypt the tweak */
220 if ((err
= aes_encrypt(tweak
, T
, &xts
->key2
.encrypt
)) != 0) {
221 return CRYPT_INVALID_KEYSIZE
;
224 /* for i = 0 to m-2 do */
231 #if defined __x86_64__ || defined __i386__
233 err
= tweak_crypt_group(pt
, ct
, T
, encrypt_ctx
, lim
);
238 for (i
= 0; i
< lim
; i
++) {
239 err
= tweak_crypt(pt
, ct
, T
, encrypt_ctx
);
245 /* if ptlen not divide 16 then */
247 /* CC = tweak encrypt block m-1 */
248 if ((err
= tweak_crypt(pt
, CC
, T
, encrypt_ctx
)) != 0) {
252 /* Cm = first ptlen % 16 bytes of CC */
253 for (i
= 0; i
< mo
; i
++) {
258 for (; i
< 16; i
++) {
262 /* Cm-1 = Tweak encrypt PP */
263 if ((err
= tweak_crypt(PP
, ct
, T
, encrypt_ctx
)) != 0) {
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
);
275 static int tweak_uncrypt(const uint8_t *C
, uint8_t *P
, uint8_t *T
, aesedp_decrypt_ctx
*ctx
)
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
]);
285 err
= aes_decrypt(P
, P
, ctx
);
287 for (x
= 0; x
< 16; x
+= sizeof(uint64_t)) {
288 *((uint64_t*)&P
[x
]) ^= *((uint64_t*)&T
[x
]);
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
308 const uint8_t *ct
, unsigned long ptlen
,
310 const uint8_t *tweak
,
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
;
319 if((pt
== NULL
) || (ct
== NULL
)|| (tweak
== NULL
) || (xts
== NULL
)) return 1;
321 /* get number of blocks */
325 /* must have at least one full block */
327 return CRYPT_INVALID_ARG
;
330 /* encrypt the tweak , yes - encrypt */
331 if ((err
= aes_encrypt(tweak
, T
, &xts
->key2
.encrypt
)) != 0) {
332 return CRYPT_INVALID_KEYSIZE
;
335 /* for i = 0 to m-2 do */
342 #if defined __x86_64__ || defined __i386__
344 err
= tweak_uncrypt_group(ct
, pt
, T
, decrypt_ctx
, lim
);
349 for (i
= 0; i
< lim
; i
++) {
350 err
= tweak_uncrypt(ct
, pt
, T
, decrypt_ctx
);
356 /* if ptlen not divide 16 then */
361 /* PP = tweak decrypt block m-1 */
362 if ((err
= tweak_uncrypt(ct
, PP
, CC
, decrypt_ctx
)) != CRYPT_OK
) {
366 /* Pm = first ptlen % 16 bytes of PP */
367 for (i
= 0; i
< mo
; i
++) {
371 for (; i
< 16; i
++) {
375 /* Pm-1 = Tweak uncrypt CC */
376 if ((err
= tweak_uncrypt(CC
, pt
, T
, decrypt_ctx
)) != CRYPT_OK
) {
386 void xts_done(symmetric_xts
*xts
)
388 if(xts
== NULL
) return;
389 aesedp_done(&xts
->key1
);
390 aesedp_done(&xts
->key2
);