File Coverage

src/symcipher/aes_pwr8_ctrcbc.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) 2018 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             const br_block_ctrcbc_class *
32             br_aes_pwr8_ctrcbc_get_vtable(void)
33             {
34             return br_aes_pwr8_supported() ? &br_aes_pwr8_ctrcbc_vtable : NULL;
35             }
36              
37             /* see bearssl_block.h */
38             void
39             br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx,
40             const void *key, size_t len)
41             {
42             ctx->vtable = &br_aes_pwr8_ctrcbc_vtable;
43             ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len);
44             }
45              
46             /*
47             * Register conventions for CTR + CBC-MAC:
48             *
49             * AES subkeys are in registers 0 to 10/12/14 (depending on keys size)
50             * Register v15 contains the byteswap index register (little-endian only)
51             * Register v16 contains the CTR counter value
52             * Register v17 contains the CBC-MAC current value
53             * Registers v18 to v27 are scratch
54             * Counter increment uses v28, v29 and v30
55             *
56             * For CTR alone:
57             *
58             * AES subkeys are in registers 0 to 10/12/14 (depending on keys size)
59             * Register v15 contains the byteswap index register (little-endian only)
60             * Registers v16 to v19 contain the CTR counter values (four blocks)
61             * Registers v20 to v27 are scratch
62             * Counter increment uses v28, v29 and v30
63             */
64              
65             #define LOAD_SUBKEYS_128 \
66             lxvw4x(32, %[cc], %[sk]) \
67             addi(%[cc], %[cc], 16) \
68             lxvw4x(33, %[cc], %[sk]) \
69             addi(%[cc], %[cc], 16) \
70             lxvw4x(34, %[cc], %[sk]) \
71             addi(%[cc], %[cc], 16) \
72             lxvw4x(35, %[cc], %[sk]) \
73             addi(%[cc], %[cc], 16) \
74             lxvw4x(36, %[cc], %[sk]) \
75             addi(%[cc], %[cc], 16) \
76             lxvw4x(37, %[cc], %[sk]) \
77             addi(%[cc], %[cc], 16) \
78             lxvw4x(38, %[cc], %[sk]) \
79             addi(%[cc], %[cc], 16) \
80             lxvw4x(39, %[cc], %[sk]) \
81             addi(%[cc], %[cc], 16) \
82             lxvw4x(40, %[cc], %[sk]) \
83             addi(%[cc], %[cc], 16) \
84             lxvw4x(41, %[cc], %[sk]) \
85             addi(%[cc], %[cc], 16) \
86             lxvw4x(42, %[cc], %[sk])
87              
88             #define LOAD_SUBKEYS_192 \
89             LOAD_SUBKEYS_128 \
90             addi(%[cc], %[cc], 16) \
91             lxvw4x(43, %[cc], %[sk]) \
92             addi(%[cc], %[cc], 16) \
93             lxvw4x(44, %[cc], %[sk])
94              
95             #define LOAD_SUBKEYS_256 \
96             LOAD_SUBKEYS_192 \
97             addi(%[cc], %[cc], 16) \
98             lxvw4x(45, %[cc], %[sk]) \
99             addi(%[cc], %[cc], 16) \
100             lxvw4x(46, %[cc], %[sk])
101              
102             #define BLOCK_ENCRYPT_128(x) \
103             vxor(x, x, 0) \
104             vcipher(x, x, 1) \
105             vcipher(x, x, 2) \
106             vcipher(x, x, 3) \
107             vcipher(x, x, 4) \
108             vcipher(x, x, 5) \
109             vcipher(x, x, 6) \
110             vcipher(x, x, 7) \
111             vcipher(x, x, 8) \
112             vcipher(x, x, 9) \
113             vcipherlast(x, x, 10)
114              
115             #define BLOCK_ENCRYPT_192(x) \
116             vxor(x, x, 0) \
117             vcipher(x, x, 1) \
118             vcipher(x, x, 2) \
119             vcipher(x, x, 3) \
120             vcipher(x, x, 4) \
121             vcipher(x, x, 5) \
122             vcipher(x, x, 6) \
123             vcipher(x, x, 7) \
124             vcipher(x, x, 8) \
125             vcipher(x, x, 9) \
126             vcipher(x, x, 10) \
127             vcipher(x, x, 11) \
128             vcipherlast(x, x, 12)
129              
130             #define BLOCK_ENCRYPT_256(x) \
131             vxor(x, x, 0) \
132             vcipher(x, x, 1) \
133             vcipher(x, x, 2) \
134             vcipher(x, x, 3) \
135             vcipher(x, x, 4) \
136             vcipher(x, x, 5) \
137             vcipher(x, x, 6) \
138             vcipher(x, x, 7) \
139             vcipher(x, x, 8) \
140             vcipher(x, x, 9) \
141             vcipher(x, x, 10) \
142             vcipher(x, x, 11) \
143             vcipher(x, x, 12) \
144             vcipher(x, x, 13) \
145             vcipherlast(x, x, 14)
146              
147             #define BLOCK_ENCRYPT_X2_128(x, y) \
148             vxor(x, x, 0) \
149             vxor(y, y, 0) \
150             vcipher(x, x, 1) \
151             vcipher(y, y, 1) \
152             vcipher(x, x, 2) \
153             vcipher(y, y, 2) \
154             vcipher(x, x, 3) \
155             vcipher(y, y, 3) \
156             vcipher(x, x, 4) \
157             vcipher(y, y, 4) \
158             vcipher(x, x, 5) \
159             vcipher(y, y, 5) \
160             vcipher(x, x, 6) \
161             vcipher(y, y, 6) \
162             vcipher(x, x, 7) \
163             vcipher(y, y, 7) \
164             vcipher(x, x, 8) \
165             vcipher(y, y, 8) \
166             vcipher(x, x, 9) \
167             vcipher(y, y, 9) \
168             vcipherlast(x, x, 10) \
169             vcipherlast(y, y, 10)
170              
171             #define BLOCK_ENCRYPT_X2_192(x, y) \
172             vxor(x, x, 0) \
173             vxor(y, y, 0) \
174             vcipher(x, x, 1) \
175             vcipher(y, y, 1) \
176             vcipher(x, x, 2) \
177             vcipher(y, y, 2) \
178             vcipher(x, x, 3) \
179             vcipher(y, y, 3) \
180             vcipher(x, x, 4) \
181             vcipher(y, y, 4) \
182             vcipher(x, x, 5) \
183             vcipher(y, y, 5) \
184             vcipher(x, x, 6) \
185             vcipher(y, y, 6) \
186             vcipher(x, x, 7) \
187             vcipher(y, y, 7) \
188             vcipher(x, x, 8) \
189             vcipher(y, y, 8) \
190             vcipher(x, x, 9) \
191             vcipher(y, y, 9) \
192             vcipher(x, x, 10) \
193             vcipher(y, y, 10) \
194             vcipher(x, x, 11) \
195             vcipher(y, y, 11) \
196             vcipherlast(x, x, 12) \
197             vcipherlast(y, y, 12)
198              
199             #define BLOCK_ENCRYPT_X2_256(x, y) \
200             vxor(x, x, 0) \
201             vxor(y, y, 0) \
202             vcipher(x, x, 1) \
203             vcipher(y, y, 1) \
204             vcipher(x, x, 2) \
205             vcipher(y, y, 2) \
206             vcipher(x, x, 3) \
207             vcipher(y, y, 3) \
208             vcipher(x, x, 4) \
209             vcipher(y, y, 4) \
210             vcipher(x, x, 5) \
211             vcipher(y, y, 5) \
212             vcipher(x, x, 6) \
213             vcipher(y, y, 6) \
214             vcipher(x, x, 7) \
215             vcipher(y, y, 7) \
216             vcipher(x, x, 8) \
217             vcipher(y, y, 8) \
218             vcipher(x, x, 9) \
219             vcipher(y, y, 9) \
220             vcipher(x, x, 10) \
221             vcipher(y, y, 10) \
222             vcipher(x, x, 11) \
223             vcipher(y, y, 11) \
224             vcipher(x, x, 12) \
225             vcipher(y, y, 12) \
226             vcipher(x, x, 13) \
227             vcipher(y, y, 13) \
228             vcipherlast(x, x, 14) \
229             vcipherlast(y, y, 14)
230              
231             #define BLOCK_ENCRYPT_X4_128(x0, x1, x2, x3) \
232             vxor(x0, x0, 0) \
233             vxor(x1, x1, 0) \
234             vxor(x2, x2, 0) \
235             vxor(x3, x3, 0) \
236             vcipher(x0, x0, 1) \
237             vcipher(x1, x1, 1) \
238             vcipher(x2, x2, 1) \
239             vcipher(x3, x3, 1) \
240             vcipher(x0, x0, 2) \
241             vcipher(x1, x1, 2) \
242             vcipher(x2, x2, 2) \
243             vcipher(x3, x3, 2) \
244             vcipher(x0, x0, 3) \
245             vcipher(x1, x1, 3) \
246             vcipher(x2, x2, 3) \
247             vcipher(x3, x3, 3) \
248             vcipher(x0, x0, 4) \
249             vcipher(x1, x1, 4) \
250             vcipher(x2, x2, 4) \
251             vcipher(x3, x3, 4) \
252             vcipher(x0, x0, 5) \
253             vcipher(x1, x1, 5) \
254             vcipher(x2, x2, 5) \
255             vcipher(x3, x3, 5) \
256             vcipher(x0, x0, 6) \
257             vcipher(x1, x1, 6) \
258             vcipher(x2, x2, 6) \
259             vcipher(x3, x3, 6) \
260             vcipher(x0, x0, 7) \
261             vcipher(x1, x1, 7) \
262             vcipher(x2, x2, 7) \
263             vcipher(x3, x3, 7) \
264             vcipher(x0, x0, 8) \
265             vcipher(x1, x1, 8) \
266             vcipher(x2, x2, 8) \
267             vcipher(x3, x3, 8) \
268             vcipher(x0, x0, 9) \
269             vcipher(x1, x1, 9) \
270             vcipher(x2, x2, 9) \
271             vcipher(x3, x3, 9) \
272             vcipherlast(x0, x0, 10) \
273             vcipherlast(x1, x1, 10) \
274             vcipherlast(x2, x2, 10) \
275             vcipherlast(x3, x3, 10)
276              
277             #define BLOCK_ENCRYPT_X4_192(x0, x1, x2, x3) \
278             vxor(x0, x0, 0) \
279             vxor(x1, x1, 0) \
280             vxor(x2, x2, 0) \
281             vxor(x3, x3, 0) \
282             vcipher(x0, x0, 1) \
283             vcipher(x1, x1, 1) \
284             vcipher(x2, x2, 1) \
285             vcipher(x3, x3, 1) \
286             vcipher(x0, x0, 2) \
287             vcipher(x1, x1, 2) \
288             vcipher(x2, x2, 2) \
289             vcipher(x3, x3, 2) \
290             vcipher(x0, x0, 3) \
291             vcipher(x1, x1, 3) \
292             vcipher(x2, x2, 3) \
293             vcipher(x3, x3, 3) \
294             vcipher(x0, x0, 4) \
295             vcipher(x1, x1, 4) \
296             vcipher(x2, x2, 4) \
297             vcipher(x3, x3, 4) \
298             vcipher(x0, x0, 5) \
299             vcipher(x1, x1, 5) \
300             vcipher(x2, x2, 5) \
301             vcipher(x3, x3, 5) \
302             vcipher(x0, x0, 6) \
303             vcipher(x1, x1, 6) \
304             vcipher(x2, x2, 6) \
305             vcipher(x3, x3, 6) \
306             vcipher(x0, x0, 7) \
307             vcipher(x1, x1, 7) \
308             vcipher(x2, x2, 7) \
309             vcipher(x3, x3, 7) \
310             vcipher(x0, x0, 8) \
311             vcipher(x1, x1, 8) \
312             vcipher(x2, x2, 8) \
313             vcipher(x3, x3, 8) \
314             vcipher(x0, x0, 9) \
315             vcipher(x1, x1, 9) \
316             vcipher(x2, x2, 9) \
317             vcipher(x3, x3, 9) \
318             vcipher(x0, x0, 10) \
319             vcipher(x1, x1, 10) \
320             vcipher(x2, x2, 10) \
321             vcipher(x3, x3, 10) \
322             vcipher(x0, x0, 11) \
323             vcipher(x1, x1, 11) \
324             vcipher(x2, x2, 11) \
325             vcipher(x3, x3, 11) \
326             vcipherlast(x0, x0, 12) \
327             vcipherlast(x1, x1, 12) \
328             vcipherlast(x2, x2, 12) \
329             vcipherlast(x3, x3, 12)
330              
331             #define BLOCK_ENCRYPT_X4_256(x0, x1, x2, x3) \
332             vxor(x0, x0, 0) \
333             vxor(x1, x1, 0) \
334             vxor(x2, x2, 0) \
335             vxor(x3, x3, 0) \
336             vcipher(x0, x0, 1) \
337             vcipher(x1, x1, 1) \
338             vcipher(x2, x2, 1) \
339             vcipher(x3, x3, 1) \
340             vcipher(x0, x0, 2) \
341             vcipher(x1, x1, 2) \
342             vcipher(x2, x2, 2) \
343             vcipher(x3, x3, 2) \
344             vcipher(x0, x0, 3) \
345             vcipher(x1, x1, 3) \
346             vcipher(x2, x2, 3) \
347             vcipher(x3, x3, 3) \
348             vcipher(x0, x0, 4) \
349             vcipher(x1, x1, 4) \
350             vcipher(x2, x2, 4) \
351             vcipher(x3, x3, 4) \
352             vcipher(x0, x0, 5) \
353             vcipher(x1, x1, 5) \
354             vcipher(x2, x2, 5) \
355             vcipher(x3, x3, 5) \
356             vcipher(x0, x0, 6) \
357             vcipher(x1, x1, 6) \
358             vcipher(x2, x2, 6) \
359             vcipher(x3, x3, 6) \
360             vcipher(x0, x0, 7) \
361             vcipher(x1, x1, 7) \
362             vcipher(x2, x2, 7) \
363             vcipher(x3, x3, 7) \
364             vcipher(x0, x0, 8) \
365             vcipher(x1, x1, 8) \
366             vcipher(x2, x2, 8) \
367             vcipher(x3, x3, 8) \
368             vcipher(x0, x0, 9) \
369             vcipher(x1, x1, 9) \
370             vcipher(x2, x2, 9) \
371             vcipher(x3, x3, 9) \
372             vcipher(x0, x0, 10) \
373             vcipher(x1, x1, 10) \
374             vcipher(x2, x2, 10) \
375             vcipher(x3, x3, 10) \
376             vcipher(x0, x0, 11) \
377             vcipher(x1, x1, 11) \
378             vcipher(x2, x2, 11) \
379             vcipher(x3, x3, 11) \
380             vcipher(x0, x0, 12) \
381             vcipher(x1, x1, 12) \
382             vcipher(x2, x2, 12) \
383             vcipher(x3, x3, 12) \
384             vcipher(x0, x0, 13) \
385             vcipher(x1, x1, 13) \
386             vcipher(x2, x2, 13) \
387             vcipher(x3, x3, 13) \
388             vcipherlast(x0, x0, 14) \
389             vcipherlast(x1, x1, 14) \
390             vcipherlast(x2, x2, 14) \
391             vcipherlast(x3, x3, 14)
392              
393             #if BR_POWER8_LE
394             static const uint32_t idx2be[] = {
395             0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
396             };
397             #define BYTESWAP_INIT lxvw4x(47, 0, %[idx2be])
398             #define BYTESWAP(x) vperm(x, x, x, 15)
399             #define BYTESWAPX(d, s) vperm(d, s, s, 15)
400             #define BYTESWAP_REG , [idx2be] "b" (idx2be)
401             #else
402             #define BYTESWAP_INIT
403             #define BYTESWAP(x)
404             #define BYTESWAPX(d, s) vand(d, s, s)
405             #define BYTESWAP_REG
406             #endif
407              
408             static const uint32_t ctrinc[] = {
409             0, 0, 0, 1
410             };
411             static const uint32_t ctrinc_x4[] = {
412             0, 0, 0, 4
413             };
414             #define INCR_128_INIT lxvw4x(60, 0, %[ctrinc])
415             #define INCR_128_X4_INIT lxvw4x(60, 0, %[ctrinc_x4])
416             #define INCR_128(d, s) \
417             vaddcuw(29, s, 28) \
418             vadduwm(d, s, 28) \
419             vsldoi(30, 29, 29, 4) \
420             vaddcuw(29, d, 30) \
421             vadduwm(d, d, 30) \
422             vsldoi(30, 29, 29, 4) \
423             vaddcuw(29, d, 30) \
424             vadduwm(d, d, 30) \
425             vsldoi(30, 29, 29, 4) \
426             vadduwm(d, d, 30)
427              
428             #define MKCTR(size) \
429             static void \
430             ctr_ ## size(const unsigned char *sk, \
431             unsigned char *ctrbuf, unsigned char *buf, size_t num_blocks_x4) \
432             { \
433             long cc, cc0, cc1, cc2, cc3; \
434             \
435             cc = 0; \
436             cc0 = 0; \
437             cc1 = 16; \
438             cc2 = 32; \
439             cc3 = 48; \
440             asm volatile ( \
441             \
442             /* \
443             * Load subkeys into v0..v10 \
444             */ \
445             LOAD_SUBKEYS_ ## size \
446             li(%[cc], 0) \
447             \
448             BYTESWAP_INIT \
449             INCR_128_X4_INIT \
450             \
451             /* \
452             * Load current CTR counters into v16 to v19. \
453             */ \
454             lxvw4x(48, %[cc0], %[ctrbuf]) \
455             lxvw4x(49, %[cc1], %[ctrbuf]) \
456             lxvw4x(50, %[cc2], %[ctrbuf]) \
457             lxvw4x(51, %[cc3], %[ctrbuf]) \
458             BYTESWAP(16) \
459             BYTESWAP(17) \
460             BYTESWAP(18) \
461             BYTESWAP(19) \
462             \
463             mtctr(%[num_blocks_x4]) \
464             \
465             label(loop) \
466             /* \
467             * Compute next counter values into v20..v23. \
468             */ \
469             INCR_128(20, 16) \
470             INCR_128(21, 17) \
471             INCR_128(22, 18) \
472             INCR_128(23, 19) \
473             \
474             /* \
475             * Encrypt counter values and XOR into next data blocks. \
476             */ \
477             lxvw4x(56, %[cc0], %[buf]) \
478             lxvw4x(57, %[cc1], %[buf]) \
479             lxvw4x(58, %[cc2], %[buf]) \
480             lxvw4x(59, %[cc3], %[buf]) \
481             BYTESWAP(24) \
482             BYTESWAP(25) \
483             BYTESWAP(26) \
484             BYTESWAP(27) \
485             BLOCK_ENCRYPT_X4_ ## size(16, 17, 18, 19) \
486             vxor(16, 16, 24) \
487             vxor(17, 17, 25) \
488             vxor(18, 18, 26) \
489             vxor(19, 19, 27) \
490             BYTESWAP(16) \
491             BYTESWAP(17) \
492             BYTESWAP(18) \
493             BYTESWAP(19) \
494             stxvw4x(48, %[cc0], %[buf]) \
495             stxvw4x(49, %[cc1], %[buf]) \
496             stxvw4x(50, %[cc2], %[buf]) \
497             stxvw4x(51, %[cc3], %[buf]) \
498             \
499             /* \
500             * Update counters and data pointer. \
501             */ \
502             vand(16, 20, 20) \
503             vand(17, 21, 21) \
504             vand(18, 22, 22) \
505             vand(19, 23, 23) \
506             addi(%[buf], %[buf], 64) \
507             \
508             bdnz(loop) \
509             \
510             /* \
511             * Write back new counter values. \
512             */ \
513             BYTESWAP(16) \
514             BYTESWAP(17) \
515             BYTESWAP(18) \
516             BYTESWAP(19) \
517             stxvw4x(48, %[cc0], %[ctrbuf]) \
518             stxvw4x(49, %[cc1], %[ctrbuf]) \
519             stxvw4x(50, %[cc2], %[ctrbuf]) \
520             stxvw4x(51, %[cc3], %[ctrbuf]) \
521             \
522             : [cc] "+b" (cc), [buf] "+b" (buf), \
523             [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3) \
524             : [sk] "b" (sk), [ctrbuf] "b" (ctrbuf), \
525             [num_blocks_x4] "b" (num_blocks_x4), [ctrinc_x4] "b" (ctrinc_x4) \
526             BYTESWAP_REG \
527             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
528             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \
529             "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
530             "v30", "ctr", "memory" \
531             ); \
532             }
533              
534             MKCTR(128)
535             MKCTR(192)
536             MKCTR(256)
537              
538             #define MKCBCMAC(size) \
539             static void \
540             cbcmac_ ## size(const unsigned char *sk, \
541             unsigned char *cbcmac, const unsigned char *buf, size_t num_blocks) \
542             { \
543             long cc; \
544             \
545             cc = 0; \
546             asm volatile ( \
547             \
548             /* \
549             * Load subkeys into v0..v10 \
550             */ \
551             LOAD_SUBKEYS_ ## size \
552             li(%[cc], 0) \
553             \
554             BYTESWAP_INIT \
555             \
556             /* \
557             * Load current CBC-MAC value into v16. \
558             */ \
559             lxvw4x(48, %[cc], %[cbcmac]) \
560             BYTESWAP(16) \
561             \
562             mtctr(%[num_blocks]) \
563             \
564             label(loop) \
565             /* \
566             * Load next block, XOR into current CBC-MAC value, \
567             * and then encrypt it. \
568             */ \
569             lxvw4x(49, %[cc], %[buf]) \
570             BYTESWAP(17) \
571             vxor(16, 16, 17) \
572             BLOCK_ENCRYPT_ ## size(16) \
573             addi(%[buf], %[buf], 16) \
574             \
575             bdnz(loop) \
576             \
577             /* \
578             * Write back new CBC-MAC value. \
579             */ \
580             BYTESWAP(16) \
581             stxvw4x(48, %[cc], %[cbcmac]) \
582             \
583             : [cc] "+b" (cc), [buf] "+b" (buf) \
584             : [sk] "b" (sk), [cbcmac] "b" (cbcmac), [num_blocks] "b" (num_blocks) \
585             BYTESWAP_REG \
586             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
587             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \
588             "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
589             "v30", "ctr", "memory" \
590             ); \
591             }
592              
593             MKCBCMAC(128)
594             MKCBCMAC(192)
595             MKCBCMAC(256)
596              
597             #define MKENCRYPT(size) \
598             static void \
599             ctrcbc_ ## size ## _encrypt(const unsigned char *sk, \
600             unsigned char *ctr, unsigned char *cbcmac, unsigned char *buf, \
601             size_t num_blocks) \
602             { \
603             long cc; \
604             \
605             cc = 0; \
606             asm volatile ( \
607             \
608             /* \
609             * Load subkeys into v0..v10 \
610             */ \
611             LOAD_SUBKEYS_ ## size \
612             li(%[cc], 0) \
613             \
614             BYTESWAP_INIT \
615             INCR_128_INIT \
616             \
617             /* \
618             * Load current CTR counter into v16, and current \
619             * CBC-MAC IV into v17. \
620             */ \
621             lxvw4x(48, %[cc], %[ctr]) \
622             lxvw4x(49, %[cc], %[cbcmac]) \
623             BYTESWAP(16) \
624             BYTESWAP(17) \
625             \
626             /* \
627             * At each iteration, we do two parallel encryption: \
628             * - new counter value for encryption of the next block; \
629             * - CBC-MAC over the previous encrypted block. \
630             * Thus, each plaintext block implies two AES instances, \
631             * over two successive iterations. This requires a single \
632             * counter encryption before the loop, and a single \
633             * CBC-MAC encryption after the loop. \
634             */ \
635             \
636             /* \
637             * Encrypt first block (into v20). \
638             */ \
639             lxvw4x(52, %[cc], %[buf]) \
640             BYTESWAP(20) \
641             INCR_128(22, 16) \
642             BLOCK_ENCRYPT_ ## size(16) \
643             vxor(20, 20, 16) \
644             BYTESWAPX(21, 20) \
645             stxvw4x(53, %[cc], %[buf]) \
646             vand(16, 22, 22) \
647             addi(%[buf], %[buf], 16) \
648             \
649             /* \
650             * Load loop counter; skip the loop if there is only \
651             * one block in total (already handled by the boundary \
652             * conditions). \
653             */ \
654             mtctr(%[num_blocks]) \
655             bdz(fastexit) \
656             \
657             label(loop) \
658             /* \
659             * Upon loop entry: \
660             * v16 counter value for next block \
661             * v17 current CBC-MAC value \
662             * v20 encrypted previous block \
663             */ \
664             vxor(17, 17, 20) \
665             INCR_128(22, 16) \
666             lxvw4x(52, %[cc], %[buf]) \
667             BYTESWAP(20) \
668             BLOCK_ENCRYPT_X2_ ## size(16, 17) \
669             vxor(20, 20, 16) \
670             BYTESWAPX(21, 20) \
671             stxvw4x(53, %[cc], %[buf]) \
672             addi(%[buf], %[buf], 16) \
673             vand(16, 22, 22) \
674             \
675             bdnz(loop) \
676             \
677             label(fastexit) \
678             vxor(17, 17, 20) \
679             BLOCK_ENCRYPT_ ## size(17) \
680             BYTESWAP(16) \
681             BYTESWAP(17) \
682             stxvw4x(48, %[cc], %[ctr]) \
683             stxvw4x(49, %[cc], %[cbcmac]) \
684             \
685             : [cc] "+b" (cc), [buf] "+b" (buf) \
686             : [sk] "b" (sk), [ctr] "b" (ctr), [cbcmac] "b" (cbcmac), \
687             [num_blocks] "b" (num_blocks), [ctrinc] "b" (ctrinc) \
688             BYTESWAP_REG \
689             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
690             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \
691             "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
692             "v30", "ctr", "memory" \
693             ); \
694             }
695              
696             MKENCRYPT(128)
697             MKENCRYPT(192)
698             MKENCRYPT(256)
699              
700             #define MKDECRYPT(size) \
701             static void \
702             ctrcbc_ ## size ## _decrypt(const unsigned char *sk, \
703             unsigned char *ctr, unsigned char *cbcmac, unsigned char *buf, \
704             size_t num_blocks) \
705             { \
706             long cc; \
707             \
708             cc = 0; \
709             asm volatile ( \
710             \
711             /* \
712             * Load subkeys into v0..v10 \
713             */ \
714             LOAD_SUBKEYS_ ## size \
715             li(%[cc], 0) \
716             \
717             BYTESWAP_INIT \
718             INCR_128_INIT \
719             \
720             /* \
721             * Load current CTR counter into v16, and current \
722             * CBC-MAC IV into v17. \
723             */ \
724             lxvw4x(48, %[cc], %[ctr]) \
725             lxvw4x(49, %[cc], %[cbcmac]) \
726             BYTESWAP(16) \
727             BYTESWAP(17) \
728             \
729             /* \
730             * At each iteration, we do two parallel encryption: \
731             * - new counter value for decryption of the next block; \
732             * - CBC-MAC over the next encrypted block. \
733             * Each iteration performs the two AES instances related \
734             * to the current block; there is thus no need for some \
735             * extra pre-loop and post-loop work as in encryption. \
736             */ \
737             \
738             mtctr(%[num_blocks]) \
739             \
740             label(loop) \
741             /* \
742             * Upon loop entry: \
743             * v16 counter value for next block \
744             * v17 current CBC-MAC value \
745             */ \
746             lxvw4x(52, %[cc], %[buf]) \
747             BYTESWAP(20) \
748             vxor(17, 17, 20) \
749             INCR_128(22, 16) \
750             BLOCK_ENCRYPT_X2_ ## size(16, 17) \
751             vxor(20, 20, 16) \
752             BYTESWAPX(21, 20) \
753             stxvw4x(53, %[cc], %[buf]) \
754             addi(%[buf], %[buf], 16) \
755             vand(16, 22, 22) \
756             \
757             bdnz(loop) \
758             \
759             /* \
760             * Store back counter and CBC-MAC value. \
761             */ \
762             BYTESWAP(16) \
763             BYTESWAP(17) \
764             stxvw4x(48, %[cc], %[ctr]) \
765             stxvw4x(49, %[cc], %[cbcmac]) \
766             \
767             : [cc] "+b" (cc), [buf] "+b" (buf) \
768             : [sk] "b" (sk), [ctr] "b" (ctr), [cbcmac] "b" (cbcmac), \
769             [num_blocks] "b" (num_blocks), [ctrinc] "b" (ctrinc) \
770             BYTESWAP_REG \
771             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
772             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \
773             "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
774             "v30", "ctr", "memory" \
775             ); \
776             }
777              
778             MKDECRYPT(128)
779             MKDECRYPT(192)
780             MKDECRYPT(256)
781              
782             /* see bearssl_block.h */
783             void
784             br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
785             void *ctr, void *cbcmac, void *data, size_t len)
786             {
787             if (len == 0) {
788             return;
789             }
790             switch (ctx->num_rounds) {
791             case 10:
792             ctrcbc_128_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
793             break;
794             case 12:
795             ctrcbc_192_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
796             break;
797             default:
798             ctrcbc_256_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
799             break;
800             }
801             }
802              
803             /* see bearssl_block.h */
804             void
805             br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
806             void *ctr, void *cbcmac, void *data, size_t len)
807             {
808             if (len == 0) {
809             return;
810             }
811             switch (ctx->num_rounds) {
812             case 10:
813             ctrcbc_128_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
814             break;
815             case 12:
816             ctrcbc_192_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
817             break;
818             default:
819             ctrcbc_256_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
820             break;
821             }
822             }
823              
824             static inline void
825             incr_ctr(void *dst, const void *src)
826             {
827             uint64_t hi, lo;
828              
829             hi = br_dec64be(src);
830             lo = br_dec64be((const unsigned char *)src + 8);
831             lo ++;
832             hi += ((lo | -lo) >> 63) ^ (uint64_t)1;
833             br_enc64be(dst, hi);
834             br_enc64be((unsigned char *)dst + 8, lo);
835             }
836              
837             /* see bearssl_block.h */
838             void
839             br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx,
840             void *ctr, void *data, size_t len)
841             {
842             unsigned char ctrbuf[64];
843              
844             memcpy(ctrbuf, ctr, 16);
845             incr_ctr(ctrbuf + 16, ctrbuf);
846             incr_ctr(ctrbuf + 32, ctrbuf + 16);
847             incr_ctr(ctrbuf + 48, ctrbuf + 32);
848             if (len >= 64) {
849             switch (ctx->num_rounds) {
850             case 10:
851             ctr_128(ctx->skey.skni, ctrbuf, data, len >> 6);
852             break;
853             case 12:
854             ctr_192(ctx->skey.skni, ctrbuf, data, len >> 6);
855             break;
856             default:
857             ctr_256(ctx->skey.skni, ctrbuf, data, len >> 6);
858             break;
859             }
860             data = (unsigned char *)data + (len & ~(size_t)63);
861             len &= 63;
862             }
863             if (len > 0) {
864             unsigned char tmp[64];
865              
866             if (len >= 32) {
867             if (len >= 48) {
868             memcpy(ctr, ctrbuf + 48, 16);
869             } else {
870             memcpy(ctr, ctrbuf + 32, 16);
871             }
872             } else {
873             if (len >= 16) {
874             memcpy(ctr, ctrbuf + 16, 16);
875             }
876             }
877             memcpy(tmp, data, len);
878             memset(tmp + len, 0, (sizeof tmp) - len);
879             switch (ctx->num_rounds) {
880             case 10:
881             ctr_128(ctx->skey.skni, ctrbuf, tmp, 1);
882             break;
883             case 12:
884             ctr_192(ctx->skey.skni, ctrbuf, tmp, 1);
885             break;
886             default:
887             ctr_256(ctx->skey.skni, ctrbuf, tmp, 1);
888             break;
889             }
890             memcpy(data, tmp, len);
891             } else {
892             memcpy(ctr, ctrbuf, 16);
893             }
894             }
895              
896             /* see bearssl_block.h */
897             void
898             br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx,
899             void *cbcmac, const void *data, size_t len)
900             {
901             if (len > 0) {
902             switch (ctx->num_rounds) {
903             case 10:
904             cbcmac_128(ctx->skey.skni, cbcmac, data, len >> 4);
905             break;
906             case 12:
907             cbcmac_192(ctx->skey.skni, cbcmac, data, len >> 4);
908             break;
909             default:
910             cbcmac_256(ctx->skey.skni, cbcmac, data, len >> 4);
911             break;
912             }
913             }
914             }
915              
916             /* see bearssl_block.h */
917             const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable = {
918             sizeof(br_aes_pwr8_ctrcbc_keys),
919             16,
920             4,
921             (void (*)(const br_block_ctrcbc_class **, const void *, size_t))
922             &br_aes_pwr8_ctrcbc_init,
923             (void (*)(const br_block_ctrcbc_class *const *,
924             void *, void *, void *, size_t))
925             &br_aes_pwr8_ctrcbc_encrypt,
926             (void (*)(const br_block_ctrcbc_class *const *,
927             void *, void *, void *, size_t))
928             &br_aes_pwr8_ctrcbc_decrypt,
929             (void (*)(const br_block_ctrcbc_class *const *,
930             void *, void *, size_t))
931             &br_aes_pwr8_ctrcbc_ctr,
932             (void (*)(const br_block_ctrcbc_class *const *,
933             void *, const void *, size_t))
934             &br_aes_pwr8_ctrcbc_mac
935             };
936              
937             #else
938              
939             /* see bearssl_block.h */
940             const br_block_ctrcbc_class *
941 0           br_aes_pwr8_ctrcbc_get_vtable(void)
942             {
943 0           return NULL;
944             }
945              
946             #endif