OCB ARM CE: Move ocb_get_l handling to assembly part
[libgcrypt.git] / cipher / rijndael-armv8-ce.c
1 /* ARMv8 Crypto Extension AES for Libgcrypt
2  * Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h> /* for memcmp() */
25
26 #include "types.h"  /* for byte and u32 typedefs */
27 #include "g10lib.h"
28 #include "cipher.h"
29 #include "bufhelp.h"
30 #include "cipher-selftest.h"
31 #include "rijndael-internal.h"
32 #include "./cipher-internal.h"
33
34
35 #ifdef USE_ARM_CE
36
37
38 typedef struct u128_s { u32 a, b, c, d; } u128_t;
39
40 extern u32 _gcry_aes_sbox4_armv8_ce(u32 in4b);
41 extern void _gcry_aes_invmixcol_armv8_ce(u128_t *dst, const u128_t *src);
42
43 extern unsigned int _gcry_aes_enc_armv8_ce(const void *keysched, byte *dst,
44                                            const byte *src,
45                                            unsigned int nrounds);
46 extern unsigned int _gcry_aes_dec_armv8_ce(const void *keysched, byte *dst,
47                                            const byte *src,
48                                            unsigned int nrounds);
49
50 extern void _gcry_aes_cbc_enc_armv8_ce (const void *keysched,
51                                         unsigned char *outbuf,
52                                         const unsigned char *inbuf,
53                                         unsigned char *iv, size_t nblocks,
54                                         int cbc_mac, unsigned int nrounds);
55 extern void _gcry_aes_cbc_dec_armv8_ce (const void *keysched,
56                                         unsigned char *outbuf,
57                                         const unsigned char *inbuf,
58                                         unsigned char *iv, size_t nblocks,
59                                         unsigned int nrounds);
60
61 extern void _gcry_aes_cfb_enc_armv8_ce (const void *keysched,
62                                         unsigned char *outbuf,
63                                         const unsigned char *inbuf,
64                                         unsigned char *iv, size_t nblocks,
65                                         unsigned int nrounds);
66 extern void _gcry_aes_cfb_dec_armv8_ce (const void *keysched,
67                                         unsigned char *outbuf,
68                                         const unsigned char *inbuf,
69                                         unsigned char *iv, size_t nblocks,
70                                         unsigned int nrounds);
71
72 extern void _gcry_aes_ctr_enc_armv8_ce (const void *keysched,
73                                         unsigned char *outbuf,
74                                         const unsigned char *inbuf,
75                                         unsigned char *iv, size_t nblocks,
76                                         unsigned int nrounds);
77
78 extern void _gcry_aes_ocb_enc_armv8_ce (const void *keysched,
79                                         unsigned char *outbuf,
80                                         const unsigned char *inbuf,
81                                         unsigned char *offset,
82                                         unsigned char *checksum,
83                                         unsigned char *L_table,
84                                         size_t nblocks,
85                                         unsigned int nrounds,
86                                         unsigned int blkn);
87 extern void _gcry_aes_ocb_dec_armv8_ce (const void *keysched,
88                                         unsigned char *outbuf,
89                                         const unsigned char *inbuf,
90                                         unsigned char *offset,
91                                         unsigned char *checksum,
92                                         unsigned char *L_table,
93                                         size_t nblocks,
94                                         unsigned int nrounds,
95                                         unsigned int blkn);
96 extern void _gcry_aes_ocb_auth_armv8_ce (const void *keysched,
97                                          const unsigned char *abuf,
98                                          unsigned char *offset,
99                                          unsigned char *checksum,
100                                          unsigned char *L_table,
101                                          size_t nblocks,
102                                          unsigned int nrounds,
103                                          unsigned int blkn);
104
105 typedef void (*ocb_crypt_fn_t) (const void *keysched, unsigned char *outbuf,
106                                 const unsigned char *inbuf,
107                                 unsigned char *offset, unsigned char *checksum,
108                                 unsigned char *L_table, size_t nblocks,
109                                 unsigned int nrounds, unsigned int blkn);
110
111 void
112 _gcry_aes_armv8_ce_setkey (RIJNDAEL_context *ctx, const byte *key)
113 {
114   union
115     {
116       PROPERLY_ALIGNED_TYPE dummy;
117       byte data[MAXKC][4];
118       u32 data32[MAXKC];
119     } tkk[2];
120   unsigned int rounds = ctx->rounds;
121   int KC = rounds - 6;
122   unsigned int keylen = KC * 4;
123   unsigned int i, r, t;
124   byte rcon = 1;
125   int j;
126 #define k      tkk[0].data
127 #define k_u32  tkk[0].data32
128 #define tk     tkk[1].data
129 #define tk_u32 tkk[1].data32
130 #define W      (ctx->keyschenc)
131 #define W_u32  (ctx->keyschenc32)
132
133   for (i = 0; i < keylen; i++)
134     {
135       k[i >> 2][i & 3] = key[i];
136     }
137
138   for (j = KC-1; j >= 0; j--)
139     {
140       tk_u32[j] = k_u32[j];
141     }
142   r = 0;
143   t = 0;
144   /* Copy values into round key array.  */
145   for (j = 0; (j < KC) && (r < rounds + 1); )
146     {
147       for (; (j < KC) && (t < 4); j++, t++)
148         {
149           W_u32[r][t] = le_bswap32(tk_u32[j]);
150         }
151       if (t == 4)
152         {
153           r++;
154           t = 0;
155         }
156     }
157
158   while (r < rounds + 1)
159     {
160       tk_u32[0] ^= _gcry_aes_sbox4_armv8_ce(rol(tk_u32[KC - 1], 24)) ^ rcon;
161
162       if (KC != 8)
163         {
164           for (j = 1; j < KC; j++)
165             {
166               tk_u32[j] ^= tk_u32[j-1];
167             }
168         }
169       else
170         {
171           for (j = 1; j < KC/2; j++)
172             {
173               tk_u32[j] ^= tk_u32[j-1];
174             }
175
176           tk_u32[KC/2] ^= _gcry_aes_sbox4_armv8_ce(tk_u32[KC/2 - 1]);
177
178           for (j = KC/2 + 1; j < KC; j++)
179             {
180               tk_u32[j] ^= tk_u32[j-1];
181             }
182         }
183
184       /* Copy values into round key array.  */
185       for (j = 0; (j < KC) && (r < rounds + 1); )
186         {
187           for (; (j < KC) && (t < 4); j++, t++)
188             {
189               W_u32[r][t] = le_bswap32(tk_u32[j]);
190             }
191           if (t == 4)
192             {
193               r++;
194               t = 0;
195             }
196         }
197
198       rcon = (rcon << 1) ^ ((rcon >> 7) * 0x1b);
199     }
200
201 #undef W
202 #undef tk
203 #undef k
204 #undef W_u32
205 #undef tk_u32
206 #undef k_u32
207   wipememory(&tkk, sizeof(tkk));
208 }
209
210 /* Make a decryption key from an encryption key. */
211 void
212 _gcry_aes_armv8_ce_prepare_decryption (RIJNDAEL_context *ctx)
213 {
214   u128_t *ekey = (u128_t *)(void *)ctx->keyschenc;
215   u128_t *dkey = (u128_t *)(void *)ctx->keyschdec;
216   int rounds = ctx->rounds;
217   int rr;
218   int r;
219
220 #define DO_AESIMC() _gcry_aes_invmixcol_armv8_ce(&dkey[r], &ekey[rr])
221
222   dkey[0] = ekey[rounds];
223   r = 1;
224   rr = rounds-1;
225   DO_AESIMC(); r++; rr--; /* round 1 */
226   DO_AESIMC(); r++; rr--; /* round 2 */
227   DO_AESIMC(); r++; rr--; /* round 3 */
228   DO_AESIMC(); r++; rr--; /* round 4 */
229   DO_AESIMC(); r++; rr--; /* round 5 */
230   DO_AESIMC(); r++; rr--; /* round 6 */
231   DO_AESIMC(); r++; rr--; /* round 7 */
232   DO_AESIMC(); r++; rr--; /* round 8 */
233   DO_AESIMC(); r++; rr--; /* round 9 */
234   if (rounds >= 12)
235     {
236       if (rounds > 12)
237         {
238           DO_AESIMC(); r++; rr--; /* round 10 */
239           DO_AESIMC(); r++; rr--; /* round 11 */
240         }
241
242       DO_AESIMC(); r++; rr--; /* round 12 / 10 */
243       DO_AESIMC(); r++; rr--; /* round 13 / 11 */
244     }
245
246   dkey[r] = ekey[0];
247
248 #undef DO_AESIMC
249 }
250
251 unsigned int
252 _gcry_aes_armv8_ce_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
253                             const unsigned char *src)
254 {
255   const void *keysched = ctx->keyschenc32;
256   unsigned int nrounds = ctx->rounds;
257
258   return _gcry_aes_enc_armv8_ce(keysched, dst, src, nrounds);
259 }
260
261 unsigned int
262 _gcry_aes_armv8_ce_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
263                             const unsigned char *src)
264 {
265   const void *keysched = ctx->keyschdec32;
266   unsigned int nrounds = ctx->rounds;
267
268   return _gcry_aes_dec_armv8_ce(keysched, dst, src, nrounds);
269 }
270
271 void
272 _gcry_aes_armv8_ce_cbc_enc (const RIJNDAEL_context *ctx, unsigned char *outbuf,
273                             const unsigned char *inbuf, unsigned char *iv,
274                             size_t nblocks, int cbc_mac)
275 {
276   const void *keysched = ctx->keyschenc32;
277   unsigned int nrounds = ctx->rounds;
278
279   _gcry_aes_cbc_enc_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, cbc_mac,
280                              nrounds);
281 }
282
283 void
284 _gcry_aes_armv8_ce_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
285                             const unsigned char *inbuf, unsigned char *iv,
286                             size_t nblocks)
287 {
288   const void *keysched = ctx->keyschdec32;
289   unsigned int nrounds = ctx->rounds;
290
291   _gcry_aes_cbc_dec_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, nrounds);
292 }
293
294 void
295 _gcry_aes_armv8_ce_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
296                             const unsigned char *inbuf, unsigned char *iv,
297                             size_t nblocks)
298 {
299   const void *keysched = ctx->keyschenc32;
300   unsigned int nrounds = ctx->rounds;
301
302   _gcry_aes_cfb_enc_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, nrounds);
303 }
304
305 void
306 _gcry_aes_armv8_ce_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
307                             const unsigned char *inbuf, unsigned char *iv,
308                             size_t nblocks)
309 {
310   const void *keysched = ctx->keyschenc32;
311   unsigned int nrounds = ctx->rounds;
312
313   _gcry_aes_cfb_dec_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, nrounds);
314 }
315
316 void
317 _gcry_aes_armv8_ce_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
318                             const unsigned char *inbuf, unsigned char *iv,
319                             size_t nblocks)
320 {
321   const void *keysched = ctx->keyschenc32;
322   unsigned int nrounds = ctx->rounds;
323
324   _gcry_aes_ctr_enc_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, nrounds);
325 }
326
327 void
328 _gcry_aes_armv8_ce_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
329                               const void *inbuf_arg, size_t nblocks,
330                               int encrypt)
331 {
332   RIJNDAEL_context *ctx = (void *)&c->context.c;
333   const void *keysched = encrypt ? ctx->keyschenc32 : ctx->keyschdec32;
334   ocb_crypt_fn_t crypt_fn = encrypt ? _gcry_aes_ocb_enc_armv8_ce
335                                     : _gcry_aes_ocb_dec_armv8_ce;
336   unsigned char *outbuf = outbuf_arg;
337   const unsigned char *inbuf = inbuf_arg;
338   unsigned int nrounds = ctx->rounds;
339   u64 blkn = c->u_mode.ocb.data_nblocks;
340
341   c->u_mode.ocb.data_nblocks = blkn + nblocks;
342
343   crypt_fn(keysched, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr,
344            c->u_mode.ocb.L[0], nblocks, nrounds, (unsigned int)blkn);
345 }
346
347 void
348 _gcry_aes_armv8_ce_ocb_auth (gcry_cipher_hd_t c, void *abuf_arg,
349                              size_t nblocks)
350 {
351   RIJNDAEL_context *ctx = (void *)&c->context.c;
352   const void *keysched = ctx->keyschenc32;
353   const unsigned char *abuf = abuf_arg;
354   unsigned int nrounds = ctx->rounds;
355   u64 blkn = c->u_mode.ocb.aad_nblocks;
356
357   c->u_mode.ocb.aad_nblocks = blkn + nblocks;
358
359   _gcry_aes_ocb_auth_armv8_ce(keysched, abuf, c->u_mode.ocb.aad_offset,
360                               c->u_mode.ocb.aad_sum, c->u_mode.ocb.L[0],
361                               nblocks, nrounds, (unsigned int)blkn);
362 }
363
364 #endif /* USE_ARM_CE */