Coverage Report

Created: 2025-06-11 06:41

/src/boringssl/crypto/fipsmodule/cmac/cmac.cc.inc
Line
Count
Source (jump to first uncovered line)
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, NULL /* 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 != NULL) {
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 == NULL) {
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, NULL,
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, NULL, NULL, NULL, kZeroIV)) {
168
0
    goto out;
169
0
  }
170
171
0
  if (block_size == AES_BLOCK_SIZE) {
172
0
    binary_field_mul_x_128(ctx->k1, scratch);
173
0
    binary_field_mul_x_128(ctx->k2, ctx->k1);
174
0
  } else {
175
0
    binary_field_mul_x_64(ctx->k1, scratch);
176
0
    binary_field_mul_x_64(ctx->k2, ctx->k1);
177
0
  }
178
0
  ctx->block_used = 0;
179
0
  ret = 1;
180
181
0
out:
182
0
  FIPS_service_indicator_unlock_state();
183
0
  return ret;
184
0
}
185
186
0
int CMAC_Reset(CMAC_CTX *ctx) {
187
0
  ctx->block_used = 0;
188
0
  return EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV);
189
0
}
190
191
0
int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len) {
192
0
  int ret = 0;
193
194
  // We have to avoid the underlying AES-CBC |EVP_Cipher| services updating the
195
  // indicator state, so we lock the state here.
196
0
  FIPS_service_indicator_lock_state();
197
198
0
  size_t block_size = EVP_CIPHER_CTX_block_size(&ctx->cipher_ctx);
199
0
  assert(block_size <= AES_BLOCK_SIZE);
200
0
  uint8_t scratch[AES_BLOCK_SIZE];
201
202
0
  if (ctx->block_used > 0) {
203
0
    size_t todo = block_size - ctx->block_used;
204
0
    if (in_len < todo) {
205
0
      todo = in_len;
206
0
    }
207
208
0
    OPENSSL_memcpy(ctx->block + ctx->block_used, in, todo);
209
0
    in += todo;
210
0
    in_len -= todo;
211
0
    ctx->block_used += todo;
212
213
    // If |in_len| is zero then either |ctx->block_used| is less than
214
    // |block_size|, in which case we can stop here, or |ctx->block_used| is
215
    // exactly |block_size| but there's no more data to process. In the latter
216
    // case we don't want to process this block now because it might be the last
217
    // block and that block is treated specially.
218
0
    if (in_len == 0) {
219
0
      ret = 1;
220
0
      goto out;
221
0
    }
222
223
0
    assert(ctx->block_used == block_size);
224
225
0
    if (!EVP_Cipher(&ctx->cipher_ctx, scratch, ctx->block, block_size)) {
226
0
      goto out;
227
0
    }
228
0
  }
229
230
  // Encrypt all but one of the remaining blocks.
231
0
  while (in_len > block_size) {
232
0
    if (!EVP_Cipher(&ctx->cipher_ctx, scratch, in, block_size)) {
233
0
      goto out;
234
0
    }
235
0
    in += block_size;
236
0
    in_len -= block_size;
237
0
  }
238
239
0
  OPENSSL_memcpy(ctx->block, in, in_len);
240
  // |in_len| is bounded by |block_size|, which fits in |unsigned|.
241
0
  static_assert(EVP_MAX_BLOCK_LENGTH < UINT_MAX,
242
0
                "EVP_MAX_BLOCK_LENGTH is too large");
243
0
  ctx->block_used = (unsigned)in_len;
244
0
  ret = 1;
245
246
0
out:
247
0
  FIPS_service_indicator_unlock_state();
248
0
  return ret;
249
0
}
250
251
0
int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len) {
252
0
  int ret = 0;
253
0
  size_t block_size = EVP_CIPHER_CTX_block_size(&ctx->cipher_ctx);
254
0
  assert(block_size <= AES_BLOCK_SIZE);
255
256
  // We have to avoid the underlying AES-CBC |EVP_Cipher| services updating the
257
  // indicator state, so we lock the state here.
258
0
  FIPS_service_indicator_lock_state();
259
260
0
  *out_len = block_size;
261
0
  const uint8_t *mask = ctx->k1;
262
0
  if (out == NULL) {
263
0
    ret = 1;
264
0
    goto out;
265
0
  }
266
267
0
  if (ctx->block_used != block_size) {
268
    // If the last block is incomplete, terminate it with a single 'one' bit
269
    // followed by zeros.
270
0
    ctx->block[ctx->block_used] = 0x80;
271
0
    OPENSSL_memset(ctx->block + ctx->block_used + 1, 0,
272
0
                   block_size - (ctx->block_used + 1));
273
274
0
    mask = ctx->k2;
275
0
  }
276
277
0
  for (unsigned i = 0; i < block_size; i++) {
278
0
    out[i] = ctx->block[i] ^ mask[i];
279
0
  }
280
0
  ret = EVP_Cipher(&ctx->cipher_ctx, out, out, block_size);
281
282
0
out:
283
0
  FIPS_service_indicator_unlock_state();
284
0
  if (ret) {
285
0
    FIPS_service_indicator_update_state();
286
0
  }
287
0
  return ret;
288
0
}