1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects
7 */
8
9 #ifdef LTC_XTS_MODE
10
s_tweak_crypt(const unsigned char * P,unsigned char * C,unsigned char * T,const symmetric_xts * xts)11 static int s_tweak_crypt(const unsigned char *P, unsigned char *C, unsigned char *T, const symmetric_xts *xts)
12 {
13 unsigned long x;
14 int err;
15
16 /* tweak encrypt block i */
17 #ifdef LTC_FAST
18 for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
19 *(LTC_FAST_TYPE_PTR_CAST(&C[x])) = *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x]));
20 }
21 #else
22 for (x = 0; x < 16; x++) {
23 C[x] = P[x] ^ T[x];
24 }
25 #endif
26
27 if ((err = cipher_descriptor[xts->cipher]->ecb_encrypt(C, C, &xts->key1)) != CRYPT_OK) {
28 return err;
29 }
30
31 #ifdef LTC_FAST
32 for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) {
33 *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x]));
34 }
35 #else
36 for (x = 0; x < 16; x++) {
37 C[x] = C[x] ^ T[x];
38 }
39 #endif
40
41 /* LFSR the tweak */
42 xts_mult_x(T);
43
44 return CRYPT_OK;
45 }
46
47 /** XTS Encryption
48 @param pt [in] Plaintext
49 @param ptlen Length of plaintext (and ciphertext)
50 @param ct [out] Ciphertext
51 @param tweak [in] The 128--bit encryption tweak (e.g. sector number)
52 @param xts The XTS structure
53 Returns CRYPT_OK upon success
54 */
xts_encrypt(const unsigned char * pt,unsigned long ptlen,unsigned char * ct,unsigned char * tweak,const symmetric_xts * xts)55 int xts_encrypt(const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tweak,
56 const symmetric_xts *xts)
57 {
58 unsigned char PP[16], CC[16], T[16];
59 unsigned long i, m, mo, lim;
60 int err;
61
62 /* check inputs */
63 LTC_ARGCHK(pt != NULL);
64 LTC_ARGCHK(ct != NULL);
65 LTC_ARGCHK(tweak != NULL);
66 LTC_ARGCHK(xts != NULL);
67
68 /* check if valid */
69 if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) {
70 return err;
71 }
72
73 /* get number of blocks */
74 m = ptlen >> 4;
75 mo = ptlen & 15;
76
77 /* must have at least one full block */
78 if (m == 0) {
79 return CRYPT_INVALID_ARG;
80 }
81
82 if (mo == 0) {
83 lim = m;
84 } else {
85 lim = m - 1;
86 }
87
88 if (cipher_descriptor[xts->cipher]->accel_xts_encrypt && lim > 0) {
89
90 /* use accelerated encryption for whole blocks */
91 if ((err = cipher_descriptor[xts->cipher]->accel_xts_encrypt(pt, ct, lim, tweak, &xts->key1, &xts->key2)) !=
92 CRYPT_OK) {
93 return err;
94 }
95 ct += lim * 16;
96 pt += lim * 16;
97
98 /* tweak is encrypted on output */
99 XMEMCPY(T, tweak, sizeof(T));
100 } else {
101
102 /* encrypt the tweak */
103 if ((err = cipher_descriptor[xts->cipher]->ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) {
104 return err;
105 }
106
107 for (i = 0; i < lim; i++) {
108 if ((err = s_tweak_crypt(pt, ct, T, xts)) != CRYPT_OK) {
109 return err;
110 }
111 ct += 16;
112 pt += 16;
113 }
114 }
115
116 /* if ptlen not divide 16 then */
117 if (mo > 0) {
118 /* CC = tweak encrypt block m-1 */
119 if ((err = s_tweak_crypt(pt, CC, T, xts)) != CRYPT_OK) {
120 return err;
121 }
122
123 /* Cm = first ptlen % 16 bytes of CC */
124 for (i = 0; i < mo; i++) {
125 PP[i] = pt[16 + i];
126 ct[16 + i] = CC[i];
127 }
128
129 for (; i < 16; i++) {
130 PP[i] = CC[i];
131 }
132
133 /* Cm-1 = Tweak encrypt PP */
134 if ((err = s_tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) {
135 return err;
136 }
137 }
138
139 /* Decrypt the tweak back */
140 if ((err = cipher_descriptor[xts->cipher]->ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) {
141 return err;
142 }
143
144 return err;
145 }
146
147 #endif
148