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