Coverage Report

Created: 2022-12-08 06:10

/src/libgcrypt/cipher/cipher-gcm-siv.c
Line
Count
Source (jump to first uncovered line)
1
/* cipher-gcm-siv.c  - GCM-SIV implementation (RFC 8452)
2
 * Copyright (C) 2021 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
#include <config.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <errno.h>
25
26
#include "g10lib.h"
27
#include "cipher.h"
28
#include "bufhelp.h"
29
#include "./cipher-internal.h"
30
31
32
0
#define GCM_SIV_NONCE_LENGTH (96 / 8)
33
34
35
static inline void
36
mulx_ghash (byte *a)
37
0
{
38
0
  u64 t[2], mask;
39
40
0
  t[0] = buf_get_be64(a + 0);
41
0
  t[1] = buf_get_be64(a + 8);
42
0
  mask = -(t[1] & 1) & 0xe1;
43
0
  mask <<= 56;
44
45
0
  buf_put_be64(a + 8, (t[1] >> 1) ^ (t[0] << 63));
46
0
  buf_put_be64(a + 0, (t[0] >> 1) ^ mask);
47
0
}
48
49
50
static inline void
51
gcm_siv_bytecounter_add (u32 ctr[2], size_t add)
52
0
{
53
0
  if (sizeof(add) > sizeof(u32))
54
0
    {
55
0
      u32 high_add = ((add >> 31) >> 1) & 0xffffffff;
56
0
      ctr[1] += high_add;
57
0
    }
58
59
0
  ctr[0] += add;
60
0
  if (ctr[0] >= add)
61
0
    return;
62
0
  ++ctr[1];
63
0
}
64
65
66
static inline int
67
gcm_siv_check_len (u32 ctr[2])
68
0
{
69
  /* len(plaintext/aadlen) <= 2^39-256 bits == 2^36-32 bytes == 2^32-2 blocks */
70
0
  if (ctr[1] > 0xfU)
71
0
    return 0;
72
0
  if (ctr[1] < 0xfU)
73
0
    return 1;
74
75
0
  if (ctr[0] <= 0xffffffe0U)
76
0
    return 1;
77
78
0
  return 0;
79
0
}
80
81
82
static void
83
polyval_set_key (gcry_cipher_hd_t c, const byte *auth_key)
84
0
{
85
0
  cipher_block_bswap (c->u_mode.gcm.u_ghash_key.key, auth_key,
86
0
          GCRY_SIV_BLOCK_LEN);
87
0
  mulx_ghash (c->u_mode.gcm.u_ghash_key.key);
88
0
  _gcry_cipher_gcm_setupM (c);
89
0
}
90
91
92
static void
93
do_polyval_buf(gcry_cipher_hd_t c, byte *hash, const byte *buf,
94
         size_t buflen, int do_padding)
95
0
{
96
0
  unsigned int blocksize = GCRY_SIV_BLOCK_LEN;
97
0
  unsigned int unused = c->u_mode.gcm.mac_unused;
98
0
  ghash_fn_t ghash_fn = c->u_mode.gcm.ghash_fn;
99
0
  ghash_fn_t polyval_fn = c->u_mode.gcm.polyval_fn;
100
0
  byte tmp_blocks[16][GCRY_SIV_BLOCK_LEN];
101
0
  size_t nblocks, n;
102
0
  unsigned int burn = 0, nburn;
103
0
  unsigned int num_blks_used = 0;
104
105
0
  if (buflen == 0 && (unused == 0 || !do_padding))
106
0
    return;
107
108
0
  do
109
0
    {
110
0
      if (buflen > 0 && (buflen + unused < blocksize || unused > 0))
111
0
        {
112
0
          n = blocksize - unused;
113
0
          n = n < buflen ? n : buflen;
114
115
0
          buf_cpy (&c->u_mode.gcm.macbuf[unused], buf, n);
116
117
0
          unused += n;
118
0
          buf += n;
119
0
          buflen -= n;
120
0
        }
121
0
      if (!buflen)
122
0
        {
123
0
          if (!do_padding && unused < blocksize)
124
0
      {
125
0
        break;
126
0
      }
127
128
0
    n = blocksize - unused;
129
0
    if (n > 0)
130
0
      {
131
0
        memset (&c->u_mode.gcm.macbuf[unused], 0, n);
132
0
        unused = blocksize;
133
0
      }
134
0
        }
135
136
0
      if (unused > 0)
137
0
        {
138
0
          gcry_assert (unused == blocksize);
139
140
          /* Process one block from macbuf.  */
141
0
          if (polyval_fn)
142
0
            {
143
0
              nburn = polyval_fn (c, hash, c->u_mode.gcm.macbuf, 1);
144
0
            }
145
0
          else
146
0
            {
147
0
              cipher_block_bswap (c->u_mode.gcm.macbuf, c->u_mode.gcm.macbuf,
148
0
                                  blocksize);
149
0
              nburn = ghash_fn (c, hash, c->u_mode.gcm.macbuf, 1);
150
0
            }
151
152
0
          burn = nburn > burn ? nburn : burn;
153
0
          unused = 0;
154
0
        }
155
156
0
      nblocks = buflen / blocksize;
157
158
0
      while (nblocks)
159
0
        {
160
0
          if (polyval_fn)
161
0
            {
162
0
              n = nblocks;
163
0
              nburn = polyval_fn (c, hash, buf, n);
164
0
            }
165
0
          else
166
0
            {
167
0
              for (n = 0; n < (nblocks > 16 ? 16 : nblocks); n++)
168
0
                cipher_block_bswap (tmp_blocks[n], buf + n * blocksize,
169
0
                                    blocksize);
170
171
0
              num_blks_used = n > num_blks_used ? n : num_blks_used;
172
173
0
              nburn = ghash_fn (c, hash, tmp_blocks[0], n);
174
0
            }
175
176
0
          burn = nburn > burn ? nburn : burn;
177
0
          buf += n * blocksize;
178
0
          buflen -= n * blocksize;
179
0
          nblocks -= n;
180
0
        }
181
0
    }
182
0
  while (buflen > 0);
183
184
0
  c->u_mode.gcm.mac_unused = unused;
185
186
0
  if (num_blks_used)
187
0
    wipememory (tmp_blocks, num_blks_used * blocksize);
188
0
  if (burn)
189
0
    _gcry_burn_stack (burn);
190
0
}
191
192
193
static void
194
do_ctr_le32 (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
195
       size_t inbuflen)
196
0
{
197
0
  gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
198
0
  unsigned char tmp[GCRY_SIV_BLOCK_LEN];
199
0
  unsigned int burn = 0, nburn;
200
0
  size_t nblocks;
201
202
0
  if (inbuflen == 0)
203
0
    return;
204
205
  /* Use a bulk method if available.  */
206
0
  nblocks = inbuflen / GCRY_SIV_BLOCK_LEN;
207
0
  if (nblocks && c->bulk.ctr32le_enc)
208
0
    {
209
0
      c->bulk.ctr32le_enc (c->context.c, c->u_ctr.ctr, outbuf, inbuf, nblocks);
210
0
      inbuf  += nblocks * GCRY_SIV_BLOCK_LEN;
211
0
      outbuf += nblocks * GCRY_SIV_BLOCK_LEN;
212
0
      inbuflen -= nblocks * GCRY_SIV_BLOCK_LEN;
213
0
    }
214
215
0
  do
216
0
    {
217
0
      nburn = enc_fn (c->context.c, tmp, c->u_ctr.ctr);
218
0
      burn = nburn > burn ? nburn : burn;
219
220
0
      buf_put_le32(c->u_ctr.ctr, buf_get_le32(c->u_ctr.ctr) + 1);
221
222
0
      if (inbuflen < GCRY_SIV_BLOCK_LEN)
223
0
  break;
224
0
      cipher_block_xor(outbuf, inbuf, tmp, GCRY_SIV_BLOCK_LEN);
225
226
0
      inbuflen -= GCRY_SIV_BLOCK_LEN;
227
0
      outbuf += GCRY_SIV_BLOCK_LEN;
228
0
      inbuf += GCRY_SIV_BLOCK_LEN;
229
0
    }
230
0
  while (inbuflen);
231
232
0
  if (inbuflen)
233
0
    {
234
0
      buf_xor(outbuf, inbuf, tmp, inbuflen);
235
236
0
      outbuf += inbuflen;
237
0
      inbuf += inbuflen;
238
0
      inbuflen -= inbuflen;
239
0
    }
240
241
0
  wipememory (tmp, sizeof(tmp));
242
243
0
  if (burn > 0)
244
0
    _gcry_burn_stack (burn + 4 * sizeof(void *));
245
0
}
246
247
248
static int
249
gcm_siv_selftest (gcry_cipher_hd_t c)
250
0
{
251
0
  static const byte in1[GCRY_SIV_BLOCK_LEN] =
252
0
      "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
253
0
  static const byte out1[GCRY_SIV_BLOCK_LEN] =
254
0
      "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
255
0
  static const byte in2[GCRY_SIV_BLOCK_LEN] =
256
0
      "\x9c\x98\xc0\x4d\xf9\x38\x7d\xed\x82\x81\x75\xa9\x2b\xa6\x52\xd8";
257
0
  static const byte out2[GCRY_SIV_BLOCK_LEN] =
258
0
      "\x4e\x4c\x60\x26\xfc\x9c\x3e\xf6\xc1\x40\xba\xd4\x95\xd3\x29\x6c";
259
0
  static const byte polyval_key[GCRY_SIV_BLOCK_LEN] =
260
0
      "\x25\x62\x93\x47\x58\x92\x42\x76\x1d\x31\xf8\x26\xba\x4b\x75\x7b";
261
0
  static const byte ghash_key[GCRY_SIV_BLOCK_LEN] =
262
0
      "\xdc\xba\xa5\xdd\x13\x7c\x18\x8e\xbb\x21\x49\x2c\x23\xc9\xb1\x12";
263
0
  static const byte polyval_data[GCRY_SIV_BLOCK_LEN * 2] =
264
0
      "\x4f\x4f\x95\x66\x8c\x83\xdf\xb6\x40\x17\x62\xbb\x2d\x01\xa2\x62"
265
0
      "\xd1\xa2\x4d\xdd\x27\x21\xd0\x06\xbb\xe4\x5f\x20\xd3\xc9\xf3\x62";
266
0
  static const byte polyval_tag[GCRY_SIV_BLOCK_LEN] =
267
0
      "\xf7\xa3\xb4\x7b\x84\x61\x19\xfa\xe5\xb7\x86\x6c\xf5\xe5\xb7\x7e";
268
0
  byte tmp[GCRY_SIV_BLOCK_LEN];
269
270
  /* Test mulx_ghash */
271
0
  memcpy (tmp, in1, GCRY_SIV_BLOCK_LEN);
272
0
  mulx_ghash (tmp);
273
0
  if (memcmp (tmp, out1, GCRY_SIV_BLOCK_LEN) != 0)
274
0
    return -1;
275
276
0
  memcpy (tmp, in2, GCRY_SIV_BLOCK_LEN);
277
0
  mulx_ghash (tmp);
278
0
  if (memcmp (tmp, out2, GCRY_SIV_BLOCK_LEN) != 0)
279
0
    return -1;
280
281
  /* Test GHASH key generation */
282
0
  memcpy (tmp, polyval_key, GCRY_SIV_BLOCK_LEN);
283
0
  cipher_block_bswap (tmp, tmp, GCRY_SIV_BLOCK_LEN);
284
0
  mulx_ghash (tmp);
285
0
  if (memcmp (tmp, ghash_key, GCRY_SIV_BLOCK_LEN) != 0)
286
0
    return -1;
287
288
  /* Test POLYVAL */
289
0
  memset (&c->u_mode.gcm, 0, sizeof(c->u_mode.gcm));
290
0
  polyval_set_key (c, polyval_key);
291
0
  memset (&tmp, 0, sizeof(tmp));
292
0
  do_polyval_buf (c, tmp, polyval_data, GCRY_SIV_BLOCK_LEN * 2, 1);
293
0
  cipher_block_bswap (tmp, tmp, GCRY_SIV_BLOCK_LEN);
294
0
  if (memcmp (tmp, polyval_tag, GCRY_SIV_BLOCK_LEN) != 0)
295
0
    return -1;
296
297
0
  return 0;
298
0
}
299
300
301
gcry_err_code_t
302
_gcry_cipher_gcm_siv_setkey (gcry_cipher_hd_t c, unsigned int keylen)
303
0
{
304
0
  static int done;
305
306
0
  if (keylen != 16 && keylen != 32)
307
0
    return GPG_ERR_INV_KEYLEN;
308
309
0
  if (!done)
310
0
    {
311
0
      if (gcm_siv_selftest (c))
312
0
  return GPG_ERR_SELFTEST_FAILED;
313
314
0
      done = 1;
315
0
    }
316
317
0
  c->marks.iv = 0;
318
0
  c->marks.tag = 0;
319
0
  memset (&c->u_mode.gcm, 0, sizeof(c->u_mode.gcm));
320
0
  c->u_mode.gcm.siv_keylen = keylen;
321
0
  return 0;
322
0
}
323
324
325
gcry_err_code_t
326
_gcry_cipher_gcm_siv_set_nonce (gcry_cipher_hd_t c, const byte *iv,
327
        size_t ivlen)
328
0
{
329
0
  byte auth_key[GCRY_SIV_BLOCK_LEN];
330
0
  byte tmp_in[GCRY_SIV_BLOCK_LEN];
331
0
  byte tmp[GCRY_SIV_BLOCK_LEN];
332
0
  byte enc_key[32];
333
0
  gcry_err_code_t err;
334
335
0
  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
336
0
    return GPG_ERR_CIPHER_ALGO;
337
0
  if (ivlen != GCM_SIV_NONCE_LENGTH)
338
0
    return GPG_ERR_INV_ARG;
339
0
  if (c->u_mode.gcm.siv_keylen == 0)
340
0
    return GPG_ERR_INV_STATE;
341
0
  if (c->marks.iv)
342
0
    {
343
      /* If nonce is already set, use cipher_reset or setkey first to reset
344
       * cipher state. */
345
0
      return GPG_ERR_INV_STATE;
346
0
    }
347
348
0
  memset (c->u_mode.gcm.aadlen, 0, sizeof(c->u_mode.gcm.aadlen));
349
0
  memset (c->u_mode.gcm.datalen, 0, sizeof(c->u_mode.gcm.datalen));
350
0
  memset (c->u_mode.gcm.u_tag.tag, 0, sizeof(c->u_mode.gcm.u_tag.tag));
351
0
  c->u_mode.gcm.datalen_over_limits = 0;
352
0
  c->u_mode.gcm.ghash_data_finalized = 0;
353
0
  c->u_mode.gcm.ghash_aad_finalized = 0;
354
355
0
  memset (c->u_iv.iv, 0, GCRY_SIV_BLOCK_LEN);
356
0
  memcpy (c->u_iv.iv, iv, ivlen);
357
0
  memcpy (tmp_in + 4, iv, ivlen);
358
359
  /* Derive message authentication key */
360
0
  buf_put_le32(tmp_in, 0);
361
0
  c->spec->encrypt (&c->context.c, tmp, tmp_in);
362
0
  memcpy (auth_key + 0, tmp, 8);
363
364
0
  buf_put_le32(tmp_in, 1);
365
0
  c->spec->encrypt (&c->context.c, tmp, tmp_in);
366
0
  memcpy (auth_key + 8, tmp, 8);
367
368
0
  polyval_set_key (c, auth_key);
369
0
  wipememory (auth_key, sizeof(auth_key));
370
371
  /* Derive message encryption key */
372
0
  buf_put_le32(tmp_in, 2);
373
0
  c->spec->encrypt (&c->context.c, tmp, tmp_in);
374
0
  memcpy (enc_key + 0, tmp, 8);
375
376
0
  buf_put_le32(tmp_in, 3);
377
0
  c->spec->encrypt (&c->context.c, tmp, tmp_in);
378
0
  memcpy (enc_key + 8, tmp, 8);
379
380
0
  if (c->u_mode.gcm.siv_keylen >= 24)
381
0
    {
382
0
      buf_put_le32(tmp_in, 4);
383
0
      c->spec->encrypt (&c->context.c, tmp, tmp_in);
384
0
      memcpy (enc_key + 16, tmp, 8);
385
0
    }
386
387
0
  if (c->u_mode.gcm.siv_keylen >= 32)
388
0
    {
389
0
      buf_put_le32(tmp_in, 5);
390
0
      c->spec->encrypt (&c->context.c, tmp, tmp_in);
391
0
      memcpy (enc_key + 24, tmp, 8);
392
0
    }
393
394
0
  wipememory (tmp, sizeof(tmp));
395
0
  wipememory (tmp_in, sizeof(tmp_in));
396
397
0
  err = c->spec->setkey (&c->context.c, enc_key, c->u_mode.gcm.siv_keylen,
398
0
       &c->bulk);
399
0
  wipememory (enc_key, sizeof(enc_key));
400
0
  if (err)
401
0
    return err;
402
403
0
  c->marks.iv = 1;
404
0
  return 0;
405
0
}
406
407
408
gcry_err_code_t
409
_gcry_cipher_gcm_siv_authenticate (gcry_cipher_hd_t c,
410
           const byte *aadbuf, size_t aadbuflen)
411
0
{
412
0
  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
413
0
    return GPG_ERR_CIPHER_ALGO;
414
0
  if (c->u_mode.gcm.datalen_over_limits)
415
0
    return GPG_ERR_INV_LENGTH;
416
0
  if (c->marks.tag
417
0
      || !c->marks.iv
418
0
      || c->u_mode.gcm.ghash_aad_finalized
419
0
      || c->u_mode.gcm.ghash_data_finalized
420
0
      || !c->u_mode.gcm.ghash_fn)
421
0
    return GPG_ERR_INV_STATE;
422
423
0
  gcm_siv_bytecounter_add (c->u_mode.gcm.aadlen, aadbuflen);
424
0
  if (!gcm_siv_check_len (c->u_mode.gcm.aadlen))
425
0
    {
426
0
      c->u_mode.gcm.datalen_over_limits = 1;
427
0
      return GPG_ERR_INV_LENGTH;
428
0
    }
429
430
0
  do_polyval_buf (c, c->u_mode.gcm.u_tag.tag, aadbuf, aadbuflen, 0);
431
432
0
  return 0;
433
0
}
434
435
436
gcry_err_code_t
437
_gcry_cipher_gcm_siv_encrypt (gcry_cipher_hd_t c,
438
            byte *outbuf, size_t outbuflen,
439
            const byte *inbuf, size_t inbuflen)
440
0
{
441
0
  u32 bitlengths[2][2];
442
443
0
  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
444
0
    return GPG_ERR_CIPHER_ALGO;
445
0
  if (outbuflen < inbuflen)
446
0
    return GPG_ERR_BUFFER_TOO_SHORT;
447
0
  if (c->u_mode.gcm.datalen_over_limits)
448
0
    return GPG_ERR_INV_LENGTH;
449
0
  if (c->marks.tag
450
0
      || !c->marks.iv
451
0
      || c->u_mode.gcm.ghash_data_finalized
452
0
      || !c->u_mode.gcm.ghash_fn)
453
0
    return GPG_ERR_INV_STATE;
454
455
0
  if (!c->u_mode.gcm.ghash_aad_finalized)
456
0
    {
457
      /* Start of encryption marks end of AAD stream. */
458
0
      do_polyval_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
459
0
      c->u_mode.gcm.ghash_aad_finalized = 1;
460
0
    }
461
462
0
  gcm_siv_bytecounter_add (c->u_mode.gcm.datalen, inbuflen);
463
0
  if (!gcm_siv_check_len (c->u_mode.gcm.datalen))
464
0
    {
465
0
      c->u_mode.gcm.datalen_over_limits = 1;
466
0
      return GPG_ERR_INV_LENGTH;
467
0
    }
468
469
  /* Plaintext and padding to POLYVAL. */
470
0
  do_polyval_buf (c, c->u_mode.gcm.u_tag.tag, inbuf, inbuflen, 1);
471
0
  c->u_mode.gcm.ghash_data_finalized = 1;
472
473
  /* aad length */
474
0
  bitlengths[0][0] = le_bswap32(c->u_mode.gcm.aadlen[0] << 3);
475
0
  bitlengths[0][1] = le_bswap32((c->u_mode.gcm.aadlen[0] >> 29) |
476
0
                                (c->u_mode.gcm.aadlen[1] << 3));
477
  /* data length */
478
0
  bitlengths[1][0] = le_bswap32(c->u_mode.gcm.datalen[0] << 3);
479
0
  bitlengths[1][1] = le_bswap32((c->u_mode.gcm.datalen[0] >> 29) |
480
0
                                (c->u_mode.gcm.datalen[1] << 3));
481
482
  /* Length block to POLYVAL. */
483
0
  do_polyval_buf(c, c->u_mode.gcm.u_tag.tag, (byte *)bitlengths,
484
0
     GCRY_SIV_BLOCK_LEN, 1);
485
0
  wipememory (bitlengths, sizeof(bitlengths));
486
487
  /* Prepare tag and counter. */
488
0
  cipher_block_bswap (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.u_tag.tag,
489
0
          GCRY_SIV_BLOCK_LEN);
490
0
  cipher_block_xor (c->u_mode.gcm.tagiv, c->u_iv.iv, c->u_mode.gcm.u_tag.tag,
491
0
        GCRY_SIV_BLOCK_LEN);
492
0
  c->u_mode.gcm.tagiv[GCRY_SIV_BLOCK_LEN - 1] &= 0x7f;
493
0
  c->spec->encrypt (&c->context.c, c->u_mode.gcm.tagiv, c->u_mode.gcm.tagiv);
494
0
  c->marks.tag = 1;
495
0
  memcpy (c->u_ctr.ctr, c->u_mode.gcm.tagiv, GCRY_SIV_BLOCK_LEN);
496
0
  c->u_ctr.ctr[GCRY_SIV_BLOCK_LEN - 1] |= 0x80;
497
498
  /* Encrypt data */
499
0
  do_ctr_le32 (c, outbuf, inbuf, inbuflen);
500
0
  return 0;
501
0
}
502
503
504
gcry_err_code_t
505
_gcry_cipher_gcm_siv_set_decryption_tag (gcry_cipher_hd_t c,
506
           const byte *tag, size_t taglen)
507
0
{
508
0
  if (taglen != GCRY_SIV_BLOCK_LEN)
509
0
    return GPG_ERR_INV_ARG;
510
0
  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
511
0
    return GPG_ERR_CIPHER_ALGO;
512
0
  if (c->marks.tag)
513
0
    return GPG_ERR_INV_STATE;
514
515
0
  memcpy (c->u_mode.gcm.tagiv, tag, GCRY_SIV_BLOCK_LEN);
516
0
  c->marks.tag = 1;
517
518
0
  return 0;
519
0
}
520
521
522
gcry_err_code_t
523
_gcry_cipher_gcm_siv_decrypt (gcry_cipher_hd_t c,
524
            byte *outbuf, size_t outbuflen,
525
            const byte *inbuf, size_t inbuflen)
526
0
{
527
0
  byte expected_tag[GCRY_SIV_BLOCK_LEN];
528
0
  u32 bitlengths[2][2];
529
0
  gcry_err_code_t rc = 0;
530
531
0
  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
532
0
    return GPG_ERR_CIPHER_ALGO;
533
0
  if (outbuflen < inbuflen)
534
0
    return GPG_ERR_BUFFER_TOO_SHORT;
535
0
  if (c->u_mode.gcm.datalen_over_limits)
536
0
    return GPG_ERR_INV_LENGTH;
537
0
  if (!c->marks.tag
538
0
      || !c->marks.iv
539
0
      || c->u_mode.gcm.ghash_data_finalized
540
0
      || !c->u_mode.gcm.ghash_fn)
541
0
    return GPG_ERR_INV_STATE;
542
543
0
  if (!c->u_mode.gcm.ghash_aad_finalized)
544
0
    {
545
      /* Start of encryption marks end of AAD stream. */
546
0
      do_polyval_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
547
0
      c->u_mode.gcm.ghash_aad_finalized = 1;
548
0
    }
549
550
0
  gcm_siv_bytecounter_add (c->u_mode.gcm.datalen, inbuflen);
551
0
  if (!gcm_siv_check_len (c->u_mode.gcm.datalen))
552
0
    {
553
0
      c->u_mode.gcm.datalen_over_limits = 1;
554
0
      return GPG_ERR_INV_LENGTH;
555
0
    }
556
557
  /* Prepare counter. */
558
0
  memcpy (c->u_ctr.ctr, c->u_mode.gcm.tagiv, GCRY_SIV_BLOCK_LEN);
559
0
  c->u_ctr.ctr[GCRY_SIV_BLOCK_LEN - 1] |= 0x80;
560
561
  /* Decrypt data. */
562
0
  do_ctr_le32 (c, outbuf, inbuf, inbuflen);
563
564
  /* Plaintext and padding to POLYVAL. */
565
0
  do_polyval_buf (c, c->u_mode.gcm.u_tag.tag, outbuf, inbuflen, 1);
566
0
  c->u_mode.gcm.ghash_data_finalized = 1;
567
568
  /* aad length */
569
0
  bitlengths[0][0] = le_bswap32(c->u_mode.gcm.aadlen[0] << 3);
570
0
  bitlengths[0][1] = le_bswap32((c->u_mode.gcm.aadlen[0] >> 29) |
571
0
                                (c->u_mode.gcm.aadlen[1] << 3));
572
  /* data length */
573
0
  bitlengths[1][0] = le_bswap32(c->u_mode.gcm.datalen[0] << 3);
574
0
  bitlengths[1][1] = le_bswap32((c->u_mode.gcm.datalen[0] >> 29) |
575
0
                                (c->u_mode.gcm.datalen[1] << 3));
576
577
  /* Length block to POLYVAL. */
578
0
  do_polyval_buf(c, c->u_mode.gcm.u_tag.tag, (byte *)bitlengths,
579
0
     GCRY_SIV_BLOCK_LEN, 1);
580
0
  wipememory (bitlengths, sizeof(bitlengths));
581
582
  /* Prepare tag. */
583
0
  cipher_block_bswap (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.u_tag.tag,
584
0
          GCRY_SIV_BLOCK_LEN);
585
0
  cipher_block_xor (expected_tag, c->u_iv.iv, c->u_mode.gcm.u_tag.tag,
586
0
        GCRY_SIV_BLOCK_LEN);
587
0
  expected_tag[GCRY_SIV_BLOCK_LEN - 1] &= 0x7f;
588
0
  c->spec->encrypt (&c->context.c, expected_tag, expected_tag);
589
590
0
  if (!buf_eq_const(c->u_mode.gcm.tagiv, expected_tag, GCRY_SIV_BLOCK_LEN))
591
0
    {
592
0
      wipememory (outbuf, inbuflen);
593
0
      rc = GPG_ERR_CHECKSUM;
594
0
    }
595
596
0
  wipememory (expected_tag, sizeof(expected_tag));
597
0
  return rc;
598
0
}
599
600
601
static gcry_err_code_t
602
_gcry_cipher_gcm_siv_tag (gcry_cipher_hd_t c,
603
        byte * outbuf, size_t outbuflen, int check)
604
0
{
605
0
  gcry_err_code_t err;
606
607
0
  if (!c->marks.tag)
608
0
    {
609
0
      if (!c->u_mode.gcm.ghash_fn)
610
0
        return GPG_ERR_INV_STATE;
611
612
0
      if (!c->marks.tag)
613
0
        {
614
          /* Finalize GCM-SIV with zero-length plaintext. */
615
0
          err = _gcry_cipher_gcm_siv_encrypt (c, NULL, 0, NULL, 0);
616
0
          if (err != 0)
617
0
            return err;
618
0
        }
619
0
    }
620
621
0
  if (c->u_mode.gcm.datalen_over_limits)
622
0
    return GPG_ERR_INV_LENGTH;
623
0
  if (!c->u_mode.gcm.ghash_data_finalized)
624
0
    return GPG_ERR_INV_STATE;
625
0
  if (!c->marks.tag)
626
0
    return GPG_ERR_INV_STATE;
627
628
0
  if (!check)
629
0
    {
630
0
      if (outbuflen > GCRY_SIV_BLOCK_LEN)
631
0
        outbuflen = GCRY_SIV_BLOCK_LEN;
632
633
      /* NB: We already checked that OUTBUF is large enough to hold
634
       * the result or has valid truncated length.  */
635
0
      memcpy (outbuf, c->u_mode.gcm.tagiv, outbuflen);
636
0
    }
637
0
  else
638
0
    {
639
      /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
640
       * and thus we need to compare its length first.  */
641
0
      if (outbuflen != GCRY_SIV_BLOCK_LEN
642
0
          || !buf_eq_const (outbuf, c->u_mode.gcm.tagiv, outbuflen))
643
0
        return GPG_ERR_CHECKSUM;
644
0
    }
645
646
0
  return 0;
647
0
}
648
649
650
gcry_err_code_t
651
_gcry_cipher_gcm_siv_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
652
            size_t taglen)
653
0
{
654
0
  return _gcry_cipher_gcm_siv_tag (c, outtag, taglen, 0);
655
0
}
656
657
658
gcry_err_code_t
659
_gcry_cipher_gcm_siv_check_tag (gcry_cipher_hd_t c,
660
           const unsigned char *intag,
661
           size_t taglen)
662
0
{
663
0
  return _gcry_cipher_gcm_siv_tag (c, (unsigned char *)intag, taglen, 1);
664
0
}