File Coverage

src/symcipher/aes_pwr8_cbcenc.c
Criterion Covered Total %
statement 0 2 0.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 0 2 0.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright (c) 2017 Thomas Pornin
3             *
4             * Permission is hereby granted, free of charge, to any person obtaining
5             * a copy of this software and associated documentation files (the
6             * "Software"), to deal in the Software without restriction, including
7             * without limitation the rights to use, copy, modify, merge, publish,
8             * distribute, sublicense, and/or sell copies of the Software, and to
9             * permit persons to whom the Software is furnished to do so, subject to
10             * the following conditions:
11             *
12             * The above copyright notice and this permission notice shall be
13             * included in all copies or substantial portions of the Software.
14             *
15             * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16             * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17             * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18             * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19             * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20             * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21             * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22             * SOFTWARE.
23             */
24              
25             #define BR_POWER_ASM_MACROS 1
26             #include "inner.h"
27              
28             #if BR_POWER8
29              
30             /* see bearssl_block.h */
31             void
32             br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx,
33             const void *key, size_t len)
34             {
35             ctx->vtable = &br_aes_pwr8_cbcenc_vtable;
36             ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len);
37             }
38              
39             static void
40             cbcenc_128(const unsigned char *sk,
41             const unsigned char *iv, unsigned char *buf, size_t len)
42             {
43             long cc;
44              
45             #if BR_POWER8_LE
46             static const uint32_t idx2be[] = {
47             0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
48             };
49             #endif
50              
51             cc = 0;
52             asm volatile (
53              
54             /*
55             * Load subkeys into v0..v10
56             */
57             lxvw4x(32, %[cc], %[sk])
58             addi(%[cc], %[cc], 16)
59             lxvw4x(33, %[cc], %[sk])
60             addi(%[cc], %[cc], 16)
61             lxvw4x(34, %[cc], %[sk])
62             addi(%[cc], %[cc], 16)
63             lxvw4x(35, %[cc], %[sk])
64             addi(%[cc], %[cc], 16)
65             lxvw4x(36, %[cc], %[sk])
66             addi(%[cc], %[cc], 16)
67             lxvw4x(37, %[cc], %[sk])
68             addi(%[cc], %[cc], 16)
69             lxvw4x(38, %[cc], %[sk])
70             addi(%[cc], %[cc], 16)
71             lxvw4x(39, %[cc], %[sk])
72             addi(%[cc], %[cc], 16)
73             lxvw4x(40, %[cc], %[sk])
74             addi(%[cc], %[cc], 16)
75             lxvw4x(41, %[cc], %[sk])
76             addi(%[cc], %[cc], 16)
77             lxvw4x(42, %[cc], %[sk])
78              
79             #if BR_POWER8_LE
80             /*
81             * v15 = constant for byteswapping words
82             */
83             lxvw4x(47, 0, %[idx2be])
84             #endif
85             /*
86             * Load IV into v16.
87             */
88             lxvw4x(48, 0, %[iv])
89             #if BR_POWER8_LE
90             vperm(16, 16, 16, 15)
91             #endif
92              
93             mtctr(%[num_blocks])
94             label(loop)
95             /*
96             * Load next plaintext word and XOR with current IV.
97             */
98             lxvw4x(49, 0, %[buf])
99             #if BR_POWER8_LE
100             vperm(17, 17, 17, 15)
101             #endif
102             vxor(16, 16, 17)
103              
104             /*
105             * Encrypt the block.
106             */
107             vxor(16, 16, 0)
108             vcipher(16, 16, 1)
109             vcipher(16, 16, 2)
110             vcipher(16, 16, 3)
111             vcipher(16, 16, 4)
112             vcipher(16, 16, 5)
113             vcipher(16, 16, 6)
114             vcipher(16, 16, 7)
115             vcipher(16, 16, 8)
116             vcipher(16, 16, 9)
117             vcipherlast(16, 16, 10)
118              
119             /*
120             * Store back result (with byteswap)
121             */
122             #if BR_POWER8_LE
123             vperm(17, 16, 16, 15)
124             stxvw4x(49, 0, %[buf])
125             #else
126             stxvw4x(48, 0, %[buf])
127             #endif
128             addi(%[buf], %[buf], 16)
129              
130             bdnz(loop)
131              
132             : [cc] "+b" (cc), [buf] "+b" (buf)
133             : [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)
134             #if BR_POWER8_LE
135             , [idx2be] "b" (idx2be)
136             #endif
137             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
138             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
139             "ctr", "memory"
140             );
141             }
142              
143             static void
144             cbcenc_192(const unsigned char *sk,
145             const unsigned char *iv, unsigned char *buf, size_t len)
146             {
147             long cc;
148              
149             #if BR_POWER8_LE
150             static const uint32_t idx2be[] = {
151             0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
152             };
153             #endif
154              
155             cc = 0;
156             asm volatile (
157              
158             /*
159             * Load subkeys into v0..v12
160             */
161             lxvw4x(32, %[cc], %[sk])
162             addi(%[cc], %[cc], 16)
163             lxvw4x(33, %[cc], %[sk])
164             addi(%[cc], %[cc], 16)
165             lxvw4x(34, %[cc], %[sk])
166             addi(%[cc], %[cc], 16)
167             lxvw4x(35, %[cc], %[sk])
168             addi(%[cc], %[cc], 16)
169             lxvw4x(36, %[cc], %[sk])
170             addi(%[cc], %[cc], 16)
171             lxvw4x(37, %[cc], %[sk])
172             addi(%[cc], %[cc], 16)
173             lxvw4x(38, %[cc], %[sk])
174             addi(%[cc], %[cc], 16)
175             lxvw4x(39, %[cc], %[sk])
176             addi(%[cc], %[cc], 16)
177             lxvw4x(40, %[cc], %[sk])
178             addi(%[cc], %[cc], 16)
179             lxvw4x(41, %[cc], %[sk])
180             addi(%[cc], %[cc], 16)
181             lxvw4x(42, %[cc], %[sk])
182             addi(%[cc], %[cc], 16)
183             lxvw4x(43, %[cc], %[sk])
184             addi(%[cc], %[cc], 16)
185             lxvw4x(44, %[cc], %[sk])
186              
187             #if BR_POWER8_LE
188             /*
189             * v15 = constant for byteswapping words
190             */
191             lxvw4x(47, 0, %[idx2be])
192             #endif
193             /*
194             * Load IV into v16.
195             */
196             lxvw4x(48, 0, %[iv])
197             #if BR_POWER8_LE
198             vperm(16, 16, 16, 15)
199             #endif
200              
201             mtctr(%[num_blocks])
202             label(loop)
203             /*
204             * Load next plaintext word and XOR with current IV.
205             */
206             lxvw4x(49, 0, %[buf])
207             #if BR_POWER8_LE
208             vperm(17, 17, 17, 15)
209             #endif
210             vxor(16, 16, 17)
211              
212             /*
213             * Encrypt the block.
214             */
215             vxor(16, 16, 0)
216             vcipher(16, 16, 1)
217             vcipher(16, 16, 2)
218             vcipher(16, 16, 3)
219             vcipher(16, 16, 4)
220             vcipher(16, 16, 5)
221             vcipher(16, 16, 6)
222             vcipher(16, 16, 7)
223             vcipher(16, 16, 8)
224             vcipher(16, 16, 9)
225             vcipher(16, 16, 10)
226             vcipher(16, 16, 11)
227             vcipherlast(16, 16, 12)
228              
229             /*
230             * Store back result (with byteswap)
231             */
232             #if BR_POWER8_LE
233             vperm(17, 16, 16, 15)
234             stxvw4x(49, 0, %[buf])
235             #else
236             stxvw4x(48, 0, %[buf])
237             #endif
238             addi(%[buf], %[buf], 16)
239              
240             bdnz(loop)
241              
242             : [cc] "+b" (cc), [buf] "+b" (buf)
243             : [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)
244             #if BR_POWER8_LE
245             , [idx2be] "b" (idx2be)
246             #endif
247             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
248             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
249             "ctr", "memory"
250             );
251             }
252              
253             static void
254             cbcenc_256(const unsigned char *sk,
255             const unsigned char *iv, unsigned char *buf, size_t len)
256             {
257             long cc;
258              
259             #if BR_POWER8_LE
260             static const uint32_t idx2be[] = {
261             0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
262             };
263             #endif
264              
265             cc = 0;
266             asm volatile (
267              
268             /*
269             * Load subkeys into v0..v14
270             */
271             lxvw4x(32, %[cc], %[sk])
272             addi(%[cc], %[cc], 16)
273             lxvw4x(33, %[cc], %[sk])
274             addi(%[cc], %[cc], 16)
275             lxvw4x(34, %[cc], %[sk])
276             addi(%[cc], %[cc], 16)
277             lxvw4x(35, %[cc], %[sk])
278             addi(%[cc], %[cc], 16)
279             lxvw4x(36, %[cc], %[sk])
280             addi(%[cc], %[cc], 16)
281             lxvw4x(37, %[cc], %[sk])
282             addi(%[cc], %[cc], 16)
283             lxvw4x(38, %[cc], %[sk])
284             addi(%[cc], %[cc], 16)
285             lxvw4x(39, %[cc], %[sk])
286             addi(%[cc], %[cc], 16)
287             lxvw4x(40, %[cc], %[sk])
288             addi(%[cc], %[cc], 16)
289             lxvw4x(41, %[cc], %[sk])
290             addi(%[cc], %[cc], 16)
291             lxvw4x(42, %[cc], %[sk])
292             addi(%[cc], %[cc], 16)
293             lxvw4x(43, %[cc], %[sk])
294             addi(%[cc], %[cc], 16)
295             lxvw4x(44, %[cc], %[sk])
296             addi(%[cc], %[cc], 16)
297             lxvw4x(45, %[cc], %[sk])
298             addi(%[cc], %[cc], 16)
299             lxvw4x(46, %[cc], %[sk])
300              
301             #if BR_POWER8_LE
302             /*
303             * v15 = constant for byteswapping words
304             */
305             lxvw4x(47, 0, %[idx2be])
306             #endif
307             /*
308             * Load IV into v16.
309             */
310             lxvw4x(48, 0, %[iv])
311             #if BR_POWER8_LE
312             vperm(16, 16, 16, 15)
313             #endif
314              
315             mtctr(%[num_blocks])
316             label(loop)
317             /*
318             * Load next plaintext word and XOR with current IV.
319             */
320             lxvw4x(49, 0, %[buf])
321             #if BR_POWER8_LE
322             vperm(17, 17, 17, 15)
323             #endif
324             vxor(16, 16, 17)
325              
326             /*
327             * Encrypt the block.
328             */
329             vxor(16, 16, 0)
330             vcipher(16, 16, 1)
331             vcipher(16, 16, 2)
332             vcipher(16, 16, 3)
333             vcipher(16, 16, 4)
334             vcipher(16, 16, 5)
335             vcipher(16, 16, 6)
336             vcipher(16, 16, 7)
337             vcipher(16, 16, 8)
338             vcipher(16, 16, 9)
339             vcipher(16, 16, 10)
340             vcipher(16, 16, 11)
341             vcipher(16, 16, 12)
342             vcipher(16, 16, 13)
343             vcipherlast(16, 16, 14)
344              
345             /*
346             * Store back result (with byteswap)
347             */
348             #if BR_POWER8_LE
349             vperm(17, 16, 16, 15)
350             stxvw4x(49, 0, %[buf])
351             #else
352             stxvw4x(48, 0, %[buf])
353             #endif
354             addi(%[buf], %[buf], 16)
355              
356             bdnz(loop)
357              
358             : [cc] "+b" (cc), [buf] "+b" (buf)
359             : [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)
360             #if BR_POWER8_LE
361             , [idx2be] "b" (idx2be)
362             #endif
363             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
364             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
365             "ctr", "memory"
366             );
367             }
368              
369             /* see bearssl_block.h */
370             void
371             br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx,
372             void *iv, void *data, size_t len)
373             {
374             if (len > 0) {
375             switch (ctx->num_rounds) {
376             case 10:
377             cbcenc_128(ctx->skey.skni, iv, data, len);
378             break;
379             case 12:
380             cbcenc_192(ctx->skey.skni, iv, data, len);
381             break;
382             default:
383             cbcenc_256(ctx->skey.skni, iv, data, len);
384             break;
385             }
386             memcpy(iv, (unsigned char *)data + (len - 16), 16);
387             }
388             }
389              
390             /* see bearssl_block.h */
391             const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable = {
392             sizeof(br_aes_pwr8_cbcenc_keys),
393             16,
394             4,
395             (void (*)(const br_block_cbcenc_class **, const void *, size_t))
396             &br_aes_pwr8_cbcenc_init,
397             (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
398             &br_aes_pwr8_cbcenc_run
399             };
400              
401             /* see bearssl_block.h */
402             const br_block_cbcenc_class *
403             br_aes_pwr8_cbcenc_get_vtable(void)
404             {
405             return br_aes_pwr8_supported() ? &br_aes_pwr8_cbcenc_vtable : NULL;
406             }
407              
408             #else
409              
410             /* see bearssl_block.h */
411             const br_block_cbcenc_class *
412 0           br_aes_pwr8_cbcenc_get_vtable(void)
413             {
414 0           return NULL;
415             }
416              
417             #endif