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