Coverage Report

Created: 2024-02-25 06:16

/src/nettle-with-mini-gmp/siv-gcm.c
Line
Count
Source (jump to first uncovered line)
1
/* siv-gcm.c
2
3
   AES-GCM-SIV, RFC8452
4
5
   Copyright (C) 2022 Red Hat, Inc.
6
7
   This file is part of GNU Nettle.
8
9
   GNU Nettle is free software: you can redistribute it and/or
10
   modify it under the terms of either:
11
12
     * the GNU Lesser General Public License as published by the Free
13
       Software Foundation; either version 3 of the License, or (at your
14
       option) any later version.
15
16
   or
17
18
     * the GNU General Public License as published by the Free
19
       Software Foundation; either version 2 of the License, or (at your
20
       option) any later version.
21
22
   or both in parallel, as here.
23
24
   GNU Nettle is distributed in the hope that it will be useful,
25
   but WITHOUT ANY WARRANTY; without even the implied warranty of
26
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27
   General Public License for more details.
28
29
   You should have received copies of the GNU General Public License and
30
   the GNU Lesser General Public License along with this program.  If
31
   not, see http://www.gnu.org/licenses/.
32
*/
33
34
#if HAVE_CONFIG_H
35
# include "config.h"
36
#endif
37
38
#include "siv-gcm.h"
39
#include "ghash-internal.h"
40
#include "block-internal.h"
41
#include "nettle-internal.h"
42
#include "macros.h"
43
#include "memops.h"
44
#include "ctr-internal.h"
45
#include <string.h>
46
47
750
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
48
49
static void
50
siv_gcm_derive_keys (const void *ctx,
51
         nettle_cipher_func *f,
52
         size_t key_size,
53
         size_t nlength, const uint8_t *nonce,
54
         union nettle_block16 *auth_key,
55
         uint8_t *encryption_key)
56
750
{
57
750
  union nettle_block16 block;
58
750
  union nettle_block16 out;
59
750
  size_t i;
60
61
750
  block16_zero (&block);
62
750
  memcpy (block.b + 4, nonce, MIN(nlength, SIV_GCM_NONCE_SIZE));
63
64
750
  f (ctx, SIV_GCM_BLOCK_SIZE, out.b, block.b);
65
750
  auth_key->u64[0] = out.u64[0];
66
67
750
  block.b[0] = 1;
68
750
  f (ctx, SIV_GCM_BLOCK_SIZE, out.b, block.b);
69
750
  auth_key->u64[1] = out.u64[0];
70
71
750
  assert (key_size % 8 == 0 && key_size / 8 + 2 <= UINT8_MAX);
72
73
3.11k
  for (i = 0; i < key_size; i += 8)
74
2.36k
    {
75
2.36k
      block.b[0]++;
76
2.36k
      f (ctx, SIV_GCM_BLOCK_SIZE, out.b, block.b);
77
2.36k
      memcpy (encryption_key + i, out.b, 8);
78
2.36k
    }
79
750
}
80
81
static nettle_fill16_func siv_gcm_fill;
82
83
static void
84
siv_gcm_fill(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer)
85
1.02k
{
86
1.02k
  uint32_t c;
87
88
1.02k
  c = LE_READ_UINT32(ctr);
89
90
2.71k
  for (; blocks-- > 0; buffer++, c++)
91
1.69k
    {
92
1.69k
      memcpy(buffer->b + 4, ctr + 4, SIV_GCM_BLOCK_SIZE - 4);
93
1.69k
      LE_WRITE_UINT32(buffer->b, c);
94
1.69k
    }
95
96
1.02k
  LE_WRITE_UINT32(ctr, c);
97
1.02k
}
98
99
static void
100
siv_ghash_pad_update (struct gcm_key *ctx,
101
          union nettle_block16 *state,
102
          size_t length, const uint8_t *data)
103
1.50k
{
104
1.50k
  size_t blocks;
105
106
1.50k
  blocks = length / SIV_GCM_BLOCK_SIZE;
107
1.50k
  if (blocks > 0)
108
897
    {
109
897
      data = _siv_ghash_update (ctx, state, blocks, data);
110
897
      length &= 0xf;
111
897
    }
112
1.50k
  if (length > 0)
113
431
    {
114
431
      uint8_t block[SIV_GCM_BLOCK_SIZE];
115
116
431
      memset (block + length, 0, SIV_GCM_BLOCK_SIZE - length);
117
431
      memcpy (block, data, length);
118
431
      _siv_ghash_update (ctx, state, 1, block);
119
431
    }
120
1.50k
}
121
122
static void
123
siv_gcm_authenticate (const void *ctx,
124
          const struct nettle_cipher *nc,
125
          const union nettle_block16 *authentication_key,
126
          const uint8_t *nonce,
127
          size_t alength, const uint8_t *adata,
128
          size_t mlength, const uint8_t *mdata,
129
          uint8_t *tag)
130
750
{
131
750
  union nettle_block16 state;
132
750
  struct gcm_key siv_ghash_key;
133
750
  union nettle_block16 block;
134
135
750
  _siv_ghash_set_key (&siv_ghash_key, authentication_key);
136
137
750
  block16_zero (&state);
138
750
  siv_ghash_pad_update (&siv_ghash_key, &state, alength, adata);
139
750
  siv_ghash_pad_update (&siv_ghash_key, &state, mlength, mdata);
140
141
750
  block.u64[0] = bswap64_if_be (alength * 8);
142
750
  block.u64[1] = bswap64_if_be (mlength * 8);
143
144
750
  _siv_ghash_update (&siv_ghash_key, &state, 1, block.b);
145
750
  block16_bswap (&state, &state);
146
147
750
  memxor (state.b, nonce, SIV_GCM_NONCE_SIZE);
148
750
  state.b[15] &= 0x7f;
149
750
  nc->encrypt (ctx, SIV_GCM_BLOCK_SIZE, tag, state.b);
150
750
}
151
152
void
153
siv_gcm_encrypt_message (const struct nettle_cipher *nc,
154
       const void *ctx,
155
       void *ctr_ctx,
156
       size_t nlength, const uint8_t *nonce,
157
       size_t alength, const uint8_t *adata,
158
       size_t clength, uint8_t *dst, const uint8_t *src)
159
321
{
160
321
  union nettle_block16 authentication_key;
161
321
  TMP_DECL(encryption_key, uint8_t, NETTLE_MAX_CIPHER_KEY_SIZE);
162
321
  uint8_t ctr[SIV_GCM_DIGEST_SIZE];
163
321
  uint8_t *tag = dst + clength - SIV_GCM_BLOCK_SIZE;
164
165
321
  assert (clength >= SIV_GCM_DIGEST_SIZE);
166
321
  assert (nlength == SIV_GCM_NONCE_SIZE);
167
168
321
  TMP_ALLOC(encryption_key, nc->key_size);
169
321
  siv_gcm_derive_keys (ctx, nc->encrypt, nc->key_size, nlength, nonce,
170
321
           &authentication_key, encryption_key);
171
172
  /* Calculate authentication tag.  */
173
321
  nc->set_encrypt_key (ctr_ctx, encryption_key);
174
175
321
  siv_gcm_authenticate (ctr_ctx, nc,
176
321
      &authentication_key,
177
321
      nonce, alength, adata,
178
321
      clength - SIV_GCM_BLOCK_SIZE, src,
179
321
      tag);
180
181
  /* Encrypt the plaintext.  */
182
183
  /* The initial counter block is the tag with the most significant
184
     bit of the last byte set to one.  */
185
321
  memcpy (ctr, tag, SIV_GCM_DIGEST_SIZE);
186
321
  ctr[15] |= 0x80;
187
321
  _nettle_ctr_crypt16 (ctr_ctx, nc->encrypt, siv_gcm_fill, ctr,
188
321
           clength - SIV_GCM_BLOCK_SIZE, dst, src);
189
321
}
190
191
int
192
siv_gcm_decrypt_message (const struct nettle_cipher *nc,
193
       const void *ctx,
194
       void *ctr_ctx,
195
       size_t nlength, const uint8_t *nonce,
196
       size_t alength, const uint8_t *adata,
197
       size_t mlength, uint8_t *dst, const uint8_t *src)
198
429
{
199
429
  union nettle_block16 authentication_key;
200
429
  TMP_DECL(encryption_key, uint8_t, NETTLE_MAX_CIPHER_KEY_SIZE);
201
429
  union nettle_block16 state;
202
429
  uint8_t tag[SIV_GCM_DIGEST_SIZE];
203
204
429
  assert (nlength == SIV_GCM_NONCE_SIZE);
205
206
429
  TMP_ALLOC(encryption_key, nc->key_size);
207
429
  siv_gcm_derive_keys (ctx, nc->encrypt, nc->key_size, nlength, nonce,
208
429
           &authentication_key, encryption_key);
209
210
429
  memcpy (state.b, src + mlength, SIV_GCM_DIGEST_SIZE);
211
  /* The initial counter block is the tag with the most significant
212
     bit of the last byte set to one.  */
213
429
  state.b[15] |= 0x80;
214
215
  /* Decrypt the ciphertext.  */
216
429
  nc->set_encrypt_key (ctr_ctx, encryption_key);
217
218
429
  _nettle_ctr_crypt16 (ctr_ctx, nc->encrypt, siv_gcm_fill, state.b,
219
429
           mlength, dst, src);
220
221
  /* Calculate authentication tag.  */
222
429
  siv_gcm_authenticate (ctr_ctx, nc,
223
429
      &authentication_key,
224
429
      nonce, alength, adata,
225
429
      mlength, dst,
226
429
      tag);
227
228
429
  return memeql_sec (tag, src + mlength, SIV_GCM_DIGEST_SIZE);
229
429
}