eax.c 4.8 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
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
/* eax.c
 *
 * EAX mode, see http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
 */

/* nettle, low-level cryptographics library
 *
 * Copyright (C) 2013 Niels Möller
 *
 * The nettle library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * The nettle library 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 Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the nettle library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02111-1301, USA.
 */

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

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

#include "eax.h"

#include "ctr.h"
#include "memxor.h"

static void
39
omac_init (union nettle_block16 *state, unsigned t)
Niels Möller's avatar
Niels Möller committed
40
{
41 42
  memset (state->b, 0, EAX_BLOCK_SIZE - 1);
  state->b[EAX_BLOCK_SIZE - 1] = t;
Niels Möller's avatar
Niels Möller committed
43 44
}

45
/* Almost the same as gcm_gf_add */
Niels Möller's avatar
Niels Möller committed
46
static void
47 48 49 50 51
block16_xor (union nettle_block16 *dst, const union nettle_block16 *src)
{
  dst->w[0] ^= src->w[0];
  dst->w[1] ^= src->w[1];
#if SIZEOF_LONG == 4
52 53
  dst->w[2] ^= src->w[2];
  dst->w[3] ^= src->w[3];
54 55 56 57 58
#endif
}

static void
omac_update (union nettle_block16 *state, const struct eax_key *key,
59
	     const void *cipher, nettle_cipher_func *f,
Niels Möller's avatar
Niels Möller committed
60 61 62 63 64
	     size_t length, const uint8_t *data)
{
  for (; length >= EAX_BLOCK_SIZE;
       length -= EAX_BLOCK_SIZE, data += EAX_BLOCK_SIZE)
    {
65 66
      f (cipher, EAX_BLOCK_SIZE, state->b, state->b);
      memxor (state->b, data, EAX_BLOCK_SIZE);
Niels Möller's avatar
Niels Möller committed
67 68 69 70
    }
  if (length > 0)
    {
      /* Allowed only for the last call */
71 72 73
      f (cipher, EAX_BLOCK_SIZE, state->b, state->b);
      memxor (state->b, data, length);
      state->b[length] ^= 0x80;
Niels Möller's avatar
Niels Möller committed
74 75
      /* XOR with (P ^ B), since the digest processing
       * unconditionally XORs with B */
76
      block16_xor (state, &key->pad_partial);
Niels Möller's avatar
Niels Möller committed
77 78 79 80
    }
}

static void
81
omac_final (union nettle_block16 *state, const struct eax_key *key,
82
	    const void *cipher, nettle_cipher_func *f)
Niels Möller's avatar
Niels Möller committed
83
{
84 85
  block16_xor (state, &key->pad_block);
  f (cipher, EAX_BLOCK_SIZE, state->b, state->b);
Niels Möller's avatar
Niels Möller committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
}

/* Allows r == a */
static void
gf2_double (uint8_t *r, const uint8_t *a)
{
  unsigned high = - (a[0] >> 7);
  unsigned i;
  /* Shift left */
  for (i = 0; i < EAX_BLOCK_SIZE - 1; i++)
    r[i] = (a[i] << 1) + (a[i+1] >> 7);

  /* Wrap around for x^{128} = x^7 + x^2 + x + 1 */
  r[EAX_BLOCK_SIZE - 1] = (a[EAX_BLOCK_SIZE - 1] << 1) ^ (high & 0x87);
}

void
103
eax_set_key (struct eax_key *key, const void *cipher, nettle_cipher_func *f)
Niels Möller's avatar
Niels Möller committed
104
{
105 106 107 108 109
  static const union nettle_block16 zero_block;
  f (cipher, EAX_BLOCK_SIZE, key->pad_block.b, zero_block.b);
  gf2_double (key->pad_block.b, key->pad_block.b);
  gf2_double (key->pad_partial.b, key->pad_block.b);
  block16_xor (&key->pad_partial, &key->pad_block);
Niels Möller's avatar
Niels Möller committed
110 111 112 113
}

void
eax_set_nonce (struct eax_ctx *eax, const struct eax_key *key,
114
	       const void *cipher, nettle_cipher_func *f,
Niels Möller's avatar
Niels Möller committed
115 116
	       size_t nonce_length, const uint8_t *nonce)
{
117 118 119 120
  omac_init (&eax->omac_nonce, 0);
  omac_update (&eax->omac_nonce, key, cipher, f, nonce_length, nonce);
  omac_final (&eax->omac_nonce, key, cipher, f);
  memcpy (eax->ctr.b, eax->omac_nonce.b, EAX_BLOCK_SIZE);
Niels Möller's avatar
Niels Möller committed
121

122 123
  omac_init (&eax->omac_data, 1);
  omac_init (&eax->omac_message, 2);
Niels Möller's avatar
Niels Möller committed
124 125 126 127
}

void
eax_update (struct eax_ctx *eax, const struct eax_key *key,
128
	    const void *cipher, nettle_cipher_func *f,
Niels Möller's avatar
Niels Möller committed
129 130
	    size_t data_length, const uint8_t *data)
{
131
  omac_update (&eax->omac_data, key, cipher, f, data_length, data);
Niels Möller's avatar
Niels Möller committed
132 133 134 135
}

void
eax_encrypt (struct eax_ctx *eax, const struct eax_key *key,
136
	     const void *cipher, nettle_cipher_func *f,
Niels Möller's avatar
Niels Möller committed
137 138
	     size_t length, uint8_t *dst, const uint8_t *src)
{
139 140
  ctr_crypt (cipher, f, EAX_BLOCK_SIZE, eax->ctr.b, length, dst, src);
  omac_update (&eax->omac_message, key, cipher, f, length, dst);
Niels Möller's avatar
Niels Möller committed
141 142 143 144
}

void
eax_decrypt (struct eax_ctx *eax, const struct eax_key *key,
145
	     const void *cipher, nettle_cipher_func *f,
Niels Möller's avatar
Niels Möller committed
146 147
	     size_t length, uint8_t *dst, const uint8_t *src)
{
148 149
  omac_update (&eax->omac_message, key, cipher, f, length, src);
  ctr_crypt (cipher, f, EAX_BLOCK_SIZE, eax->ctr.b, length, dst, src);
Niels Möller's avatar
Niels Möller committed
150 151 152 153
}

void
eax_digest (struct eax_ctx *eax, const struct eax_key *key,
154
	    const void *cipher, nettle_cipher_func *f,
Niels Möller's avatar
Niels Möller committed
155 156 157 158
	    size_t length, uint8_t *digest)
{
  assert (length > 0);
  assert (length <= EAX_BLOCK_SIZE);
159 160
  omac_final (&eax->omac_data, key, cipher, f);
  omac_final (&eax->omac_message, key, cipher, f);
Niels Möller's avatar
Niels Möller committed
161

162 163
  block16_xor (&eax->omac_nonce, &eax->omac_data);
  memxor3 (digest, eax->omac_nonce.b, eax->omac_message.b, length);
Niels Möller's avatar
Niels Möller committed
164
}