Blame lib/nettle/backport/cmac.c

Packit Service 4684c1
/*
Packit Service 4684c1
   AES-CMAC-128 (rfc 4493)
Packit Service 4684c1
   Copyright (C) Stefan Metzmacher 2012
Packit Service 4684c1
   Copyright (C) Jeremy Allison 2012
Packit Service 4684c1
   Copyright (C) Michael Adam 2012
Packit Service 4684c1
   Copyright (C) 2017, Red Hat Inc.
Packit Service 4684c1
Packit Service 4684c1
   This file is part of GNU Nettle.
Packit Service 4684c1
Packit Service 4684c1
   GNU Nettle is free software: you can redistribute it and/or
Packit Service 4684c1
   modify it under the terms of either:
Packit Service 4684c1
Packit Service 4684c1
     * the GNU Lesser General Public License as published by the Free
Packit Service 4684c1
       Software Foundation; either version 3 of the License, or (at your
Packit Service 4684c1
       option) any later version.
Packit Service 4684c1
Packit Service 4684c1
   or
Packit Service 4684c1
Packit Service 4684c1
     * the GNU General Public License as published by the Free
Packit Service 4684c1
       Software Foundation; either version 2 of the License, or (at your
Packit Service 4684c1
       option) any later version.
Packit Service 4684c1
Packit Service 4684c1
   or both in parallel, as here.
Packit Service 4684c1
Packit Service 4684c1
   GNU Nettle is distributed in the hope that it will be useful,
Packit Service 4684c1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 4684c1
   General Public License for more details.
Packit Service 4684c1
Packit Service 4684c1
   You should have received copies of the GNU General Public License and
Packit Service 4684c1
   the GNU Lesser General Public License along with this program.  If
Packit Service 4684c1
   not, see http://www.gnu.org/licenses/.
Packit Service 4684c1
*/
Packit Service 4684c1
Packit Service 4684c1
#if HAVE_CONFIG_H
Packit Service 4684c1
# include "config.h"
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
#include <assert.h>
Packit Service 4684c1
#include <stdlib.h>
Packit Service 4684c1
#include <string.h>
Packit Service 4684c1
Packit Service 4684c1
#include "cmac.h"
Packit Service 4684c1
Packit Service 4684c1
#include <nettle/memxor.h>
Packit Service 4684c1
#include "nettle-alloca.h"
Packit Service 4684c1
#include "block-internal.h"
Packit Service 4684c1
#include <nettle/macros.h>
Packit Service 4684c1
Packit Service 4684c1
void
Packit Service 4684c1
cmac128_set_key(struct cmac128_key *key, const void *cipher,
Packit Service 4684c1
		nettle_cipher_func *encrypt)
Packit Service 4684c1
{
Packit Service 4684c1
  static const union nettle_block16 zero_block;
Packit Service 4684c1
  union nettle_block16 L;
Packit Service 4684c1
Packit Service 4684c1
  /* step 1 - generate subkeys k1 and k2 */
Packit Service 4684c1
  encrypt(cipher, 16, L.b, zero_block.b);
Packit Service 4684c1
Packit Service 4684c1
  block16_mulx_be(&key->K1, &L);
Packit Service 4684c1
  block16_mulx_be(&key->K2, &key->K1);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
void
Packit Service 4684c1
cmac128_init(struct cmac128_ctx *ctx)
Packit Service 4684c1
{
Packit Service 4684c1
  memset(&ctx->X, 0, sizeof(ctx->X));
Packit Service 4684c1
  ctx->index = 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#define MIN(x,y) ((x)<(y)?(x):(y))
Packit Service 4684c1
Packit Service 4684c1
void
Packit Service 4684c1
cmac128_update(struct cmac128_ctx *ctx, const void *cipher,
Packit Service 4684c1
	       nettle_cipher_func *encrypt,
Packit Service 4684c1
	       size_t msg_len, const uint8_t *msg)
Packit Service 4684c1
{
Packit Service 4684c1
  union nettle_block16 Y;
Packit Service 4684c1
  /*
Packit Service 4684c1
   * check if we expand the block
Packit Service 4684c1
   */
Packit Service 4684c1
  if (ctx->index < 16)
Packit Service 4684c1
    {
Packit Service 4684c1
      size_t len = MIN(16 - ctx->index, msg_len);
Packit Service 4684c1
      memcpy(&ctx->block.b[ctx->index], msg, len);
Packit Service 4684c1
      msg += len;
Packit Service 4684c1
      msg_len -= len;
Packit Service 4684c1
      ctx->index += len;
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  if (msg_len == 0) {
Packit Service 4684c1
    /* if it is still the last block, we are done */
Packit Service 4684c1
    return;
Packit Service 4684c1
  }
Packit Service 4684c1
Packit Service 4684c1
  /*
Packit Service 4684c1
   * now checksum everything but the last block
Packit Service 4684c1
   */
Packit Service 4684c1
  block16_xor3(&Y, &ctx->X, &ctx->block);
Packit Service 4684c1
  encrypt(cipher, 16, ctx->X.b, Y.b);
Packit Service 4684c1
Packit Service 4684c1
  while (msg_len > 16)
Packit Service 4684c1
    {
Packit Service 4684c1
      block16_xor_bytes (&Y, &ctx->X, msg);
Packit Service 4684c1
      encrypt(cipher, 16, ctx->X.b, Y.b);
Packit Service 4684c1
      msg += 16;
Packit Service 4684c1
      msg_len -= 16;
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  /*
Packit Service 4684c1
   * copy the last block, it will be processed in
Packit Service 4684c1
   * cmac128_digest().
Packit Service 4684c1
   */
Packit Service 4684c1
  memcpy(ctx->block.b, msg, msg_len);
Packit Service 4684c1
  ctx->index = msg_len;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
void
Packit Service 4684c1
cmac128_digest(struct cmac128_ctx *ctx, const struct cmac128_key *key,
Packit Service 4684c1
	       const void *cipher, nettle_cipher_func *encrypt,
Packit Service 4684c1
	       unsigned length, uint8_t *dst)
Packit Service 4684c1
{
Packit Service 4684c1
  union nettle_block16 Y;
Packit Service 4684c1
Packit Service 4684c1
  /* re-use ctx->block for memxor output */
Packit Service 4684c1
  if (ctx->index < 16)
Packit Service 4684c1
    {
Packit Service 4684c1
      ctx->block.b[ctx->index] = 0x80;
Packit Service 4684c1
      memset(ctx->block.b + ctx->index + 1, 0, 16 - 1 - ctx->index);
Packit Service 4684c1
Packit Service 4684c1
      block16_xor (&ctx->block, &key->K2);
Packit Service 4684c1
    }
Packit Service 4684c1
  else
Packit Service 4684c1
    {
Packit Service 4684c1
      block16_xor (&ctx->block, &key->K1);
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  block16_xor3 (&Y, &ctx->block, &ctx->X);
Packit Service 4684c1
Packit Service 4684c1
  assert(length <= 16);
Packit Service 4684c1
  if (length == 16)
Packit Service 4684c1
    {
Packit Service 4684c1
      encrypt(cipher, 16, dst, Y.b);
Packit Service 4684c1
    }
Packit Service 4684c1
  else
Packit Service 4684c1
    {
Packit Service 4684c1
      encrypt(cipher, 16, ctx->block.b, Y.b);
Packit Service 4684c1
      memcpy(dst, ctx->block.b, length);
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  /* reset state for re-use */
Packit Service 4684c1
  cmac128_init(ctx);
Packit Service 4684c1
}