summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2014-02-14 15:31:21 +0100
committerNiels Möller <nisse@lysator.liu.se>2014-02-14 15:31:21 +0100
commitd76caf61011c5fbe553ea0f024d9f43edc6f14de (patch)
treeb2526a25afb9d1d4c5cbee00c07abdddc8e1430c
parentc6ce389e5fa32c848c06e96bff81c55d626f9118 (diff)
downloadnettle-d76caf61011c5fbe553ea0f024d9f43edc6f14de.tar.gz
First sketch of aead convenience functions.
-rw-r--r--ChangeLog10
-rw-r--r--Makefile.in6
-rw-r--r--aead-decrypt-msg.c73
-rw-r--r--aead-decrypt.c180
-rw-r--r--aead-encrypt-msg.c53
-rw-r--r--aead-encrypt.c167
6 files changed, 487 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index fd75fe8c..3be3a9ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2014-02-14 Niels Möller <nisse@lysator.liu.se>
+
+ * aead.h: New file.
+ * aead-encrypt.c: New file.
+ * aead-decrypt.c: New file.
+ * aead-encrypt-msg.c: New file.
+ * aead-decrypt-msg.c: New file.
+ * Makefile.in (nettle_SOURCES): Added new source files.
+ (HEADERS): Added aead.h.
+
2014-02-13 Niels Möller <nisse@lysator.liu.se>
* Makefile.in (nettle_SOURCES): Added eax-aes128.c
diff --git a/Makefile.in b/Makefile.in
index 18090053..10ae274b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -62,7 +62,9 @@ dvi installcheck uninstallcheck:
all-here: $(TARGETS) $(DOCTARGETS)
-nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
+nettle_SOURCES = aead-decrypt.c aead-decrypt-msg.c \
+ aead-encrypt.c aead-encrypt-msg.c \
+ aes-decrypt-internal.c aes-decrypt.c \
aes-encrypt-internal.c aes-encrypt.c aes-encrypt-table.c \
aes-invert-internal.c aes-set-key-internal.c \
aes-set-encrypt-key.c aes-set-decrypt-key.c \
@@ -164,7 +166,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
ecc-ecdsa-sign.c ecdsa-sign.c \
ecc-ecdsa-verify.c ecdsa-verify.c ecdsa-keygen.c
-HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
+HEADERS = aead.h aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
base16.h base64.h buffer.h camellia.h cast128.h \
cbc.h chacha.h chacha-poly1305.h ctr.h \
des.h des-compat.h dsa.h eax.h ecc-curve.h ecc.h ecdsa.h \
diff --git a/aead-decrypt-msg.c b/aead-decrypt-msg.c
new file mode 100644
index 00000000..026aaeff
--- /dev/null
+++ b/aead-decrypt-msg.c
@@ -0,0 +1,73 @@
+/* aead-decrypt-msg.c
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 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 <string.h>
+
+#include "aead.h"
+
+#include "nettle-internal.h"
+#include "nettle-meta.h"
+
+size_t
+aead_decrypt_msg_size(const struct nettle_aead *aead, size_t size)
+{
+ if (size < aead->digest_size)
+ /* Invalid message */
+ return 0;
+ else
+ return size - aead->digest_size;
+}
+
+int
+aead_decrypt_msg (const struct nettle_aead *aead,
+ void *ctx, const uint8_t *nonce,
+ size_t ad_size, const uint8_t *ad,
+ size_t gibberish_size,
+ uint8_t *plaintext, const uint8_t *gibberish)
+{
+ TMP_DECL (digest, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+ size_t plaintext_size;
+
+ TMP_ALLOC (digest, aead->digest_size);
+ plaintext_size = gibberish_size - aead->digest_size;
+
+ /* Allow NULL nonce, for the case that the caller already has done
+ that. E.g., if the application uses a nonce size different from
+ aead->nonce_size. */
+ if (nonce)
+ aead->set_nonce (ctx, nonce);
+
+ if (gibberish_size < aead->digest_size)
+ /* Invalid message */
+ return 0;
+
+ aead->update (ctx, ad_size, ad);
+ aead->decrypt (ctx, plaintext_size, plaintext, gibberish);
+ aead->digest (ctx, aead->digest_size, digest);
+ return memcmp (gibberish + plaintext_size,
+ digest, aead->digest_size) == 0;
+}
diff --git a/aead-decrypt.c b/aead-decrypt.c
new file mode 100644
index 00000000..a024d7c2
--- /dev/null
+++ b/aead-decrypt.c
@@ -0,0 +1,180 @@
+/* aead-decrypt.c
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 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 "aead.h"
+
+#include "buffer.h"
+#include "nettle-internal.h"
+#include "nettle-meta.h"
+
+#define GET_BUF(aead, ctx) \
+ ((uint8_t *)((char *) (ctx) + (aead)->context_size))
+
+/* Needs a buffer of digest_size + block_size - 1 bytes. Let this be
+ followed by an uint8_t buffer index; using a small type avoids
+ alignment issues. */
+
+size_t
+aead_decrypt_ctx_size (const struct nettle_aead *aead)
+{
+ return aead->context_size + aead->block_size + aead->digest_size;
+}
+
+void
+aead_decrypt_init (const struct nettle_aead *aead,
+ void *ctx, const uint8_t *nonce)
+{
+ /* The case of unbuffered underlying method not supported. Niether
+ is block sizes larger than 256 bytes. */
+ assert (aead->block_size > 0);
+ assert (aead->block_size <= 256);
+
+ /* Allow NULL nonce, for the case that the caller already has done
+ that. E.g., if the application uses a nonce size different from
+ aead->nonce_size. */
+ if (nonce)
+ aead->set_nonce (ctx, nonce);
+
+ /* Initialize buffer index. */
+ GET_BUF (aead, ctx)[aead->block_size + aead->digest_size - 1] = 0;
+}
+
+size_t
+aead_decrypt (const struct nettle_aead *aead,
+ void *ctx, struct nettle_buffer *buffer,
+ size_t size, const uint8_t *gibberish)
+{
+ uint8_t *buf;
+ uint8_t *dst;
+ uint8_t left_over;
+ size_t done;
+
+ buf = GET_BUF (aead, ctx);
+ left_over = buf[aead->block_size + aead->digest_size-1];
+ assert (left_over < aead->block_size + aead->digest_size);
+
+ done = 0;
+ /* First try to process buffered data, one block at a time. */
+ while (left_over > 0
+ && left_over + size >= aead->block_size + aead->digest_size)
+ {
+ dst = nettle_buffer_space (buffer, aead->block_size);
+ if (!dst)
+ return done;
+
+ if (left_over < aead->block_size)
+ {
+ unsigned part = aead->block_size - left_over;
+
+ memcpy (buf + left_over, gibberish, part);
+ aead->decrypt (ctx, aead->block_size, dst, buf);
+ done += part;
+ size -= part;
+
+ left_over = 0;
+ }
+ else
+ {
+ aead->decrypt (ctx, aead->block_size, dst, buf);
+ left_over -= aead->block_size;
+ memmove (buf, buf + aead->block_size, left_over);
+ }
+ }
+
+ if (left_over + size < aead->block_size + aead->digest_size)
+ {
+ /* Buffer new data */
+ assert (left_over + size < aead->block_size + aead->digest_size);
+ memcpy (buf + left_over, gibberish, size);
+ buf[aead->block_size + aead->digest_size-1] = left_over + size;
+ return done + size;
+ }
+ assert (left_over == 0);
+ assert (size >= aead->digest_size);
+
+ size -= aead->digest_size;
+ left_over = size % aead->block_size;
+ size -= left_over;
+
+ dst = nettle_buffer_space (buffer, size);
+ if (!dst)
+ {
+ /* Process as many blocks as possible, without growing the
+ buffer. */
+ size_t avail = (buffer->alloc - buffer->size);
+ avail -= (avail % aead->block_size);
+ assert (avail < size);
+ size = avail;
+ left_over = 0;
+ dst = nettle_buffer_space (buffer, size);
+ assert (dst != NULL);
+ }
+ aead->encrypt (ctx, size, dst, gibberish);
+ done += size;
+
+ /* Buffer left over + potential digest */
+ left_over += aead->digest_size;
+ memcpy (buf, gibberish + size, left_over);
+ buf[aead->block_size + aead->digest_size - 1] = left_over;
+
+ done += left_over;
+ return done;
+}
+
+size_t
+aead_decrypt_final_size (const struct nettle_aead *aead)
+{
+ return aead->block_size - 1;
+}
+
+int
+aead_decrypt_final (const struct nettle_aead *aead,
+ void *ctx, struct nettle_buffer *buffer)
+{
+ TMP_DECL (digest, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+ const uint8_t *buf = GET_BUF (aead, ctx);
+ uint8_t *dst;
+ unsigned left_over = buf[aead->block_size - 1];
+ assert (left_over < aead->block_size + aead->digest_size);
+
+ if (left_over < aead->digest_size)
+ /* Too short */
+ return 0;
+ left_over -= aead->digest_size;
+ dst = nettle_buffer_space (buffer, left_over);
+ if (!dst)
+ return 0;
+
+ aead->encrypt (ctx, left_over, dst, buf);
+
+ TMP_ALLOC (digest, aead->digest_size);
+ aead->digest (ctx, aead->digest_size, digest);
+ return memcmp (buf + left_over, digest, aead->digest_size) == 0;
+}
diff --git a/aead-encrypt-msg.c b/aead-encrypt-msg.c
new file mode 100644
index 00000000..450548f4
--- /dev/null
+++ b/aead-encrypt-msg.c
@@ -0,0 +1,53 @@
+/* aead-encrypt-msg.c
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 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 "aead.h"
+
+#include "nettle-meta.h"
+
+size_t
+aead_encrypt_msg_size(const struct nettle_aead *aead, size_t size)
+{
+ return size + aead->digest_size;
+}
+
+void
+aead_encrypt_msg (const struct nettle_aead *aead,
+ void *ctx, const uint8_t *nonce,
+ size_t ad_size, const uint8_t *ad,
+ size_t plaintext_size,
+ uint8_t *gibberish, const uint8_t *plaintext)
+{
+ /* Allow NULL nonce, for the case that the caller already has done
+ that. E.g., if the application uses a nonce size different from
+ aead->nonce_size. */
+ if (nonce)
+ aead->set_nonce (ctx, nonce);
+ aead->update (ctx, ad_size, ad);
+ aead->encrypt (ctx, plaintext_size, gibberish, plaintext);
+ aead->digest (ctx, aead->digest_size, gibberish + plaintext_size);
+}
diff --git a/aead-encrypt.c b/aead-encrypt.c
new file mode 100644
index 00000000..1eaaa98e
--- /dev/null
+++ b/aead-encrypt.c
@@ -0,0 +1,167 @@
+/* aead-encrypt.c
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2014 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 "aead.h"
+
+#include "nettle-meta.h"
+#include "buffer.h"
+
+/* Needs a buffer of block_size - 1 bytes. Let this be followed by an
+ uint8_t buffer index; using a small type avoids alignment
+ issues. */
+#define GET_BUF(aead, ctx) \
+ ((uint8_t *)((char *) (ctx) + (aead)->context_size))
+
+size_t
+aead_encrypt_ctx_size (const struct nettle_aead *aead)
+{
+ return aead->context_size + aead->block_size;
+}
+
+void
+aead_encrypt_init (const struct nettle_aead *aead,
+ void *ctx, const uint8_t *nonce)
+{
+ /* The case of unbuffered underlying method not supported. Niether
+ is block sizes larger than 256 bytes. */
+ assert (aead->block_size > 0);
+ assert (aead->block_size <= 256);
+
+ /* Allow NULL nonce, for the case that the caller already has done
+ that. E.g., if the application uses a nonce size different from
+ aead->nonce_size. */
+ if (nonce)
+ aead->set_nonce (ctx, nonce);
+
+ /* Initialize buffer index. */
+ GET_BUF (aead, ctx)[aead->block_size-1] = 0;
+}
+
+size_t
+aead_encrypt (const struct nettle_aead *aead,
+ void *ctx, struct nettle_buffer *buffer,
+ size_t size, const uint8_t *plaintext)
+{
+ uint8_t *buf;
+ uint8_t *dst;
+ uint8_t left_over;
+ size_t done;
+
+ buf = GET_BUF (aead, ctx);
+ left_over = buf[aead->block_size-1];
+ assert (left_over < aead->block_size);
+
+ if (left_over > 0)
+ {
+ /* Try to fill buffer */
+ if (size >= aead->block_size - left_over)
+ {
+ dst = nettle_buffer_space (buffer, aead->block_size);
+ if (!dst)
+ /* Would could copy some more data into our buffer, but we
+ really can't make any progress until the caller
+ provides a larger output buffer. */
+ return 0;
+
+ done = aead->block_size - left_over;
+ memcpy (buf + left_over, plaintext, done);
+ aead->encrypt (ctx, aead->block_size, dst, buf);
+ size -= done;
+ plaintext += done;
+ }
+ else
+ {
+ memcpy (buf + left_over, plaintext, size);
+ left_over += size;
+ assert (left_over < aead->block_size);
+ buf[aead->block_size-1] = left_over;
+ return size;
+ }
+ }
+ else
+ done = 0;
+
+ left_over = size % aead->block_size;
+
+ dst = nettle_buffer_space (buffer, size - left_over);
+ if (dst)
+ {
+ /* Buffer rest of input. */
+ size -= left_over;
+ memcpy (buf, plaintext + size, left_over);
+ done += left_over;
+ }
+ else
+ {
+ /* Process as many blocks as possible, without growing the buffer. */
+ size_t avail = (buffer->alloc - buffer->size);
+ avail -= (avail % aead->block_size);
+ assert (avail < size);
+ size = avail;
+ left_over = 0;
+ dst = nettle_buffer_space (buffer, size);
+ assert (dst != NULL);
+ }
+ aead->encrypt (ctx, size, dst, plaintext);
+ done += size;
+
+ buf[aead->block_size-1] = left_over;
+
+ return done;
+}
+
+size_t
+aead_encrypt_final_size (const struct nettle_aead *aead)
+{
+ return aead->digest_size + aead->block_size - 1;
+}
+
+int
+aead_encrypt_final (const struct nettle_aead *aead,
+ void *ctx, struct nettle_buffer *buffer)
+{
+ uint8_t *buf = GET_BUF (aead, ctx);
+ uint8_t *dst;
+ uint8_t left_over = buf[aead->block_size - 1];
+ assert (left_over < aead->block_size);
+ if (left_over)
+ {
+ dst = nettle_buffer_space (buffer, left_over);
+ if (!dst)
+ return 0;
+ aead->encrypt (ctx, left_over, dst, buf);
+ buf[aead->block_size - 1] = 0;
+ }
+ dst = nettle_buffer_space (buffer, aead->digest_size);
+ if (!dst)
+ return 0;
+ aead->digest (ctx, aead->digest_size, dst);
+ return 1;
+}