Coverage Report

Created: 2024-11-21 07:03

/src/boringssl/crypto/fipsmodule/cmac/cmac.c.inc
Line
Count
Source (jump to first uncovered line)
1
/* ====================================================================
2
 * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 *
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in
13
 *    the documentation and/or other materials provided with the
14
 *    distribution.
15
 *
16
 * 3. All advertising materials mentioning features or use of this
17
 *    software must display the following acknowledgment:
18
 *    "This product includes software developed by the OpenSSL Project
19
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
20
 *
21
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22
 *    endorse or promote products derived from this software without
23
 *    prior written permission. For written permission, please contact
24
 *    licensing@OpenSSL.org.
25
 *
26
 * 5. Products derived from this software may not be called "OpenSSL"
27
 *    nor may "OpenSSL" appear in their names without prior written
28
 *    permission of the OpenSSL Project.
29
 *
30
 * 6. Redistributions of any form whatsoever must retain the following
31
 *    acknowledgment:
32
 *    "This product includes software developed by the OpenSSL Project
33
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
34
 *
35
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46
 * OF THE POSSIBILITY OF SUCH DAMAGE.
47
 * ==================================================================== */
48
49
#include <openssl/cmac.h>
50
51
#include <assert.h>
52
#include <limits.h>
53
#include <string.h>
54
55
#include <openssl/aes.h>
56
#include <openssl/cipher.h>
57
#include <openssl/mem.h>
58
59
#include "../../internal.h"
60
#include "../service_indicator/internal.h"
61
62
63
struct cmac_ctx_st {
64
  EVP_CIPHER_CTX cipher_ctx;
65
  // k1 and k2 are the CMAC subkeys. See
66
  // https://tools.ietf.org/html/rfc4493#section-2.3
67
  uint8_t k1[AES_BLOCK_SIZE];
68
  uint8_t k2[AES_BLOCK_SIZE];
69
  // Last (possibly partial) scratch
70
  uint8_t block[AES_BLOCK_SIZE];
71
  // block_used contains the number of valid bytes in |block|.
72
  unsigned block_used;
73
};
74
75
7.17k
static void CMAC_CTX_init(CMAC_CTX *ctx) {
76
7.17k
  EVP_CIPHER_CTX_init(&ctx->cipher_ctx);
77
7.17k
}
78
79
7.17k
static void CMAC_CTX_cleanup(CMAC_CTX *ctx) {
80
7.17k
  EVP_CIPHER_CTX_cleanup(&ctx->cipher_ctx);
81
7.17k
  OPENSSL_cleanse(ctx->k1, sizeof(ctx->k1));
82
7.17k
  OPENSSL_cleanse(ctx->k2, sizeof(ctx->k2));
83
7.17k
  OPENSSL_cleanse(ctx->block, sizeof(ctx->block));
84
7.17k
}
85
86
int AES_CMAC(uint8_t out[16], const uint8_t *key, size_t key_len,
87
0
             const uint8_t *in, size_t in_len) {
88
0
  const EVP_CIPHER *cipher;
89
0
  switch (key_len) {
90
    // WARNING: this code assumes that all supported key sizes are FIPS
91
    // Approved.
92
0
    case 16:
93
0
      cipher = EVP_aes_128_cbc();
94
0
      break;
95
0
    case 32:
96
0
      cipher = EVP_aes_256_cbc();
97
0
      break;
98
0
    default:
99
0
      return 0;
100
0
  }
101
102
0
  size_t scratch_out_len;
103
0
  CMAC_CTX ctx;
104
0
  CMAC_CTX_init(&ctx);
105
106
  // We have to verify that all the CMAC services actually succeed before
107
  // updating the indicator state, so we lock the state here.
108
0
  FIPS_service_indicator_lock_state();
109
0
  const int ok = CMAC_Init(&ctx, key, key_len, cipher, NULL /* engine */) &&
110
0
                 CMAC_Update(&ctx, in, in_len) &&
111
0
                 CMAC_Final(&ctx, out, &scratch_out_len);
112
0
  FIPS_service_indicator_unlock_state();
113
114
0
  if (ok) {
115
0
    FIPS_service_indicator_update_state();
116
0
  }
117
0
  CMAC_CTX_cleanup(&ctx);
118
0
  return ok;
119
0
}
120
121
7.17k
CMAC_CTX *CMAC_CTX_new(void) {
122
7.17k
  CMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
123
7.17k
  if (ctx != NULL) {
124
7.17k
    CMAC_CTX_init(ctx);
125
7.17k
  }
126
7.17k
  return ctx;
127
7.17k
}
128
129
7.17k
void CMAC_CTX_free(CMAC_CTX *ctx) {
130
7.17k
  if (ctx == NULL) {
131
0
    return;
132
0
  }
133
134
7.17k
  CMAC_CTX_cleanup(ctx);
135
7.17k
  OPENSSL_free(ctx);
136
7.17k
}
137
138
6.84k
int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in) {
139
6.84k
  if (!EVP_CIPHER_CTX_copy(&out->cipher_ctx, &in->cipher_ctx)) {
140
165
    return 0;
141
165
  }
142
6.67k
  OPENSSL_memcpy(out->k1, in->k1, AES_BLOCK_SIZE);
143
6.67k
  OPENSSL_memcpy(out->k2, in->k2, AES_BLOCK_SIZE);
144
6.67k
  OPENSSL_memcpy(out->block, in->block, AES_BLOCK_SIZE);
145
6.67k
  out->block_used = in->block_used;
146
6.67k
  return 1;
147
6.84k
}
148
149
// binary_field_mul_x_128 treats the 128 bits at |in| as an element of GF(2¹²⁸)
150
// with a hard-coded reduction polynomial and sets |out| as x times the input.
151
//
152
// See https://tools.ietf.org/html/rfc4493#section-2.3
153
210
static void binary_field_mul_x_128(uint8_t out[16], const uint8_t in[16]) {
154
210
  unsigned i;
155
156
  // Shift |in| to left, including carry.
157
3.36k
  for (i = 0; i < 15; i++) {
158
3.15k
    out[i] = (in[i] << 1) | (in[i+1] >> 7);
159
3.15k
  }
160
161
  // If MSB set fixup with R.
162
210
  const uint8_t carry = in[0] >> 7;
163
210
  out[i] = (in[i] << 1) ^ ((0 - carry) & 0x87);
164
210
}
165
166
// binary_field_mul_x_64 behaves like |binary_field_mul_x_128| but acts on an
167
// element of GF(2⁶⁴).
168
//
169
// See https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
170
76
static void binary_field_mul_x_64(uint8_t out[8], const uint8_t in[8]) {
171
76
  unsigned i;
172
173
  // Shift |in| to left, including carry.
174
608
  for (i = 0; i < 7; i++) {
175
532
    out[i] = (in[i] << 1) | (in[i+1] >> 7);
176
532
  }
177
178
  // If MSB set fixup with R.
179
76
  const uint8_t carry = in[0] >> 7;
180
76
  out[i] = (in[i] << 1) ^ ((0 - carry) & 0x1b);
181
76
}
182
183
static const uint8_t kZeroIV[AES_BLOCK_SIZE] = {0};
184
185
int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t key_len,
186
191
              const EVP_CIPHER *cipher, ENGINE *engine) {
187
191
  int ret = 0;
188
191
  uint8_t scratch[AES_BLOCK_SIZE];
189
190
  // We have to avoid the underlying AES-CBC |EVP_CIPHER| services updating the
191
  // indicator state, so we lock the state here.
192
191
  FIPS_service_indicator_lock_state();
193
194
191
  size_t block_size = EVP_CIPHER_block_size(cipher);
195
191
  if ((block_size != AES_BLOCK_SIZE && block_size != 8 /* 3-DES */) ||
196
191
      EVP_CIPHER_key_length(cipher) != key_len ||
197
191
      !EVP_EncryptInit_ex(&ctx->cipher_ctx, cipher, NULL, key, kZeroIV) ||
198
191
      !EVP_Cipher(&ctx->cipher_ctx, scratch, kZeroIV, block_size) ||
199
      // Reset context again ready for first data.
200
191
      !EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV)) {
201
48
    goto out;
202
48
  }
203
204
143
  if (block_size == AES_BLOCK_SIZE) {
205
105
    binary_field_mul_x_128(ctx->k1, scratch);
206
105
    binary_field_mul_x_128(ctx->k2, ctx->k1);
207
105
  } else {
208
38
    binary_field_mul_x_64(ctx->k1, scratch);
209
38
    binary_field_mul_x_64(ctx->k2, ctx->k1);
210
38
  }
211
143
  ctx->block_used = 0;
212
143
  ret = 1;
213
214
191
out:
215
191
  FIPS_service_indicator_unlock_state();
216
191
  return ret;
217
143
}
218
219
0
int CMAC_Reset(CMAC_CTX *ctx) {
220
0
  ctx->block_used = 0;
221
0
  return EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV);
222
0
}
223
224
6.53k
int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len) {
225
6.53k
  int ret = 0;
226
227
  // We have to avoid the underlying AES-CBC |EVP_Cipher| services updating the
228
  // indicator state, so we lock the state here.
229
6.53k
  FIPS_service_indicator_lock_state();
230
231
6.53k
  size_t block_size = EVP_CIPHER_CTX_block_size(&ctx->cipher_ctx);
232
6.53k
  assert(block_size <= AES_BLOCK_SIZE);
233
6.53k
  uint8_t scratch[AES_BLOCK_SIZE];
234
235
6.53k
  if (ctx->block_used > 0) {
236
6.38k
    size_t todo = block_size - ctx->block_used;
237
6.38k
    if (in_len < todo) {
238
4.58k
      todo = in_len;
239
4.58k
    }
240
241
6.38k
    OPENSSL_memcpy(ctx->block + ctx->block_used, in, todo);
242
6.38k
    in += todo;
243
6.38k
    in_len -= todo;
244
6.38k
    ctx->block_used += todo;
245
246
    // If |in_len| is zero then either |ctx->block_used| is less than
247
    // |block_size|, in which case we can stop here, or |ctx->block_used| is
248
    // exactly |block_size| but there's no more data to process. In the latter
249
    // case we don't want to process this block now because it might be the last
250
    // block and that block is treated specially.
251
6.38k
    if (in_len == 0) {
252
6.12k
      ret = 1;
253
6.12k
      goto out;
254
6.12k
    }
255
256
261
    assert(ctx->block_used == block_size);
257
258
261
    if (!EVP_Cipher(&ctx->cipher_ctx, scratch, ctx->block, block_size)) {
259
0
      goto out;
260
0
    }
261
261
  }
262
263
  // Encrypt all but one of the remaining blocks.
264
3.36k
  while (in_len > block_size) {
265
2.95k
    if (!EVP_Cipher(&ctx->cipher_ctx, scratch, in, block_size)) {
266
0
      goto out;
267
0
    }
268
2.95k
    in += block_size;
269
2.95k
    in_len -= block_size;
270
2.95k
  }
271
272
405
  OPENSSL_memcpy(ctx->block, in, in_len);
273
  // |in_len| is bounded by |block_size|, which fits in |unsigned|.
274
405
  static_assert(EVP_MAX_BLOCK_LENGTH < UINT_MAX,
275
405
                "EVP_MAX_BLOCK_LENGTH is too large");
276
405
  ctx->block_used = (unsigned)in_len;
277
405
  ret = 1;
278
279
6.53k
out:
280
6.53k
  FIPS_service_indicator_unlock_state();
281
6.53k
  return ret;
282
405
}
283
284
143
int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len) {
285
143
  int ret = 0;
286
143
  size_t block_size = EVP_CIPHER_CTX_block_size(&ctx->cipher_ctx);
287
143
  assert(block_size <= AES_BLOCK_SIZE);
288
289
  // We have to avoid the underlying AES-CBC |EVP_Cipher| services updating the
290
  // indicator state, so we lock the state here.
291
143
  FIPS_service_indicator_lock_state();
292
293
143
  *out_len = block_size;
294
143
  if (out == NULL) {
295
0
    ret = 1;
296
0
    goto out;
297
0
  }
298
299
143
  const uint8_t *mask = ctx->k1;
300
301
143
  if (ctx->block_used != block_size) {
302
    // If the last block is incomplete, terminate it with a single 'one' bit
303
    // followed by zeros.
304
123
    ctx->block[ctx->block_used] = 0x80;
305
123
    OPENSSL_memset(ctx->block + ctx->block_used + 1, 0,
306
123
                   block_size - (ctx->block_used + 1));
307
308
123
    mask = ctx->k2;
309
123
  }
310
311
2.12k
  for (unsigned i = 0; i < block_size; i++) {
312
1.98k
    out[i] = ctx->block[i] ^ mask[i];
313
1.98k
  }
314
143
  ret = EVP_Cipher(&ctx->cipher_ctx, out, out, block_size);
315
316
143
out:
317
143
  FIPS_service_indicator_unlock_state();
318
143
  if (ret) {
319
143
    FIPS_service_indicator_update_state();
320
143
  }
321
143
  return ret;
322
143
}