Coverage Report

Created: 2024-11-21 06:47

/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
0
static void CMAC_CTX_init(CMAC_CTX *ctx) {
76
0
  EVP_CIPHER_CTX_init(&ctx->cipher_ctx);
77
0
}
78
79
0
static void CMAC_CTX_cleanup(CMAC_CTX *ctx) {
80
0
  EVP_CIPHER_CTX_cleanup(&ctx->cipher_ctx);
81
0
  OPENSSL_cleanse(ctx->k1, sizeof(ctx->k1));
82
0
  OPENSSL_cleanse(ctx->k2, sizeof(ctx->k2));
83
0
  OPENSSL_cleanse(ctx->block, sizeof(ctx->block));
84
0
}
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
0
CMAC_CTX *CMAC_CTX_new(void) {
122
0
  CMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
123
0
  if (ctx != NULL) {
124
0
    CMAC_CTX_init(ctx);
125
0
  }
126
0
  return ctx;
127
0
}
128
129
0
void CMAC_CTX_free(CMAC_CTX *ctx) {
130
0
  if (ctx == NULL) {
131
0
    return;
132
0
  }
133
134
0
  CMAC_CTX_cleanup(ctx);
135
0
  OPENSSL_free(ctx);
136
0
}
137
138
0
int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in) {
139
0
  if (!EVP_CIPHER_CTX_copy(&out->cipher_ctx, &in->cipher_ctx)) {
140
0
    return 0;
141
0
  }
142
0
  OPENSSL_memcpy(out->k1, in->k1, AES_BLOCK_SIZE);
143
0
  OPENSSL_memcpy(out->k2, in->k2, AES_BLOCK_SIZE);
144
0
  OPENSSL_memcpy(out->block, in->block, AES_BLOCK_SIZE);
145
0
  out->block_used = in->block_used;
146
0
  return 1;
147
0
}
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
0
static void binary_field_mul_x_128(uint8_t out[16], const uint8_t in[16]) {
154
0
  unsigned i;
155
156
  // Shift |in| to left, including carry.
157
0
  for (i = 0; i < 15; i++) {
158
0
    out[i] = (in[i] << 1) | (in[i+1] >> 7);
159
0
  }
160
161
  // If MSB set fixup with R.
162
0
  const uint8_t carry = in[0] >> 7;
163
0
  out[i] = (in[i] << 1) ^ ((0 - carry) & 0x87);
164
0
}
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
0
static void binary_field_mul_x_64(uint8_t out[8], const uint8_t in[8]) {
171
0
  unsigned i;
172
173
  // Shift |in| to left, including carry.
174
0
  for (i = 0; i < 7; i++) {
175
0
    out[i] = (in[i] << 1) | (in[i+1] >> 7);
176
0
  }
177
178
  // If MSB set fixup with R.
179
0
  const uint8_t carry = in[0] >> 7;
180
0
  out[i] = (in[i] << 1) ^ ((0 - carry) & 0x1b);
181
0
}
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
0
              const EVP_CIPHER *cipher, ENGINE *engine) {
187
0
  int ret = 0;
188
0
  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
0
  FIPS_service_indicator_lock_state();
193
194
0
  size_t block_size = EVP_CIPHER_block_size(cipher);
195
0
  if ((block_size != AES_BLOCK_SIZE && block_size != 8 /* 3-DES */) ||
196
0
      EVP_CIPHER_key_length(cipher) != key_len ||
197
0
      !EVP_EncryptInit_ex(&ctx->cipher_ctx, cipher, NULL, key, kZeroIV) ||
198
0
      !EVP_Cipher(&ctx->cipher_ctx, scratch, kZeroIV, block_size) ||
199
      // Reset context again ready for first data.
200
0
      !EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV)) {
201
0
    goto out;
202
0
  }
203
204
0
  if (block_size == AES_BLOCK_SIZE) {
205
0
    binary_field_mul_x_128(ctx->k1, scratch);
206
0
    binary_field_mul_x_128(ctx->k2, ctx->k1);
207
0
  } else {
208
0
    binary_field_mul_x_64(ctx->k1, scratch);
209
0
    binary_field_mul_x_64(ctx->k2, ctx->k1);
210
0
  }
211
0
  ctx->block_used = 0;
212
0
  ret = 1;
213
214
0
out:
215
0
  FIPS_service_indicator_unlock_state();
216
0
  return ret;
217
0
}
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
0
int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len) {
225
0
  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
0
  FIPS_service_indicator_lock_state();
230
231
0
  size_t block_size = EVP_CIPHER_CTX_block_size(&ctx->cipher_ctx);
232
0
  assert(block_size <= AES_BLOCK_SIZE);
233
0
  uint8_t scratch[AES_BLOCK_SIZE];
234
235
0
  if (ctx->block_used > 0) {
236
0
    size_t todo = block_size - ctx->block_used;
237
0
    if (in_len < todo) {
238
0
      todo = in_len;
239
0
    }
240
241
0
    OPENSSL_memcpy(ctx->block + ctx->block_used, in, todo);
242
0
    in += todo;
243
0
    in_len -= todo;
244
0
    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
0
    if (in_len == 0) {
252
0
      ret = 1;
253
0
      goto out;
254
0
    }
255
256
0
    assert(ctx->block_used == block_size);
257
258
0
    if (!EVP_Cipher(&ctx->cipher_ctx, scratch, ctx->block, block_size)) {
259
0
      goto out;
260
0
    }
261
0
  }
262
263
  // Encrypt all but one of the remaining blocks.
264
0
  while (in_len > block_size) {
265
0
    if (!EVP_Cipher(&ctx->cipher_ctx, scratch, in, block_size)) {
266
0
      goto out;
267
0
    }
268
0
    in += block_size;
269
0
    in_len -= block_size;
270
0
  }
271
272
0
  OPENSSL_memcpy(ctx->block, in, in_len);
273
  // |in_len| is bounded by |block_size|, which fits in |unsigned|.
274
0
  static_assert(EVP_MAX_BLOCK_LENGTH < UINT_MAX,
275
0
                "EVP_MAX_BLOCK_LENGTH is too large");
276
0
  ctx->block_used = (unsigned)in_len;
277
0
  ret = 1;
278
279
0
out:
280
0
  FIPS_service_indicator_unlock_state();
281
0
  return ret;
282
0
}
283
284
0
int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len) {
285
0
  int ret = 0;
286
0
  size_t block_size = EVP_CIPHER_CTX_block_size(&ctx->cipher_ctx);
287
0
  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
0
  FIPS_service_indicator_lock_state();
292
293
0
  *out_len = block_size;
294
0
  if (out == NULL) {
295
0
    ret = 1;
296
0
    goto out;
297
0
  }
298
299
0
  const uint8_t *mask = ctx->k1;
300
301
0
  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
0
    ctx->block[ctx->block_used] = 0x80;
305
0
    OPENSSL_memset(ctx->block + ctx->block_used + 1, 0,
306
0
                   block_size - (ctx->block_used + 1));
307
308
0
    mask = ctx->k2;
309
0
  }
310
311
0
  for (unsigned i = 0; i < block_size; i++) {
312
0
    out[i] = ctx->block[i] ^ mask[i];
313
0
  }
314
0
  ret = EVP_Cipher(&ctx->cipher_ctx, out, out, block_size);
315
316
0
out:
317
0
  FIPS_service_indicator_unlock_state();
318
0
  if (ret) {
319
0
    FIPS_service_indicator_update_state();
320
0
  }
321
0
  return ret;
322
0
}