Coverage Report

Created: 2025-11-17 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/fipsmodule/cmac/cmac.cc.inc
Line
Count
Source
1
// Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/cmac.h>
16
17
#include <assert.h>
18
#include <limits.h>
19
#include <string.h>
20
21
#include <openssl/aes.h>
22
#include <openssl/cipher.h>
23
#include <openssl/mem.h>
24
25
#include "../../internal.h"
26
#include "../service_indicator/internal.h"
27
28
29
struct cmac_ctx_st {
30
  EVP_CIPHER_CTX cipher_ctx;
31
  // k1 and k2 are the CMAC subkeys. See
32
  // https://tools.ietf.org/html/rfc4493#section-2.3
33
  uint8_t k1[AES_BLOCK_SIZE];
34
  uint8_t k2[AES_BLOCK_SIZE];
35
  // Last (possibly partial) scratch
36
  uint8_t block[AES_BLOCK_SIZE];
37
  // block_used contains the number of valid bytes in |block|.
38
  unsigned block_used;
39
};
40
41
0
static void CMAC_CTX_init(CMAC_CTX *ctx) {
42
0
  EVP_CIPHER_CTX_init(&ctx->cipher_ctx);
43
0
}
44
45
0
static void CMAC_CTX_cleanup(CMAC_CTX *ctx) {
46
0
  EVP_CIPHER_CTX_cleanup(&ctx->cipher_ctx);
47
0
  OPENSSL_cleanse(ctx->k1, sizeof(ctx->k1));
48
0
  OPENSSL_cleanse(ctx->k2, sizeof(ctx->k2));
49
0
  OPENSSL_cleanse(ctx->block, sizeof(ctx->block));
50
0
}
51
52
int AES_CMAC(uint8_t out[16], const uint8_t *key, size_t key_len,
53
0
             const uint8_t *in, size_t in_len) {
54
0
  const EVP_CIPHER *cipher;
55
0
  switch (key_len) {
56
    // WARNING: this code assumes that all supported key sizes are FIPS
57
    // Approved.
58
0
    case 16:
59
0
      cipher = EVP_aes_128_cbc();
60
0
      break;
61
0
    case 32:
62
0
      cipher = EVP_aes_256_cbc();
63
0
      break;
64
0
    default:
65
0
      return 0;
66
0
  }
67
68
0
  size_t scratch_out_len;
69
0
  CMAC_CTX ctx;
70
0
  CMAC_CTX_init(&ctx);
71
72
  // We have to verify that all the CMAC services actually succeed before
73
  // updating the indicator state, so we lock the state here.
74
0
  FIPS_service_indicator_lock_state();
75
0
  const int ok = CMAC_Init(&ctx, key, key_len, cipher, nullptr /* engine */) &&
76
0
                 CMAC_Update(&ctx, in, in_len) &&
77
0
                 CMAC_Final(&ctx, out, &scratch_out_len);
78
0
  FIPS_service_indicator_unlock_state();
79
80
0
  if (ok) {
81
0
    FIPS_service_indicator_update_state();
82
0
  }
83
0
  CMAC_CTX_cleanup(&ctx);
84
0
  return ok;
85
0
}
86
87
0
CMAC_CTX *CMAC_CTX_new(void) {
88
0
  CMAC_CTX *ctx = reinterpret_cast<CMAC_CTX *>(OPENSSL_malloc(sizeof(*ctx)));
89
0
  if (ctx != nullptr) {
90
0
    CMAC_CTX_init(ctx);
91
0
  }
92
0
  return ctx;
93
0
}
94
95
0
void CMAC_CTX_free(CMAC_CTX *ctx) {
96
0
  if (ctx == nullptr) {
97
0
    return;
98
0
  }
99
100
0
  CMAC_CTX_cleanup(ctx);
101
0
  OPENSSL_free(ctx);
102
0
}
103
104
0
int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in) {
105
0
  if (!EVP_CIPHER_CTX_copy(&out->cipher_ctx, &in->cipher_ctx)) {
106
0
    return 0;
107
0
  }
108
0
  OPENSSL_memcpy(out->k1, in->k1, AES_BLOCK_SIZE);
109
0
  OPENSSL_memcpy(out->k2, in->k2, AES_BLOCK_SIZE);
110
0
  OPENSSL_memcpy(out->block, in->block, AES_BLOCK_SIZE);
111
0
  out->block_used = in->block_used;
112
0
  return 1;
113
0
}
114
115
// binary_field_mul_x_128 treats the 128 bits at |in| as an element of GF(2¹²⁸)
116
// with a hard-coded reduction polynomial and sets |out| as x times the input.
117
//
118
// See https://tools.ietf.org/html/rfc4493#section-2.3
119
0
static void binary_field_mul_x_128(uint8_t out[16], const uint8_t in[16]) {
120
0
  unsigned i;
121
122
  // Shift |in| to left, including carry.
123
0
  for (i = 0; i < 15; i++) {
124
0
    out[i] = (in[i] << 1) | (in[i + 1] >> 7);
125
0
  }
126
127
  // If MSB set fixup with R.
128
0
  const uint8_t carry = in[0] >> 7;
129
0
  out[i] = (in[i] << 1) ^ ((0 - carry) & 0x87);
130
0
}
131
132
// binary_field_mul_x_64 behaves like |binary_field_mul_x_128| but acts on an
133
// element of GF(2⁶⁴).
134
//
135
// See https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
136
0
static void binary_field_mul_x_64(uint8_t out[8], const uint8_t in[8]) {
137
0
  unsigned i;
138
139
  // Shift |in| to left, including carry.
140
0
  for (i = 0; i < 7; i++) {
141
0
    out[i] = (in[i] << 1) | (in[i + 1] >> 7);
142
0
  }
143
144
  // If MSB set fixup with R.
145
0
  const uint8_t carry = in[0] >> 7;
146
0
  out[i] = (in[i] << 1) ^ ((0 - carry) & 0x1b);
147
0
}
148
149
static const uint8_t kZeroIV[AES_BLOCK_SIZE] = {0};
150
151
int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t key_len,
152
0
              const EVP_CIPHER *cipher, ENGINE *engine) {
153
0
  int ret = 0;
154
0
  uint8_t scratch[AES_BLOCK_SIZE];
155
156
  // We have to avoid the underlying AES-CBC |EVP_CIPHER| services updating the
157
  // indicator state, so we lock the state here.
158
0
  FIPS_service_indicator_lock_state();
159
160
0
  size_t block_size = EVP_CIPHER_block_size(cipher);
161
0
  if ((block_size != AES_BLOCK_SIZE && block_size != 8 /* 3-DES */) ||
162
0
      EVP_CIPHER_key_length(cipher) != key_len ||
163
0
      !EVP_EncryptInit_ex(&ctx->cipher_ctx, cipher, nullptr,
164
0
                          reinterpret_cast<const uint8_t *>(key), kZeroIV) ||
165
0
      !EVP_Cipher(&ctx->cipher_ctx, scratch, kZeroIV, block_size) ||
166
      // Reset context again ready for first data.
167
0
      !EVP_EncryptInit_ex(&ctx->cipher_ctx, nullptr, nullptr, nullptr,
168
0
                          kZeroIV)) {
169
0
    goto out;
170
0
  }
171
172
0
  if (block_size == AES_BLOCK_SIZE) {
173
0
    binary_field_mul_x_128(ctx->k1, scratch);
174
0
    binary_field_mul_x_128(ctx->k2, ctx->k1);
175
0
  } else {
176
0
    binary_field_mul_x_64(ctx->k1, scratch);
177
0
    binary_field_mul_x_64(ctx->k2, ctx->k1);
178
0
  }
179
0
  ctx->block_used = 0;
180
0
  ret = 1;
181
182
0
out:
183
0
  FIPS_service_indicator_unlock_state();
184
0
  return ret;
185
0
}
186
187
0
int CMAC_Reset(CMAC_CTX *ctx) {
188
0
  ctx->block_used = 0;
189
0
  return EVP_EncryptInit_ex(&ctx->cipher_ctx, nullptr, nullptr, nullptr,
190
0
                            kZeroIV);
191
0
}
192
193
0
int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len) {
194
0
  int ret = 0;
195
196
  // We have to avoid the underlying AES-CBC |EVP_Cipher| services updating the
197
  // indicator state, so we lock the state here.
198
0
  FIPS_service_indicator_lock_state();
199
200
0
  size_t block_size = EVP_CIPHER_CTX_block_size(&ctx->cipher_ctx);
201
0
  assert(block_size <= AES_BLOCK_SIZE);
202
0
  uint8_t scratch[AES_BLOCK_SIZE];
203
204
0
  if (ctx->block_used > 0) {
205
0
    size_t todo = block_size - ctx->block_used;
206
0
    if (in_len < todo) {
207
0
      todo = in_len;
208
0
    }
209
210
0
    OPENSSL_memcpy(ctx->block + ctx->block_used, in, todo);
211
0
    in += todo;
212
0
    in_len -= todo;
213
0
    ctx->block_used += todo;
214
215
    // If |in_len| is zero then either |ctx->block_used| is less than
216
    // |block_size|, in which case we can stop here, or |ctx->block_used| is
217
    // exactly |block_size| but there's no more data to process. In the latter
218
    // case we don't want to process this block now because it might be the last
219
    // block and that block is treated specially.
220
0
    if (in_len == 0) {
221
0
      ret = 1;
222
0
      goto out;
223
0
    }
224
225
0
    assert(ctx->block_used == block_size);
226
227
0
    if (!EVP_Cipher(&ctx->cipher_ctx, scratch, ctx->block, block_size)) {
228
0
      goto out;
229
0
    }
230
0
  }
231
232
  // Encrypt all but one of the remaining blocks.
233
0
  while (in_len > block_size) {
234
0
    if (!EVP_Cipher(&ctx->cipher_ctx, scratch, in, block_size)) {
235
0
      goto out;
236
0
    }
237
0
    in += block_size;
238
0
    in_len -= block_size;
239
0
  }
240
241
0
  OPENSSL_memcpy(ctx->block, in, in_len);
242
  // |in_len| is bounded by |block_size|, which fits in |unsigned|.
243
0
  static_assert(EVP_MAX_BLOCK_LENGTH < UINT_MAX,
244
0
                "EVP_MAX_BLOCK_LENGTH is too large");
245
0
  ctx->block_used = (unsigned)in_len;
246
0
  ret = 1;
247
248
0
out:
249
0
  FIPS_service_indicator_unlock_state();
250
0
  return ret;
251
0
}
252
253
0
int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len) {
254
0
  int ret = 0;
255
0
  size_t block_size = EVP_CIPHER_CTX_block_size(&ctx->cipher_ctx);
256
0
  assert(block_size <= AES_BLOCK_SIZE);
257
258
  // We have to avoid the underlying AES-CBC |EVP_Cipher| services updating the
259
  // indicator state, so we lock the state here.
260
0
  FIPS_service_indicator_lock_state();
261
262
0
  *out_len = block_size;
263
0
  const uint8_t *mask = ctx->k1;
264
0
  if (out == nullptr) {
265
0
    ret = 1;
266
0
    goto out;
267
0
  }
268
269
0
  if (ctx->block_used != block_size) {
270
    // If the last block is incomplete, terminate it with a single 'one' bit
271
    // followed by zeros.
272
0
    ctx->block[ctx->block_used] = 0x80;
273
0
    OPENSSL_memset(ctx->block + ctx->block_used + 1, 0,
274
0
                   block_size - (ctx->block_used + 1));
275
276
0
    mask = ctx->k2;
277
0
  }
278
279
0
  for (unsigned i = 0; i < block_size; i++) {
280
0
    out[i] = ctx->block[i] ^ mask[i];
281
0
  }
282
0
  ret = EVP_Cipher(&ctx->cipher_ctx, out, out, block_size);
283
284
0
out:
285
0
  FIPS_service_indicator_unlock_state();
286
0
  if (ret) {
287
0
    FIPS_service_indicator_update_state();
288
0
  }
289
0
  return ret;
290
0
}