xref: /optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c (revision 8411e6ad673d20c4742ed30c785e3f5cdea54dfa)
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