xref: /freebsd/crypto/openssl/crypto/modes/xts128gb.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery  *
4*e7be843bSPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e7be843bSPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*e7be843bSPierre Pronchery  * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery  * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery  */
9*e7be843bSPierre Pronchery 
10*e7be843bSPierre Pronchery #include <string.h>
11*e7be843bSPierre Pronchery #include <openssl/crypto.h>
12*e7be843bSPierre Pronchery #include "internal/endian.h"
13*e7be843bSPierre Pronchery #include "crypto/modes.h"
14*e7be843bSPierre Pronchery 
15*e7be843bSPierre Pronchery #ifndef STRICT_ALIGNMENT
16*e7be843bSPierre Pronchery # ifdef __GNUC__
17*e7be843bSPierre Pronchery typedef u64 u64_a1 __attribute((__aligned__(1)));
18*e7be843bSPierre Pronchery # else
19*e7be843bSPierre Pronchery typedef u64 u64_a1;
20*e7be843bSPierre Pronchery # endif
21*e7be843bSPierre Pronchery #endif
22*e7be843bSPierre Pronchery 
ossl_crypto_xts128gb_encrypt(const XTS128_CONTEXT * ctx,const unsigned char iv[16],const unsigned char * inp,unsigned char * out,size_t len,int enc)23*e7be843bSPierre Pronchery int ossl_crypto_xts128gb_encrypt(const XTS128_CONTEXT *ctx,
24*e7be843bSPierre Pronchery                                  const unsigned char iv[16],
25*e7be843bSPierre Pronchery                                  const unsigned char *inp, unsigned char *out,
26*e7be843bSPierre Pronchery                                  size_t len, int enc)
27*e7be843bSPierre Pronchery {
28*e7be843bSPierre Pronchery     DECLARE_IS_ENDIAN;
29*e7be843bSPierre Pronchery     union {
30*e7be843bSPierre Pronchery         u64 u[2];
31*e7be843bSPierre Pronchery         u32 d[4];
32*e7be843bSPierre Pronchery         u8 c[16];
33*e7be843bSPierre Pronchery     } tweak, scratch;
34*e7be843bSPierre Pronchery     unsigned int i;
35*e7be843bSPierre Pronchery 
36*e7be843bSPierre Pronchery     if (len < 16)
37*e7be843bSPierre Pronchery         return -1;
38*e7be843bSPierre Pronchery 
39*e7be843bSPierre Pronchery     memcpy(tweak.c, iv, 16);
40*e7be843bSPierre Pronchery 
41*e7be843bSPierre Pronchery     (*ctx->block2) (tweak.c, tweak.c, ctx->key2);
42*e7be843bSPierre Pronchery 
43*e7be843bSPierre Pronchery     if (!enc && (len % 16))
44*e7be843bSPierre Pronchery         len -= 16;
45*e7be843bSPierre Pronchery 
46*e7be843bSPierre Pronchery     while (len >= 16) {
47*e7be843bSPierre Pronchery #if defined(STRICT_ALIGNMENT)
48*e7be843bSPierre Pronchery         memcpy(scratch.c, inp, 16);
49*e7be843bSPierre Pronchery         scratch.u[0] ^= tweak.u[0];
50*e7be843bSPierre Pronchery         scratch.u[1] ^= tweak.u[1];
51*e7be843bSPierre Pronchery #else
52*e7be843bSPierre Pronchery         scratch.u[0] = ((u64_a1 *)inp)[0] ^ tweak.u[0];
53*e7be843bSPierre Pronchery         scratch.u[1] = ((u64_a1 *)inp)[1] ^ tweak.u[1];
54*e7be843bSPierre Pronchery #endif
55*e7be843bSPierre Pronchery         (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
56*e7be843bSPierre Pronchery #if defined(STRICT_ALIGNMENT)
57*e7be843bSPierre Pronchery         scratch.u[0] ^= tweak.u[0];
58*e7be843bSPierre Pronchery         scratch.u[1] ^= tweak.u[1];
59*e7be843bSPierre Pronchery         memcpy(out, scratch.c, 16);
60*e7be843bSPierre Pronchery #else
61*e7be843bSPierre Pronchery         ((u64_a1 *)out)[0] = scratch.u[0] ^= tweak.u[0];
62*e7be843bSPierre Pronchery         ((u64_a1 *)out)[1] = scratch.u[1] ^= tweak.u[1];
63*e7be843bSPierre Pronchery #endif
64*e7be843bSPierre Pronchery         inp += 16;
65*e7be843bSPierre Pronchery         out += 16;
66*e7be843bSPierre Pronchery         len -= 16;
67*e7be843bSPierre Pronchery 
68*e7be843bSPierre Pronchery         if (len == 0)
69*e7be843bSPierre Pronchery             return 0;
70*e7be843bSPierre Pronchery 
71*e7be843bSPierre Pronchery         if (IS_LITTLE_ENDIAN) {
72*e7be843bSPierre Pronchery             u8 res;
73*e7be843bSPierre Pronchery             u64 hi, lo;
74*e7be843bSPierre Pronchery #ifdef BSWAP8
75*e7be843bSPierre Pronchery             hi = BSWAP8(tweak.u[0]);
76*e7be843bSPierre Pronchery             lo = BSWAP8(tweak.u[1]);
77*e7be843bSPierre Pronchery #else
78*e7be843bSPierre Pronchery             u8 *p = tweak.c;
79*e7be843bSPierre Pronchery 
80*e7be843bSPierre Pronchery             hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
81*e7be843bSPierre Pronchery             lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
82*e7be843bSPierre Pronchery #endif
83*e7be843bSPierre Pronchery             res = (u8)lo & 1;
84*e7be843bSPierre Pronchery             tweak.u[0] = (lo >> 1) | (hi << 63);
85*e7be843bSPierre Pronchery             tweak.u[1] = hi >> 1;
86*e7be843bSPierre Pronchery             if (res)
87*e7be843bSPierre Pronchery                 tweak.c[15] ^= 0xe1;
88*e7be843bSPierre Pronchery #ifdef BSWAP8
89*e7be843bSPierre Pronchery             hi = BSWAP8(tweak.u[0]);
90*e7be843bSPierre Pronchery             lo = BSWAP8(tweak.u[1]);
91*e7be843bSPierre Pronchery #else
92*e7be843bSPierre Pronchery             p = tweak.c;
93*e7be843bSPierre Pronchery 
94*e7be843bSPierre Pronchery             hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
95*e7be843bSPierre Pronchery             lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
96*e7be843bSPierre Pronchery #endif
97*e7be843bSPierre Pronchery             tweak.u[0] = lo;
98*e7be843bSPierre Pronchery             tweak.u[1] = hi;
99*e7be843bSPierre Pronchery         } else {
100*e7be843bSPierre Pronchery             u8 carry, res;
101*e7be843bSPierre Pronchery             carry = 0;
102*e7be843bSPierre Pronchery             for (i = 0; i < 16; ++i) {
103*e7be843bSPierre Pronchery                 res = (tweak.c[i] << 7) & 0x80;
104*e7be843bSPierre Pronchery                 tweak.c[i] = ((tweak.c[i] >> 1) + carry) & 0xff;
105*e7be843bSPierre Pronchery                 carry = res;
106*e7be843bSPierre Pronchery             }
107*e7be843bSPierre Pronchery             if (res)
108*e7be843bSPierre Pronchery                 tweak.c[0] ^= 0xe1;
109*e7be843bSPierre Pronchery         }
110*e7be843bSPierre Pronchery     }
111*e7be843bSPierre Pronchery     if (enc) {
112*e7be843bSPierre Pronchery         for (i = 0; i < len; ++i) {
113*e7be843bSPierre Pronchery             u8 c = inp[i];
114*e7be843bSPierre Pronchery             out[i] = scratch.c[i];
115*e7be843bSPierre Pronchery             scratch.c[i] = c;
116*e7be843bSPierre Pronchery         }
117*e7be843bSPierre Pronchery         scratch.u[0] ^= tweak.u[0];
118*e7be843bSPierre Pronchery         scratch.u[1] ^= tweak.u[1];
119*e7be843bSPierre Pronchery         (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
120*e7be843bSPierre Pronchery         scratch.u[0] ^= tweak.u[0];
121*e7be843bSPierre Pronchery         scratch.u[1] ^= tweak.u[1];
122*e7be843bSPierre Pronchery         memcpy(out - 16, scratch.c, 16);
123*e7be843bSPierre Pronchery     } else {
124*e7be843bSPierre Pronchery         union {
125*e7be843bSPierre Pronchery             u64 u[2];
126*e7be843bSPierre Pronchery             u8 c[16];
127*e7be843bSPierre Pronchery         } tweak1;
128*e7be843bSPierre Pronchery 
129*e7be843bSPierre Pronchery         if (IS_LITTLE_ENDIAN) {
130*e7be843bSPierre Pronchery             u8 res;
131*e7be843bSPierre Pronchery             u64 hi, lo;
132*e7be843bSPierre Pronchery #ifdef BSWAP8
133*e7be843bSPierre Pronchery             hi = BSWAP8(tweak.u[0]);
134*e7be843bSPierre Pronchery             lo = BSWAP8(tweak.u[1]);
135*e7be843bSPierre Pronchery #else
136*e7be843bSPierre Pronchery             u8 *p = tweak.c;
137*e7be843bSPierre Pronchery 
138*e7be843bSPierre Pronchery             hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
139*e7be843bSPierre Pronchery             lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
140*e7be843bSPierre Pronchery #endif
141*e7be843bSPierre Pronchery             res = (u8)lo & 1;
142*e7be843bSPierre Pronchery             tweak1.u[0] = (lo >> 1) | (hi << 63);
143*e7be843bSPierre Pronchery             tweak1.u[1] = hi >> 1;
144*e7be843bSPierre Pronchery             if (res)
145*e7be843bSPierre Pronchery                 tweak1.c[15] ^= 0xe1;
146*e7be843bSPierre Pronchery #ifdef BSWAP8
147*e7be843bSPierre Pronchery             hi = BSWAP8(tweak1.u[0]);
148*e7be843bSPierre Pronchery             lo = BSWAP8(tweak1.u[1]);
149*e7be843bSPierre Pronchery #else
150*e7be843bSPierre Pronchery             p = tweak1.c;
151*e7be843bSPierre Pronchery 
152*e7be843bSPierre Pronchery             hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
153*e7be843bSPierre Pronchery             lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
154*e7be843bSPierre Pronchery #endif
155*e7be843bSPierre Pronchery             tweak1.u[0] = lo;
156*e7be843bSPierre Pronchery             tweak1.u[1] = hi;
157*e7be843bSPierre Pronchery         } else {
158*e7be843bSPierre Pronchery             u8 carry, res;
159*e7be843bSPierre Pronchery             carry = 0;
160*e7be843bSPierre Pronchery             for (i = 0; i < 16; ++i) {
161*e7be843bSPierre Pronchery                 res = (tweak.c[i] << 7) & 0x80;
162*e7be843bSPierre Pronchery                 tweak1.c[i] = ((tweak.c[i] >> 1) + carry) & 0xff;
163*e7be843bSPierre Pronchery                 carry = res;
164*e7be843bSPierre Pronchery             }
165*e7be843bSPierre Pronchery             if (res)
166*e7be843bSPierre Pronchery                 tweak1.c[0] ^= 0xe1;
167*e7be843bSPierre Pronchery         }
168*e7be843bSPierre Pronchery #if defined(STRICT_ALIGNMENT)
169*e7be843bSPierre Pronchery         memcpy(scratch.c, inp, 16);
170*e7be843bSPierre Pronchery         scratch.u[0] ^= tweak1.u[0];
171*e7be843bSPierre Pronchery         scratch.u[1] ^= tweak1.u[1];
172*e7be843bSPierre Pronchery #else
173*e7be843bSPierre Pronchery         scratch.u[0] = ((u64_a1 *)inp)[0] ^ tweak1.u[0];
174*e7be843bSPierre Pronchery         scratch.u[1] = ((u64_a1 *)inp)[1] ^ tweak1.u[1];
175*e7be843bSPierre Pronchery #endif
176*e7be843bSPierre Pronchery         (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
177*e7be843bSPierre Pronchery         scratch.u[0] ^= tweak1.u[0];
178*e7be843bSPierre Pronchery         scratch.u[1] ^= tweak1.u[1];
179*e7be843bSPierre Pronchery 
180*e7be843bSPierre Pronchery         for (i = 0; i < len; ++i) {
181*e7be843bSPierre Pronchery             u8 c = inp[16 + i];
182*e7be843bSPierre Pronchery             out[16 + i] = scratch.c[i];
183*e7be843bSPierre Pronchery             scratch.c[i] = c;
184*e7be843bSPierre Pronchery         }
185*e7be843bSPierre Pronchery         scratch.u[0] ^= tweak.u[0];
186*e7be843bSPierre Pronchery         scratch.u[1] ^= tweak.u[1];
187*e7be843bSPierre Pronchery         (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
188*e7be843bSPierre Pronchery #if defined(STRICT_ALIGNMENT)
189*e7be843bSPierre Pronchery         scratch.u[0] ^= tweak.u[0];
190*e7be843bSPierre Pronchery         scratch.u[1] ^= tweak.u[1];
191*e7be843bSPierre Pronchery         memcpy(out, scratch.c, 16);
192*e7be843bSPierre Pronchery #else
193*e7be843bSPierre Pronchery         ((u64_a1 *)out)[0] = scratch.u[0] ^ tweak.u[0];
194*e7be843bSPierre Pronchery         ((u64_a1 *)out)[1] = scratch.u[1] ^ tweak.u[1];
195*e7be843bSPierre Pronchery #endif
196*e7be843bSPierre Pronchery     }
197*e7be843bSPierre Pronchery 
198*e7be843bSPierre Pronchery     return 0;
199*e7be843bSPierre Pronchery }
200