diff --git a/Makefile.in b/Makefile.in
index afdc689d1dd778aa182243ef8cb676c1140c8e44..d328a639fb7a6640bceef6c439ebff36eecdc394 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -65,6 +65,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
 		 md2.c md2-meta.c md4.c md4-meta.c \
 		 md5.c md5-compress.c md5-compat.c md5-meta.c \
 		 sha1.c sha1-compress.c sha1-meta.c sha256.c sha256-meta.c \
+		 sha512.c sha512-meta.c \
 		 serpent.c serpent-meta.c \
 		 twofish.c twofish-meta.c \
 		 yarrow256.c yarrow_key_event.c \
diff --git a/nettle-meta.h b/nettle-meta.h
index 15c32dc16eca9ef6c8de474d8c3c3e27ae809a48..c5d664eb931f37223f90680843c4da852ae28193 100644
--- a/nettle-meta.h
+++ b/nettle-meta.h
@@ -138,6 +138,7 @@ extern const struct nettle_hash nettle_md4;
 extern const struct nettle_hash nettle_md5;
 extern const struct nettle_hash nettle_sha1;
 extern const struct nettle_hash nettle_sha256;
+extern const struct nettle_hash nettle_sha512;
 
 struct nettle_armor
 {
diff --git a/sha.h b/sha.h
index 22725d14756831eeee0ca54ae770e4c4e59c98e0..5040e705f127892aa0a80f147f96b4d2ac8fa54a 100644
--- a/sha.h
+++ b/sha.h
@@ -39,6 +39,9 @@ extern "C" {
 #define sha256_init nettle_sha256_init
 #define sha256_update nettle_sha256_update
 #define sha256_digest nettle_sha256_digest
+#define sha512_init nettle_sha512_init
+#define sha512_update nettle_sha512_update
+#define sha512_digest nettle_sha512_digest
 
 /* SHA1 */
 
@@ -103,6 +106,35 @@ sha256_digest(struct sha256_ctx *ctx,
 	      unsigned length,
 	      uint8_t *digest);
 
+/* SHA512 */
+
+#define SHA512_DIGEST_SIZE 64
+#define SHA512_DATA_SIZE 128
+
+/* Digest is kept internally as 8 64-bit words. */
+#define _SHA512_DIGEST_LENGTH 8
+
+struct sha512_ctx
+{
+  uint64_t state[_SHA512_DIGEST_LENGTH];    /* State variables */
+  uint64_t count_low, count_high;           /* 128-bit block count */
+  uint8_t block[SHA512_DATA_SIZE];          /* SHA512 data buffer */
+  unsigned int index;                       /* index into buffer */
+};
+
+void
+sha512_init(struct sha512_ctx *ctx);
+
+void
+sha512_update(struct sha512_ctx *ctx,
+	      unsigned length,
+	      const uint8_t *data);
+
+void
+sha512_digest(struct sha512_ctx *ctx,
+	      unsigned length,
+	      uint8_t *digest);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sha512-meta.c b/sha512-meta.c
new file mode 100644
index 0000000000000000000000000000000000000000..d9ba03e7fb2b0b30933ed86ebc2733cc52d610d4
--- /dev/null
+++ b/sha512-meta.c
@@ -0,0 +1,32 @@
+/* sha512-meta.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2002, 2010 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., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "nettle-meta.h"
+
+#include "sha.h"
+
+const struct nettle_hash nettle_sha512
+= _NETTLE_HASH(sha512, SHA512);
diff --git a/sha512.c b/sha512.c
new file mode 100644
index 0000000000000000000000000000000000000000..aba7317eee91be7a74f215926902c1a902048d66
--- /dev/null
+++ b/sha512.c
@@ -0,0 +1,413 @@
+/* sha512.c
+ *
+ * The sha512 hash function FIXME: Add the SHA384 variant.
+ *
+ * See http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2001, 2010 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., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/* Modelled after the sha1.c code by Peter Gutmann. */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sha.h"
+
+#include "macros.h"
+
+/* A block, treated as a sequence of 64-bit words. */
+#define SHA512_DATA_LENGTH 16
+
+#define ROTR(n,x) ((x)>>(n) | ((x)<<(64-(n))))
+#define SHR(n,x) ((x)>>(n))
+
+/* The SHA512 functions. The Choice function is the same as the SHA1
+   function f1, and the majority function is the same as the SHA1 f3
+   function, and the same as for SHA256. */
+
+#define Choice(x,y,z)   ( (z) ^ ( (x) & ( (y) ^ (z) ) ) ) 
+#define Majority(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
+
+#define S0(x) (ROTR(28,(x)) ^ ROTR(34,(x)) ^ ROTR(39,(x))) 
+#define S1(x) (ROTR(14,(x)) ^ ROTR(18,(x)) ^ ROTR(41,(x)))
+
+#define s0(x) (ROTR(1,(x)) ^ ROTR(8,(x)) ^ SHR(7,(x)))
+#define s1(x) (ROTR(19,(x)) ^ ROTR(61,(x)) ^ SHR(6,(x)))
+
+/* Generated by the gp script
+
+     {
+       print("obase=16");
+       for (i = 1,80,
+         root = prime(i)^(1/3);
+         fraction = root - floor(root);
+         print(floor(2^64 * fraction));
+       );
+       quit();
+     }
+
+   piped through
+
+     |grep -v '^[' | bc \
+       |awk '{printf("0x%sULL,%s", $1, NR%3 == 0 ? "\n" : "");}'
+
+   to convert it to hex.
+*/
+
+static const uint64_t
+K[80] =
+{
+  0x428A2F98D728AE22ULL,0x7137449123EF65CDULL,
+  0xB5C0FBCFEC4D3B2FULL,0xE9B5DBA58189DBBCULL,
+  0x3956C25BF348B538ULL,0x59F111F1B605D019ULL,
+  0x923F82A4AF194F9BULL,0xAB1C5ED5DA6D8118ULL,
+  0xD807AA98A3030242ULL,0x12835B0145706FBEULL,
+  0x243185BE4EE4B28CULL,0x550C7DC3D5FFB4E2ULL,
+  0x72BE5D74F27B896FULL,0x80DEB1FE3B1696B1ULL,
+  0x9BDC06A725C71235ULL,0xC19BF174CF692694ULL,
+  0xE49B69C19EF14AD2ULL,0xEFBE4786384F25E3ULL,
+  0xFC19DC68B8CD5B5ULL,0x240CA1CC77AC9C65ULL,
+  0x2DE92C6F592B0275ULL,0x4A7484AA6EA6E483ULL,
+  0x5CB0A9DCBD41FBD4ULL,0x76F988DA831153B5ULL,
+  0x983E5152EE66DFABULL,0xA831C66D2DB43210ULL,
+  0xB00327C898FB213FULL,0xBF597FC7BEEF0EE4ULL,
+  0xC6E00BF33DA88FC2ULL,0xD5A79147930AA725ULL,
+  0x6CA6351E003826FULL,0x142929670A0E6E70ULL,
+  0x27B70A8546D22FFCULL,0x2E1B21385C26C926ULL,
+  0x4D2C6DFC5AC42AEDULL,0x53380D139D95B3DFULL,
+  0x650A73548BAF63DEULL,0x766A0ABB3C77B2A8ULL,
+  0x81C2C92E47EDAEE6ULL,0x92722C851482353BULL,
+  0xA2BFE8A14CF10364ULL,0xA81A664BBC423001ULL,
+  0xC24B8B70D0F89791ULL,0xC76C51A30654BE30ULL,
+  0xD192E819D6EF5218ULL,0xD69906245565A910ULL,
+  0xF40E35855771202AULL,0x106AA07032BBD1B8ULL,
+  0x19A4C116B8D2D0C8ULL,0x1E376C085141AB53ULL,
+  0x2748774CDF8EEB99ULL,0x34B0BCB5E19B48A8ULL,
+  0x391C0CB3C5C95A63ULL,0x4ED8AA4AE3418ACBULL,
+  0x5B9CCA4F7763E373ULL,0x682E6FF3D6B2B8A3ULL,
+  0x748F82EE5DEFB2FCULL,0x78A5636F43172F60ULL,
+  0x84C87814A1F0AB72ULL,0x8CC702081A6439ECULL,
+  0x90BEFFFA23631E28ULL,0xA4506CEBDE82BDE9ULL,
+  0xBEF9A3F7B2C67915ULL,0xC67178F2E372532BULL,
+  0xCA273ECEEA26619CULL,0xD186B8C721C0C207ULL,
+  0xEADA7DD6CDE0EB1EULL,0xF57D4F7FEE6ED178ULL,
+  0x6F067AA72176FBAULL,0xA637DC5A2C898A6ULL,
+  0x113F9804BEF90DAEULL,0x1B710B35131C471BULL,
+  0x28DB77F523047D84ULL,0x32CAAB7B40C72493ULL,
+  0x3C9EBE0A15C9BEBCULL,0x431D67C49C100D4CULL,
+  0x4CC5D4BECB3E42B6ULL,0x597F299CFC657E2AULL,
+  0x5FCB6FAB3AD6FAECULL,0x6C44198C4A475817ULL,
+};
+
+/* The initial expanding function. The hash function is defined over
+   an 64-word expanded input array W, where the first 16 are copies of
+   the input data, and the remaining 64 are defined by
+
+        W[ t ] = s1(W[t-2]) + W[t-7] + s0(W[i-15]) + W[i-16]
+
+   This implementation generates these values on the fly in a circular
+   buffer.
+*/
+
+#define EXPAND(W,i) \
+( W[(i) & 15 ] += (s1(W[((i)-2) & 15]) + W[((i)-7) & 15] + s0(W[((i)-15) & 15])) )
+
+/* The prototype SHA sub-round.  The fundamental sub-round is:
+
+        T1 = h + S1(e) + Choice(e,f,g) + K[t] + W[t]
+	T2 = S0(a) + Majority(a,b,c)
+	a' = T1+T2
+	b' = a
+	c' = b
+	d' = c
+	e' = d + T1
+	f' = e
+	g' = f
+	h' = g
+
+   but this is implemented by unrolling the loop 8 times and renaming
+   the variables
+   ( h, a, b, c, d, e, f, g ) = ( a, b, c, d, e, f, g, h ) each
+   iteration. This code is then replicated 8, using the next 8 values
+   from the W[] array each time */
+
+/* It's crucial that DATA is only used once, as that argument will
+ * have side effects. */
+#define ROUND(a,b,c,d,e,f,g,h,k,data) do {		\
+  uint64_t T = h + S1(e) + Choice(e,f,g) + k + data;	\
+  d += T;						\
+  h = T + S0(a) + Majority(a,b,c);			\
+} while (0)
+
+void
+sha512_init(struct sha512_ctx *ctx)
+{
+  /* Initial values, generated by the gp script
+       {
+         for (i = 1,8,
+	   root = prime(i)^(1/2);
+	   fraction = root - floor(root);
+	   print(floor(2^64 * fraction));
+	 );
+       }
+. */
+  static const uint64_t H0[_SHA512_DIGEST_LENGTH] =
+  {
+    0x6A09E667F3BCC908ULL,0xBB67AE8584CAA73BULL,
+    0x3C6EF372FE94F82BULL,0xA54FF53A5F1D36F1ULL,
+    0x510E527FADE682D1ULL,0x9B05688C2B3E6C1FULL,
+    0x1F83D9ABFB41BD6BULL,0x5BE0CD19137E2179ULL,
+  };
+
+  memcpy(ctx->state, H0, sizeof(H0));
+
+  /* Initialize bit count */
+  ctx->count_low = ctx->count_high = 0;
+  
+  /* Initialize buffer */
+  ctx->index = 0;
+}
+
+/* Perform the SHA transformation. Note that this function destroys
+   the data area */
+
+static void
+sha512_transform(uint64_t *state, uint64_t *data)
+{
+  /* FIXME: XXX Just copied from sha256. */
+  uint64_t A, B, C, D, E, F, G, H;     /* Local vars */
+  unsigned i;
+  const uint64_t *k;
+  uint64_t *d;
+  
+  /* Set up first buffer and local data buffer */
+  A = state[0];
+  B = state[1];
+  C = state[2];
+  D = state[3];
+  E = state[4];
+  F = state[5];
+  G = state[6];
+  H = state[7];
+  
+  /* Heavy mangling */
+  /* First 16 subrounds that act on the original data */
+
+  for (i = 0, k = K, d = data; i<16; i+=8, k += 8, d+= 8)
+    {
+      ROUND(A, B, C, D, E, F, G, H, k[0], d[0]);
+      ROUND(H, A, B, C, D, E, F, G, k[1], d[1]);
+      ROUND(G, H, A, B, C, D, E, F, k[2], d[2]);
+      ROUND(F, G, H, A, B, C, D, E, k[3], d[3]);
+      ROUND(E, F, G, H, A, B, C, D, k[4], d[4]);
+      ROUND(D, E, F, G, H, A, B, C, k[5], d[5]);
+      ROUND(C, D, E, F, G, H, A, B, k[6], d[6]);
+      ROUND(B, C, D, E, F, G, H, A, k[7], d[7]);
+    }
+  
+  for (; i<80; i += 16, k+= 16)
+    {
+      ROUND(A, B, C, D, E, F, G, H, k[ 0], EXPAND(data,  0));
+      ROUND(H, A, B, C, D, E, F, G, k[ 1], EXPAND(data,  1));
+      ROUND(G, H, A, B, C, D, E, F, k[ 2], EXPAND(data,  2));
+      ROUND(F, G, H, A, B, C, D, E, k[ 3], EXPAND(data,  3));
+      ROUND(E, F, G, H, A, B, C, D, k[ 4], EXPAND(data,  4));
+      ROUND(D, E, F, G, H, A, B, C, k[ 5], EXPAND(data,  5));
+      ROUND(C, D, E, F, G, H, A, B, k[ 6], EXPAND(data,  6));
+      ROUND(B, C, D, E, F, G, H, A, k[ 7], EXPAND(data,  7));
+      ROUND(A, B, C, D, E, F, G, H, k[ 8], EXPAND(data,  8));
+      ROUND(H, A, B, C, D, E, F, G, k[ 9], EXPAND(data,  9));
+      ROUND(G, H, A, B, C, D, E, F, k[10], EXPAND(data, 10));
+      ROUND(F, G, H, A, B, C, D, E, k[11], EXPAND(data, 11));
+      ROUND(E, F, G, H, A, B, C, D, k[12], EXPAND(data, 12));
+      ROUND(D, E, F, G, H, A, B, C, k[13], EXPAND(data, 13));
+      ROUND(C, D, E, F, G, H, A, B, k[14], EXPAND(data, 14));
+      ROUND(B, C, D, E, F, G, H, A, k[15], EXPAND(data, 15));
+    }
+
+  /* Update state */
+  state[0] += A;
+  state[1] += B;
+  state[2] += C;
+  state[3] += D;
+  state[4] += E;
+  state[5] += F;
+  state[6] += G;
+  state[7] += H;
+}
+
+static void
+sha512_block(struct sha512_ctx *ctx, const uint8_t *block)
+{
+  uint64_t data[SHA512_DATA_LENGTH];
+  int i;
+
+  /* Update block count */
+  if (!++ctx->count_low)
+    ++ctx->count_high;
+
+  /* Endian independent conversion */
+  for (i = 0; i<SHA512_DATA_LENGTH; i++, block += 8)
+    data[i] = READ_UINT64(block);
+
+  sha512_transform(ctx->state, data);
+}
+
+void
+sha512_update(struct sha512_ctx *ctx,
+	      unsigned length, const uint8_t *buffer)
+{
+  if (ctx->index)
+    { /* Try to fill partial block */
+      unsigned left = SHA512_DATA_SIZE - ctx->index;
+      if (length < left)
+	{
+	  memcpy(ctx->block + ctx->index, buffer, length);
+	  ctx->index += length;
+	  return; /* Finished */
+	}
+      else
+	{
+	  memcpy(ctx->block + ctx->index, buffer, left);
+	  sha512_block(ctx, ctx->block);
+	  buffer += left;
+	  length -= left;
+	}
+    }
+  while (length >= SHA512_DATA_SIZE)
+    {
+      sha512_block(ctx, buffer);
+      buffer += SHA512_DATA_SIZE;
+      length -= SHA512_DATA_SIZE;
+    }
+
+  /* Buffer leftovers */
+  memcpy(ctx->block, buffer, length);
+  ctx->index = length;
+}
+
+/* Final wrapup - pad to SHA1_DATA_SIZE-byte boundary with the bit pattern
+   1 0* (64-bit count of bits processed, MSB-first) */
+
+static void
+sha512_final(struct sha512_ctx *ctx)
+{
+  uint64_t data[SHA512_DATA_LENGTH];
+  int i;
+  int words;
+
+  i = ctx->index;
+  
+  /* Set the first char of padding to 0x80.  This is safe since there is
+     always at least one byte free */
+
+  assert(i < SHA512_DATA_SIZE);
+  ctx->block[i++] = 0x80;
+
+  /* Fill rest of word */
+  for( ; i & 7; i++)
+    ctx->block[i] = 0;
+
+  /* i is now a multiple of the word size 8 */
+  words = i >> 3;
+  for (i = 0; i < words; i++)
+    data[i] = READ_UINT64(ctx->block + 8*i);
+  
+  if (words > (SHA512_DATA_LENGTH-2))
+    { /* No room for length in this block. Process it and
+       * pad with another one */
+      for (i = words ; i < SHA512_DATA_LENGTH; i++)
+	data[i] = 0;
+      sha512_transform(ctx->state, data);
+      for (i = 0; i < (SHA512_DATA_LENGTH-2); i++)
+	data[i] = 0;
+    }
+  else
+    for (i = words ; i < SHA512_DATA_LENGTH - 2; i++)
+      data[i] = 0;
+
+  /* There are 1024 = 2^10 bits in one block */
+  data[SHA512_DATA_LENGTH-2] = (ctx->count_high << 10) | (ctx->count_low >> 54);
+  data[SHA512_DATA_LENGTH-1] = (ctx->count_low << 10) | (ctx->index << 3);
+  sha512_transform(ctx->state, data);
+}
+
+void
+sha512_digest(struct sha512_ctx *ctx,
+	      unsigned length,
+	      uint8_t *digest)
+{
+  unsigned i;
+  unsigned words;
+  unsigned leftover;
+  
+  assert(length <= SHA512_DIGEST_SIZE);
+
+  sha512_final(ctx);
+  
+  words = length / 8;
+  leftover = length % 8;
+
+  for (i = 0; i < words; i++, digest += 8)
+    WRITE_UINT64(digest, ctx->state[i]);
+
+  if (leftover)
+    {
+      uint64_t word;
+      unsigned j = leftover;
+      
+      assert(i < _SHA512_DIGEST_LENGTH);
+      
+      word = ctx->state[i];
+      
+      switch (leftover)
+	{
+	default:
+	  abort();
+	case 7:
+	  digest[--j] = (word >> 8) & 0xff;
+	  /* Fall through */
+	case 6:
+	  digest[--j] = (word >> 16) & 0xff;
+	  /* Fall through */
+	case 5:
+	  digest[--j] = (word >> 24) & 0xff;
+	  /* Fall through */
+	case 4:
+	  digest[--j] = (word >> 32) & 0xff;
+	case 3:
+	  digest[--j] = (word >> 40) & 0xff;
+	  /* Fall through */
+	case 2:
+	  digest[--j] = (word >> 48) & 0xff;
+	  /* Fall through */
+	case 1:
+	  digest[--j] = (word >> 56) & 0xff;
+	}
+    }
+  sha512_init(ctx);
+}