Coverage Report

Created: 2024-11-21 07:03

/src/boringssl/crypto/fipsmodule/cipher/aead.c.inc
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2014, Google Inc.
2
 *
3
 * Permission to use, copy, modify, and/or distribute this software for any
4
 * purpose with or without fee is hereby granted, provided that the above
5
 * copyright notice and this permission notice appear in all copies.
6
 *
7
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15
#include <openssl/aead.h>
16
17
#include <assert.h>
18
#include <string.h>
19
20
#include <openssl/cipher.h>
21
#include <openssl/err.h>
22
#include <openssl/mem.h>
23
24
#include "internal.h"
25
#include "../../internal.h"
26
27
28
102
size_t EVP_AEAD_key_length(const EVP_AEAD *aead) { return aead->key_len; }
29
30
184
size_t EVP_AEAD_nonce_length(const EVP_AEAD *aead) { return aead->nonce_len; }
31
32
102
size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead) { return aead->overhead; }
33
34
102
size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead) { return aead->max_tag_len; }
35
36
1.09k
void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx) {
37
1.09k
  OPENSSL_memset(ctx, 0, sizeof(EVP_AEAD_CTX));
38
1.09k
}
39
40
EVP_AEAD_CTX *EVP_AEAD_CTX_new(const EVP_AEAD *aead, const uint8_t *key,
41
1.09k
                               size_t key_len, size_t tag_len) {
42
1.09k
  EVP_AEAD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_AEAD_CTX));
43
1.09k
  EVP_AEAD_CTX_zero(ctx);
44
45
1.09k
  if (EVP_AEAD_CTX_init(ctx, aead, key, key_len, tag_len, NULL)) {
46
929
    return ctx;
47
929
  }
48
49
164
  EVP_AEAD_CTX_free(ctx);
50
164
  return NULL;
51
1.09k
}
52
53
1.25k
void EVP_AEAD_CTX_free(EVP_AEAD_CTX *ctx) {
54
1.25k
  if (ctx == NULL) {
55
164
    return;
56
164
  }
57
1.09k
  EVP_AEAD_CTX_cleanup(ctx);
58
1.09k
  OPENSSL_free(ctx);
59
1.09k
}
60
61
int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
62
                      const uint8_t *key, size_t key_len, size_t tag_len,
63
1.09k
                      ENGINE *impl) {
64
1.09k
  if (!aead->init) {
65
16
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_DIRECTION_SET);
66
16
    ctx->aead = NULL;
67
16
    return 0;
68
16
  }
69
1.07k
  return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, tag_len,
70
1.07k
                                          evp_aead_open);
71
1.09k
}
72
73
int EVP_AEAD_CTX_init_with_direction(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
74
                                     const uint8_t *key, size_t key_len,
75
                                     size_t tag_len,
76
1.07k
                                     enum evp_aead_direction_t dir) {
77
1.07k
  if (key_len != aead->key_len) {
78
41
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_KEY_SIZE);
79
41
    ctx->aead = NULL;
80
41
    return 0;
81
41
  }
82
83
1.03k
  ctx->aead = aead;
84
85
1.03k
  int ok;
86
1.03k
  if (aead->init) {
87
1.03k
    ok = aead->init(ctx, key, key_len, tag_len);
88
1.03k
  } else {
89
0
    ok = aead->init_with_direction(ctx, key, key_len, tag_len, dir);
90
0
  }
91
92
1.03k
  if (!ok) {
93
107
    ctx->aead = NULL;
94
107
  }
95
96
1.03k
  return ok;
97
1.07k
}
98
99
1.09k
void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) {
100
1.09k
  if (ctx->aead == NULL) {
101
164
    return;
102
164
  }
103
929
  ctx->aead->cleanup(ctx);
104
929
  ctx->aead = NULL;
105
929
}
106
107
// check_alias returns 1 if |out| is compatible with |in| and 0 otherwise. If
108
// |in| and |out| alias, we require that |in| == |out|.
109
static int check_alias(const uint8_t *in, size_t in_len, const uint8_t *out,
110
1.39k
                       size_t out_len) {
111
1.39k
  if (!buffers_alias(in, in_len, out, out_len)) {
112
1.39k
    return 1;
113
1.39k
  }
114
115
0
  return in == out;
116
1.39k
}
117
118
int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
119
                      size_t max_out_len, const uint8_t *nonce,
120
                      size_t nonce_len, const uint8_t *in, size_t in_len,
121
456
                      const uint8_t *ad, size_t ad_len) {
122
456
  if (in_len + ctx->aead->overhead < in_len /* overflow */) {
123
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
124
0
    goto error;
125
0
  }
126
127
456
  if (max_out_len < in_len) {
128
3
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
129
3
    goto error;
130
3
  }
131
132
453
  if (!check_alias(in, in_len, out, max_out_len)) {
133
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
134
0
    goto error;
135
0
  }
136
137
453
  size_t out_tag_len;
138
453
  if (ctx->aead->seal_scatter(ctx, out, out + in_len, &out_tag_len,
139
453
                              max_out_len - in_len, nonce, nonce_len, in,
140
453
                              in_len, NULL, 0, ad, ad_len)) {
141
371
    *out_len = in_len + out_tag_len;
142
371
    return 1;
143
371
  }
144
145
85
error:
146
  // In the event of an error, clear the output buffer so that a caller
147
  // that doesn't check the return value doesn't send raw data.
148
85
  OPENSSL_memset(out, 0, max_out_len);
149
85
  *out_len = 0;
150
85
  return 0;
151
453
}
152
153
int EVP_AEAD_CTX_seal_scatter(
154
    const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag, size_t
155
    *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce, size_t
156
    nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
157
0
    size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
158
  // |in| and |out| may alias exactly, |out_tag| may not alias.
159
0
  if (!check_alias(in, in_len, out, in_len) ||
160
0
      buffers_alias(out, in_len, out_tag, max_out_tag_len) ||
161
0
      buffers_alias(in, in_len, out_tag, max_out_tag_len)) {
162
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
163
0
    goto error;
164
0
  }
165
166
0
  if (!ctx->aead->seal_scatter_supports_extra_in && extra_in_len) {
167
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
168
0
    goto error;
169
0
  }
170
171
0
  if (ctx->aead->seal_scatter(ctx, out, out_tag, out_tag_len, max_out_tag_len,
172
0
                              nonce, nonce_len, in, in_len, extra_in,
173
0
                              extra_in_len, ad, ad_len)) {
174
0
    return 1;
175
0
  }
176
177
0
error:
178
  // In the event of an error, clear the output buffer so that a caller
179
  // that doesn't check the return value doesn't send raw data.
180
0
  OPENSSL_memset(out, 0, in_len);
181
0
  OPENSSL_memset(out_tag, 0, max_out_tag_len);
182
0
  *out_tag_len = 0;
183
0
  return 0;
184
0
}
185
186
int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
187
                      size_t max_out_len, const uint8_t *nonce,
188
                      size_t nonce_len, const uint8_t *in, size_t in_len,
189
473
                      const uint8_t *ad, size_t ad_len) {
190
473
  if (!check_alias(in, in_len, out, max_out_len)) {
191
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
192
0
    goto error;
193
0
  }
194
195
473
  if (ctx->aead->open) {
196
0
    if (!ctx->aead->open(ctx, out, out_len, max_out_len, nonce, nonce_len, in,
197
0
                        in_len, ad, ad_len)) {
198
0
      goto error;
199
0
    }
200
0
    return 1;
201
0
  }
202
203
  // AEADs that use the default implementation of open() must set |tag_len| at
204
  // initialization time.
205
473
  assert(ctx->tag_len);
206
207
473
  if (in_len < ctx->tag_len) {
208
1
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
209
1
    goto error;
210
1
  }
211
212
472
  size_t plaintext_len = in_len - ctx->tag_len;
213
472
  if (max_out_len < plaintext_len) {
214
1
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
215
1
    goto error;
216
1
  }
217
471
  if (EVP_AEAD_CTX_open_gather(ctx, out, nonce, nonce_len, in, plaintext_len,
218
471
                               in + plaintext_len, ctx->tag_len, ad, ad_len)) {
219
254
    *out_len = plaintext_len;
220
254
    return 1;
221
254
  }
222
223
219
error:
224
  // In the event of an error, clear the output buffer so that a caller
225
  // that doesn't check the return value doesn't try and process bad
226
  // data.
227
219
  OPENSSL_memset(out, 0, max_out_len);
228
219
  *out_len = 0;
229
219
  return 0;
230
471
}
231
232
int EVP_AEAD_CTX_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
233
                             const uint8_t *nonce, size_t nonce_len,
234
                             const uint8_t *in, size_t in_len,
235
                             const uint8_t *in_tag, size_t in_tag_len,
236
471
                             const uint8_t *ad, size_t ad_len) {
237
471
  if (!check_alias(in, in_len, out, in_len)) {
238
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
239
0
    goto error;
240
0
  }
241
242
471
  if (!ctx->aead->open_gather) {
243
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_NOT_IMPLEMENTED);
244
0
    goto error;
245
0
  }
246
247
471
  if (ctx->aead->open_gather(ctx, out, nonce, nonce_len, in, in_len, in_tag,
248
471
                             in_tag_len, ad, ad_len)) {
249
254
    return 1;
250
254
  }
251
252
217
error:
253
  // In the event of an error, clear the output buffer so that a caller
254
  // that doesn't check the return value doesn't try and process bad
255
  // data.
256
217
  OPENSSL_memset(out, 0, in_len);
257
217
  return 0;
258
471
}
259
260
0
const EVP_AEAD *EVP_AEAD_CTX_aead(const EVP_AEAD_CTX *ctx) { return ctx->aead; }
261
262
int EVP_AEAD_CTX_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
263
0
                        size_t *out_len) {
264
0
  if (ctx->aead->get_iv == NULL) {
265
0
    OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
266
0
    return 0;
267
0
  }
268
269
0
  return ctx->aead->get_iv(ctx, out_iv, out_len);
270
0
}
271
272
int EVP_AEAD_CTX_tag_len(const EVP_AEAD_CTX *ctx, size_t *out_tag_len,
273
153
                         const size_t in_len, const size_t extra_in_len) {
274
153
  assert(ctx->aead->seal_scatter_supports_extra_in || !extra_in_len);
275
276
153
  if (ctx->aead->tag_len) {
277
0
    *out_tag_len = ctx->aead->tag_len(ctx, in_len, extra_in_len);
278
0
    return 1;
279
0
  }
280
281
153
  if (extra_in_len + ctx->tag_len < extra_in_len) {
282
0
    OPENSSL_PUT_ERROR(CIPHER, ERR_R_OVERFLOW);
283
0
    *out_tag_len = 0;
284
0
    return 0;
285
0
  }
286
153
  *out_tag_len = extra_in_len + ctx->tag_len;
287
153
  return 1;
288
153
}