xref: /optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.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_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