1 /*******************************************************************************
2   Copyright (c) 2009-2020, Intel Corporation
3 
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions are met:
6 
7       * Redistributions of source code must retain the above copyright notice,
8         this list of conditions and the following disclaimer.
9       * Redistributions in binary form must reproduce the above copyright
10         notice, this list of conditions and the following disclaimer in the
11         documentation and/or other materials provided with the distribution.
12       * Neither the name of Intel Corporation nor the names of its contributors
13         may be used to endorse or promote products derived from this software
14         without specific prior written permission.
15 
16   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *******************************************************************************/
27 
28 #include <limits.h>
29 
30 #define CLEAR_SCRATCH_SIMD_REGS clear_scratch_xmms_sse
31 
32 #include "include/kasumi_internal.h"
33 #include "include/save_xmms.h"
34 #include "include/clear_regs_mem.h"
35 
36 #define SAVE_XMMS               save_xmms
37 #define RESTORE_XMMS            restore_xmms
38 
39 void
kasumi_f8_1_buffer_sse(const kasumi_key_sched_t * pCtx,const uint64_t IV,const void * pBufferIn,void * pBufferOut,const uint32_t cipherLengthInBytes)40 kasumi_f8_1_buffer_sse(const kasumi_key_sched_t *pCtx, const uint64_t IV,
41                        const void *pBufferIn, void *pBufferOut,
42                        const uint32_t cipherLengthInBytes)
43 {
44 #ifndef LINUX
45         DECLARE_ALIGNED(imb_uint128_t xmm_save[10], 16);
46 
47         SAVE_XMMS(xmm_save);
48 #endif
49 #ifdef SAFE_PARAM
50         /* Check for NULL pointers */
51         if (pCtx == NULL || pBufferIn == NULL || pBufferOut == NULL)
52                 return;
53 
54         /* Check input data is in range of supported length */
55         if (cipherLengthInBytes == 0 ||
56             cipherLengthInBytes > (KASUMI_MAX_LEN / CHAR_BIT))
57                 return;
58 #endif
59         kasumi_f8_1_buffer(pCtx, IV, pBufferIn, pBufferOut,
60                            cipherLengthInBytes);
61 #ifdef SAFE_DATA
62         /* Clear sensitive data in registers */
63         CLEAR_SCRATCH_GPS();
64         CLEAR_SCRATCH_SIMD_REGS();
65 #endif
66 #ifndef LINUX
67         RESTORE_XMMS(xmm_save);
68 #endif
69 }
70 
71 void
kasumi_f8_1_buffer_bit_sse(const kasumi_key_sched_t * pCtx,const uint64_t IV,const void * pBufferIn,void * pBufferOut,const uint32_t cipherLengthInBits,const uint32_t offsetInBits)72 kasumi_f8_1_buffer_bit_sse(const kasumi_key_sched_t *pCtx,
73                            const uint64_t IV,
74                            const void *pBufferIn, void *pBufferOut,
75                            const uint32_t cipherLengthInBits,
76                            const uint32_t offsetInBits)
77 {
78 #ifndef LINUX
79         DECLARE_ALIGNED(imb_uint128_t xmm_save[10], 16);
80 
81         SAVE_XMMS(xmm_save);
82 #endif
83 #ifdef SAFE_PARAM
84         /* Check for NULL pointers */
85         if (pCtx == NULL || pBufferIn == NULL || pBufferOut == NULL)
86                 return;
87 
88         /* Check input data is in range of supported length */
89         if (cipherLengthInBits == 0 ||
90             cipherLengthInBits > KASUMI_MAX_LEN)
91                 return;
92 #endif
93         kasumi_f8_1_buffer_bit(pCtx, IV, pBufferIn, pBufferOut,
94                                cipherLengthInBits, offsetInBits);
95 #ifdef SAFE_DATA
96         /* Clear sensitive data in registers */
97         CLEAR_SCRATCH_GPS();
98         CLEAR_SCRATCH_SIMD_REGS();
99 #endif
100 #ifndef LINUX
101         RESTORE_XMMS(xmm_save);
102 #endif
103 }
104 
105 void
kasumi_f8_2_buffer_sse(const kasumi_key_sched_t * pCtx,const uint64_t IV1,const uint64_t IV2,const void * pBufferIn1,void * pBufferOut1,const uint32_t lengthInBytes1,const void * pBufferIn2,void * pBufferOut2,const uint32_t lengthInBytes2)106 kasumi_f8_2_buffer_sse(const kasumi_key_sched_t *pCtx, const uint64_t IV1,
107                        const uint64_t IV2, const void *pBufferIn1,
108                        void *pBufferOut1, const uint32_t lengthInBytes1,
109                        const void *pBufferIn2, void *pBufferOut2,
110                        const uint32_t lengthInBytes2)
111 {
112 #ifndef LINUX
113         DECLARE_ALIGNED(imb_uint128_t xmm_save[10], 16);
114 
115         SAVE_XMMS(xmm_save);
116 #endif
117 #ifdef SAFE_PARAM
118         /* Check for NULL pointers */
119         if (pCtx == NULL)
120                 return;
121 
122         if (pBufferIn1 == NULL || pBufferOut1 == NULL)
123                 return;
124 
125         if (pBufferIn2 == NULL || pBufferOut2 == NULL)
126                 return;
127 
128         /* Check input data is in range of supported length */
129         if (lengthInBytes1 == 0 || lengthInBytes1 > (KASUMI_MAX_LEN / CHAR_BIT))
130                 return;
131 
132         if (lengthInBytes2 == 0 || lengthInBytes2 > (KASUMI_MAX_LEN / CHAR_BIT))
133                 return;
134 #endif
135         kasumi_f8_2_buffer(pCtx, IV1, IV2,
136                            pBufferIn1, pBufferOut1, lengthInBytes1,
137                            pBufferIn2, pBufferOut2, lengthInBytes2);
138 #ifdef SAFE_DATA
139         /* Clear sensitive data in registers */
140         CLEAR_SCRATCH_GPS();
141         CLEAR_SCRATCH_SIMD_REGS();
142 #endif
143 #ifndef LINUX
144         RESTORE_XMMS(xmm_save);
145 #endif
146 }
147 
148 void
kasumi_f8_3_buffer_sse(const kasumi_key_sched_t * pCtx,const uint64_t IV1,const uint64_t IV2,const uint64_t IV3,const void * pBufferIn1,void * pBufferOut1,const void * pBufferIn2,void * pBufferOut2,const void * pBufferIn3,void * pBufferOut3,const uint32_t lengthInBytes)149 kasumi_f8_3_buffer_sse(const kasumi_key_sched_t *pCtx, const uint64_t IV1,
150                        const uint64_t IV2, const uint64_t IV3,
151                        const void *pBufferIn1, void *pBufferOut1,
152                        const void *pBufferIn2, void *pBufferOut2,
153                        const void *pBufferIn3, void *pBufferOut3,
154                        const uint32_t lengthInBytes)
155 {
156 #ifndef LINUX
157         DECLARE_ALIGNED(imb_uint128_t xmm_save[10], 16);
158 
159         SAVE_XMMS(xmm_save);
160 #endif
161 #ifdef SAFE_PARAM
162         /* Check for NULL pointers */
163         if (pCtx == NULL)
164                 return;
165 
166         if (pBufferIn1 == NULL || pBufferOut1 == NULL)
167                 return;
168 
169         if (pBufferIn2 == NULL || pBufferOut2 == NULL)
170                 return;
171 
172         if (pBufferIn3 == NULL || pBufferOut3 == NULL)
173                 return;
174 
175         /* Check input data is in range of supported length */
176         if (lengthInBytes == 0 || lengthInBytes > (KASUMI_MAX_LEN / CHAR_BIT))
177                 return;
178 #endif
179         kasumi_f8_3_buffer(pCtx, IV1, IV2, IV3,
180                            pBufferIn1, pBufferOut1,
181                            pBufferIn2, pBufferOut2,
182                            pBufferIn3, pBufferOut3, lengthInBytes);
183 #ifdef SAFE_DATA
184         /* Clear sensitive data in registers */
185         CLEAR_SCRATCH_GPS();
186         CLEAR_SCRATCH_SIMD_REGS();
187 #endif
188 #ifndef LINUX
189         RESTORE_XMMS(xmm_save);
190 #endif
191 }
192 
193 void
kasumi_f8_4_buffer_sse(const kasumi_key_sched_t * pCtx,const uint64_t IV1,const uint64_t IV2,const uint64_t IV3,const uint64_t IV4,const void * pBufferIn1,void * pBufferOut1,const void * pBufferIn2,void * pBufferOut2,const void * pBufferIn3,void * pBufferOut3,const void * pBufferIn4,void * pBufferOut4,const uint32_t lengthInBytes)194 kasumi_f8_4_buffer_sse(const kasumi_key_sched_t *pCtx,
195                        const uint64_t IV1, const uint64_t IV2,
196                        const uint64_t IV3, const uint64_t IV4,
197                        const void *pBufferIn1, void *pBufferOut1,
198                        const void *pBufferIn2, void *pBufferOut2,
199                        const void *pBufferIn3, void *pBufferOut3,
200                        const void *pBufferIn4, void *pBufferOut4,
201                        const uint32_t lengthInBytes)
202 {
203 #ifndef LINUX
204         DECLARE_ALIGNED(imb_uint128_t xmm_save[10], 16);
205 
206         SAVE_XMMS(xmm_save);
207 #endif
208 #ifdef SAFE_PARAM
209         /* Check for NULL pointers */
210         if (pCtx == NULL)
211                 return;
212 
213         if (pBufferIn1 == NULL || pBufferOut1 == NULL)
214                 return;
215 
216         if (pBufferIn2 == NULL || pBufferOut2 == NULL)
217                 return;
218 
219         if (pBufferIn3 == NULL || pBufferOut3 == NULL)
220                 return;
221 
222         if (pBufferIn4 == NULL || pBufferOut4 == NULL)
223                 return;
224 
225         /* Check input data is in range of supported length */
226         if (lengthInBytes == 0 || lengthInBytes > (KASUMI_MAX_LEN / CHAR_BIT))
227                 return;
228 #endif
229         kasumi_f8_4_buffer(pCtx, IV1, IV2, IV3, IV4,
230                            pBufferIn1, pBufferOut1,
231                            pBufferIn2, pBufferOut2,
232                            pBufferIn3, pBufferOut3,
233                            pBufferIn4, pBufferOut4,
234                            lengthInBytes);
235 #ifdef SAFE_DATA
236         /* Clear sensitive data in registers */
237         CLEAR_SCRATCH_GPS();
238         CLEAR_SCRATCH_SIMD_REGS();
239 #endif
240 #ifndef LINUX
241         RESTORE_XMMS(xmm_save);
242 #endif
243 }
244 
245 void
kasumi_f8_n_buffer_sse(const kasumi_key_sched_t * pKeySchedule,const uint64_t IV[],const void * const pDataIn[],void * pDataOut[],const uint32_t dataLen[],const uint32_t dataCount)246 kasumi_f8_n_buffer_sse(const kasumi_key_sched_t *pKeySchedule,
247                        const uint64_t IV[],
248                        const void * const pDataIn[], void *pDataOut[],
249                        const uint32_t dataLen[], const uint32_t dataCount)
250 {
251 #ifndef LINUX
252         DECLARE_ALIGNED(imb_uint128_t xmm_save[10], 16);
253 
254         SAVE_XMMS(xmm_save);
255 #endif
256         uint32_t numLeft = dataCount;
257         const uint64_t *IVPtr;
258         const void * const *pDataInPtr;
259         void **pDataOutPtr;
260         const uint32_t *dataLenPtr;
261         uint32_t i = 0;
262         uint32_t numBuffs;
263 
264 #ifdef SAFE_PARAM
265         /* Check for NULL pointers */
266         if (pKeySchedule == NULL || pDataIn == NULL || pDataOut == NULL ||
267             dataLen == NULL || IV == NULL)
268                 return;
269 
270         for (i = 0; i < dataCount; i++) {
271                 /* Check for NULL pointers */
272                 if (pDataIn[i] == NULL || pDataOut[i] == NULL)
273                         return;
274 
275                 /* Check input data is in range of supported length */
276                 if (dataLen[i] == 0 || dataLen[i] > (KASUMI_MAX_LEN / CHAR_BIT))
277                         return;
278         }
279 #endif
280 
281         i = 0;
282 
283         /* KASUMI F8 n buffer function can handle up to 16 buffers */
284         while (numLeft > 0) {
285                 IVPtr = &IV[i];
286                 pDataInPtr = &pDataIn[i];
287                 pDataOutPtr = &pDataOut[i];
288                 dataLenPtr = &dataLen[i];
289                 numBuffs = (numLeft > 16) ? 16 : numLeft;
290 
291                 kasumi_f8_n_buffer(pKeySchedule, IVPtr, pDataInPtr, pDataOutPtr,
292                                    dataLenPtr, numBuffs);
293                 i += numBuffs;
294                 numLeft -= numBuffs;
295         }
296 #ifdef SAFE_DATA
297         /* Clear sensitive data in registers */
298         CLEAR_SCRATCH_GPS();
299         CLEAR_SCRATCH_SIMD_REGS();
300 #endif
301 #ifndef LINUX
302         RESTORE_XMMS(xmm_save);
303 #endif
304 }
305 
306 
307 void
kasumi_f9_1_buffer_sse(const kasumi_key_sched_t * pCtx,const void * pBufferIn,const uint32_t lengthInBytes,void * pDigest)308 kasumi_f9_1_buffer_sse(const kasumi_key_sched_t *pCtx, const void *pBufferIn,
309                        const uint32_t lengthInBytes, void *pDigest)
310 {
311 #ifndef LINUX
312         DECLARE_ALIGNED(imb_uint128_t xmm_save[10], 16);
313 
314         SAVE_XMMS(xmm_save);
315 #endif
316 #ifdef SAFE_PARAM
317         /* Check for NULL pointers */
318         if (pCtx == NULL || pBufferIn == NULL || pDigest == NULL)
319                 return;
320 
321         /* Check input data is in range of supported length */
322         if (lengthInBytes == 0 || lengthInBytes > (KASUMI_MAX_LEN / CHAR_BIT))
323                 return;
324 #endif
325         kasumi_f9_1_buffer(pCtx, pBufferIn, lengthInBytes, pDigest);
326 #ifdef SAFE_DATA
327         /* Clear sensitive data in registers */
328         CLEAR_SCRATCH_GPS();
329         CLEAR_SCRATCH_SIMD_REGS();
330 #endif
331 #ifndef LINUX
332         RESTORE_XMMS(xmm_save);
333 #endif
334 }
335 
336 void
kasumi_f9_1_buffer_user_sse(const kasumi_key_sched_t * pCtx,const uint64_t IV,const void * pBufferIn,const uint32_t lengthInBits,void * pDigest,const uint32_t direction)337 kasumi_f9_1_buffer_user_sse(const kasumi_key_sched_t *pCtx, const uint64_t IV,
338                             const void *pBufferIn, const uint32_t lengthInBits,
339                             void *pDigest, const uint32_t direction)
340 {
341 #ifndef LINUX
342         DECLARE_ALIGNED(imb_uint128_t xmm_save[10], 16);
343 
344         SAVE_XMMS(xmm_save);
345 #endif
346 #ifdef SAFE_PARAM
347         /* Check for NULL pointers */
348         if (pCtx == NULL || pBufferIn == NULL || pDigest == NULL)
349                 return;
350 
351         /* Check input data is in range of supported length */
352         if (lengthInBits == 0 || lengthInBits > KASUMI_MAX_LEN)
353                 return;
354 #endif
355         kasumi_f9_1_buffer_user(pCtx, IV, pBufferIn, lengthInBits,
356                                 pDigest, direction);
357 #ifdef SAFE_DATA
358         /* Clear sensitive data in registers */
359         CLEAR_SCRATCH_GPS();
360         CLEAR_SCRATCH_SIMD_REGS();
361 #endif
362 #ifndef LINUX
363         RESTORE_XMMS(xmm_save);
364 #endif
365 }
366 
367 int
kasumi_init_f8_key_sched_sse(const void * const pKey,kasumi_key_sched_t * pCtx)368 kasumi_init_f8_key_sched_sse(const void *const pKey,
369                              kasumi_key_sched_t *pCtx)
370 {
371         return kasumi_init_f8_key_sched(pKey, pCtx);
372 }
373 
374 int
kasumi_init_f9_key_sched_sse(const void * const pKey,kasumi_key_sched_t * pCtx)375 kasumi_init_f9_key_sched_sse(const void *const pKey,
376                              kasumi_key_sched_t *pCtx)
377 {
378         return kasumi_init_f9_key_sched(pKey, pCtx);
379 }
380 
381 size_t
kasumi_key_sched_size_sse(void)382 kasumi_key_sched_size_sse(void)
383 {
384         return kasumi_key_sched_size();
385 }
386