]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
First sketch of aead convenience functions.
authorNiels Möller <nisse@lysator.liu.se>
Fri, 14 Feb 2014 14:31:21 +0000 (15:31 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Fri, 14 Feb 2014 14:31:21 +0000 (15:31 +0100)
ChangeLog
Makefile.in
aead-decrypt-msg.c [new file with mode: 0644]
aead-decrypt.c [new file with mode: 0644]
aead-encrypt-msg.c [new file with mode: 0644]
aead-encrypt.c [new file with mode: 0644]

index fd75fe8caa5e738676d6e97885a280682de13b87..3be3a9ed194ad2eb791e89a24f01641b22add224 100644 (file)
--- 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
index 180900539afac296656a9d7c3af8e07ee00668e6..10ae274b8494157a635aa01d7cdc8a4147b74403 100644 (file)
@@ -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 (file)
index 0000000..026aaef
--- /dev/null
@@ -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 (file)
index 0000000..a024d7c
--- /dev/null
@@ -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 (file)
index 0000000..450548f
--- /dev/null
@@ -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 (file)
index 0000000..1eaaa98
--- /dev/null
@@ -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;
+}