Coverage Report

Created: 2026-09-14 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/BearSSL/src/symcipher/aes_x86ni_ctrcbc.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
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_ENABLE_INTRINSICS   1
26
#include "inner.h"
27
28
#if BR_AES_X86NI
29
30
/* see bearssl_block.h */
31
const br_block_ctrcbc_class *
32
br_aes_x86ni_ctrcbc_get_vtable(void)
33
285
{
34
285
  return br_aes_x86ni_supported() ? &br_aes_x86ni_ctrcbc_vtable : NULL;
35
285
}
36
37
/* see bearssl_block.h */
38
void
39
br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx,
40
  const void *key, size_t len)
41
282
{
42
282
  ctx->vtable = &br_aes_x86ni_ctrcbc_vtable;
43
282
  ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len);
44
282
}
45
46
BR_TARGETS_X86_UP
47
48
/* see bearssl_block.h */
49
BR_TARGET("sse2,sse4.1,aes")
50
void
51
br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx,
52
  void *ctr, void *data, size_t len)
53
496
{
54
496
  unsigned char *buf;
55
496
  unsigned num_rounds;
56
496
  __m128i sk[15];
57
496
  __m128i ivx0, ivx1, ivx2, ivx3;
58
496
  __m128i erev, zero, one, four, notthree;
59
496
  unsigned u;
60
61
496
  buf = data;
62
496
  num_rounds = ctx->num_rounds;
63
7.05k
  for (u = 0; u <= num_rounds; u ++) {
64
6.55k
    sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
65
6.55k
  }
66
67
  /*
68
   * Some SSE2 constants.
69
   */
70
496
  erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
71
496
    8, 9, 10, 11, 12, 13, 14, 15);
72
496
  zero = _mm_setzero_si128();
73
496
  one = _mm_set_epi64x(0, 1);
74
496
  four = _mm_set_epi64x(0, 4);
75
496
  notthree = _mm_sub_epi64(zero, four);
76
77
  /*
78
   * Decode the counter in big-endian and pre-increment the other
79
   * three counters.
80
   */
81
496
  ivx0 = _mm_shuffle_epi8(_mm_loadu_si128((void *)ctr), erev);
82
496
  ivx1 = _mm_add_epi64(ivx0, one);
83
496
  ivx1 = _mm_sub_epi64(ivx1,
84
496
    _mm_slli_si128(_mm_cmpeq_epi64(ivx1, zero), 8));
85
496
  ivx2 = _mm_add_epi64(ivx1, one);
86
496
  ivx2 = _mm_sub_epi64(ivx2,
87
496
    _mm_slli_si128(_mm_cmpeq_epi64(ivx2, zero), 8));
88
496
  ivx3 = _mm_add_epi64(ivx2, one);
89
496
  ivx3 = _mm_sub_epi64(ivx3,
90
496
    _mm_slli_si128(_mm_cmpeq_epi64(ivx3, zero), 8));
91
496
  while (len > 0) {
92
496
    __m128i x0, x1, x2, x3;
93
94
    /*
95
     * Load counter values; we need to byteswap them because
96
     * the specification says that they use big-endian.
97
     */
98
496
    x0 = _mm_shuffle_epi8(ivx0, erev);
99
496
    x1 = _mm_shuffle_epi8(ivx1, erev);
100
496
    x2 = _mm_shuffle_epi8(ivx2, erev);
101
496
    x3 = _mm_shuffle_epi8(ivx3, erev);
102
103
496
    x0 = _mm_xor_si128(x0, sk[0]);
104
496
    x1 = _mm_xor_si128(x1, sk[0]);
105
496
    x2 = _mm_xor_si128(x2, sk[0]);
106
496
    x3 = _mm_xor_si128(x3, sk[0]);
107
496
    x0 = _mm_aesenc_si128(x0, sk[1]);
108
496
    x1 = _mm_aesenc_si128(x1, sk[1]);
109
496
    x2 = _mm_aesenc_si128(x2, sk[1]);
110
496
    x3 = _mm_aesenc_si128(x3, sk[1]);
111
496
    x0 = _mm_aesenc_si128(x0, sk[2]);
112
496
    x1 = _mm_aesenc_si128(x1, sk[2]);
113
496
    x2 = _mm_aesenc_si128(x2, sk[2]);
114
496
    x3 = _mm_aesenc_si128(x3, sk[2]);
115
496
    x0 = _mm_aesenc_si128(x0, sk[3]);
116
496
    x1 = _mm_aesenc_si128(x1, sk[3]);
117
496
    x2 = _mm_aesenc_si128(x2, sk[3]);
118
496
    x3 = _mm_aesenc_si128(x3, sk[3]);
119
496
    x0 = _mm_aesenc_si128(x0, sk[4]);
120
496
    x1 = _mm_aesenc_si128(x1, sk[4]);
121
496
    x2 = _mm_aesenc_si128(x2, sk[4]);
122
496
    x3 = _mm_aesenc_si128(x3, sk[4]);
123
496
    x0 = _mm_aesenc_si128(x0, sk[5]);
124
496
    x1 = _mm_aesenc_si128(x1, sk[5]);
125
496
    x2 = _mm_aesenc_si128(x2, sk[5]);
126
496
    x3 = _mm_aesenc_si128(x3, sk[5]);
127
496
    x0 = _mm_aesenc_si128(x0, sk[6]);
128
496
    x1 = _mm_aesenc_si128(x1, sk[6]);
129
496
    x2 = _mm_aesenc_si128(x2, sk[6]);
130
496
    x3 = _mm_aesenc_si128(x3, sk[6]);
131
496
    x0 = _mm_aesenc_si128(x0, sk[7]);
132
496
    x1 = _mm_aesenc_si128(x1, sk[7]);
133
496
    x2 = _mm_aesenc_si128(x2, sk[7]);
134
496
    x3 = _mm_aesenc_si128(x3, sk[7]);
135
496
    x0 = _mm_aesenc_si128(x0, sk[8]);
136
496
    x1 = _mm_aesenc_si128(x1, sk[8]);
137
496
    x2 = _mm_aesenc_si128(x2, sk[8]);
138
496
    x3 = _mm_aesenc_si128(x3, sk[8]);
139
496
    x0 = _mm_aesenc_si128(x0, sk[9]);
140
496
    x1 = _mm_aesenc_si128(x1, sk[9]);
141
496
    x2 = _mm_aesenc_si128(x2, sk[9]);
142
496
    x3 = _mm_aesenc_si128(x3, sk[9]);
143
496
    if (num_rounds == 10) {
144
158
      x0 = _mm_aesenclast_si128(x0, sk[10]);
145
158
      x1 = _mm_aesenclast_si128(x1, sk[10]);
146
158
      x2 = _mm_aesenclast_si128(x2, sk[10]);
147
158
      x3 = _mm_aesenclast_si128(x3, sk[10]);
148
338
    } else if (num_rounds == 12) {
149
126
      x0 = _mm_aesenc_si128(x0, sk[10]);
150
126
      x1 = _mm_aesenc_si128(x1, sk[10]);
151
126
      x2 = _mm_aesenc_si128(x2, sk[10]);
152
126
      x3 = _mm_aesenc_si128(x3, sk[10]);
153
126
      x0 = _mm_aesenc_si128(x0, sk[11]);
154
126
      x1 = _mm_aesenc_si128(x1, sk[11]);
155
126
      x2 = _mm_aesenc_si128(x2, sk[11]);
156
126
      x3 = _mm_aesenc_si128(x3, sk[11]);
157
126
      x0 = _mm_aesenclast_si128(x0, sk[12]);
158
126
      x1 = _mm_aesenclast_si128(x1, sk[12]);
159
126
      x2 = _mm_aesenclast_si128(x2, sk[12]);
160
126
      x3 = _mm_aesenclast_si128(x3, sk[12]);
161
212
    } else {
162
212
      x0 = _mm_aesenc_si128(x0, sk[10]);
163
212
      x1 = _mm_aesenc_si128(x1, sk[10]);
164
212
      x2 = _mm_aesenc_si128(x2, sk[10]);
165
212
      x3 = _mm_aesenc_si128(x3, sk[10]);
166
212
      x0 = _mm_aesenc_si128(x0, sk[11]);
167
212
      x1 = _mm_aesenc_si128(x1, sk[11]);
168
212
      x2 = _mm_aesenc_si128(x2, sk[11]);
169
212
      x3 = _mm_aesenc_si128(x3, sk[11]);
170
212
      x0 = _mm_aesenc_si128(x0, sk[12]);
171
212
      x1 = _mm_aesenc_si128(x1, sk[12]);
172
212
      x2 = _mm_aesenc_si128(x2, sk[12]);
173
212
      x3 = _mm_aesenc_si128(x3, sk[12]);
174
212
      x0 = _mm_aesenc_si128(x0, sk[13]);
175
212
      x1 = _mm_aesenc_si128(x1, sk[13]);
176
212
      x2 = _mm_aesenc_si128(x2, sk[13]);
177
212
      x3 = _mm_aesenc_si128(x3, sk[13]);
178
212
      x0 = _mm_aesenclast_si128(x0, sk[14]);
179
212
      x1 = _mm_aesenclast_si128(x1, sk[14]);
180
212
      x2 = _mm_aesenclast_si128(x2, sk[14]);
181
212
      x3 = _mm_aesenclast_si128(x3, sk[14]);
182
212
    }
183
496
    if (len >= 64) {
184
0
      x0 = _mm_xor_si128(x0,
185
0
        _mm_loadu_si128((void *)(buf +  0)));
186
0
      x1 = _mm_xor_si128(x1,
187
0
        _mm_loadu_si128((void *)(buf + 16)));
188
0
      x2 = _mm_xor_si128(x2,
189
0
        _mm_loadu_si128((void *)(buf + 32)));
190
0
      x3 = _mm_xor_si128(x3,
191
0
        _mm_loadu_si128((void *)(buf + 48)));
192
0
      _mm_storeu_si128((void *)(buf +  0), x0);
193
0
      _mm_storeu_si128((void *)(buf + 16), x1);
194
0
      _mm_storeu_si128((void *)(buf + 32), x2);
195
0
      _mm_storeu_si128((void *)(buf + 48), x3);
196
0
      buf += 64;
197
0
      len -= 64;
198
496
    } else {
199
496
      unsigned char tmp[64];
200
201
496
      _mm_storeu_si128((void *)(tmp +  0), x0);
202
496
      _mm_storeu_si128((void *)(tmp + 16), x1);
203
496
      _mm_storeu_si128((void *)(tmp + 32), x2);
204
496
      _mm_storeu_si128((void *)(tmp + 48), x3);
205
8.43k
      for (u = 0; u < len; u ++) {
206
7.93k
        buf[u] ^= tmp[u];
207
7.93k
      }
208
496
      switch (len) {
209
496
      case 16:
210
496
        ivx0 = ivx1;
211
496
        break;
212
0
      case 32:
213
0
        ivx0 = ivx2;
214
0
        break;
215
0
      case 48:
216
0
        ivx0 = ivx3;
217
0
        break;
218
496
      }
219
496
      break;
220
496
    }
221
222
    /*
223
     * Add 4 to each counter value. For carry propagation
224
     * into the upper 64-bit words, we would need to compare
225
     * the results with 4, but SSE2+ has only _signed_
226
     * comparisons. Instead, we mask out the low two bits,
227
     * and check whether the remaining bits are zero.
228
     */
229
0
    ivx0 = _mm_add_epi64(ivx0, four);
230
0
    ivx1 = _mm_add_epi64(ivx1, four);
231
0
    ivx2 = _mm_add_epi64(ivx2, four);
232
0
    ivx3 = _mm_add_epi64(ivx3, four);
233
0
    ivx0 = _mm_sub_epi64(ivx0,
234
0
      _mm_slli_si128(_mm_cmpeq_epi64(
235
0
        _mm_and_si128(ivx0, notthree), zero), 8));
236
0
    ivx1 = _mm_sub_epi64(ivx1,
237
0
      _mm_slli_si128(_mm_cmpeq_epi64(
238
0
        _mm_and_si128(ivx1, notthree), zero), 8));
239
0
    ivx2 = _mm_sub_epi64(ivx2,
240
0
      _mm_slli_si128(_mm_cmpeq_epi64(
241
0
        _mm_and_si128(ivx2, notthree), zero), 8));
242
0
    ivx3 = _mm_sub_epi64(ivx3,
243
0
      _mm_slli_si128(_mm_cmpeq_epi64(
244
0
        _mm_and_si128(ivx3, notthree), zero), 8));
245
0
  }
246
247
  /*
248
   * Write back new counter value. The loop took care to put the
249
   * right counter value in ivx0.
250
   */
251
496
  _mm_storeu_si128((void *)ctr, _mm_shuffle_epi8(ivx0, erev));
252
496
}
253
254
/* see bearssl_block.h */
255
BR_TARGET("sse2,sse4.1,aes")
256
void
257
br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx,
258
  void *cbcmac, const void *data, size_t len)
259
996
{
260
996
  const unsigned char *buf;
261
996
  unsigned num_rounds;
262
996
  __m128i sk[15], ivx;
263
996
  unsigned u;
264
265
996
  buf = data;
266
996
  ivx = _mm_loadu_si128(cbcmac);
267
996
  num_rounds = ctx->num_rounds;
268
14.1k
  for (u = 0; u <= num_rounds; u ++) {
269
13.1k
    sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
270
13.1k
  }
271
2.57k
  while (len > 0) {
272
1.58k
    __m128i x;
273
274
1.58k
    x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx);
275
1.58k
    x = _mm_xor_si128(x, sk[0]);
276
1.58k
    x = _mm_aesenc_si128(x, sk[1]);
277
1.58k
    x = _mm_aesenc_si128(x, sk[2]);
278
1.58k
    x = _mm_aesenc_si128(x, sk[3]);
279
1.58k
    x = _mm_aesenc_si128(x, sk[4]);
280
1.58k
    x = _mm_aesenc_si128(x, sk[5]);
281
1.58k
    x = _mm_aesenc_si128(x, sk[6]);
282
1.58k
    x = _mm_aesenc_si128(x, sk[7]);
283
1.58k
    x = _mm_aesenc_si128(x, sk[8]);
284
1.58k
    x = _mm_aesenc_si128(x, sk[9]);
285
1.58k
    if (num_rounds == 10) {
286
317
      x = _mm_aesenclast_si128(x, sk[10]);
287
1.26k
    } else if (num_rounds == 12) {
288
811
      x = _mm_aesenc_si128(x, sk[10]);
289
811
      x = _mm_aesenc_si128(x, sk[11]);
290
811
      x = _mm_aesenclast_si128(x, sk[12]);
291
811
    } else {
292
453
      x = _mm_aesenc_si128(x, sk[10]);
293
453
      x = _mm_aesenc_si128(x, sk[11]);
294
453
      x = _mm_aesenc_si128(x, sk[12]);
295
453
      x = _mm_aesenc_si128(x, sk[13]);
296
453
      x = _mm_aesenclast_si128(x, sk[14]);
297
453
    }
298
1.58k
    ivx = x;
299
1.58k
    buf += 16;
300
1.58k
    len -= 16;
301
1.58k
  }
302
996
  _mm_storeu_si128(cbcmac, ivx);
303
996
}
304
305
/* see bearssl_block.h */
306
BR_TARGET("sse2,sse4.1,aes")
307
void
308
br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
309
  void *ctr, void *cbcmac, void *data, size_t len)
310
410
{
311
410
  unsigned char *buf;
312
410
  unsigned num_rounds;
313
410
  __m128i sk[15];
314
410
  __m128i ivx, cmx;
315
410
  __m128i erev, zero, one;
316
410
  unsigned u;
317
410
  int first_iter;
318
319
410
  num_rounds = ctx->num_rounds;
320
5.77k
  for (u = 0; u <= num_rounds; u ++) {
321
5.36k
    sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
322
5.36k
  }
323
324
  /*
325
   * Some SSE2 constants.
326
   */
327
410
  erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
328
410
    8, 9, 10, 11, 12, 13, 14, 15);
329
410
  zero = _mm_setzero_si128();
330
410
  one = _mm_set_epi64x(0, 1);
331
332
  /*
333
   * Decode the counter in big-endian.
334
   */
335
410
  ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev);
336
410
  cmx = _mm_loadu_si128(cbcmac);
337
338
410
  buf = data;
339
410
  first_iter = 1;
340
989
  while (len > 0) {
341
735
    __m128i dx, x0, x1;
342
343
    /*
344
     * Load initial values:
345
     *   dx   encrypted block of data
346
     *   x0   counter (for CTR encryption)
347
     *   x1   input for CBC-MAC
348
     */
349
735
    dx = _mm_loadu_si128((void *)buf);
350
735
    x0 = _mm_shuffle_epi8(ivx, erev);
351
735
    x1 = cmx;
352
353
735
    x0 = _mm_xor_si128(x0, sk[0]);
354
735
    x1 = _mm_xor_si128(x1, sk[0]);
355
735
    x0 = _mm_aesenc_si128(x0, sk[1]);
356
735
    x1 = _mm_aesenc_si128(x1, sk[1]);
357
735
    x0 = _mm_aesenc_si128(x0, sk[2]);
358
735
    x1 = _mm_aesenc_si128(x1, sk[2]);
359
735
    x0 = _mm_aesenc_si128(x0, sk[3]);
360
735
    x1 = _mm_aesenc_si128(x1, sk[3]);
361
735
    x0 = _mm_aesenc_si128(x0, sk[4]);
362
735
    x1 = _mm_aesenc_si128(x1, sk[4]);
363
735
    x0 = _mm_aesenc_si128(x0, sk[5]);
364
735
    x1 = _mm_aesenc_si128(x1, sk[5]);
365
735
    x0 = _mm_aesenc_si128(x0, sk[6]);
366
735
    x1 = _mm_aesenc_si128(x1, sk[6]);
367
735
    x0 = _mm_aesenc_si128(x0, sk[7]);
368
735
    x1 = _mm_aesenc_si128(x1, sk[7]);
369
735
    x0 = _mm_aesenc_si128(x0, sk[8]);
370
735
    x1 = _mm_aesenc_si128(x1, sk[8]);
371
735
    x0 = _mm_aesenc_si128(x0, sk[9]);
372
735
    x1 = _mm_aesenc_si128(x1, sk[9]);
373
735
    if (num_rounds == 10) {
374
166
      x0 = _mm_aesenclast_si128(x0, sk[10]);
375
166
      x1 = _mm_aesenclast_si128(x1, sk[10]);
376
569
    } else if (num_rounds == 12) {
377
165
      x0 = _mm_aesenc_si128(x0, sk[10]);
378
165
      x1 = _mm_aesenc_si128(x1, sk[10]);
379
165
      x0 = _mm_aesenc_si128(x0, sk[11]);
380
165
      x1 = _mm_aesenc_si128(x1, sk[11]);
381
165
      x0 = _mm_aesenclast_si128(x0, sk[12]);
382
165
      x1 = _mm_aesenclast_si128(x1, sk[12]);
383
404
    } else {
384
404
      x0 = _mm_aesenc_si128(x0, sk[10]);
385
404
      x1 = _mm_aesenc_si128(x1, sk[10]);
386
404
      x0 = _mm_aesenc_si128(x0, sk[11]);
387
404
      x1 = _mm_aesenc_si128(x1, sk[11]);
388
404
      x0 = _mm_aesenc_si128(x0, sk[12]);
389
404
      x1 = _mm_aesenc_si128(x1, sk[12]);
390
404
      x0 = _mm_aesenc_si128(x0, sk[13]);
391
404
      x1 = _mm_aesenc_si128(x1, sk[13]);
392
404
      x0 = _mm_aesenclast_si128(x0, sk[14]);
393
404
      x1 = _mm_aesenclast_si128(x1, sk[14]);
394
404
    }
395
396
735
    x0 = _mm_xor_si128(x0, dx);
397
735
    if (first_iter) {
398
156
      cmx = _mm_xor_si128(cmx, x0);
399
156
      first_iter = 0;
400
579
    } else {
401
579
      cmx = _mm_xor_si128(x1, x0);
402
579
    }
403
735
    _mm_storeu_si128((void *)buf, x0);
404
405
735
    buf += 16;
406
735
    len -= 16;
407
408
    /*
409
     * Increment the counter value.
410
     */
411
735
    ivx = _mm_add_epi64(ivx, one);
412
735
    ivx = _mm_sub_epi64(ivx,
413
735
      _mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8));
414
415
    /*
416
     * If this was the last iteration, then compute the
417
     * extra block encryption to complete CBC-MAC.
418
     */
419
735
    if (len == 0) {
420
156
      cmx = _mm_xor_si128(cmx, sk[0]);
421
156
      cmx = _mm_aesenc_si128(cmx, sk[1]);
422
156
      cmx = _mm_aesenc_si128(cmx, sk[2]);
423
156
      cmx = _mm_aesenc_si128(cmx, sk[3]);
424
156
      cmx = _mm_aesenc_si128(cmx, sk[4]);
425
156
      cmx = _mm_aesenc_si128(cmx, sk[5]);
426
156
      cmx = _mm_aesenc_si128(cmx, sk[6]);
427
156
      cmx = _mm_aesenc_si128(cmx, sk[7]);
428
156
      cmx = _mm_aesenc_si128(cmx, sk[8]);
429
156
      cmx = _mm_aesenc_si128(cmx, sk[9]);
430
156
      if (num_rounds == 10) {
431
20
        cmx = _mm_aesenclast_si128(cmx, sk[10]);
432
136
      } else if (num_rounds == 12) {
433
71
        cmx = _mm_aesenc_si128(cmx, sk[10]);
434
71
        cmx = _mm_aesenc_si128(cmx, sk[11]);
435
71
        cmx = _mm_aesenclast_si128(cmx, sk[12]);
436
71
      } else {
437
65
        cmx = _mm_aesenc_si128(cmx, sk[10]);
438
65
        cmx = _mm_aesenc_si128(cmx, sk[11]);
439
65
        cmx = _mm_aesenc_si128(cmx, sk[12]);
440
65
        cmx = _mm_aesenc_si128(cmx, sk[13]);
441
65
        cmx = _mm_aesenclast_si128(cmx, sk[14]);
442
65
      }
443
156
      break;
444
156
    }
445
735
  }
446
447
  /*
448
   * Write back new counter value and CBC-MAC value.
449
   */
450
410
  _mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev));
451
410
  _mm_storeu_si128(cbcmac, cmx);
452
410
}
453
454
/* see bearssl_block.h */
455
BR_TARGET("sse2,sse4.1,aes")
456
void
457
br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
458
  void *ctr, void *cbcmac, void *data, size_t len)
459
393
{
460
393
  unsigned char *buf;
461
393
  unsigned num_rounds;
462
393
  __m128i sk[15];
463
393
  __m128i ivx, cmx;
464
393
  __m128i erev, zero, one;
465
393
  unsigned u;
466
467
393
  num_rounds = ctx->num_rounds;
468
5.49k
  for (u = 0; u <= num_rounds; u ++) {
469
5.09k
    sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
470
5.09k
  }
471
472
  /*
473
   * Some SSE2 constants.
474
   */
475
393
  erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
476
393
    8, 9, 10, 11, 12, 13, 14, 15);
477
393
  zero = _mm_setzero_si128();
478
393
  one = _mm_set_epi64x(0, 1);
479
480
  /*
481
   * Decode the counter in big-endian.
482
   */
483
393
  ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev);
484
393
  cmx = _mm_loadu_si128(cbcmac);
485
486
393
  buf = data;
487
1.38k
  while (len > 0) {
488
992
    __m128i dx, x0, x1;
489
490
    /*
491
     * Load initial values:
492
     *   dx   encrypted block of data
493
     *   x0   counter (for CTR encryption)
494
     *   x1   input for CBC-MAC
495
     */
496
992
    dx = _mm_loadu_si128((void *)buf);
497
992
    x0 = _mm_shuffle_epi8(ivx, erev);
498
992
    x1 = _mm_xor_si128(cmx, dx);
499
500
992
    x0 = _mm_xor_si128(x0, sk[0]);
501
992
    x1 = _mm_xor_si128(x1, sk[0]);
502
992
    x0 = _mm_aesenc_si128(x0, sk[1]);
503
992
    x1 = _mm_aesenc_si128(x1, sk[1]);
504
992
    x0 = _mm_aesenc_si128(x0, sk[2]);
505
992
    x1 = _mm_aesenc_si128(x1, sk[2]);
506
992
    x0 = _mm_aesenc_si128(x0, sk[3]);
507
992
    x1 = _mm_aesenc_si128(x1, sk[3]);
508
992
    x0 = _mm_aesenc_si128(x0, sk[4]);
509
992
    x1 = _mm_aesenc_si128(x1, sk[4]);
510
992
    x0 = _mm_aesenc_si128(x0, sk[5]);
511
992
    x1 = _mm_aesenc_si128(x1, sk[5]);
512
992
    x0 = _mm_aesenc_si128(x0, sk[6]);
513
992
    x1 = _mm_aesenc_si128(x1, sk[6]);
514
992
    x0 = _mm_aesenc_si128(x0, sk[7]);
515
992
    x1 = _mm_aesenc_si128(x1, sk[7]);
516
992
    x0 = _mm_aesenc_si128(x0, sk[8]);
517
992
    x1 = _mm_aesenc_si128(x1, sk[8]);
518
992
    x0 = _mm_aesenc_si128(x0, sk[9]);
519
992
    x1 = _mm_aesenc_si128(x1, sk[9]);
520
992
    if (num_rounds == 10) {
521
423
      x0 = _mm_aesenclast_si128(x0, sk[10]);
522
423
      x1 = _mm_aesenclast_si128(x1, sk[10]);
523
569
    } else if (num_rounds == 12) {
524
255
      x0 = _mm_aesenc_si128(x0, sk[10]);
525
255
      x1 = _mm_aesenc_si128(x1, sk[10]);
526
255
      x0 = _mm_aesenc_si128(x0, sk[11]);
527
255
      x1 = _mm_aesenc_si128(x1, sk[11]);
528
255
      x0 = _mm_aesenclast_si128(x0, sk[12]);
529
255
      x1 = _mm_aesenclast_si128(x1, sk[12]);
530
314
    } else {
531
314
      x0 = _mm_aesenc_si128(x0, sk[10]);
532
314
      x1 = _mm_aesenc_si128(x1, sk[10]);
533
314
      x0 = _mm_aesenc_si128(x0, sk[11]);
534
314
      x1 = _mm_aesenc_si128(x1, sk[11]);
535
314
      x0 = _mm_aesenc_si128(x0, sk[12]);
536
314
      x1 = _mm_aesenc_si128(x1, sk[12]);
537
314
      x0 = _mm_aesenc_si128(x0, sk[13]);
538
314
      x1 = _mm_aesenc_si128(x1, sk[13]);
539
314
      x0 = _mm_aesenclast_si128(x0, sk[14]);
540
314
      x1 = _mm_aesenclast_si128(x1, sk[14]);
541
314
    }
542
992
    x0 = _mm_xor_si128(x0, dx);
543
992
    cmx = x1;
544
992
    _mm_storeu_si128((void *)buf, x0);
545
546
992
    buf += 16;
547
992
    len -= 16;
548
549
    /*
550
     * Increment the counter value.
551
     */
552
992
    ivx = _mm_add_epi64(ivx, one);
553
992
    ivx = _mm_sub_epi64(ivx,
554
992
      _mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8));
555
992
  }
556
557
  /*
558
   * Write back new counter value and CBC-MAC value.
559
   */
560
393
  _mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev));
561
393
  _mm_storeu_si128(cbcmac, cmx);
562
393
}
563
564
BR_TARGETS_X86_DOWN
565
566
/* see bearssl_block.h */
567
const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable = {
568
  sizeof(br_aes_x86ni_ctrcbc_keys),
569
  16,
570
  4,
571
  (void (*)(const br_block_ctrcbc_class **, const void *, size_t))
572
    &br_aes_x86ni_ctrcbc_init,
573
  (void (*)(const br_block_ctrcbc_class *const *,
574
    void *, void *, void *, size_t))
575
    &br_aes_x86ni_ctrcbc_encrypt,
576
  (void (*)(const br_block_ctrcbc_class *const *,
577
    void *, void *, void *, size_t))
578
    &br_aes_x86ni_ctrcbc_decrypt,
579
  (void (*)(const br_block_ctrcbc_class *const *,
580
    void *, void *, size_t))
581
    &br_aes_x86ni_ctrcbc_ctr,
582
  (void (*)(const br_block_ctrcbc_class *const *,
583
    void *, const void *, size_t))
584
    &br_aes_x86ni_ctrcbc_mac
585
};
586
587
#else
588
589
/* see bearssl_block.h */
590
const br_block_ctrcbc_class *
591
br_aes_x86ni_ctrcbc_get_vtable(void)
592
{
593
  return NULL;
594
}
595
596
#endif