Coverage Report

Created: 2023-03-26 07:33

/src/gnutls/lib/accelerated/afalg.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2017 Stephan Mueller <smueller@chronox.de>
3
 *
4
 * Author: Stephan Mueller
5
 *
6
 * This code is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public License
8
 * as published by the Free Software Foundation; either version 2.1 of
9
 * the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful, but
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
#include "config.h"
21
22
#include <accelerated/afalg.h>
23
24
#ifdef ENABLE_AFALG
25
26
# include "errors.h"
27
# include "gnutls_int.h"
28
29
# include <gnutls/crypto.h>
30
# include <kcapi.h>
31
# include <limits.h>
32
# include "malloca.h"
33
34
/************************ Symmetric cipher algorithms ************************/
35
36
struct kcapi_ctx {
37
  struct kcapi_handle *handle;
38
  int enc;
39
  uint8_t iv[MAX_CIPHER_IV_SIZE];
40
};
41
42
static const char *gnutls_cipher_map[] = {
43
  [GNUTLS_CIPHER_AES_128_CBC] = "cbc(aes)",
44
  [GNUTLS_CIPHER_AES_192_CBC] = "cbc(aes)",
45
  [GNUTLS_CIPHER_AES_256_CBC] = "cbc(aes)",
46
  [GNUTLS_CIPHER_3DES_CBC] = "cbc(des3_ede)",
47
  [GNUTLS_CIPHER_CAMELLIA_128_CBC] = "cbc(camellia)",
48
  [GNUTLS_CIPHER_CAMELLIA_192_CBC] = "cbc(camellia)",
49
  [GNUTLS_CIPHER_CAMELLIA_256_CBC] = "cbc(camellia)",
50
  [GNUTLS_CIPHER_SALSA20_256] = "salsa20",
51
  [GNUTLS_CIPHER_AES_128_XTS] = "xts(aes)",
52
  [GNUTLS_CIPHER_AES_256_XTS] = "xts(aes)",
53
};
54
55
static int
56
afalg_cipher_init(gnutls_cipher_algorithm_t algorithm, void **_ctx, int enc)
57
{
58
  struct kcapi_handle *handle;
59
  struct kcapi_ctx *ctx;
60
61
  if (kcapi_cipher_init(&handle, gnutls_cipher_map[algorithm], 0) < 0) {
62
    gnutls_assert();
63
    return GNUTLS_E_MEMORY_ERROR;
64
  }
65
66
  if (unlikely(kcapi_cipher_ivsize(handle) > MAX_CIPHER_IV_SIZE)) {
67
    gnutls_assert();
68
    return GNUTLS_E_INTERNAL_ERROR;
69
  }
70
71
  ctx = gnutls_malloc(sizeof(struct kcapi_ctx));
72
  if (ctx == NULL) {
73
    gnutls_assert();
74
    kcapi_cipher_destroy(handle);
75
    return GNUTLS_E_MEMORY_ERROR;
76
  }
77
78
  ctx->handle = handle;
79
  ctx->enc = enc;
80
  *_ctx = ctx;
81
  return 0;
82
}
83
84
static int afalg_cipher_setkey(void *_ctx, const void *key, size_t keysize)
85
{
86
  struct kcapi_ctx *ctx = _ctx;
87
88
  if (kcapi_cipher_setkey(ctx->handle, key, keysize) < 0) {
89
    gnutls_assert();
90
    return GNUTLS_E_ENCRYPTION_FAILED;
91
  }
92
93
  return 0;
94
}
95
96
static int afalg_cipher_setiv(void *_ctx, const void *iv, size_t iv_size)
97
{
98
  struct kcapi_ctx *ctx = _ctx;
99
100
  if (iv_size > kcapi_cipher_ivsize(ctx->handle))
101
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
102
103
  memcpy(ctx->iv, iv, iv_size);
104
  if (ctx->enc) {
105
    if (kcapi_cipher_stream_init_enc(ctx->handle, ctx->iv, NULL, 0)
106
        < 0) {
107
      gnutls_assert();
108
      return GNUTLS_E_ENCRYPTION_FAILED;
109
    }
110
  } else {
111
    if (kcapi_cipher_stream_init_dec(ctx->handle, ctx->iv, NULL, 0)
112
        < 0) {
113
      gnutls_assert();
114
      return GNUTLS_E_ENCRYPTION_FAILED;
115
    }
116
  }
117
118
  return 0;
119
}
120
121
static int afalg_cipher_encrypt(void *_ctx, const void *src, size_t src_size,
122
        void *dst, size_t dst_size)
123
{
124
  struct kcapi_ctx *ctx = _ctx;
125
  struct iovec iov;
126
127
  iov.iov_base = (void *)src;
128
  iov.iov_len = src_size;
129
130
  if (unlikely(src_size % kcapi_cipher_blocksize(ctx->handle))) {
131
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
132
  }
133
134
  if (kcapi_cipher_stream_update(ctx->handle, &iov, 1) < 0) {
135
    return gnutls_assert_val(GNUTLS_E_ENCRYPTION_FAILED);
136
  }
137
138
  if (unlikely(dst_size < src_size))
139
    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
140
141
  iov.iov_base = (void *)dst;
142
  iov.iov_len = src_size;
143
144
  if (kcapi_cipher_stream_op(ctx->handle, &iov, 1) < 0) {
145
    gnutls_assert();
146
    return GNUTLS_E_ENCRYPTION_FAILED;
147
  }
148
149
  return 0;
150
}
151
152
static int afalg_cipher_decrypt(void *_ctx, const void *src, size_t src_size,
153
        void *dst, size_t dst_size)
154
{
155
  struct kcapi_ctx *ctx = _ctx;
156
  struct iovec iov;
157
158
  iov.iov_base = (void *)src;
159
  iov.iov_len = src_size;
160
161
  if (unlikely(src_size % kcapi_cipher_blocksize(ctx->handle))) {
162
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
163
  }
164
165
  if (kcapi_cipher_stream_update(ctx->handle, &iov, 1) < 0) {
166
    return gnutls_assert_val(GNUTLS_E_ENCRYPTION_FAILED);
167
  }
168
169
  if (unlikely(dst_size < src_size))
170
    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
171
172
  iov.iov_base = (void *)dst;
173
  iov.iov_len = src_size;
174
175
  if (kcapi_cipher_stream_op(ctx->handle, &iov, 1) < 0) {
176
    gnutls_assert();
177
    return GNUTLS_E_ENCRYPTION_FAILED;
178
  }
179
180
  return 0;
181
}
182
183
static void afalg_cipher_deinit(void *_ctx)
184
{
185
  struct kcapi_ctx *ctx = _ctx;
186
187
  kcapi_cipher_destroy(ctx->handle);
188
  gnutls_free(ctx);
189
}
190
191
static const gnutls_crypto_cipher_st afalg_cipher_struct = {
192
  .init = afalg_cipher_init,
193
  .setkey = afalg_cipher_setkey,
194
  .setiv = afalg_cipher_setiv,
195
  .encrypt = afalg_cipher_encrypt,
196
  .decrypt = afalg_cipher_decrypt,
197
  .deinit = afalg_cipher_deinit,
198
};
199
200
static int afalg_cipher_register(void)
201
{
202
  unsigned int i;
203
  int ret = 0;
204
205
  for (i = 0;
206
       i < sizeof(gnutls_cipher_map) / sizeof(gnutls_cipher_map[0]);
207
       i++) {
208
    struct kcapi_handle *handle;
209
210
    if (gnutls_cipher_map[i] == 0)
211
      continue;
212
213
    /* Check whether cipher is available. */
214
    if (kcapi_cipher_init(&handle, gnutls_cipher_map[i], 0))
215
      continue;
216
217
    kcapi_cipher_destroy(handle);
218
219
    _gnutls_debug_log("afalg: registering: %s\n",
220
          gnutls_cipher_get_name(i));
221
    ret = gnutls_crypto_single_cipher_register(i, 90,
222
                 &afalg_cipher_struct,
223
                 0);
224
    if (ret < 0) {
225
      gnutls_assert();
226
      return ret;
227
    }
228
  }
229
230
  return ret;
231
}
232
233
/************************ Symmetric cipher algorithms ************************/
234
235
struct kcapi_aead_ctx {
236
  struct kcapi_handle *handle;
237
  int taglen_set;
238
  int ccm;
239
};
240
241
static const char *gnutls_aead_map[] = {
242
  [GNUTLS_CIPHER_CAMELLIA_128_GCM] = "gcm(camellia)",
243
  [GNUTLS_CIPHER_CAMELLIA_256_GCM] = "gcm(camellia)",
244
  [GNUTLS_CIPHER_AES_128_CCM] = "ccm(aes)",
245
  [GNUTLS_CIPHER_AES_256_CCM] = "ccm(aes)",
246
  [GNUTLS_CIPHER_AES_128_GCM] = "gcm(aes)",
247
  [GNUTLS_CIPHER_AES_256_GCM] = "gcm(aes)",
248
};
249
250
static void afalg_aead_deinit(void *_ctx)
251
{
252
  struct kcapi_aead_ctx *ctx = _ctx;
253
254
  kcapi_aead_destroy(ctx->handle);
255
  gnutls_free(ctx);
256
}
257
258
static int
259
afalg_aead_init(gnutls_cipher_algorithm_t algorithm, void **_ctx, int enc)
260
{
261
  struct kcapi_handle *handle;
262
  struct kcapi_aead_ctx *ctx;
263
264
  if (kcapi_aead_init(&handle, gnutls_aead_map[algorithm], 0) < 0) {
265
    gnutls_assert();
266
    return GNUTLS_E_MEMORY_ERROR;
267
  }
268
269
  ctx = gnutls_malloc(sizeof(struct kcapi_aead_ctx));
270
  if (ctx == NULL) {
271
    gnutls_assert();
272
    kcapi_aead_destroy(handle);
273
    return GNUTLS_E_MEMORY_ERROR;
274
  }
275
276
  switch (algorithm) {
277
  case GNUTLS_CIPHER_AES_128_CCM:
278
  case GNUTLS_CIPHER_AES_256_CCM:
279
    ctx->ccm = 1;
280
    break;
281
  default:
282
    ctx->ccm = 0;
283
  }
284
  ctx->handle = handle;
285
  *_ctx = ctx;
286
287
  return 0;
288
}
289
290
static int afalg_aead_setkey(void *_ctx, const void *key, size_t keysize)
291
{
292
  struct kcapi_aead_ctx *ctx = _ctx;
293
294
  if (kcapi_aead_setkey(ctx->handle, key, keysize) < 0) {
295
    gnutls_assert();
296
    return GNUTLS_E_ENCRYPTION_FAILED;
297
  }
298
299
  return 0;
300
}
301
302
static int afalg_aead_decrypt(void *_ctx,
303
            const void *nonce, size_t nonce_size,
304
            const void *auth, size_t auth_size,
305
            size_t tag_size,
306
            const void *encr, size_t encr_size,
307
            void *plain, size_t plain_size)
308
{
309
  int ret = 0;
310
  struct kcapi_aead_ctx *ctx = _ctx;
311
  struct iovec iov[2];
312
  uint8_t *authtmp = malloca(auth_size);
313
  if (authtmp == NULL) {
314
    gnutls_assert();
315
    return GNUTLS_E_MEMORY_ERROR;
316
  }
317
  if (encr_size < tag_size) {
318
    gnutls_assert();
319
    ret = GNUTLS_E_DECRYPTION_FAILED;
320
    goto end;
321
  }
322
323
  if (unlikely(plain_size < encr_size - tag_size)) {
324
    gnutls_assert();
325
    ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
326
    goto end;
327
  }
328
329
  /* Init stream once. */
330
  if (!ctx->taglen_set) {
331
    ctx->taglen_set = 1;
332
    if (kcapi_aead_settaglen(ctx->handle, tag_size) < 0) {
333
      gnutls_assert();
334
      ret = GNUTLS_E_DECRYPTION_FAILED;
335
      goto end;
336
    }
337
  }
338
339
  kcapi_aead_setassoclen(ctx->handle, auth_size);
340
341
  /* CCM nonce to IV conversion */
342
  if (ctx->ccm) {
343
    uint8_t *ccm_iv = NULL;
344
    uint32_t ccm_iv_len;
345
346
    if (kcapi_aead_ccm_nonce_to_iv(nonce, nonce_size, &ccm_iv,
347
                 &ccm_iv_len)) {
348
      gnutls_assert();
349
      ret = GNUTLS_E_DECRYPTION_FAILED;
350
      goto end;
351
    }
352
    if (kcapi_aead_stream_init_dec(ctx->handle, ccm_iv, NULL, 0)
353
        < 0) {
354
      free(ccm_iv);
355
      gnutls_assert();
356
      ret = GNUTLS_E_DECRYPTION_FAILED;
357
      goto end;
358
    }
359
    free(ccm_iv);
360
  } else {
361
    if (kcapi_aead_stream_init_dec(ctx->handle, nonce, NULL, 0)
362
        < 0) {
363
      gnutls_assert();
364
      ret = GNUTLS_E_DECRYPTION_FAILED;
365
      goto end;
366
    }
367
  }
368
369
  /*
370
   * Set AAD: IOVECs do not support const, this buffer is guaranteed to be
371
   * read-only
372
   */
373
  iov[0].iov_base = (void *)auth;
374
  iov[0].iov_len = auth_size;
375
376
  /*
377
   * Set CT: IOVECs do not support const, this buffer is guaranteed to be
378
   * read-only
379
   */
380
  iov[1].iov_base = (void *)encr;
381
  iov[1].iov_len = encr_size;
382
383
  if (kcapi_aead_stream_update_last(ctx->handle, iov, 2) < 0) {
384
    gnutls_assert();
385
    ret = GNUTLS_E_DECRYPTION_FAILED;
386
    goto end;
387
  }
388
389
  iov[0].iov_base = authtmp;
390
  iov[0].iov_len = auth_size;
391
392
  /* Set PT buffer to be filled by kernel */
393
  uint32_t outbuflen = kcapi_aead_outbuflen_dec(ctx->handle,
394
                  encr_size - tag_size,
395
                  auth_size,
396
                  tag_size) - auth_size;
397
  iov[1].iov_base = (void *)plain;
398
  iov[1].iov_len = (plain_size > outbuflen) ? outbuflen : plain_size;
399
400
  if (kcapi_aead_stream_op(ctx->handle, iov, 2) < 0) {
401
    gnutls_assert();
402
    ret = GNUTLS_E_DECRYPTION_FAILED;
403
    goto end;
404
  }
405
406
 end:
407
  freea(authtmp);
408
  return ret;
409
}
410
411
static int afalg_aead_encrypt(void *_ctx, const void *nonce, size_t nonce_size,
412
            const void *auth, size_t auth_size,
413
            size_t tag_size,
414
            const void *plain, size_t plain_size,
415
            void *encr, size_t encr_size)
416
{
417
  int ret = 0;
418
  struct kcapi_aead_ctx *ctx = _ctx;
419
  struct iovec iov[3];
420
  uint32_t iovlen = 2;
421
  uint8_t *authtmp = malloca(auth_size);
422
  if (authtmp == NULL) {
423
    gnutls_assert();
424
    return GNUTLS_E_MEMORY_ERROR;
425
  }
426
427
  if (unlikely(encr_size - tag_size < plain_size)) {
428
    ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
429
    gnutls_assert();
430
    goto end;
431
  }
432
433
  if (nonce_size > kcapi_aead_ivsize(ctx->handle)) {
434
    ret = GNUTLS_E_INVALID_REQUEST;
435
    gnutls_assert();
436
    goto end;
437
  }
438
439
  /* Init taglen once. */
440
  if (!ctx->taglen_set) {
441
    ctx->taglen_set = 1;
442
443
    if (kcapi_aead_settaglen(ctx->handle, tag_size) < 0) {
444
      gnutls_assert();
445
      ret = GNUTLS_E_ENCRYPTION_FAILED;
446
      goto end;
447
    }
448
  }
449
450
  kcapi_aead_setassoclen(ctx->handle, auth_size);
451
452
  /* CCM nonce to IV conversion */
453
  if (ctx->ccm) {
454
    uint8_t *ccm_iv = NULL;
455
    uint32_t ccm_iv_len;
456
457
    if (kcapi_aead_ccm_nonce_to_iv(nonce, nonce_size, &ccm_iv,
458
                 &ccm_iv_len)) {
459
      gnutls_assert();
460
      ret = GNUTLS_E_ENCRYPTION_FAILED;
461
      goto end;
462
    }
463
    if (kcapi_aead_stream_init_enc(ctx->handle, ccm_iv, NULL, 0)
464
        < 0) {
465
      free(ccm_iv);
466
      gnutls_assert();
467
      ret = GNUTLS_E_ENCRYPTION_FAILED;
468
      goto end;
469
    }
470
    free(ccm_iv);
471
  } else {
472
    if (kcapi_aead_stream_init_enc(ctx->handle, nonce, NULL, 0)
473
        < 0) {
474
      gnutls_assert();
475
      ret = GNUTLS_E_ENCRYPTION_FAILED;
476
      goto end;
477
    }
478
  }
479
480
  /*
481
   * Set AAD: IOVECs do not support const, this buffer is guaranteed to be
482
   * read-only
483
   */
484
  iov[0].iov_base = (void *)auth;
485
  iov[0].iov_len = auth_size;
486
487
  /*
488
   * Set PT: IOVECs do not support const, this buffer is guaranteed to be
489
   * read-only
490
   */
491
  iov[1].iov_base = (void *)plain;
492
  iov[1].iov_len = plain_size;
493
494
  /*
495
   * Older kernels require tag as input. This buffer data is unused
496
   * which implies the encr buffer can serve as tmp space.
497
   */
498
  uint32_t inbuflen = kcapi_aead_inbuflen_enc(ctx->handle, plain_size,
499
                auth_size, tag_size);
500
  if ((auth_size + plain_size) < inbuflen) {
501
    iov[2].iov_base = encr;
502
    iov[2].iov_len = tag_size;
503
    iovlen = 3;
504
  }
505
506
  if (kcapi_aead_stream_update_last(ctx->handle, iov, iovlen) < 0) {
507
    gnutls_assert();
508
    ret = GNUTLS_E_ENCRYPTION_FAILED;
509
    goto end;
510
  }
511
512
  iov[0].iov_base = authtmp;
513
  iov[0].iov_len = auth_size;
514
515
  /* Set CT buffer to be filled by kernel */
516
  uint32_t outbuflen = kcapi_aead_outbuflen_enc(ctx->handle,
517
                  plain_size, auth_size,
518
                  tag_size) - auth_size;
519
520
  iov[1].iov_base = encr;
521
  iov[1].iov_len = (encr_size > outbuflen) ? outbuflen : encr_size;
522
523
  if (kcapi_aead_stream_op(ctx->handle, iov, 2) < 0) {
524
    gnutls_assert();
525
    ret = GNUTLS_E_ENCRYPTION_FAILED;
526
    goto end;
527
  }
528
529
 end:
530
  freea(authtmp);
531
  return ret;
532
}
533
534
static const gnutls_crypto_cipher_st afalg_aead_struct = {
535
  .init = afalg_aead_init,
536
  .setkey = afalg_aead_setkey,
537
  .aead_encrypt = afalg_aead_encrypt,
538
  .aead_decrypt = afalg_aead_decrypt,
539
  .deinit = afalg_aead_deinit,
540
};
541
542
static int afalg_aead_register(void)
543
{
544
  unsigned int i;
545
  int ret = 0;
546
547
  for (i = 0;
548
       i < sizeof(gnutls_aead_map) / sizeof(gnutls_aead_map[0]); i++) {
549
    struct kcapi_handle *handle;
550
551
    if (gnutls_aead_map[i] == 0)
552
      continue;
553
554
    /* Check whether cipher is available. */
555
    if (kcapi_aead_init(&handle, gnutls_aead_map[i], 0))
556
      continue;
557
558
    kcapi_aead_destroy(handle);
559
560
    _gnutls_debug_log("afalg: registering: %s\n",
561
          gnutls_cipher_get_name(i));
562
    ret = gnutls_crypto_single_cipher_register(i, 90,
563
                 &afalg_aead_struct,
564
                 0);
565
    if (ret < 0) {
566
      gnutls_assert();
567
      return ret;
568
    }
569
  }
570
571
  return ret;
572
}
573
574
/********************** Keyed message digest algorithms **********************/
575
576
static const char *gnutls_mac_map[] = {
577
  [GNUTLS_MAC_SHA1] = "hmac(sha1)",
578
  [GNUTLS_MAC_SHA256] = "hmac(sha256)",
579
  [GNUTLS_MAC_SHA384] = "hmac(sha384)",
580
  [GNUTLS_MAC_SHA512] = "hmac(sha512)",
581
};
582
583
static int afalg_mac_init(gnutls_mac_algorithm_t algorithm, void **ctx)
584
{
585
  struct kcapi_handle *handle;
586
587
  if (kcapi_md_init(&handle, gnutls_mac_map[algorithm], 0) < 0) {
588
    gnutls_assert();
589
    return GNUTLS_E_MEMORY_ERROR;
590
  }
591
592
  *ctx = handle;
593
594
  return 0;
595
}
596
597
static int afalg_mac_setkey(void *ctx, const void *key, size_t keysize)
598
{
599
  struct kcapi_handle *handle = ctx;
600
601
  if (kcapi_md_setkey(handle, key, keysize) < 0) {
602
    gnutls_assert();
603
    return GNUTLS_E_ENCRYPTION_FAILED;
604
  }
605
606
  return 0;
607
}
608
609
static int afalg_mac_hash(void *ctx, const void *_text, size_t textsize)
610
{
611
  struct kcapi_handle *handle = ctx;
612
  const uint8_t *text = _text;
613
  size_t offset;
614
615
  for (offset = 0; offset < textsize - textsize % INT_MAX;
616
       offset += INT_MAX) {
617
    if (kcapi_md_update(handle, text + offset, INT_MAX) < 0) {
618
      return gnutls_assert_val(GNUTLS_E_ENCRYPTION_FAILED);
619
    }
620
  }
621
622
  if (offset < textsize) {
623
    if (kcapi_md_update(handle, text + offset, textsize - offset) <
624
        0) {
625
      return gnutls_assert_val(GNUTLS_E_ENCRYPTION_FAILED);
626
    }
627
  }
628
629
  return 0;
630
}
631
632
static int afalg_mac_output(void *ctx, void *digest, size_t digestsize)
633
{
634
  struct kcapi_handle *handle = ctx;
635
636
  if (kcapi_md_final(handle, digest, digestsize) < 0) {
637
    gnutls_assert();
638
    return GNUTLS_E_ENCRYPTION_FAILED;
639
  }
640
641
  return 0;
642
643
}
644
645
static void afalg_mac_deinit(void *ctx)
646
{
647
  struct kcapi_handle *handle = ctx;
648
649
  kcapi_md_destroy(handle);
650
}
651
652
static int afalg_mac_fast(gnutls_mac_algorithm_t algorithm, const void *nonce,
653
        size_t nonce_size, const void *key, size_t keysize,
654
        const void *text, size_t textsize, void *digest)
655
{
656
  struct kcapi_handle *handle;
657
  int ret = GNUTLS_E_ENCRYPTION_FAILED;
658
659
  if (kcapi_md_init(&handle, gnutls_mac_map[algorithm], 0) < 0) {
660
    gnutls_assert();
661
    return GNUTLS_E_MEMORY_ERROR;
662
  }
663
664
  if (kcapi_md_setkey(handle, key, keysize) < 0) {
665
    gnutls_assert();
666
    goto out;
667
  }
668
669
  if (textsize <= INT_MAX) {
670
    if (kcapi_md_digest(handle, text, textsize, digest,
671
            kcapi_md_digestsize(handle)) < 0) {
672
      gnutls_assert();
673
      goto out;
674
    }
675
  } else {
676
    ret = afalg_mac_hash(handle, text, textsize);
677
    if (ret < 0) {
678
      goto out;
679
    }
680
    if (kcapi_md_final(handle, digest,
681
           kcapi_md_digestsize(handle)) < 0) {
682
      gnutls_assert();
683
      return GNUTLS_E_ENCRYPTION_FAILED;
684
    }
685
  }
686
687
  ret = 0;
688
689
 out:
690
  kcapi_md_destroy(handle);
691
692
  return ret;
693
}
694
695
static const gnutls_crypto_mac_st afalg_mac_struct = {
696
  .init = afalg_mac_init,
697
  .setkey = afalg_mac_setkey,
698
  .setnonce = NULL,
699
  .hash = afalg_mac_hash,
700
  .output = afalg_mac_output,
701
  .deinit = afalg_mac_deinit,
702
  .fast = afalg_mac_fast,
703
};
704
705
static int afalg_mac_register(void)
706
{
707
  unsigned int i;
708
  int ret = 0;
709
710
  for (i = 0; i < sizeof(gnutls_mac_map) / sizeof(gnutls_mac_map[0]); i++) {
711
    struct kcapi_handle *handle;
712
713
    if (gnutls_mac_map[i] == 0)
714
      continue;
715
716
    /* Check whether cipher is available. */
717
    if (kcapi_md_init(&handle, gnutls_mac_map[i], 0))
718
      continue;
719
720
    kcapi_md_destroy(handle);
721
722
    _gnutls_debug_log("afalg: registering: %s\n",
723
          gnutls_mac_get_name(i));
724
    ret = gnutls_crypto_single_mac_register(i, 90,
725
              &afalg_mac_struct, 0);
726
    if (ret < 0) {
727
      gnutls_assert();
728
      return ret;
729
    }
730
  }
731
732
  return ret;
733
}
734
735
/***************************** Digest algorithms *****************************/
736
737
static const char *gnutls_digest_map[] = {
738
  [GNUTLS_DIG_SHA1] = "sha1",
739
  [GNUTLS_DIG_SHA256] = "sha256",
740
  [GNUTLS_DIG_SHA384] = "sha384",
741
  [GNUTLS_DIG_SHA512] = "sha512",
742
};
743
744
static int afalg_digest_init(gnutls_digest_algorithm_t algorithm, void **ctx)
745
{
746
  struct kcapi_handle *handle;
747
748
  if (kcapi_md_init(&handle, gnutls_digest_map[algorithm], 0) < 0) {
749
    gnutls_assert();
750
    return GNUTLS_E_MEMORY_ERROR;
751
  }
752
753
  *ctx = handle;
754
755
  return 0;
756
}
757
758
static int afalg_digest_fast(gnutls_digest_algorithm_t algorithm,
759
           const void *text, size_t textsize, void *digest)
760
{
761
  struct kcapi_handle *handle;
762
  int ret = GNUTLS_E_ENCRYPTION_FAILED;
763
764
  if (kcapi_md_init(&handle, gnutls_digest_map[algorithm], 0) < 0) {
765
    gnutls_assert();
766
    return GNUTLS_E_MEMORY_ERROR;
767
  }
768
769
  if (textsize <= INT_MAX) {
770
    if (kcapi_md_digest(handle, text, textsize, digest,
771
            kcapi_md_digestsize(handle)) < 0) {
772
      gnutls_assert();
773
      goto out;
774
    }
775
  } else {
776
    ret = afalg_mac_hash(handle, text, textsize);
777
    if (ret < 0) {
778
      goto out;
779
    }
780
781
    if (kcapi_md_final(handle, digest,
782
           kcapi_md_digestsize(handle)) < 0) {
783
      gnutls_assert();
784
      return GNUTLS_E_ENCRYPTION_FAILED;
785
    }
786
  }
787
788
  ret = 0;
789
790
 out:
791
  kcapi_md_destroy(handle);
792
793
  return ret;
794
}
795
796
static const gnutls_crypto_digest_st afalg_digest_struct = {
797
  .init = afalg_digest_init,
798
  .hash = afalg_mac_hash,
799
  .output = afalg_mac_output,
800
  .deinit = afalg_mac_deinit,
801
  .fast = afalg_digest_fast
802
};
803
804
static int afalg_digest_register(void)
805
{
806
  unsigned int i;
807
  int ret = 0;
808
809
  for (i = 0;
810
       i < sizeof(gnutls_digest_map) / sizeof(gnutls_digest_map[0]);
811
       i++) {
812
    struct kcapi_handle *handle;
813
814
    if (gnutls_digest_map[i] == 0)
815
      continue;
816
817
    /* Check whether cipher is available. */
818
    if (kcapi_md_init(&handle, gnutls_digest_map[i], 0))
819
      continue;
820
821
    kcapi_md_destroy(handle);
822
823
    _gnutls_debug_log("afalg: registering: %s\n",
824
          gnutls_digest_get_name(i));
825
    ret = gnutls_crypto_single_digest_register(i, 90,
826
                 &afalg_digest_struct,
827
                 0);
828
    if (ret < 0) {
829
      gnutls_assert();
830
      return ret;
831
    }
832
  }
833
834
  return ret;
835
}
836
837
int _gnutls_afalg_init(void)
838
{
839
  int ret;
840
841
  ret = afalg_cipher_register();
842
  if (ret)
843
    return ret;
844
845
  ret = afalg_aead_register();
846
  if (ret)
847
    return ret;
848
849
  ret = afalg_mac_register();
850
  if (ret)
851
    return ret;
852
853
  return afalg_digest_register();
854
}
855
856
void _gnutls_afalg_deinit(void)
857
{
858
  return;
859
}
860
861
#else       /* ENABLE_AFALG */
862
863
int _gnutls_afalg_init(void)
864
2
{
865
2
  return 0;
866
2
}
867
868
void _gnutls_afalg_deinit(void)
869
0
{
870
0
  return;
871
0
}
872
873
#endif        /* ENABLE_AFALG */