Commit ffec6637 authored by Niels Möller's avatar Niels Möller

Implemented EAX.

parent 6438331a
2013-10-05 Niels Möller <nisse@lysator.liu.se>
* Makefile.in (nettle_SOURCES): Added eax.c.
(HEADERS): Added eax.h.
* testsuite/Makefile.in (TS_NETTLE_SOURCES): Added eax-test.c.
* testsuite/eax-test.c: New file.
* nettle-internal.c (nettle_eax_aes128): New aead algorithm.
(eax_aes128_set_key, eax_aes128_set_nonce, eax_aes128_update)
(eax_aes128_encrypt, eax_aes128_decrypt, eax_aes128_digest): New
functions.
* eax.c: New file.
* eax.h: New file.
* aes.h: Fixed type in name mangling for new aes functions.
2013-09-28 Niels Möller <nisse@lysator.liu.se>
......
......@@ -82,8 +82,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
cast128.c cast128-meta.c \
blowfish.c \
cbc.c ctr.c gcm.c gcm-aes.c \
des.c \
des3.c des-compat.c \
des.c des3.c des-compat.c eax.c \
hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \
hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \
pbkdf2.c pbkdf2-hmac-sha1.c pbkdf2-hmac-sha256.c \
......@@ -151,7 +150,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
base16.h base64.h buffer.h camellia.h cast128.h \
cbc.h ctr.h \
des.h des-compat.h dsa.h ecc-curve.h ecc.h ecdsa.h \
des.h des-compat.h dsa.h eax.h ecc-curve.h ecc.h ecdsa.h \
gcm.h gosthash94.h hmac.h \
knuth-lfib.h \
macros.h \
......
/* 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
omac_init (uint8_t *state, unsigned t)
{
memset (state, 0, EAX_BLOCK_SIZE - 1);
state[EAX_BLOCK_SIZE - 1] = t;
}
static void
omac_update (uint8_t *state, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t length, const uint8_t *data)
{
for (; length >= EAX_BLOCK_SIZE;
length -= EAX_BLOCK_SIZE, data += EAX_BLOCK_SIZE)
{
f (cipher, EAX_BLOCK_SIZE, state, state);
memxor (state, data, EAX_BLOCK_SIZE);
}
if (length > 0)
{
/* Allowed only for the last call */
f (cipher, EAX_BLOCK_SIZE, state, state);
memxor (state, data, length);
state[length] ^= 0x80;
/* XOR with (P ^ B), since the digest processing
* unconditionally XORs with B */
memxor (state, key->pad_partial, EAX_BLOCK_SIZE);
}
}
static void
omac_final (uint8_t *state, const struct eax_key *key,
void *cipher, nettle_crypt_func *f)
{
memxor (state, key->pad_block, EAX_BLOCK_SIZE);
f (cipher, EAX_BLOCK_SIZE, state, state);
}
/* 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
eax_set_key (struct eax_key *key, void *cipher, nettle_crypt_func *f)
{
static const uint8_t zero_block[EAX_BLOCK_SIZE];
f (cipher, EAX_BLOCK_SIZE, key->pad_block, zero_block);
gf2_double (key->pad_block, key->pad_block);
gf2_double (key->pad_partial, key->pad_block);
memxor (key->pad_partial, key->pad_block, EAX_BLOCK_SIZE);
}
void
eax_set_nonce (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t nonce_length, const uint8_t *nonce)
{
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, eax->omac_nonce, EAX_BLOCK_SIZE);
omac_init (eax->omac_data, 1);
omac_init (eax->omac_message, 2);
}
void
eax_update (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t data_length, const uint8_t *data)
{
omac_update (eax->omac_data, key, cipher, f, data_length, data);
}
void
eax_encrypt (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t length, uint8_t *dst, const uint8_t *src)
{
ctr_crypt (cipher, f, EAX_BLOCK_SIZE, eax->ctr, length, dst, src);
omac_update (eax->omac_message, key, cipher, f, length, dst);
}
void
eax_decrypt (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t length, uint8_t *dst, const uint8_t *src)
{
omac_update (eax->omac_message, key, cipher, f, length, src);
ctr_crypt (cipher, f, EAX_BLOCK_SIZE, eax->ctr, length, dst, src);
}
void
eax_digest (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t length, uint8_t *digest)
{
assert (length > 0);
assert (length <= EAX_BLOCK_SIZE);
omac_final (eax->omac_data, key, cipher, f);
omac_final (eax->omac_message, key, cipher, f);
memxor (eax->omac_nonce, eax->omac_data, length);
memxor3 (digest, eax->omac_nonce, eax->omac_message, length);
}
/* eax.h
*
* 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.
*/
#ifndef NETTLE_EAX_H_INCLUDED
#define NETTLE_EAX_H_INCLUDED
#include "aes.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Name mangling */
#define eax_set_key nettle_eax_set_key
#define eax_set_nonce nettle_eax_set_nonce
#define eax_update nettle_eax_update
#define eax_encrypt nettle_eax_encrypt
#define eax_decrypt nettle_eax_decrypt
#define eax_digest nettle_eax_digest
#define eax_aes_set_key nettle_eax_aes_set_key
#define eax_aes_set_nonce nettle_eax_aes_set_nonce
#define eax_aes_update nettle_eax_aes_update
#define eax_aes_encrypt nettle_eax_aes_encrypt
#define eax_aes_decrypt nettle_eax_aes_decrypt
#define eax_aes_digest nettle_eax_aes_digest
/* Restricted to block ciphers with 128 bit block size. FIXME: Reflect
this in naming? */
#define EAX_BLOCK_SIZE 16
/* FIXME: Ensure nice alignment. See gcm.h, union gcm_block. */
/* Values independent of message and nonce */
struct eax_key
{
uint8_t pad_block[EAX_BLOCK_SIZE];
uint8_t pad_partial[EAX_BLOCK_SIZE];
};
struct eax_ctx
{
uint8_t omac_nonce[EAX_BLOCK_SIZE];
uint8_t omac_data[EAX_BLOCK_SIZE];
uint8_t omac_message[EAX_BLOCK_SIZE];
uint8_t ctr[EAX_BLOCK_SIZE];
};
void
eax_set_key (struct eax_key *key, void *cipher, nettle_crypt_func *f);
void
eax_set_nonce (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t nonce_length, const uint8_t *nonce);
void
eax_update (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t data_length, const uint8_t *data);
void
eax_encrypt (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t length, uint8_t *dst, const uint8_t *src);
void
eax_decrypt (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t length, uint8_t *dst, const uint8_t *src);
void
eax_digest (struct eax_ctx *eax, const struct eax_key *key,
void *cipher, nettle_crypt_func *f,
size_t length, uint8_t *digest);
/* Put the cipher last, to get cipher-independent offsets for the EAX
* state. */
#define EAX_CTX(type) \
{ struct eax_key key; struct eax_ctx eax; type cipher; }
#define EAX_SET_KEY(ctx, set_key, encrypt, length, data) \
do { \
(set_key)(&(ctx)->cipher, (length), (data)); \
if (0) (encrypt) (&(ctx)->cipher, 0, (void *) 0, (void *) 0); \
eax_set_key (&(ctx)->key, &(ctx)->cipher, (nettle_crypt_func *) encrypt); \
} while (0)
#define EAX_SET_NONCE(ctx, encrypt, length, nonce) \
(0 ? (encrypt) (&(ctx)->cipher, 0, (void *) 0, (void *) 0) \
: eax_set_nonce (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_crypt_func *) (encrypt), \
(length), (nonce)))
#define EAX_UPDATE(ctx, encrypt, length, data) \
(0 ? (encrypt) (&(ctx)->cipher, 0, (void *) 0, (void *) 0) \
: eax_update (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_crypt_func *) (encrypt), \
(length), (data)))
#define EAX_ENCRYPT(ctx, encrypt, length, dst, src) \
(0 ? (encrypt) (&(ctx)->cipher, 0, (void *) 0, (void *) 0) \
: eax_encrypt (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_crypt_func *) (encrypt), \
(length), (dst), (src)))
#define EAX_DECRYPT(ctx, encrypt, length, dst, src) \
(0 ? (encrypt) (&(ctx)->cipher, 0, (void *) 0, (void *) 0) \
: eax_decrypt (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_crypt_func *) (encrypt), \
(length), (dst), (src)))
#define EAX_DIGEST(ctx, encrypt, length, digest) \
(0 ? (encrypt) (&(ctx)->cipher, 0, (void *) 0, (void *) 0) \
: eax_digest (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_crypt_func *) (encrypt), \
(length), (digest)))
#ifdef __cplusplus
}
#endif
#endif /* NETTLE_EAX_H_INCLUDED */
......@@ -34,6 +34,7 @@
#include "nettle-internal.h"
#include "blowfish.h"
#include "des.h"
#include "eax.h"
#include "gcm.h"
#include "salsa20.h"
......@@ -122,3 +123,57 @@ const struct nettle_cipher nettle_unified_aes192
const struct nettle_cipher nettle_unified_aes256
= _NETTLE_CIPHER_SEP(aes, AES, 256);
/* eax-aes128 */
void
eax_aes128_set_key(struct eax_aes128_ctx *ctx, size_t length,
const uint8_t *key)
{
assert (length == AES128_KEY_SIZE);
aes128_set_encrypt_key (&ctx->cipher, key);
eax_set_key (&ctx->key, &ctx->cipher,
(nettle_crypt_func *) aes128_encrypt);
/* Can't use EAX_SET_KEY due to aes128_set_encrypt_key /
nettle_crypt_func impedance mismatch */
}
void
eax_aes128_set_nonce(struct eax_aes128_ctx *ctx,
size_t length, const uint8_t *iv)
{
EAX_SET_NONCE(ctx, aes128_encrypt, length, iv);
}
void
eax_aes128_update(struct eax_aes128_ctx *ctx, size_t length, const uint8_t *data)
{
EAX_UPDATE(ctx, aes128_encrypt, length, data);
}
void
eax_aes128_encrypt(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src)
{
EAX_ENCRYPT(ctx, aes128_encrypt, length, dst, src);
}
void
eax_aes128_decrypt(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src)
{
EAX_DECRYPT(ctx, aes128_encrypt, length, dst, src);
}
void
eax_aes128_digest(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *digest)
{
EAX_DIGEST(ctx, aes128_encrypt, length, digest);
}
/* FIXME: Rename to set_nonce, in struct nettle_aead. */
#define eax_aes128_set_iv eax_aes128_set_nonce
const struct nettle_aead
nettle_eax_aes128 = _NETTLE_AEAD_FIX(eax, EAX, aes128, 128);
......@@ -29,6 +29,8 @@
#include "nettle-meta.h"
#include "eax.h"
/* Temporary allocation, for systems that don't support alloca. Note
* that the allocation requests should always be reasonably small, so
* that they can fit on the stack. For non-alloca systems, we use a
......@@ -115,6 +117,19 @@ struct nettle_aead
(nettle_hash_digest_func *) type##_##name##_digest, \
}
#define _NETTLE_AEAD_FIX(type, TYPE, name, key_size) { \
#type "-" #name, \
sizeof(struct type##_##name##_ctx), \
TYPE##_BLOCK_SIZE, \
key_size / 8, \
(nettle_set_key_func *) type##_##name##_set_key, \
(nettle_set_key_func *) type##_##name##_set_iv, \
(nettle_hash_update_func *) type##_##name##_update, \
(nettle_crypt_func *) type##_##name##_encrypt, \
(nettle_crypt_func *) type##_##name##_decrypt, \
(nettle_hash_digest_func *) type##_##name##_digest, \
}
extern const struct nettle_aead nettle_gcm_aes128;
extern const struct nettle_aead nettle_gcm_aes192;
extern const struct nettle_aead nettle_gcm_aes256;
......@@ -131,4 +146,32 @@ extern const struct nettle_aead nettle_gcm_twofish128;
extern const struct nettle_aead nettle_gcm_twofish192;
extern const struct nettle_aead nettle_gcm_twofish256;
/* Tentative interface. */
struct eax_aes128_ctx EAX_CTX(struct aes128_ctx);
void
eax_aes128_set_key(struct eax_aes128_ctx *ctx,
size_t length, const uint8_t *key);
void
eax_aes128_set_nonce(struct eax_aes128_ctx *ctx,
size_t length, const uint8_t *iv);
void
eax_aes128_update(struct eax_aes128_ctx *ctx,
size_t length, const uint8_t *data);
void
eax_aes128_encrypt(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src);
void
eax_aes128_decrypt(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src);
void
eax_aes128_digest(struct eax_aes128_ctx *ctx, size_t length, uint8_t *digest);
extern const struct nettle_aead nettle_eax_aes128;
#endif /* NETTLE_INTERNAL_H_INCLUDED */
......@@ -103,6 +103,9 @@ ctr-test$(EXEEXT): ctr-test.$(OBJEXT)
gcm-test$(EXEEXT): gcm-test.$(OBJEXT)
$(LINK) gcm-test.$(OBJEXT) $(TEST_OBJS) -o gcm-test$(EXEEXT)
eax-test$(EXEEXT): eax-test.$(OBJEXT)
$(LINK) eax-test.$(OBJEXT) $(TEST_OBJS) -o eax-test$(EXEEXT)
hmac-test$(EXEEXT): hmac-test.$(OBJEXT)
$(LINK) hmac-test.$(OBJEXT) $(TEST_OBJS) -o hmac-test$(EXEEXT)
......
......@@ -25,7 +25,8 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
sha3-384-test.c sha3-512-test.c \
serpent-test.c twofish-test.c \
knuth-lfib-test.c \
cbc-test.c ctr-test.c gcm-test.c hmac-test.c umac-test.c \
cbc-test.c ctr-test.c gcm-test.c eax-test.c \
hmac-test.c umac-test.c \
meta-hash-test.c meta-cipher-test.c meta-armor-test.c \
buffer-test.c yarrow-test.c pbkdf2-test.c
......
#include "testutils.h"
#include "nettle-internal.h"
void
test_main(void)
{
/* From the EAX specification,
http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf */
test_aead(&nettle_eax_aes128,
SHEX("233952DEE4D5ED5F9B9C6D6FF80FF478"), /* key */
SHEX("6BFB914FD07EAE6B"), /* auth data */
SHEX(""), /* plaintext */
SHEX(""), /* ciphertext */
SHEX("62EC67F9C3A4A407FCB2A8C49031A8B3"), /* nonce */
SHEX("E037830E8389F27B025A2D6527E79D01")); /* tag */
test_aead(&nettle_eax_aes128,
SHEX("91945D3F4DCBEE0BF45EF52255F095A4"),
SHEX("FA3BFD4806EB53FA"),
SHEX("F7FB"),
SHEX("19DD"),
SHEX("BECAF043B0A23D843194BA972C66DEBD"),
SHEX("5C4C9331049D0BDAB0277408F67967E5"));
test_aead(&nettle_eax_aes128,
SHEX("01F74AD64077F2E704C0F60ADA3DD523"),
SHEX("234A3463C1264AC6"),
SHEX("1A47CB4933"),
SHEX("D851D5BAE0"),
SHEX("70C3DB4F0D26368400A10ED05D2BFF5E"),
SHEX("3A59F238A23E39199DC9266626C40F80"));
test_aead(&nettle_eax_aes128,
SHEX("D07CF6CBB7F313BDDE66B727AFD3C5E8"),
SHEX("33CCE2EABFF5A79D"),
SHEX("481C9E39B1"),
SHEX("632A9D131A"),
SHEX("8408DFFF3C1A2B1292DC199E46B7D617"),
SHEX("D4C168A4225D8E1FF755939974A7BEDE"));
test_aead(&nettle_eax_aes128,
SHEX("35B6D0580005BBC12B0587124557D2C2"),
SHEX("AEB96EAEBE2970E9"),
SHEX("40D0C07DA5E4"),
SHEX("071DFE16C675"),
SHEX("FDB6B06676EEDC5C61D74276E1F8E816"),
SHEX("CB0677E536F73AFE6A14B74EE49844DD"));
test_aead(&nettle_eax_aes128,
SHEX("BD8E6E11475E60B268784C38C62FEB22"),
SHEX("D4482D1CA78DCE0F"),
SHEX("4DE3B35C3FC039245BD1FB7D"),
SHEX("835BB4F15D743E350E728414"),
SHEX("6EAC5C93072D8E8513F750935E46DA1B"),
SHEX("ABB8644FD6CCB86947C5E10590210A4F"));
test_aead(&nettle_eax_aes128,
SHEX("7C77D6E813BED5AC98BAA417477A2E7D"),
SHEX("65D2017990D62528"),
SHEX("8B0A79306C9CE7ED99DAE4F87F8DD61636"),
SHEX("02083E3979DA014812F59F11D52630DA30"),
SHEX("1A8C98DCD73D38393B2BF1569DEEFC19"),
SHEX("137327D10649B0AA6E1C181DB617D7F2"));
test_aead(&nettle_eax_aes128,
SHEX("5FFF20CAFAB119CA2FC73549E20F5B0D"),
SHEX("54B9F04E6A09189A"),
SHEX("1BDA122BCE8A8DBAF1877D962B8592DD2D56"),
SHEX("2EC47B2C4954A489AFC7BA4897EDCDAE8CC3"),
SHEX("DDE59B97D722156D4D9AFF2BC7559826"),
SHEX("3B60450599BD02C96382902AEF7F832A"));
test_aead(&nettle_eax_aes128,
SHEX("A4A4782BCFFD3EC5E7EF6D8C34A56123"),
SHEX("899A175897561D7E"),
SHEX("6CF36720872B8513F6EAB1A8A44438D5EF11"),
SHEX("0DE18FD0FDD91E7AF19F1D8EE8733938B1E8"),
SHEX("B781FCF2F75FA5A8DE97A9CA48E522EC"),
SHEX("E7F6D2231618102FDB7FE55FF1991700"));
test_aead(&nettle_eax_aes128,
SHEX("8395FCF1E95BEBD697BD010BC766AAC3"),
SHEX("126735FCC320D25A"),
SHEX("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7"),
SHEX("CB8920F87A6C75CFF39627B56E3ED197C552D295A7"),
SHEX("22E7ADD93CFC6393C57EC0B3C17D6B44"),
SHEX("CFC46AFC253B4652B1AF3795B124AB6E"));
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment