Blame lib/nettle/backport/siv-cmac.c

Packit Service 4684c1
/* siv-cmac.c
Packit Service 4684c1
Packit Service 4684c1
   SIV-CMAC, RFC5297
Packit Service 4684c1
Packit Service 4684c1
   Copyright (C) 2017 Nikos Mavrogiannopoulos
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 <string.h>
Packit Service 4684c1
Packit Service 4684c1
#include <nettle/aes.h>
Packit Service 4684c1
#include "siv-cmac.h"
Packit Service 4684c1
#ifdef HAVE_NETTLE_CMAC128_UPDATE
Packit Service 4684c1
#include <nettle/cmac.h>
Packit Service 4684c1
#else
Packit Service 4684c1
#include "cmac.h"
Packit Service 4684c1
#endif
Packit Service 4684c1
#include <nettle/ctr.h>
Packit Service 4684c1
#include <nettle/memxor.h>
Packit Service 4684c1
#include <nettle/memops.h>
Packit Service 4684c1
#include "nettle-alloca.h"
Packit Service 4684c1
#include "block-internal.h"
Packit Service 4684c1
Packit Service 4684c1
/* This is an implementation of S2V for the AEAD case where
Packit Service 4684c1
 * vectors if zero, are considered as S empty components */
Packit Service 4684c1
static void
Packit Service 4684c1
_siv_s2v (const struct nettle_cipher *nc,
Packit Service 4684c1
	  const struct cmac128_key *cmac_key,
Packit Service 4684c1
	  const void *cmac_cipher,
Packit Service 4684c1
	  size_t alength, const uint8_t * adata,
Packit Service 4684c1
	  size_t nlength, const uint8_t * nonce,
Packit Service 4684c1
	  size_t plength, const uint8_t * pdata, uint8_t * v)
Packit Service 4684c1
{
Packit Service 4684c1
  union nettle_block16 D, S, T;
Packit Service 4684c1
  static const union nettle_block16 const_zero = {.b = 0 };
Packit Service 4684c1
  struct cmac128_ctx cmac_ctx;
Packit Service 4684c1
  assert (nlength >= SIV_MIN_NONCE_SIZE);
Packit Service 4684c1
Packit Service 4684c1
  cmac128_init(&cmac_ctx);
Packit Service 4684c1
  cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, 16, const_zero.b);
Packit Service 4684c1
  cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, D.b);
Packit Service 4684c1
Packit Service 4684c1
  block16_mulx_be (&D, &D);
Packit Service 4684c1
  cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, alength, adata);
Packit Service 4684c1
  cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, S.b);
Packit Service 4684c1
  block16_xor (&D, &S);
Packit Service 4684c1
Packit Service 4684c1
  block16_mulx_be (&D, &D);
Packit Service 4684c1
  cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, nlength, nonce);
Packit Service 4684c1
  cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, S.b);
Packit Service 4684c1
  block16_xor (&D, &S);
Packit Service 4684c1
Packit Service 4684c1
  /* Sn */
Packit Service 4684c1
  if (plength >= 16)
Packit Service 4684c1
    {
Packit Service 4684c1
      cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, plength - 16, pdata);
Packit Service 4684c1
Packit Service 4684c1
      pdata += plength - 16;
Packit Service 4684c1
Packit Service 4684c1
      block16_xor_bytes (&T, &D, pdata);
Packit Service 4684c1
    }
Packit Service 4684c1
  else
Packit Service 4684c1
    {
Packit Service 4684c1
      union nettle_block16 pad;
Packit Service 4684c1
Packit Service 4684c1
      block16_mulx_be (&T, &D);
Packit Service 4684c1
      memcpy (pad.b, pdata, plength);
Packit Service 4684c1
      pad.b[plength] = 0x80;
Packit Service 4684c1
      if (plength + 1 < 16)
Packit Service 4684c1
	memset (&pad.b[plength + 1], 0, 16 - plength - 1);
Packit Service 4684c1
Packit Service 4684c1
      block16_xor (&T, &pad;;
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, 16, T.b);
Packit Service 4684c1
  cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, v);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
void
Packit Service 4684c1
siv_cmac_set_key (struct cmac128_key *cmac_key, void *cmac_cipher, void *siv_cipher,
Packit Service 4684c1
		  const struct nettle_cipher *nc, const uint8_t * key)
Packit Service 4684c1
{
Packit Service 4684c1
  nc->set_encrypt_key (cmac_cipher, key);
Packit Service 4684c1
  cmac128_set_key (cmac_key, cmac_cipher, nc->encrypt);
Packit Service 4684c1
  nc->set_encrypt_key (siv_cipher, key + nc->key_size);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
void
Packit Service 4684c1
siv_cmac_encrypt_message (const struct cmac128_key *cmac_key,
Packit Service 4684c1
			  const void *cmac_cipher,
Packit Service 4684c1
			  const struct nettle_cipher *nc,
Packit Service 4684c1
			  const void *ctr_cipher,
Packit Service 4684c1
			  size_t nlength, const uint8_t * nonce,
Packit Service 4684c1
			  size_t alength, const uint8_t * adata,
Packit Service 4684c1
			  size_t clength, uint8_t * dst, const uint8_t * src)
Packit Service 4684c1
{
Packit Service 4684c1
  union nettle_block16 siv;
Packit Service 4684c1
  size_t slength;
Packit Service 4684c1
Packit Service 4684c1
  assert (clength >= SIV_DIGEST_SIZE);
Packit Service 4684c1
  slength = clength - SIV_DIGEST_SIZE;
Packit Service 4684c1
Packit Service 4684c1
  /* create CTR nonce */
Packit Service 4684c1
  _siv_s2v (nc, cmac_key, cmac_cipher, alength, adata, nlength, nonce, slength, src, siv.b);
Packit Service 4684c1
Packit Service 4684c1
  memcpy (dst, siv.b, SIV_DIGEST_SIZE);
Packit Service 4684c1
  siv.b[8] &= ~0x80;
Packit Service 4684c1
  siv.b[12] &= ~0x80;
Packit Service 4684c1
Packit Service 4684c1
  ctr_crypt (ctr_cipher, nc->encrypt, AES_BLOCK_SIZE, siv.b, slength,
Packit Service 4684c1
	     dst + SIV_DIGEST_SIZE, src);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
siv_cmac_decrypt_message (const struct cmac128_key *cmac_key,
Packit Service 4684c1
			  const void *cmac_cipher,
Packit Service 4684c1
			  const struct nettle_cipher *nc,
Packit Service 4684c1
			  const void *ctr_cipher,
Packit Service 4684c1
			  size_t nlength, const uint8_t * nonce,
Packit Service 4684c1
			  size_t alength, const uint8_t * adata,
Packit Service 4684c1
			  size_t mlength, uint8_t * dst, const uint8_t * src)
Packit Service 4684c1
{
Packit Service 4684c1
  union nettle_block16 siv;
Packit Service 4684c1
  union nettle_block16 ctr;
Packit Service 4684c1
Packit Service 4684c1
  memcpy (ctr.b, src, SIV_DIGEST_SIZE);
Packit Service 4684c1
  ctr.b[8] &= ~0x80;
Packit Service 4684c1
  ctr.b[12] &= ~0x80;
Packit Service 4684c1
Packit Service 4684c1
  ctr_crypt (ctr_cipher, nc->encrypt, AES_BLOCK_SIZE, ctr.b,
Packit Service 4684c1
	     mlength, dst, src + SIV_DIGEST_SIZE);
Packit Service 4684c1
Packit Service 4684c1
  /* create CTR nonce */
Packit Service 4684c1
  _siv_s2v (nc,
Packit Service 4684c1
	    cmac_key, cmac_cipher, alength, adata,
Packit Service 4684c1
	    nlength, nonce, mlength, dst, siv.b);
Packit Service 4684c1
Packit Service 4684c1
  return memeql_sec (siv.b, src, SIV_DIGEST_SIZE);
Packit Service 4684c1
}