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