Coverage Report

Created: 2026-04-15 06:25

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