diff --git a/ChangeLog b/ChangeLog
index 7efd3bdb168257c0b08619f239200e5bf36192eb..592080810503c9c1a84960940d6d9dcdad69bcaa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2013-02-15  Niels Möller  <nisse@lysator.liu.se>
 
+	* gmp-glue.c: New file, mpn <-> mpz conversions.
+	* gmp-glue.h: New file.
+	* Makefile.in: Added to hogweed_SOURCES and DISTFILES, respectively.
+
 	* eccdata.c: New program, for generating ECC-related tables.
 	* Makefile.in (ecc-192.h, ecc-224.h, ecc-256.h, ecc-384.h)
 	(ecc-512.h): New generated files.
diff --git a/Makefile.in b/Makefile.in
index b1f02e9e0067af192b5cf4dc44df2851b189db3b..7d219d50afab7b3302739c79aba16118546b3d5f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -122,7 +122,8 @@ hogweed_SOURCES = sexp.c sexp-format.c \
 		  dsa-sha256-sign.c dsa-sha256-verify.c  \
 		  dsa2sexp.c sexp2dsa.c \
 		  pgp-encode.c rsa2openpgp.c \
-		  der-iterator.c der2rsa.c der2dsa.c
+		  der-iterator.c der2rsa.c der2dsa.c \
+		  gmp-glue.c
 
 HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
 	  base16.h base64.h buffer.h camellia.h cast128.h \
@@ -159,6 +160,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h .bootstrap run-tests \
 	aes-internal.h camellia-internal.h serpent-internal.h \
 	cast128_sboxes.h desinfo.h desCode.h \
 	nettle-internal.h nettle-write.h prime-list.h \
+	gmp-glue.h \
 	asm.m4 \
 	nettle.texinfo nettle.info nettle.html nettle.pdf sha-example.c
 
diff --git a/gmp-glue.c b/gmp-glue.c
new file mode 100644
index 0000000000000000000000000000000000000000..5e3a9c2ad958fb4c4710120db2e65e0b75b9f2f9
--- /dev/null
+++ b/gmp-glue.c
@@ -0,0 +1,146 @@
+/* gmp-glue.c */
+
+/* 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.
+ */
+
+#include <assert.h>
+
+#include "gmp-glue.h"
+
+/* This implementation tries to make a minimal use of GMP internals.
+   We access and _mp_size and _mp_d, but not _mp_alloc. */
+
+/* Use macros compatible with gmp-impl.h. */
+#define ABS(x) ((x) >= 0 ? (x) : -(x))
+#define PTR(x) ((x)->_mp_d)
+#define SIZ(x) ((x)->_mp_size)
+#define ABSIZ(x) ABS (SIZ (x))
+
+#define MPN_NORMALIZE(xp, xn) do {		\
+    while ( (xn) > 0 && (xp)[xn-1] == 0)	\
+      (xn)--;					\
+  }  while (0)
+
+/* NOTE: Makes an unnecessary realloc if allocation is already large
+   enough, but looking at _mp_alloc may break in future GMP
+   versions. */
+#define MPZ_REALLOC(x, n) \
+  (ABSIZ(x) >= (n) ? PTR(x) : (_mpz_realloc ((x),(n)), PTR (x)))
+
+#define MPZ_NEWALLOC MPZ_REALLOC
+
+int
+_mpz_cmp_limbs (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn)
+{
+  mp_size_t an = SIZ (a);
+  if (an < bn)
+    return -1;
+  if (an > bn)
+    return 1;
+  if (an == 0)
+    return 0;
+
+  return mpn_cmp (PTR(a), bp, an);
+}
+
+
+/* Read access to mpz numbers. */
+
+/* Return limb pointer, for read-only operations. Use mpz_size to get
+   the number of limbs. */
+const mp_limb_t *
+_mpz_read_limbs (mpz_srcptr x)
+{
+  return PTR (x);
+}
+
+/* Get a pointer to an n limb area, for read-only operation. n must be
+   greater or equal to the current size, and the mpz is zero-padded if
+   needed. */
+const mp_limb_t *
+_mpz_read_limbs_n (mpz_ptr x, mp_size_t n)
+{
+  mp_size_t xn = ABSIZ (x);
+
+  assert (xn <= n);
+
+  if (xn < n)
+    {
+      /* Makes an unnecessary realloc if allocation is already large
+	 enough. */
+      mpz_realloc (x, n);
+      mpn_zero (PTR(x) + xn, n - xn);
+    }
+
+  return PTR(x);
+}
+
+void
+_mpz_copy_limbs (mp_limb_t *xp, mpz_srcptr x, mp_size_t n)
+{
+  mp_size_t xn = ABSIZ (x);
+
+  assert (xn <= n);
+  mpn_copyi (xp, PTR(x), xn);
+  if (xn < n)
+    mpn_zero (xp + xn, n - xn);
+}
+
+/* Write access to mpz numbers. */
+
+/* Get a limb pointer for writing, previous contents may be
+   destroyed. */
+mp_limb_t *
+_mpz_write_limbs (mpz_ptr x, mp_size_t n)
+{
+  assert (n > 0);
+  return MPZ_NEWALLOC (x, n);
+}
+
+/* Get a limb pointer for writing, previous contents is intact. */
+mp_limb_t *
+_mpz_modify_limbs (mpz_ptr x, mp_size_t n)
+{
+  assert (n > 0);
+  return MPZ_REALLOC (x, n);
+}
+
+void
+_mpz_done_limbs (mpz_ptr x, mp_size_t n)
+{
+  assert (n >= 0);
+  MPN_NORMALIZE (PTR(x), n);
+
+  SIZ (x) = n;
+}
+
+/* Needs some ugly casts. */
+mpz_srcptr
+_mpz_init_mpn (mpz_ptr x, const mp_limb_t *xp, mp_size_t xs)
+{
+  mp_size_t xn = ABS (xs);
+  
+  MPN_NORMALIZE (xp, xn);
+
+  x->_mp_size = xs < 0 ? -xn : xn;
+  x->_mp_alloc = 0;
+  x->_mp_d = (mp_limb_t *) xp;
+  return x;
+}
diff --git a/gmp-glue.h b/gmp-glue.h
new file mode 100644
index 0000000000000000000000000000000000000000..cddd534f05dfdd8c46ae67b0f07da79fcfc3ee5c
--- /dev/null
+++ b/gmp-glue.h
@@ -0,0 +1,85 @@
+/* gmp-glue.h */
+
+/* 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_GMP_GLUE_H_INCLUDED
+#define NETTLE_GMP_GLUE_H_INCLUDED
+
+#include <gmp.h>
+
+/* Name mangling. */
+#define _mpz_cmp_limbs _nettle_mpz_cmp_limbs
+#define _mpz_read_limbs _nettle_mpz_read_limbs
+#define _mpz_read_limbs_n _nettle_mpz_read_limbs_n
+#define _mpz_copy_limbs _nettle_mpz_copy_limbs
+#define _mpz_write_limbs _nettle_mpz_write_limbs
+#define _mpz_modify_limbs _nettle_mpz_modify_limbs
+#define _mpz_done_limbs _nettle_mpz_done_limbs
+#define _mpz_init_mpn _nettle_mpz_init_mpn
+
+/* Some functions for interfacing between mpz and mpn code. Signs of
+   the mpz numbers are generally ignored. */
+
+int
+_mpz_cmp_limbs (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn);
+
+/* Read access to mpz numbers. */
+
+/* Return limb pointer, for read-only operations. Use mpz_size to get
+   the number of limbs. */
+const mp_limb_t *
+_mpz_read_limbs (const mpz_srcptr x);
+
+/* Get a pointer to an n limb area, for read-only operation. n must be
+   greater or equal to the current size, and the mpz is zero-padded if
+   needed. */
+const mp_limb_t *
+_mpz_read_limbs_n (mpz_ptr x, mp_size_t n);
+
+/* Copy limbs, with zero-padding. */
+/* FIXME: Reorder arguments, on the theory that the first argument of
+   an _mpz_* fucntion should be an mpz_t? Or rename to _mpz_get_limbs,
+   with argument order consistent with mpz_get_*. */
+void
+_mpz_copy_limbs (mp_limb_t *xp, mpz_srcptr x, mp_size_t n);
+
+/* Write access to mpz numbers. */
+
+/* Get a limb pointer for writing, previous contents may be
+   destroyed. */
+mp_limb_t *
+_mpz_write_limbs (mpz_ptr x, mp_size_t n);
+
+/* Get a limb pointer for writing, previous contents is intact. */
+mp_limb_t *
+_mpz_modify_limbs (mpz_ptr x, mp_size_t n);
+
+/* Update size. */
+void
+_mpz_done_limbs (mpz_ptr x, mp_size_t n);
+
+
+/* Using an mpn number as an mpz. Can be used for read-only access
+   only. x must not be cleared or reallocated. */
+mpz_srcptr
+_mpz_init_mpn (mpz_ptr x, const mp_limb_t *xp, mp_size_t xs);
+
+#endif /* NETTLE_GMP_GLUE_H_INCLUDED */