Coverage Report

Created: 2026-06-08 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/BearSSL/src/aead/gcm.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
#include "inner.h"
26
27
/*
28
 * Implementation Notes
29
 * ====================
30
 *
31
 * Since CTR and GHASH implementations can handle only full blocks, a
32
 * 16-byte buffer (buf[]) is maintained in the context:
33
 *
34
 *  - When processing AAD, buf[] contains the 0-15 unprocessed bytes.
35
 *
36
 *  - When doing CTR encryption / decryption, buf[] contains the AES output
37
 *    for the last partial block, to be used with the next few bytes of
38
 *    data, as well as the already encrypted bytes. For instance, if the
39
 *    processed data length so far is 21 bytes, then buf[0..4] contains
40
 *    the five last encrypted bytes, and buf[5..15] contains the next 11
41
 *    AES output bytes to be XORed with the next 11 bytes of input.
42
 *
43
 *    The recorded AES output bytes are used to complete the block when
44
 *    the corresponding bytes are obtained. Note that buf[] always
45
 *    contains the _encrypted_ bytes, whether we apply encryption or
46
 *    decryption: these bytes are used as input to GHASH when the block
47
 *    is complete.
48
 *
49
 * In both cases, the low bits of the data length counters (count_aad,
50
 * count_ctr) are used to work out the current situation.
51
 */
52
53
/* see bearssl_aead.h */
54
void
55
br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh)
56
1.53k
{
57
1.53k
  unsigned char iv[12];
58
59
1.53k
  ctx->vtable = &br_gcm_vtable;
60
1.53k
  ctx->bctx = bctx;
61
1.53k
  ctx->gh = gh;
62
63
  /*
64
   * The GHASH key h[] is the raw encryption of the all-zero
65
   * block. Since we only have a CTR implementation, we use it
66
   * with an all-zero IV and a zero counter, to CTR-encrypt an
67
   * all-zero block.
68
   */
69
1.53k
  memset(ctx->h, 0, sizeof ctx->h);
70
1.53k
  memset(iv, 0, sizeof iv);
71
1.53k
  (*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h);
72
1.53k
}
73
74
/* see bearssl_aead.h */
75
void
76
br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len)
77
1.53k
{
78
  /*
79
   * If the provided nonce is 12 bytes, then this is the initial
80
   * IV for CTR mode; it will be used with a counter that starts
81
   * at 2 (value 1 is for encrypting the GHASH output into the tag).
82
   *
83
   * If the provided nonce has any other length, then it is hashed
84
   * (with GHASH) into a 16-byte value that will be the IV for CTR
85
   * (both 12-byte IV and 32-bit counter).
86
   */
87
1.53k
  if (len == 12) {
88
101
    memcpy(ctx->j0_1, iv, 12);
89
101
    ctx->j0_2 = 1;
90
1.43k
  } else {
91
1.43k
    unsigned char ty[16], tmp[16];
92
93
1.43k
    memset(ty, 0, sizeof ty);
94
1.43k
    ctx->gh(ty, ctx->h, iv, len);
95
1.43k
    memset(tmp, 0, 8);
96
1.43k
    br_enc64be(tmp + 8, (uint64_t)len << 3);
97
1.43k
    ctx->gh(ty, ctx->h, tmp, 16);
98
1.43k
    memcpy(ctx->j0_1, ty, 12);
99
1.43k
    ctx->j0_2 = br_dec32be(ty + 12);
100
1.43k
  }
101
1.53k
  ctx->jc = ctx->j0_2 + 1;
102
1.53k
  memset(ctx->y, 0, sizeof ctx->y);
103
1.53k
  ctx->count_aad = 0;
104
1.53k
  ctx->count_ctr = 0;
105
1.53k
}
106
107
/* see bearssl_aead.h */
108
void
109
br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len)
110
2.12k
{
111
2.12k
  size_t ptr, dlen;
112
113
2.12k
  ptr = (size_t)ctx->count_aad & (size_t)15;
114
2.12k
  if (ptr != 0) {
115
    /*
116
     * If there is a partial block, then we first try to
117
     * complete it.
118
     */
119
798
    size_t clen;
120
121
798
    clen = 16 - ptr;
122
798
    if (len < clen) {
123
676
      memcpy(ctx->buf + ptr, data, len);
124
676
      ctx->count_aad += (uint64_t)len;
125
676
      return;
126
676
    }
127
122
    memcpy(ctx->buf + ptr, data, clen);
128
122
    ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
129
122
    data = (const unsigned char *)data + clen;
130
122
    len -= clen;
131
122
    ctx->count_aad += (uint64_t)clen;
132
122
  }
133
134
  /*
135
   * Now AAD is aligned on a 16-byte block (with regards to GHASH).
136
   * We process all complete blocks, and save the last partial
137
   * block.
138
   */
139
1.45k
  dlen = len & ~(size_t)15;
140
1.45k
  ctx->gh(ctx->y, ctx->h, data, dlen);
141
1.45k
  memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen);
142
1.45k
  ctx->count_aad += (uint64_t)len;
143
1.45k
}
144
145
/* see bearssl_aead.h */
146
void
147
br_gcm_flip(br_gcm_context *ctx)
148
1.53k
{
149
  /*
150
   * We complete the GHASH computation if there is a partial block.
151
   * The GHASH implementation automatically applies padding with
152
   * zeros.
153
   */
154
1.53k
  size_t ptr;
155
156
1.53k
  ptr = (size_t)ctx->count_aad & (size_t)15;
157
1.53k
  if (ptr != 0) {
158
281
    ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
159
281
  }
160
1.53k
}
161
162
/* see bearssl_aead.h */
163
void
164
br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len)
165
19.0k
{
166
19.0k
  unsigned char *buf;
167
19.0k
  size_t ptr, dlen;
168
169
19.0k
  buf = data;
170
19.0k
  ptr = (size_t)ctx->count_ctr & (size_t)15;
171
19.0k
  if (ptr != 0) {
172
    /*
173
     * If we have a partial block, then we try to complete it.
174
     */
175
12.5k
    size_t u, clen;
176
177
12.5k
    clen = 16 - ptr;
178
12.5k
    if (len < clen) {
179
11.9k
      clen = len;
180
11.9k
    }
181
17.5k
    for (u = 0; u < clen; u ++) {
182
4.97k
      unsigned x, y;
183
184
4.97k
      x = buf[u];
185
4.97k
      y = x ^ ctx->buf[ptr + u];
186
4.97k
      ctx->buf[ptr + u] = encrypt ? y : x;
187
4.97k
      buf[u] = y;
188
4.97k
    }
189
12.5k
    ctx->count_ctr += (uint64_t)clen;
190
12.5k
    buf += clen;
191
12.5k
    len -= clen;
192
12.5k
    if (ptr + clen < 16) {
193
11.9k
      return;
194
11.9k
    }
195
565
    ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
196
565
  }
197
198
  /*
199
   * Process full blocks.
200
   */
201
7.09k
  dlen = len & ~(size_t)15;
202
7.09k
  if (!encrypt) {
203
1.38k
    ctx->gh(ctx->y, ctx->h, buf, dlen);
204
1.38k
  }
205
7.09k
  ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, buf, dlen);
206
7.09k
  if (encrypt) {
207
5.70k
    ctx->gh(ctx->y, ctx->h, buf, dlen);
208
5.70k
  }
209
7.09k
  buf += dlen;
210
7.09k
  len -= dlen;
211
7.09k
  ctx->count_ctr += (uint64_t)dlen;
212
213
7.09k
  if (len > 0) {
214
    /*
215
     * There is a partial block.
216
     */
217
1.70k
    size_t u;
218
219
1.70k
    memset(ctx->buf, 0, sizeof ctx->buf);
220
1.70k
    ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1,
221
1.70k
      ctx->jc, ctx->buf, 16);
222
9.06k
    for (u = 0; u < len; u ++) {
223
7.35k
      unsigned x, y;
224
225
7.35k
      x = buf[u];
226
7.35k
      y = x ^ ctx->buf[u];
227
7.35k
      ctx->buf[u] = encrypt ? y : x;
228
7.35k
      buf[u] = y;
229
7.35k
    }
230
1.70k
    ctx->count_ctr += (uint64_t)len;
231
1.70k
  }
232
7.09k
}
233
234
/* see bearssl_aead.h */
235
void
236
br_gcm_get_tag(br_gcm_context *ctx, void *tag)
237
588
{
238
588
  size_t ptr;
239
588
  unsigned char tmp[16];
240
241
588
  ptr = (size_t)ctx->count_ctr & (size_t)15;
242
588
  if (ptr > 0) {
243
    /*
244
     * There is a partial block: encrypted/decrypted data has
245
     * been produced, but the encrypted bytes must still be
246
     * processed by GHASH.
247
     */
248
435
    ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
249
435
  }
250
251
  /*
252
   * Final block for GHASH: the AAD and plaintext lengths (in bits).
253
   */
254
588
  br_enc64be(tmp, ctx->count_aad << 3);
255
588
  br_enc64be(tmp + 8, ctx->count_ctr << 3);
256
588
  ctx->gh(ctx->y, ctx->h, tmp, 16);
257
258
  /*
259
   * Tag is the GHASH output XORed with the encryption of the
260
   * nonce with the initial counter value.
261
   */
262
588
  memcpy(tag, ctx->y, 16);
263
588
  (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16);
264
588
}
265
266
/* see bearssl_aead.h */
267
void
268
br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len)
269
0
{
270
0
  unsigned char tmp[16];
271
272
0
  br_gcm_get_tag(ctx, tmp);
273
0
  memcpy(tag, tmp, len);
274
0
}
275
276
/* see bearssl_aead.h */
277
uint32_t
278
br_gcm_check_tag_trunc(br_gcm_context *ctx, const void *tag, size_t len)
279
303
{
280
303
  unsigned char tmp[16];
281
303
  size_t u;
282
303
  int x;
283
284
303
  br_gcm_get_tag(ctx, tmp);
285
303
  x = 0;
286
5.15k
  for (u = 0; u < len; u ++) {
287
4.84k
    x |= tmp[u] ^ ((const unsigned char *)tag)[u];
288
4.84k
  }
289
303
  return EQ0(x);
290
303
}
291
292
/* see bearssl_aead.h */
293
uint32_t
294
br_gcm_check_tag(br_gcm_context *ctx, const void *tag)
295
303
{
296
303
  return br_gcm_check_tag_trunc(ctx, tag, 16);
297
303
}
298
299
/* see bearssl_aead.h */
300
const br_aead_class br_gcm_vtable = {
301
  16,
302
  (void (*)(const br_aead_class **, const void *, size_t))
303
    &br_gcm_reset,
304
  (void (*)(const br_aead_class **, const void *, size_t))
305
    &br_gcm_aad_inject,
306
  (void (*)(const br_aead_class **))
307
    &br_gcm_flip,
308
  (void (*)(const br_aead_class **, int, void *, size_t))
309
    &br_gcm_run,
310
  (void (*)(const br_aead_class **, void *))
311
    &br_gcm_get_tag,
312
  (uint32_t (*)(const br_aead_class **, const void *))
313
    &br_gcm_check_tag,
314
  (void (*)(const br_aead_class **, void *, size_t))
315
    &br_gcm_get_tag_trunc,
316
  (uint32_t (*)(const br_aead_class **, const void *, size_t))
317
    &br_gcm_check_tag_trunc
318
};