Coverage Report

Created: 2024-11-21 06:47

/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
0
size_t EVP_AEAD_key_length(const EVP_AEAD *aead) { return aead->key_len; }
29
30
0
size_t EVP_AEAD_nonce_length(const EVP_AEAD *aead) { return aead->nonce_len; }
31
32
0
size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead) { return aead->overhead; }
33
34
0
size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead) { return aead->max_tag_len; }
35
36
0
void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx) {
37
0
  OPENSSL_memset(ctx, 0, sizeof(EVP_AEAD_CTX));
38
0
}
39
40
EVP_AEAD_CTX *EVP_AEAD_CTX_new(const EVP_AEAD *aead, const uint8_t *key,
41
0
                               size_t key_len, size_t tag_len) {
42
0
  EVP_AEAD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_AEAD_CTX));
43
0
  EVP_AEAD_CTX_zero(ctx);
44
45
0
  if (EVP_AEAD_CTX_init(ctx, aead, key, key_len, tag_len, NULL)) {
46
0
    return ctx;
47
0
  }
48
49
0
  EVP_AEAD_CTX_free(ctx);
50
0
  return NULL;
51
0
}
52
53
0
void EVP_AEAD_CTX_free(EVP_AEAD_CTX *ctx) {
54
0
  if (ctx == NULL) {
55
0
    return;
56
0
  }
57
0
  EVP_AEAD_CTX_cleanup(ctx);
58
0
  OPENSSL_free(ctx);
59
0
}
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
0
                      ENGINE *impl) {
64
0
  if (!aead->init) {
65
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_DIRECTION_SET);
66
0
    ctx->aead = NULL;
67
0
    return 0;
68
0
  }
69
0
  return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, tag_len,
70
0
                                          evp_aead_open);
71
0
}
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
0
                                     enum evp_aead_direction_t dir) {
77
0
  if (key_len != aead->key_len) {
78
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_KEY_SIZE);
79
0
    ctx->aead = NULL;
80
0
    return 0;
81
0
  }
82
83
0
  ctx->aead = aead;
84
85
0
  int ok;
86
0
  if (aead->init) {
87
0
    ok = aead->init(ctx, key, key_len, tag_len);
88
0
  } else {
89
0
    ok = aead->init_with_direction(ctx, key, key_len, tag_len, dir);
90
0
  }
91
92
0
  if (!ok) {
93
0
    ctx->aead = NULL;
94
0
  }
95
96
0
  return ok;
97
0
}
98
99
0
void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) {
100
0
  if (ctx->aead == NULL) {
101
0
    return;
102
0
  }
103
0
  ctx->aead->cleanup(ctx);
104
0
  ctx->aead = NULL;
105
0
}
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
0
                       size_t out_len) {
111
0
  if (!buffers_alias(in, in_len, out, out_len)) {
112
0
    return 1;
113
0
  }
114
115
0
  return in == out;
116
0
}
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
0
                      const uint8_t *ad, size_t ad_len) {
122
0
  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
0
  if (max_out_len < in_len) {
128
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
129
0
    goto error;
130
0
  }
131
132
0
  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
0
  size_t out_tag_len;
138
0
  if (ctx->aead->seal_scatter(ctx, out, out + in_len, &out_tag_len,
139
0
                              max_out_len - in_len, nonce, nonce_len, in,
140
0
                              in_len, NULL, 0, ad, ad_len)) {
141
0
    *out_len = in_len + out_tag_len;
142
0
    return 1;
143
0
  }
144
145
0
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
0
  OPENSSL_memset(out, 0, max_out_len);
149
0
  *out_len = 0;
150
0
  return 0;
151
0
}
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
0
                      const uint8_t *ad, size_t ad_len) {
190
0
  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
0
  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
0
  assert(ctx->tag_len);
206
207
0
  if (in_len < ctx->tag_len) {
208
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
209
0
    goto error;
210
0
  }
211
212
0
  size_t plaintext_len = in_len - ctx->tag_len;
213
0
  if (max_out_len < plaintext_len) {
214
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
215
0
    goto error;
216
0
  }
217
0
  if (EVP_AEAD_CTX_open_gather(ctx, out, nonce, nonce_len, in, plaintext_len,
218
0
                               in + plaintext_len, ctx->tag_len, ad, ad_len)) {
219
0
    *out_len = plaintext_len;
220
0
    return 1;
221
0
  }
222
223
0
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
0
  OPENSSL_memset(out, 0, max_out_len);
228
0
  *out_len = 0;
229
0
  return 0;
230
0
}
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
0
                             const uint8_t *ad, size_t ad_len) {
237
0
  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
0
  if (!ctx->aead->open_gather) {
243
0
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_NOT_IMPLEMENTED);
244
0
    goto error;
245
0
  }
246
247
0
  if (ctx->aead->open_gather(ctx, out, nonce, nonce_len, in, in_len, in_tag,
248
0
                             in_tag_len, ad, ad_len)) {
249
0
    return 1;
250
0
  }
251
252
0
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
0
  OPENSSL_memset(out, 0, in_len);
257
0
  return 0;
258
0
}
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
0
                         const size_t in_len, const size_t extra_in_len) {
274
0
  assert(ctx->aead->seal_scatter_supports_extra_in || !extra_in_len);
275
276
0
  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
0
  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
0
  *out_tag_len = extra_in_len + ctx->tag_len;
287
0
  return 1;
288
0
}