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