File Coverage

src/symcipher/aes_pwr8_ctr.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_ctr_init(br_aes_pwr8_ctr_keys *ctx,
33             const void *key, size_t len)
34             {
35             ctx->vtable = &br_aes_pwr8_ctr_vtable;
36             ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len);
37             }
38              
39             static void
40             ctr_128(const unsigned char *sk, const unsigned char *ivbuf,
41             unsigned char *buf, size_t num_blocks)
42             {
43             long cc0, cc1, cc2, cc3;
44              
45             #if BR_POWER8_LE
46             static const uint32_t idx2be[] = {
47             0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
48             };
49             #endif
50             static const uint32_t ctrinc[] = {
51             0, 0, 0, 4
52             };
53              
54             cc0 = 0;
55             cc1 = 16;
56             cc2 = 32;
57             cc3 = 48;
58             asm volatile (
59              
60             /*
61             * Load subkeys into v0..v10
62             */
63             lxvw4x(32, %[cc0], %[sk])
64             addi(%[cc0], %[cc0], 16)
65             lxvw4x(33, %[cc0], %[sk])
66             addi(%[cc0], %[cc0], 16)
67             lxvw4x(34, %[cc0], %[sk])
68             addi(%[cc0], %[cc0], 16)
69             lxvw4x(35, %[cc0], %[sk])
70             addi(%[cc0], %[cc0], 16)
71             lxvw4x(36, %[cc0], %[sk])
72             addi(%[cc0], %[cc0], 16)
73             lxvw4x(37, %[cc0], %[sk])
74             addi(%[cc0], %[cc0], 16)
75             lxvw4x(38, %[cc0], %[sk])
76             addi(%[cc0], %[cc0], 16)
77             lxvw4x(39, %[cc0], %[sk])
78             addi(%[cc0], %[cc0], 16)
79             lxvw4x(40, %[cc0], %[sk])
80             addi(%[cc0], %[cc0], 16)
81             lxvw4x(41, %[cc0], %[sk])
82             addi(%[cc0], %[cc0], 16)
83             lxvw4x(42, %[cc0], %[sk])
84             li(%[cc0], 0)
85              
86             #if BR_POWER8_LE
87             /*
88             * v15 = constant for byteswapping words
89             */
90             lxvw4x(47, 0, %[idx2be])
91             #endif
92             /*
93             * v28 = increment for IV counter.
94             */
95             lxvw4x(60, 0, %[ctrinc])
96              
97             /*
98             * Load IV into v16..v19
99             */
100             lxvw4x(48, %[cc0], %[ivbuf])
101             lxvw4x(49, %[cc1], %[ivbuf])
102             lxvw4x(50, %[cc2], %[ivbuf])
103             lxvw4x(51, %[cc3], %[ivbuf])
104             #if BR_POWER8_LE
105             vperm(16, 16, 16, 15)
106             vperm(17, 17, 17, 15)
107             vperm(18, 18, 18, 15)
108             vperm(19, 19, 19, 15)
109             #endif
110              
111             mtctr(%[num_blocks])
112             label(loop)
113             /*
114             * Compute next IV into v24..v27
115             */
116             vadduwm(24, 16, 28)
117             vadduwm(25, 17, 28)
118             vadduwm(26, 18, 28)
119             vadduwm(27, 19, 28)
120              
121             /*
122             * Load next data blocks. We do this early on but we
123             * won't need them until IV encryption is done.
124             */
125             lxvw4x(52, %[cc0], %[buf])
126             lxvw4x(53, %[cc1], %[buf])
127             lxvw4x(54, %[cc2], %[buf])
128             lxvw4x(55, %[cc3], %[buf])
129              
130             /*
131             * Encrypt the current IV.
132             */
133             vxor(16, 16, 0)
134             vxor(17, 17, 0)
135             vxor(18, 18, 0)
136             vxor(19, 19, 0)
137             vcipher(16, 16, 1)
138             vcipher(17, 17, 1)
139             vcipher(18, 18, 1)
140             vcipher(19, 19, 1)
141             vcipher(16, 16, 2)
142             vcipher(17, 17, 2)
143             vcipher(18, 18, 2)
144             vcipher(19, 19, 2)
145             vcipher(16, 16, 3)
146             vcipher(17, 17, 3)
147             vcipher(18, 18, 3)
148             vcipher(19, 19, 3)
149             vcipher(16, 16, 4)
150             vcipher(17, 17, 4)
151             vcipher(18, 18, 4)
152             vcipher(19, 19, 4)
153             vcipher(16, 16, 5)
154             vcipher(17, 17, 5)
155             vcipher(18, 18, 5)
156             vcipher(19, 19, 5)
157             vcipher(16, 16, 6)
158             vcipher(17, 17, 6)
159             vcipher(18, 18, 6)
160             vcipher(19, 19, 6)
161             vcipher(16, 16, 7)
162             vcipher(17, 17, 7)
163             vcipher(18, 18, 7)
164             vcipher(19, 19, 7)
165             vcipher(16, 16, 8)
166             vcipher(17, 17, 8)
167             vcipher(18, 18, 8)
168             vcipher(19, 19, 8)
169             vcipher(16, 16, 9)
170             vcipher(17, 17, 9)
171             vcipher(18, 18, 9)
172             vcipher(19, 19, 9)
173             vcipherlast(16, 16, 10)
174             vcipherlast(17, 17, 10)
175             vcipherlast(18, 18, 10)
176             vcipherlast(19, 19, 10)
177              
178             #if BR_POWER8_LE
179             vperm(16, 16, 16, 15)
180             vperm(17, 17, 17, 15)
181             vperm(18, 18, 18, 15)
182             vperm(19, 19, 19, 15)
183             #endif
184              
185             /*
186             * Load next plaintext word and XOR with encrypted IV.
187             */
188             vxor(16, 20, 16)
189             vxor(17, 21, 17)
190             vxor(18, 22, 18)
191             vxor(19, 23, 19)
192             stxvw4x(48, %[cc0], %[buf])
193             stxvw4x(49, %[cc1], %[buf])
194             stxvw4x(50, %[cc2], %[buf])
195             stxvw4x(51, %[cc3], %[buf])
196              
197             addi(%[buf], %[buf], 64)
198              
199             /*
200             * Update IV.
201             */
202             vand(16, 24, 24)
203             vand(17, 25, 25)
204             vand(18, 26, 26)
205             vand(19, 27, 27)
206              
207             bdnz(loop)
208              
209             : [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
210             [buf] "+b" (buf)
211             : [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2),
212             [ctrinc] "b" (ctrinc)
213             #if BR_POWER8_LE
214             , [idx2be] "b" (idx2be)
215             #endif
216             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
217             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
218             "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
219             "ctr", "memory"
220             );
221             }
222              
223             static void
224             ctr_192(const unsigned char *sk, const unsigned char *ivbuf,
225             unsigned char *buf, size_t num_blocks)
226             {
227             long cc0, cc1, cc2, cc3;
228              
229             #if BR_POWER8_LE
230             static const uint32_t idx2be[] = {
231             0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
232             };
233             #endif
234             static const uint32_t ctrinc[] = {
235             0, 0, 0, 4
236             };
237              
238             cc0 = 0;
239             cc1 = 16;
240             cc2 = 32;
241             cc3 = 48;
242             asm volatile (
243              
244             /*
245             * Load subkeys into v0..v12
246             */
247             lxvw4x(32, %[cc0], %[sk])
248             addi(%[cc0], %[cc0], 16)
249             lxvw4x(33, %[cc0], %[sk])
250             addi(%[cc0], %[cc0], 16)
251             lxvw4x(34, %[cc0], %[sk])
252             addi(%[cc0], %[cc0], 16)
253             lxvw4x(35, %[cc0], %[sk])
254             addi(%[cc0], %[cc0], 16)
255             lxvw4x(36, %[cc0], %[sk])
256             addi(%[cc0], %[cc0], 16)
257             lxvw4x(37, %[cc0], %[sk])
258             addi(%[cc0], %[cc0], 16)
259             lxvw4x(38, %[cc0], %[sk])
260             addi(%[cc0], %[cc0], 16)
261             lxvw4x(39, %[cc0], %[sk])
262             addi(%[cc0], %[cc0], 16)
263             lxvw4x(40, %[cc0], %[sk])
264             addi(%[cc0], %[cc0], 16)
265             lxvw4x(41, %[cc0], %[sk])
266             addi(%[cc0], %[cc0], 16)
267             lxvw4x(42, %[cc0], %[sk])
268             addi(%[cc0], %[cc0], 16)
269             lxvw4x(43, %[cc0], %[sk])
270             addi(%[cc0], %[cc0], 16)
271             lxvw4x(44, %[cc0], %[sk])
272             li(%[cc0], 0)
273              
274             #if BR_POWER8_LE
275             /*
276             * v15 = constant for byteswapping words
277             */
278             lxvw4x(47, 0, %[idx2be])
279             #endif
280             /*
281             * v28 = increment for IV counter.
282             */
283             lxvw4x(60, 0, %[ctrinc])
284              
285             /*
286             * Load IV into v16..v19
287             */
288             lxvw4x(48, %[cc0], %[ivbuf])
289             lxvw4x(49, %[cc1], %[ivbuf])
290             lxvw4x(50, %[cc2], %[ivbuf])
291             lxvw4x(51, %[cc3], %[ivbuf])
292             #if BR_POWER8_LE
293             vperm(16, 16, 16, 15)
294             vperm(17, 17, 17, 15)
295             vperm(18, 18, 18, 15)
296             vperm(19, 19, 19, 15)
297             #endif
298              
299             mtctr(%[num_blocks])
300             label(loop)
301             /*
302             * Compute next IV into v24..v27
303             */
304             vadduwm(24, 16, 28)
305             vadduwm(25, 17, 28)
306             vadduwm(26, 18, 28)
307             vadduwm(27, 19, 28)
308              
309             /*
310             * Load next data blocks. We do this early on but we
311             * won't need them until IV encryption is done.
312             */
313             lxvw4x(52, %[cc0], %[buf])
314             lxvw4x(53, %[cc1], %[buf])
315             lxvw4x(54, %[cc2], %[buf])
316             lxvw4x(55, %[cc3], %[buf])
317              
318             /*
319             * Encrypt the current IV.
320             */
321             vxor(16, 16, 0)
322             vxor(17, 17, 0)
323             vxor(18, 18, 0)
324             vxor(19, 19, 0)
325             vcipher(16, 16, 1)
326             vcipher(17, 17, 1)
327             vcipher(18, 18, 1)
328             vcipher(19, 19, 1)
329             vcipher(16, 16, 2)
330             vcipher(17, 17, 2)
331             vcipher(18, 18, 2)
332             vcipher(19, 19, 2)
333             vcipher(16, 16, 3)
334             vcipher(17, 17, 3)
335             vcipher(18, 18, 3)
336             vcipher(19, 19, 3)
337             vcipher(16, 16, 4)
338             vcipher(17, 17, 4)
339             vcipher(18, 18, 4)
340             vcipher(19, 19, 4)
341             vcipher(16, 16, 5)
342             vcipher(17, 17, 5)
343             vcipher(18, 18, 5)
344             vcipher(19, 19, 5)
345             vcipher(16, 16, 6)
346             vcipher(17, 17, 6)
347             vcipher(18, 18, 6)
348             vcipher(19, 19, 6)
349             vcipher(16, 16, 7)
350             vcipher(17, 17, 7)
351             vcipher(18, 18, 7)
352             vcipher(19, 19, 7)
353             vcipher(16, 16, 8)
354             vcipher(17, 17, 8)
355             vcipher(18, 18, 8)
356             vcipher(19, 19, 8)
357             vcipher(16, 16, 9)
358             vcipher(17, 17, 9)
359             vcipher(18, 18, 9)
360             vcipher(19, 19, 9)
361             vcipher(16, 16, 10)
362             vcipher(17, 17, 10)
363             vcipher(18, 18, 10)
364             vcipher(19, 19, 10)
365             vcipher(16, 16, 11)
366             vcipher(17, 17, 11)
367             vcipher(18, 18, 11)
368             vcipher(19, 19, 11)
369             vcipherlast(16, 16, 12)
370             vcipherlast(17, 17, 12)
371             vcipherlast(18, 18, 12)
372             vcipherlast(19, 19, 12)
373              
374             #if BR_POWER8_LE
375             vperm(16, 16, 16, 15)
376             vperm(17, 17, 17, 15)
377             vperm(18, 18, 18, 15)
378             vperm(19, 19, 19, 15)
379             #endif
380              
381             /*
382             * Load next plaintext word and XOR with encrypted IV.
383             */
384             vxor(16, 20, 16)
385             vxor(17, 21, 17)
386             vxor(18, 22, 18)
387             vxor(19, 23, 19)
388             stxvw4x(48, %[cc0], %[buf])
389             stxvw4x(49, %[cc1], %[buf])
390             stxvw4x(50, %[cc2], %[buf])
391             stxvw4x(51, %[cc3], %[buf])
392              
393             addi(%[buf], %[buf], 64)
394              
395             /*
396             * Update IV.
397             */
398             vand(16, 24, 24)
399             vand(17, 25, 25)
400             vand(18, 26, 26)
401             vand(19, 27, 27)
402              
403             bdnz(loop)
404              
405             : [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
406             [buf] "+b" (buf)
407             : [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2),
408             [ctrinc] "b" (ctrinc)
409             #if BR_POWER8_LE
410             , [idx2be] "b" (idx2be)
411             #endif
412             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
413             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
414             "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
415             "ctr", "memory"
416             );
417             }
418              
419             static void
420             ctr_256(const unsigned char *sk, const unsigned char *ivbuf,
421             unsigned char *buf, size_t num_blocks)
422             {
423             long cc0, cc1, cc2, cc3;
424              
425             #if BR_POWER8_LE
426             static const uint32_t idx2be[] = {
427             0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
428             };
429             #endif
430             static const uint32_t ctrinc[] = {
431             0, 0, 0, 4
432             };
433              
434             cc0 = 0;
435             cc1 = 16;
436             cc2 = 32;
437             cc3 = 48;
438             asm volatile (
439              
440             /*
441             * Load subkeys into v0..v14
442             */
443             lxvw4x(32, %[cc0], %[sk])
444             addi(%[cc0], %[cc0], 16)
445             lxvw4x(33, %[cc0], %[sk])
446             addi(%[cc0], %[cc0], 16)
447             lxvw4x(34, %[cc0], %[sk])
448             addi(%[cc0], %[cc0], 16)
449             lxvw4x(35, %[cc0], %[sk])
450             addi(%[cc0], %[cc0], 16)
451             lxvw4x(36, %[cc0], %[sk])
452             addi(%[cc0], %[cc0], 16)
453             lxvw4x(37, %[cc0], %[sk])
454             addi(%[cc0], %[cc0], 16)
455             lxvw4x(38, %[cc0], %[sk])
456             addi(%[cc0], %[cc0], 16)
457             lxvw4x(39, %[cc0], %[sk])
458             addi(%[cc0], %[cc0], 16)
459             lxvw4x(40, %[cc0], %[sk])
460             addi(%[cc0], %[cc0], 16)
461             lxvw4x(41, %[cc0], %[sk])
462             addi(%[cc0], %[cc0], 16)
463             lxvw4x(42, %[cc0], %[sk])
464             addi(%[cc0], %[cc0], 16)
465             lxvw4x(43, %[cc0], %[sk])
466             addi(%[cc0], %[cc0], 16)
467             lxvw4x(44, %[cc0], %[sk])
468             addi(%[cc0], %[cc0], 16)
469             lxvw4x(45, %[cc0], %[sk])
470             addi(%[cc0], %[cc0], 16)
471             lxvw4x(46, %[cc0], %[sk])
472             li(%[cc0], 0)
473              
474             #if BR_POWER8_LE
475             /*
476             * v15 = constant for byteswapping words
477             */
478             lxvw4x(47, 0, %[idx2be])
479             #endif
480             /*
481             * v28 = increment for IV counter.
482             */
483             lxvw4x(60, 0, %[ctrinc])
484              
485             /*
486             * Load IV into v16..v19
487             */
488             lxvw4x(48, %[cc0], %[ivbuf])
489             lxvw4x(49, %[cc1], %[ivbuf])
490             lxvw4x(50, %[cc2], %[ivbuf])
491             lxvw4x(51, %[cc3], %[ivbuf])
492             #if BR_POWER8_LE
493             vperm(16, 16, 16, 15)
494             vperm(17, 17, 17, 15)
495             vperm(18, 18, 18, 15)
496             vperm(19, 19, 19, 15)
497             #endif
498              
499             mtctr(%[num_blocks])
500             label(loop)
501             /*
502             * Compute next IV into v24..v27
503             */
504             vadduwm(24, 16, 28)
505             vadduwm(25, 17, 28)
506             vadduwm(26, 18, 28)
507             vadduwm(27, 19, 28)
508              
509             /*
510             * Load next data blocks. We do this early on but we
511             * won't need them until IV encryption is done.
512             */
513             lxvw4x(52, %[cc0], %[buf])
514             lxvw4x(53, %[cc1], %[buf])
515             lxvw4x(54, %[cc2], %[buf])
516             lxvw4x(55, %[cc3], %[buf])
517              
518             /*
519             * Encrypt the current IV.
520             */
521             vxor(16, 16, 0)
522             vxor(17, 17, 0)
523             vxor(18, 18, 0)
524             vxor(19, 19, 0)
525             vcipher(16, 16, 1)
526             vcipher(17, 17, 1)
527             vcipher(18, 18, 1)
528             vcipher(19, 19, 1)
529             vcipher(16, 16, 2)
530             vcipher(17, 17, 2)
531             vcipher(18, 18, 2)
532             vcipher(19, 19, 2)
533             vcipher(16, 16, 3)
534             vcipher(17, 17, 3)
535             vcipher(18, 18, 3)
536             vcipher(19, 19, 3)
537             vcipher(16, 16, 4)
538             vcipher(17, 17, 4)
539             vcipher(18, 18, 4)
540             vcipher(19, 19, 4)
541             vcipher(16, 16, 5)
542             vcipher(17, 17, 5)
543             vcipher(18, 18, 5)
544             vcipher(19, 19, 5)
545             vcipher(16, 16, 6)
546             vcipher(17, 17, 6)
547             vcipher(18, 18, 6)
548             vcipher(19, 19, 6)
549             vcipher(16, 16, 7)
550             vcipher(17, 17, 7)
551             vcipher(18, 18, 7)
552             vcipher(19, 19, 7)
553             vcipher(16, 16, 8)
554             vcipher(17, 17, 8)
555             vcipher(18, 18, 8)
556             vcipher(19, 19, 8)
557             vcipher(16, 16, 9)
558             vcipher(17, 17, 9)
559             vcipher(18, 18, 9)
560             vcipher(19, 19, 9)
561             vcipher(16, 16, 10)
562             vcipher(17, 17, 10)
563             vcipher(18, 18, 10)
564             vcipher(19, 19, 10)
565             vcipher(16, 16, 11)
566             vcipher(17, 17, 11)
567             vcipher(18, 18, 11)
568             vcipher(19, 19, 11)
569             vcipher(16, 16, 12)
570             vcipher(17, 17, 12)
571             vcipher(18, 18, 12)
572             vcipher(19, 19, 12)
573             vcipher(16, 16, 13)
574             vcipher(17, 17, 13)
575             vcipher(18, 18, 13)
576             vcipher(19, 19, 13)
577             vcipherlast(16, 16, 14)
578             vcipherlast(17, 17, 14)
579             vcipherlast(18, 18, 14)
580             vcipherlast(19, 19, 14)
581              
582             #if BR_POWER8_LE
583             vperm(16, 16, 16, 15)
584             vperm(17, 17, 17, 15)
585             vperm(18, 18, 18, 15)
586             vperm(19, 19, 19, 15)
587             #endif
588              
589             /*
590             * Load next plaintext word and XOR with encrypted IV.
591             */
592             vxor(16, 20, 16)
593             vxor(17, 21, 17)
594             vxor(18, 22, 18)
595             vxor(19, 23, 19)
596             stxvw4x(48, %[cc0], %[buf])
597             stxvw4x(49, %[cc1], %[buf])
598             stxvw4x(50, %[cc2], %[buf])
599             stxvw4x(51, %[cc3], %[buf])
600              
601             addi(%[buf], %[buf], 64)
602              
603             /*
604             * Update IV.
605             */
606             vand(16, 24, 24)
607             vand(17, 25, 25)
608             vand(18, 26, 26)
609             vand(19, 27, 27)
610              
611             bdnz(loop)
612              
613             : [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
614             [buf] "+b" (buf)
615             : [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2),
616             [ctrinc] "b" (ctrinc)
617             #if BR_POWER8_LE
618             , [idx2be] "b" (idx2be)
619             #endif
620             : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
621             "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
622             "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
623             "ctr", "memory"
624             );
625             }
626              
627             /* see bearssl_block.h */
628             uint32_t
629             br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx,
630             const void *iv, uint32_t cc, void *data, size_t len)
631             {
632             unsigned char *buf;
633             unsigned char ivbuf[64];
634              
635             buf = data;
636             memcpy(ivbuf + 0, iv, 12);
637             memcpy(ivbuf + 16, iv, 12);
638             memcpy(ivbuf + 32, iv, 12);
639             memcpy(ivbuf + 48, iv, 12);
640             if (len >= 64) {
641             br_enc32be(ivbuf + 12, cc + 0);
642             br_enc32be(ivbuf + 28, cc + 1);
643             br_enc32be(ivbuf + 44, cc + 2);
644             br_enc32be(ivbuf + 60, cc + 3);
645             switch (ctx->num_rounds) {
646             case 10:
647             ctr_128(ctx->skey.skni, ivbuf, buf,
648             (len >> 4) & ~(size_t)3);
649             break;
650             case 12:
651             ctr_192(ctx->skey.skni, ivbuf, buf,
652             (len >> 4) & ~(size_t)3);
653             break;
654             default:
655             ctr_256(ctx->skey.skni, ivbuf, buf,
656             (len >> 4) & ~(size_t)3);
657             break;
658             }
659             cc += (len >> 4) & ~(size_t)3;
660             buf += len & ~(size_t)63;
661             len &= 63;
662             }
663             if (len > 0) {
664             unsigned char tmp[64];
665              
666             memcpy(tmp, buf, len);
667             memset(tmp + len, 0, (sizeof tmp) - len);
668             br_enc32be(ivbuf + 12, cc + 0);
669             br_enc32be(ivbuf + 28, cc + 1);
670             br_enc32be(ivbuf + 44, cc + 2);
671             br_enc32be(ivbuf + 60, cc + 3);
672             switch (ctx->num_rounds) {
673             case 10:
674             ctr_128(ctx->skey.skni, ivbuf, tmp, 4);
675             break;
676             case 12:
677             ctr_192(ctx->skey.skni, ivbuf, tmp, 4);
678             break;
679             default:
680             ctr_256(ctx->skey.skni, ivbuf, tmp, 4);
681             break;
682             }
683             memcpy(buf, tmp, len);
684             cc += (len + 15) >> 4;
685             }
686             return cc;
687             }
688              
689             /* see bearssl_block.h */
690             const br_block_ctr_class br_aes_pwr8_ctr_vtable = {
691             sizeof(br_aes_pwr8_ctr_keys),
692             16,
693             4,
694             (void (*)(const br_block_ctr_class **, const void *, size_t))
695             &br_aes_pwr8_ctr_init,
696             (uint32_t (*)(const br_block_ctr_class *const *,
697             const void *, uint32_t, void *, size_t))
698             &br_aes_pwr8_ctr_run
699             };
700              
701             /* see bearssl_block.h */
702             const br_block_ctr_class *
703             br_aes_pwr8_ctr_get_vtable(void)
704             {
705             return br_aes_pwr8_supported() ? &br_aes_pwr8_ctr_vtable : NULL;
706             }
707              
708             #else
709              
710             /* see bearssl_block.h */
711             const br_block_ctr_class *
712 0           br_aes_pwr8_ctr_get_vtable(void)
713             {
714 0           return NULL;
715             }
716              
717             #endif