siv-cmac.c 4.71 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
/* siv-cmac.c

   SIV-CMAC, RFC5297

   Copyright (C) 2017 Nikos Mavrogiannopoulos

   This file is part of GNU Nettle.

   GNU Nettle is free software: you can redistribute it and/or
   modify it under the terms of either:

     * the GNU Lesser General Public License as published by the Free
       Software Foundation; either version 3 of the License, or (at your
       option) any later version.

   or

     * the GNU General Public License as published by the Free
       Software Foundation; either version 2 of the License, or (at your
       option) any later version.

   or both in parallel, as here.

   GNU Nettle is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received copies of the GNU General Public License and
   the GNU Lesser General Public License along with this program.  If
   not, see http://www.gnu.org/licenses/.
*/

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <assert.h>
#include <string.h>

#include "aes.h"
#include "siv-cmac.h"
#include "cmac.h"
#include "ctr.h"
#include "memxor.h"
#include "memops.h"
#include "nettle-internal.h"
48
#include "block-internal.h"
49 50 51 52 53

/* This is an implementation of S2V for the AEAD case where
 * vectors if zero, are considered as S empty components */
static void
_siv_s2v (const struct nettle_cipher *nc,
54 55
	  const struct cmac128_key *cmac_key,
	  const void *cmac_cipher,
56 57 58 59 60 61
	  size_t alength, const uint8_t * adata,
	  size_t nlength, const uint8_t * nonce,
	  size_t plength, const uint8_t * pdata, uint8_t * v)
{
  union nettle_block16 D, S, T;
  static const union nettle_block16 const_zero = {.b = 0 };
62
  struct cmac128_ctx cmac_ctx;
63 64
  assert (nlength >= SIV_MIN_NONCE_SIZE);

65 66 67
  cmac128_init(&cmac_ctx);
  cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, 16, const_zero.b);
  cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, D.b);
68

69
  block16_mulx_be (&D, &D);
70 71
  cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, alength, adata);
  cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, S.b);
72
  block16_xor (&D, &S);
73

74
  block16_mulx_be (&D, &D);
75 76
  cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, nlength, nonce);
  cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, S.b);
77
  block16_xor (&D, &S);
78 79 80 81

  /* Sn */
  if (plength >= 16)
    {
82
      cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, plength - 16, pdata);
83 84 85

      pdata += plength - 16;

86
      block16_xor_bytes (&T, &D, pdata);
87 88 89 90 91
    }
  else
    {
      union nettle_block16 pad;

92
      block16_mulx_be (&T, &D);
93 94 95 96 97
      memcpy (pad.b, pdata, plength);
      pad.b[plength] = 0x80;
      if (plength + 1 < 16)
	memset (&pad.b[plength + 1], 0, 16 - plength - 1);

98
      block16_xor (&T, &pad);
99 100
    }

101 102
  cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, 16, T.b);
  cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, v);
103 104 105
}

void
106
siv_cmac_set_key (struct cmac128_key *cmac_key, void *cmac_cipher, void *siv_cipher,
107 108
		  const struct nettle_cipher *nc, const uint8_t * key)
{
109 110 111
  nc->set_encrypt_key (cmac_cipher, key);
  cmac128_set_key (cmac_key, cmac_cipher, nc->encrypt);
  nc->set_encrypt_key (siv_cipher, key + nc->key_size);
112 113 114
}

void
115 116
siv_cmac_encrypt_message (const struct cmac128_key *cmac_key,
			  const void *cmac_cipher,
117
			  const struct nettle_cipher *nc,
118
			  const void *ctr_cipher,
119 120 121 122 123 124 125 126 127 128 129
			  size_t nlength, const uint8_t * nonce,
			  size_t alength, const uint8_t * adata,
			  size_t clength, uint8_t * dst, const uint8_t * src)
{
  union nettle_block16 siv;
  size_t slength;

  assert (clength >= SIV_DIGEST_SIZE);
  slength = clength - SIV_DIGEST_SIZE;

  /* create CTR nonce */
130
  _siv_s2v (nc, cmac_key, cmac_cipher, alength, adata, nlength, nonce, slength, src, siv.b);
131 132 133 134 135

  memcpy (dst, siv.b, SIV_DIGEST_SIZE);
  siv.b[8] &= ~0x80;
  siv.b[12] &= ~0x80;

136
  ctr_crypt (ctr_cipher, nc->encrypt, AES_BLOCK_SIZE, siv.b, slength,
137 138 139 140
	     dst + SIV_DIGEST_SIZE, src);
}

int
141 142
siv_cmac_decrypt_message (const struct cmac128_key *cmac_key,
			  const void *cmac_cipher,
143
			  const struct nettle_cipher *nc,
144
			  const void *ctr_cipher,
145 146 147 148 149 150 151 152 153 154 155
			  size_t nlength, const uint8_t * nonce,
			  size_t alength, const uint8_t * adata,
			  size_t mlength, uint8_t * dst, const uint8_t * src)
{
  union nettle_block16 siv;
  union nettle_block16 ctr;

  memcpy (ctr.b, src, SIV_DIGEST_SIZE);
  ctr.b[8] &= ~0x80;
  ctr.b[12] &= ~0x80;

156
  ctr_crypt (ctr_cipher, nc->encrypt, AES_BLOCK_SIZE, ctr.b,
157 158 159 160
	     mlength, dst, src + SIV_DIGEST_SIZE);

  /* create CTR nonce */
  _siv_s2v (nc,
161
	    cmac_key, cmac_cipher, alength, adata,
162 163 164 165
	    nlength, nonce, mlength, dst, siv.b);

  return memeql_sec (siv.b, src, SIV_DIGEST_SIZE);
}