[PATCH] Add NTRUEncrypt public key encryption algorithm

Zhenfei Zhang zzhang at securityinnovation.com
Tue Sep 8 20:45:33 CEST 2015


Hi list,

I wish to contribute this patch to the libgcrypt.
Can I please ask what is the right approach to get this patch included in a
release?
Thanks.

Signed-off-by: Zhenfei Zhang <zzhang at securityinnovation.com>.

Commit attached. Can also be found at
https://github.com/wwhyte-si/libgcrypt-ntru/commit/1cec836ec7fded3284c769b05daf4eb285527b38




On Wed, Aug 5, 2015 at 10:35 AM, Zhenfei Zhang <
zzhang at securityinnovation.com> wrote:

> Hi all,
>
> This is a patch to enable NTRUEncrypt public key encryption algorithm for
> libgcrypt.
> Here is the link to the commit:
>
> https://github.com/wwhyte-si/libgcrypt-ntru/commit/1cec836ec7fded3284c769b05daf4eb285527b38
>
> PS: I am new to big projects like this. So please let me know if this is
> not the correct way to do it.
>
> Cheers,
> Zhenfei
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/attachments/20150908/c12dbf7e/attachment-0001.html>
-------------- next part --------------
diff --git a/.gitignore b/.gitignore
index 3929e4d..db863dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,3 +84,6 @@ tests/rsacvt
 tests/t-mpi-bit
 tests/tsexp
 tests/version
+*~
+sample/a.out
+.*
diff --git a/README b/README
index 938c6c6..0dc0509 100644
--- a/README
+++ b/README
@@ -36,6 +36,10 @@
 
     You should get the latest versions of course.
 
+    To build libgcrypt with NTRU public key crypto:
+      https://github.com/NTRUOpenSourceProject/ntru-crypto 
+
+
     After building and installing the libgpg-error package, you may
     continue with Libgcrypt installation as with allmost all GNU
     packages, you just have to do
@@ -185,8 +189,11 @@
                      the feature under the assumption that either good
                      CFLAGS are given or the compiler can grok the code.
 
-
-
+     --enable-ntru
+                     This let libgcrypt to link against libntruencrypt.
+                     To check if it is linked propoerly, run the sample
+                     code from sample/test_ntru_gcrypt.cpp.
+                     
 
     Build Problems
     --------------
diff --git a/README_NTRU b/README_NTRU
new file mode 100644
index 0000000..e8b1aa4
--- /dev/null
+++ b/README_NTRU
@@ -0,0 +1,18 @@
+		    libgcrypt : enabling NTRUEncrypt for libgcrypt
+		-------------------------------------------------------
+
+Dependency:
+  libntruencrypt 1.0.0
+  https://github.com/NTRUOpenSourceProject/ntru-crypto
+
+Installation:
+
+  ./autogen.sh
+  ./configure --enable-maintainer-mode --enable-ntru
+  make
+  sudo make install
+
+Example code:
+  cd sample
+  g++ test_ntru_gcrypt.cpp -lgcrypt -o test.o
+  ./test.o
diff --git a/autogen.rc b/autogen.rc
index 09a9b9c..1e800f6 100644
--- a/autogen.rc
+++ b/autogen.rc
@@ -14,4 +14,4 @@ case "$myhost" in
     ;;
 esac
 
-final_info="./configure --enable-maintainer-mode && make"
+final_info="./configure --enable-maintainer-mode --enable-ntru && make"
diff --git a/autogen.sh b/autogen.sh
index 471193c..d8da839 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -277,7 +277,7 @@ if [ "$myhost" = "amd64" ]; then
         fi
     fi
 
-    $tsdir/configure --enable-maintainer-mode ${SILENT} \
+    $tsdir/configure --enable-maintainer-mode --enable-ntru ${SILENT} \
              --prefix=${amd64root}  \
              --host=${host} --build=${build} \
              ${configure_opts} ${extraoptions} "$@"
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index 33a68ff..c82f8d5 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -57,9 +57,13 @@ bufhelp.h  \
 primegen.c  \
 hash-common.c hash-common.h \
 dsa-common.c rsa-common.c \
+base64.c \
+base64.h \
 rmd.h
 
 EXTRA_libcipher_la_SOURCES = \
+ntru-gcrypt-wrapper.c \
+ntru-gcrypt-wrapper.h \
 arcfour.c arcfour-amd64.S \
 blowfish.c blowfish-amd64.S blowfish-arm.S \
 cast5.c cast5-amd64.S cast5-arm.S \
diff --git a/cipher/base64.c b/cipher/base64.c
new file mode 100644
index 0000000..cfedfb9
--- /dev/null
+++ b/cipher/base64.c
@@ -0,0 +1,295 @@
+/*
+ *  RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_BASE64_C)
+
+#include "polarssl/base64.h"
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#include <string.h>
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+//#endif /* POLARSSL_SELF_TEST */
+
+
+#include "base64.h"
+#include <unistd.h>
+
+
+static const unsigned char base64_enc_map[64] =
+{
+    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', '+', '/'
+};
+
+static const unsigned char base64_dec_map[128] =
+{
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
+     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
+    127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
+      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
+     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
+     25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
+     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
+     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+     49,  50,  51, 127, 127, 127, 127, 127
+};
+
+/*
+ * Encode a buffer into base64 format
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen )
+{
+    size_t i, n;
+    int C1, C2, C3;
+    unsigned char *p;
+
+    if( slen == 0 )
+    {
+        *dlen = 0;
+        return( 0 );
+    }
+    n = ( slen << 3 ) / 6;
+
+    switch( ( slen << 3 ) - ( n * 6 ) )
+    {
+        case  2: n += 3; break;
+        case  4: n += 2; break;
+        default: break;
+    }
+
+    if( *dlen < n + 1 )
+    {
+        *dlen = n + 1;
+        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+    n = ( slen / 3 ) * 3;
+
+    for( i = 0, p = dst; i < n; i += 3 )
+    {
+        C1 = *src++;
+        C2 = *src++;
+        C3 = *src++;
+
+        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+        *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
+        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
+        *p++ = base64_enc_map[C3 & 0x3F];
+    }
+
+    if( i < slen )
+    {
+        C1 = *src++;
+        C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
+
+        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+
+        if( ( i + 1 ) < slen )
+             *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+        else *p++ = '=';
+
+        *p++ = '=';
+    }
+
+    *dlen = p - dst;
+    *p = 0;
+
+    return( 0 );
+}
+
+/*
+ * Decode a base64-formatted buffer
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen )
+{
+    size_t i, n;
+    uint32_t j, x;
+    unsigned char *p;
+
+    /* First pass: check for validity and get output length */
+    for( i = n = j = 0; i < slen; i++ )
+    {
+        /* Skip spaces before checking for EOL */
+        x = 0;
+        while( i < slen && src[i] == ' ' )
+        {
+            ++i;
+            ++x;
+        }
+
+        /* Spaces at end of buffer are OK */
+        if( i == slen )
+            break;
+
+        if( ( slen - i ) >= 2 &&
+            src[i] == '\r' && src[i + 1] == '\n' )
+            continue;
+
+        if( src[i] == '\n' )
+            continue;
+
+        /* Space inside a line is an error */
+        if( x != 0 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        if( src[i] == '=' && ++j > 2 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        if( base64_dec_map[src[i]] < 64 && j != 0 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        n++;
+    }
+
+    if( n == 0 )
+        return( 0 );
+
+    n = ( ( n * 6 ) + 7 ) >> 3;
+    n -= j;
+
+    if( dst == NULL || *dlen < n )
+    {
+        *dlen = n;
+        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+   {
+        if( *src == '\r' || *src == '\n' || *src == ' ' )
+            continue;
+
+        j -= ( base64_dec_map[*src] == 64 );
+        x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
+
+        if( ++n == 4 )
+        {
+            n = 0;
+            if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+            if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
+            if( j > 2 ) *p++ = (unsigned char)( x       );
+        }
+    }
+
+    *dlen = p - dst;
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+static const unsigned char base64_test_dec[64] =
+{
+    0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
+    0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
+    0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
+    0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
+    0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
+    0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
+    0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
+    0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
+};
+
+static const unsigned char base64_test_enc[] =
+    "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
+    "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
+
+/*
+ * Checkup routine
+ */
+int base64_self_test( int verbose )
+{
+    size_t len;
+    const unsigned char *src;
+    unsigned char buffer[128];
+
+    if( verbose != 0 )
+        polarssl_printf( "  Base64 encoding test: " );
+
+    len = sizeof( buffer );
+    src = base64_test_dec;
+
+    if( base64_encode( buffer, &len, src, 64 ) != 0 ||
+         memcmp( base64_test_enc, buffer, 88 ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n  Base64 decoding test: " );
+
+    len = sizeof( buffer );
+    src = base64_test_enc;
+
+    if( base64_decode( buffer, &len, src, 88 ) != 0 ||
+         memcmp( base64_test_dec, buffer, 64 ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+//#endif /* POLARSSL_BASE64_C */
diff --git a/cipher/base64.h b/cipher/base64.h
new file mode 100644
index 0000000..2fd1ac6
--- /dev/null
+++ b/cipher/base64.h
@@ -0,0 +1,86 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BASE64_H
+#define POLARSSL_BASE64_H
+
+#include <stddef.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */
+#define POLARSSL_ERR_BASE64_INVALID_CHARACTER              -0x002C  /**< Invalid character in input. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Encode a buffer into base64 format
+ *
+ * \param dst      destination buffer
+ * \param dlen     size of the buffer
+ * \param src      source buffer
+ * \param slen     amount of data to be encoded
+ *
+ * \return         0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
+ *                 *dlen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *dlen = 0 to obtain the
+ *                 required buffer size in *dlen
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Decode a base64-formatted buffer
+ *
+ * \param dst      destination buffer (can be NULL for checking size)
+ * \param dlen     size of the buffer
+ * \param src      source buffer
+ * \param slen     amount of data to be decoded
+ *
+ * \return         0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
+ *                 POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is
+ *                 not correct. *dlen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *dst = NULL or *dlen = 0 to obtain
+ *                 the required buffer size in *dlen
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */
diff --git a/cipher/ntru-gcrypt-wrapper.c b/cipher/ntru-gcrypt-wrapper.c
new file mode 100644
index 0000000..28d35e2
--- /dev/null
+++ b/cipher/ntru-gcrypt-wrapper.c
@@ -0,0 +1,459 @@
+/* ntru-grcrypt-wrapper.h
+ * Copyright (C) 2015, Security Innovation.
+ * Author Zhenfei Zhang <zzhang at securityinnovation.com>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt 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.
+ *
+ * Libgcrypt 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This code is a wrapper for libgcrypt to be linked with libntruencrypt
+ * NTRUEncrypt is a lattice-based public key encryption algorithm.
+ * For the latest version of the NTRUEncrypt specs, visit
+ *  https://github.com/NTRUOpenSourceProject/NTRUEncrypt
+ */
+
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+#include "g10lib.h"
+#include "gcrypt.h"
+#include "cipher.h"
+#include "bufhelp.h"
+#include "gcrypt-int.h"
+#include "base64.h"
+#include <libntruencrypt/ntru_crypto.h>
+#include "ntru-gcrypt-wrapper.h"
+
+static const char *ntru_names[] =
+{
+	"ntru",
+	NULL,
+};
+
+gcry_pk_spec_t _gcry_pubkey_spec_ntru = {
+	GCRY_PK_NTRU,               //  algo;
+	{0,0},                      //  struct {
+								//  unsigned int disabled:1;
+								//  unsigned int fips:1;
+								//  } flags;
+	GCRY_PK_USAGE_ENCR,         //  int use;
+	"ntru",                     //  const char *name;
+	ntru_names,                 //  const char **aliases;
+	NULL,                       //  const char *elements_pkey;
+	NULL,                       //  const char *elements_skey;
+	NULL,                       //  const char *elements_enc;
+	NULL,                       //  const char *elements_sig;
+	NULL,                       //  const char *elements_grip;
+	gcry_ntru_keygen,           //  gcry_pk_generate_t generate;
+	gcry_ntru_check_secret_key, //  gcry_pk_check_secret_key_t check_secret_key;
+	gcry_ntru_encrypt,          //  gcry_pk_encrypt_t encrypt;
+	gcry_ntru_decrypt,          //  gcry_pk_decrypt_t decrypt;
+	NULL,                       //  gcry_pk_sign_t sign;
+	NULL,                       //  gcry_pk_verify_t verify;
+	gcry_ntru_get_nbits,        //  gcry_pk_get_nbits_t get_nbits;
+	NULL,						//  selftest_func_t selftest;
+	gcry_ntru_comp_keygrip,     //  pk_comp_keygrip_t comp_keygrip;
+	NULL,                       //  pk_get_curve_t get_curve;
+	NULL                        //  pk_get_curve_param_t get_curve_param;
+};
+
+static gpg_err_code_t gcry_ntru_comp_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
+{
+    fprintf (stderr,"NTRU compute keygrip function not required/implemented\n");
+	return 0;
+}
+
+static unsigned int gcry_ntru_get_nbits (gcry_sexp_t parms)
+{
+    fprintf (stderr,"NTRU get nbits function not required/implemented\n");
+	return 0;
+}
+static gcry_err_code_t gcry_ntru_check_secret_key (gcry_sexp_t keyparms)
+{
+    fprintf (stderr,"NTRU check secret key function not required/implemented\n");
+	return 0;
+}
+
+
+NTRU_ENCRYPT_PARAM_SET_ID gcry_ntru_get_param_id (gcry_sexp_t genparms)
+{
+    if ((_gcry_sexp_find_token(genparms, "n439", 4)!= NULL) ||
+            (_gcry_sexp_find_token(genparms, "b128", 4)!= NULL))
+        return     NTRU_EES439EP1;
+
+    if ((_gcry_sexp_find_token(genparms, "n593", 4)!= NULL) ||
+            (_gcry_sexp_find_token(genparms, "b192", 4)!= NULL))
+        return     NTRU_EES593EP1;
+
+    if ((_gcry_sexp_find_token(genparms, "n743", 4)!= NULL) ||
+            (_gcry_sexp_find_token(genparms, "b256", 4)!= NULL))
+        return     NTRU_EES743EP1;
+
+    return -1;
+}
+
+
+/* Type for the pk_generate function.  */
+// typedef gcry_err_code_t (*gcry_pk_generate_t) (gcry_sexp_t genparms,
+//                                                gcry_sexp_t *r_skey);
+gcry_err_code_t gcry_ntru_keygen (gcry_sexp_t genparms, gcry_sexp_t *r_skey)
+{
+
+    NTRU_ENCRYPT_PARAM_SET_ID   paramid;
+    int                         rc;                                     /* return code */
+    uint8_t                     *public_key;                            /* sized for EES401EP2 */
+    uint16_t                    public_key_len;                         /* no. of octets in public key */
+    uint8_t                     *private_key;                           /* sized for EES401EP2 */
+    uint16_t                    private_key_len;                        /* no. of octets in private key */
+    DRBG_HANDLE                 drbg;                                   /* handle for instantiated DRBG */
+    uint8_t                     *pers_str;
+    gcry_sexp_t                 temp_pk, temp_sk;
+
+    /* start key generation */
+    paramid = gcry_ntru_get_param_id (genparms);
+
+    if (paramid <0)
+    {
+        fprintf (stderr, "gcry_ntru: unrecognized parameter id\n");
+        return -1;
+    }
+/*
+    if (paramid == NTRU_EES439EP1)
+        printf("using NTRU_EES439EP1\n");
+    if (paramid == NTRU_EES593EP1)
+        printf("using NTRU_EES593EP1\n");
+    if (paramid == NTRU_EES743EP1)
+        printf("using NTRU_EES743EP1\n");
+*/
+    /* optional personal string for DRBG */
+    /* use this prg for best security */
+//    pers_str    = (uint8_t*)_gcry_random_bytes (32, GCRY_STRONG_RANDOM);
+    /* use this one to improve performance */
+    pers_str    = (uint8_t*)_gcry_random_bytes (32, GCRY_WEAK_RANDOM);
+
+
+    public_key  = (uint8_t *) malloc (_MAX_NTRU_BUF_SIZE_);
+    private_key = (uint8_t *) malloc (_MAX_NTRU_BUF_SIZE_);
+
+    memset(public_key, 0, _MAX_NTRU_BUF_SIZE_);
+    memset(private_key, 0, _MAX_NTRU_BUF_SIZE_);
+
+    /* generating NTRU keys */
+
+    rc = ntru_crypto_drbg_instantiate(256, pers_str, sizeof(pers_str), (ENTROPY_FN) &get_entropy, &drbg);
+    if (rc!=0)
+    {
+        fprintf (stderr, "drbg error, ntru code: %d\n", rc);
+        return rc;
+    }
+    rc = ntru_crypto_ntru_encrypt_keygen(drbg, paramid , &public_key_len, NULL, &private_key_len, NULL);
+    if (rc!=0)
+    {
+        fprintf (stderr, "key gen error, ntru code: %d\n", rc);
+        return rc;
+    }
+    rc = ntru_crypto_ntru_encrypt_keygen(drbg, paramid , &public_key_len, public_key, &private_key_len, private_key);
+    if (rc!=0)
+    {
+        fprintf (stderr, "key gen error, ntru code: %d\n", rc);
+        return rc;
+    }
+
+    /* extract the key pair */
+    temp_pk = convert_ntru_data_to_sexp (public_key, public_key_len);
+    temp_sk = convert_ntru_data_to_sexp (private_key, private_key_len);
+    rc = _gcry_sexp_build (r_skey, NULL,
+         "(key-data(public-key(ntru%S))(private-key(ntru%S)))", temp_pk, temp_sk);
+    if (rc!=0)
+    {
+        fprintf (stderr, "gcry_sexp_build error: %s\n",  _gcry_strerror (rc));
+        return rc;
+    }
+
+//    _gcry_sexp_dump(*r_skey);
+
+    /* cleaning up */
+    rc = ntru_crypto_drbg_uninstantiate(drbg);
+    if (rc!=0)
+    {
+        fprintf (stderr, "drbg error, ntru code: %d\n", rc);
+        return rc;
+    }
+    free(public_key);
+    free(private_key);
+    free(pers_str);
+    xfree(temp_sk);
+    xfree(temp_pk);
+    return rc;
+}
+
+/* Type for the pk_encrypt function.  */
+// typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph,
+//                                               gcry_sexp_t s_data,
+//                                               gcry_sexp_t keyparms);
+gcry_err_code_t gcry_ntru_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
+{
+	uint8_t     rc;
+    uint8_t     *msg_buf;
+    uint8_t     *key_buf;
+    uint8_t     *working_buf;
+    size_t      msg_len;
+    size_t      key_len;
+    size_t      working_buf_len;
+    DRBG_HANDLE drbg;
+
+    working_buf = (uint8_t *) malloc (_MAX_NTRU_BUF_SIZE_);
+    msg_buf     = (uint8_t *) malloc (_MAX_NTRU_BUF_SIZE_);
+    key_buf     = (uint8_t *) malloc (_MAX_NTRU_BUF_SIZE_);
+    memset(msg_buf, 0, _MAX_NTRU_BUF_SIZE_);
+    memset(key_buf, 0, _MAX_NTRU_BUF_SIZE_);
+    memset(working_buf, 0, _MAX_NTRU_BUF_SIZE_);
+    msg_len     = _MAX_NTRU_BUF_SIZE_;
+    key_len     = _MAX_NTRU_BUF_SIZE_;
+    working_buf_len = _MAX_NTRU_BUF_SIZE_;
+
+    /* extracting the message */
+    msg_buf     = _gcry_sexp_nth_data (_gcry_sexp_find_token(s_data, "value", 0), 1, &msg_len);
+    /* extracting the public key; removing ntru header */
+    working_buf = _gcry_sexp_nth_data (_gcry_sexp_cadr (keyparms), 0, &working_buf_len);
+    base64_decode(key_buf, &key_len, working_buf+4, working_buf_len-4);
+
+    /* performing ntru encryption */
+    rc = ntru_crypto_drbg_instantiate(256, NULL, 0, (ENTROPY_FN) &get_entropy, &drbg);
+    if (rc!=0)
+    {
+        fprintf (stderr, "drbg error, ntru code: %d\n", rc);
+        return rc;
+    }
+    rc = ntru_crypto_ntru_encrypt(drbg, key_len, key_buf, msg_len, msg_buf, &working_buf_len, NULL);
+    if (rc!=0)
+    {
+        fprintf (stderr, "encryption error, ntru code: %d\n", rc);
+        return rc;
+    }
+    rc = ntru_crypto_ntru_encrypt(drbg, key_len, key_buf, msg_len, msg_buf, &working_buf_len, working_buf);
+    if (rc!=0)
+    {
+        fprintf (stderr, "encryption error, ntru code: %d\n", rc);
+        return rc;
+    }
+
+    *r_ciph     = convert_ntru_data_to_sexp (working_buf, working_buf_len);
+//    _gcry_sexp_dump(*r_ciph);
+
+    /* cleaning up */
+    rc = ntru_crypto_drbg_uninstantiate(drbg);
+    if (rc!=0)
+    {
+        fprintf (stderr, "drbg error, ntru code: %d\n", rc);
+        return rc;
+    }
+    free(key_buf);
+//    free(working_buf);
+//    free(msg_buf);
+    return rc;
+}
+
+
+
+/* Type for the pk_decrypt function.  */
+// typedef gcry_err_code_t (*gcry_pk_decrypt_t) (gcry_sexp_t *r_plain,
+//                                               gcry_sexp_t s_data,
+//                                               gcry_sexp_t keyparms);
+gcry_err_code_t gcry_ntru_decrypt (gcry_sexp_t *r_msg, gcry_sexp_t s_data, gcry_sexp_t keyparms)
+{
+    int         rc;
+    uint8_t     *cipher_buf;
+    uint8_t     *key_buf;
+    uint8_t     *working_buf;
+    size_t      cipher_len;
+    size_t      key_len;
+    size_t      working_buf_len;
+    gcry_sexp_t key;
+
+    working_buf = (uint8_t *) malloc (_MAX_NTRU_BUF_SIZE_);
+    cipher_buf  = (uint8_t *) malloc (_MAX_NTRU_BUF_SIZE_);
+    key_buf     = (uint8_t *) malloc (_MAX_NTRU_BUF_SIZE_);
+    memset(cipher_buf, 0, _MAX_NTRU_BUF_SIZE_);
+    memset(key_buf, 0, _MAX_NTRU_BUF_SIZE_);
+    memset(working_buf, 0, _MAX_NTRU_BUF_SIZE_);
+    cipher_len  = _MAX_NTRU_BUF_SIZE_;
+    key_len     = _MAX_NTRU_BUF_SIZE_;
+    working_buf_len = _MAX_NTRU_BUF_SIZE_;
+
+    /* extracting the cipher; removing ntru header */
+    working_buf =  _gcry_sexp_nth_data (s_data, 0, &working_buf_len);
+    base64_decode(cipher_buf, &cipher_len, working_buf+4, working_buf_len-4);
+
+    /* extracting the private key; removing ntru header */
+    key         =  _gcry_sexp_cadr (keyparms);
+    working_buf =  _gcry_sexp_nth_data (key, 0, &working_buf_len);
+    base64_decode(key_buf, &key_len, working_buf+4, working_buf_len-4);
+
+    /* performing ntru decryption */
+    rc = ntru_crypto_ntru_decrypt(key_len, key_buf, cipher_len, cipher_buf, &working_buf_len, NULL);
+    if (rc!=0)
+    {
+        fprintf (stderr, "decryption error, ntru code: %d\n", rc);
+        return rc;
+    }
+    rc = ntru_crypto_ntru_decrypt(key_len, key_buf, cipher_len, cipher_buf, &working_buf_len, working_buf);
+    if (rc!=0)
+    {
+        fprintf (stderr, "decryption error, ntru code: %d\n", rc);
+        return rc;
+    }
+    working_buf[working_buf_len] = '\0';
+    rc = _gcry_sexp_build (r_msg, NULL, "%s", working_buf);
+    if (rc!=0)
+    {
+        fprintf (stderr, "gcry_sexp_build error: %s\n",  _gcry_strerror (rc));
+        return rc;
+    }
+    /* cleaning up */
+    free(cipher_buf);
+    free(key_buf);
+    xfree(key);
+    return rc;
+}
+
+/*
+ * convert an ntru blob in ntru_data to a s-expression:
+ * 1. convert ASCII coded ntru blob into base64 encoding string
+ * 2. add guard string "NTRU" to the start of the string
+ *    (if the base64 encoded string starts with a non-alphabetic
+ *    char, sexp builder will bug)
+ * 3. form the sexp
+ */
+gcry_sexp_t convert_ntru_data_to_sexp (const uint8_t* ntru_data, const size_t ntru_data_len)
+{
+    gcry_sexp_t sexp_data;
+    uint8_t     *base64_data;
+    size_t      base64_data_len = _MAX_NTRU_BUF_SIZE_;
+    uint8_t     *tmp_str;
+    int rc;
+    base64_data = (uint8_t*) malloc (ntru_data_len*2*sizeof(uint8_t));
+    tmp_str     = (uint8_t*) malloc ((base64_data_len+2)*sizeof(uint8_t));
+
+    rc = base64_encode(base64_data, &base64_data_len, ntru_data, ntru_data_len);
+
+    tmp_str[0] = '(';
+    tmp_str[1] = 'N';
+    tmp_str[2] = 'T';
+    tmp_str[3] = 'R';
+    tmp_str[4] = 'U';
+    memcpy(tmp_str+5, base64_data, base64_data_len*sizeof(uint8_t));
+    tmp_str[base64_data_len+5]  = ')';
+    tmp_str[base64_data_len+6]  = '\0';
+
+    rc = _gcry_sexp_sscan (&sexp_data, NULL, tmp_str, strlen(tmp_str));
+    if (rc!=0)
+    {
+        fprintf (stderr, "gcry_sexp_new: %s\n",  _gcry_strerror (rc));
+        return rc;
+    }
+//    _gcry_sexp_dump(sexp_data);
+
+    free(tmp_str);
+    free(base64_data);
+    return sexp_data;
+}
+/*
+ *  turns out those two functions are no longer required
+ *
+void convert_sexp_data_to_ntru (const gcry_sexp_t sexp_data, uint8_t* ntru_data, size_t* ntru_data_len)
+{
+    uint8_t *buffer           = (uint8_t*) malloc(_MAX_NTRU_BUF_SIZE_);
+    uint8_t *ntru_data_buf    = (uint8_t*) malloc(_MAX_NTRU_BUF_SIZE_);
+    uint8_t *buffer_pt        = buffer;
+    size_t  length;
+    *ntru_data_len = _MAX_NTRU_BUF_SIZE_;
+    _gcry_sexp_sprint (sexp_data, 3, buffer, ntru_data_len);
+    int i=0;
+    printf("buffer: ");
+    while(buffer[i]!='\0'){
+        printf("%c ",buffer[i]);i++;}
+    printf("\n");
+    length              = my_strlen(buffer) - 7 ;   // one for '(', four for "NTRU", one for ')', one for '\0'
+    buffer_pt           = buffer+5;                 // removing the first five chars '(NTRU'
+    buffer_pt [length]  = '\0';                     // removing the last char ')'
+
+    base64_decode( (uint8_t*)ntru_data_buf, ntru_data_len, buffer_pt, length);
+
+    free (buffer);
+    free (ntru_data_buf);
+}
+
+size_t my_strlen(const uint8_t *str)
+{
+  size_t i;
+  for (i = 0; str[i]; i++);
+  return i;
+}
+*/
+
+static uint8_t
+get_entropy(
+    ENTROPY_CMD  cmd,
+    uint8_t     *out)
+{
+
+    int num_bytes = 48;
+    /*
+     * dimension        number of bytes
+     * 439              24
+     * 593              36
+     * 743              48
+     */
+    /* use this prg for best security */
+//    uint8_t *seed = (uint8_t*)_gcry_random_bytes (num_bytes, GCRY_STRONG_RANDOM);
+    /* use this prg to improve performance */
+    uint8_t *seed = (uint8_t*)_gcry_random_bytes (num_bytes, GCRY_WEAK_RANDOM);
+
+
+
+    static size_t   index;
+
+    if (cmd == INIT) {
+        /* Any initialization for a real entropy source goes here. */
+        index = 0;
+        return 1;
+    }
+
+    if (out == NULL)
+        return 0;
+
+    if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
+        /* Here we return the number of bytes needed from the entropy
+         * source to obtain 8 bits of entropy.  Maximum is 8.
+         */
+        *out = 1;                       /* this is a perfectly random source */
+        return 1;
+    }
+
+    if (cmd == GET_BYTE_OF_ENTROPY) {
+        if (index == 128)
+            return 0;                   /* used up all our entropy */
+
+        *out = seed[index++];           /* deliver an entropy byte */
+        return 1;
+    }
+    return 0;
+}
diff --git a/cipher/ntru-gcrypt-wrapper.h b/cipher/ntru-gcrypt-wrapper.h
new file mode 100644
index 0000000..0b5c3ab
--- /dev/null
+++ b/cipher/ntru-gcrypt-wrapper.h
@@ -0,0 +1,81 @@
+/* ntru-grcrypt-wrapper.h
+ * Copyright (C) 2015, Security Innovation.
+ * Author Zhenfei Zhang <zzhang at securityinnovation.com>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt 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.
+ *
+ * Libgcrypt 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This code is a wrapper for libgcrypt to be linked with libntruencrypt
+ * NTRUEncrypt is a lattice-based public key encryption algorithm.
+ * For the latest version of the NTRUEncrypt specs, visit
+ *  https://github.com/NTRUOpenSourceProject/NTRUEncrypt
+ */
+
+
+#ifndef NTRU_GCRYPT_WRAPPER_H
+#define NTRU_GCRYPT_WRAPPER_H
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+#include "g10lib.h"
+#include "gcrypt.h"
+#include "cipher.h"
+#include "bufhelp.h"
+#include "gcrypt-int.h"
+#include "base64.h"
+#include <libntruencrypt/ntru_crypto.h>
+
+
+#ifndef _MAX_NTRU_BUF_SIZE_
+#define _MAX_NTRU_BUF_SIZE_ 2000
+#endif
+
+/* NTRUEncrypt keygen function, input genparms, output a keypair in r_skey
+ * sample genparms:
+ * (genkey(ntru(b256))), (genkey(ntru(n743))) = 256 bits security with dimension 743
+ * (genkey(ntru(b192))), (genkey(ntru(n593))) = 192 bits security with dimension 593
+ * (genkey(ntru(b128))), (genkey(ntru(n439))) = 128 bits security with dimension 439
+ */
+gcry_err_code_t gcry_ntru_keygen (gcry_sexp_t genparms, gcry_sexp_t *r_skey);
+
+gcry_err_code_t gcry_ntru_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms);
+gcry_err_code_t gcry_ntru_decrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms);
+
+// data conversion: S expression <---> ntru data
+gcry_sexp_t convert_ntru_data_to_sexp (const uint8_t* ntru_data, const size_t ntru_data_len);
+// void convert_sexp_data_to_ntru (const gcry_sexp_t sexp_data, uint8_t* ntru_data, size_t* ntru_data_len);
+
+/*
+ * dump functions
+ */
+static gpg_err_code_t gcry_ntru_comp_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms);
+static unsigned int gcry_ntru_get_nbits (gcry_sexp_t parms);
+static gcry_err_code_t gcry_ntru_check_secret_key (gcry_sexp_t keyparms);
+//static gcry_err_code_t gcry_ntru_self_tests (int algo, int extended, selftest_report_func_t report);
+//static gcry_err_code_t ntru_self_tests (selftest_report_func_t report);
+
+/*
+ * misc functions
+ */
+static uint8_t get_entropy(ENTROPY_CMD  cmd, uint8_t *out);
+//size_t my_strlen(const unsigned char *str);
+
+#endif //NTRU_GCRYPT_WRAPPER_H
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index e3842c0..39c7f14 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -48,6 +48,9 @@ static gcry_pk_spec_t *pubkey_list[] =
 #if USE_ELGAMAL
     &_gcry_pubkey_spec_elg,
 #endif
+#if USE_NTRU
+    &_gcry_pubkey_spec_ntru,
+#endif
     NULL
   };
 
@@ -62,6 +65,7 @@ map_algo (int algo)
    case GCRY_PK_ELG_E: return GCRY_PK_ELG;
    case GCRY_PK_ECDSA: return GCRY_PK_ECC;
    case GCRY_PK_ECDH:  return GCRY_PK_ECC;
+   case GCRY_PK_NTRU:  return GCRY_PK_NTRU;
    default:            return algo;
    }
 }
diff --git a/configure.ac b/configure.ac
index 0f16175..c9bdb6d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -329,6 +329,18 @@ case "${host}" in
         ;;
 esac
 
+# check if configured with libntruencrypt
+AC_ARG_ENABLE(ntru,
+  AS_HELP_STRING(--enable-ntru, Build libgcrypt with support for NTRUEncrypt algorithm), [], [enable_ntru=no])
+
+if test $enable_ntru != no; then
+  AC_CHECK_HEADERS([libntruencrypt/ntru_crypto.h])
+  LIBS="$LIBS -lntruencrypt"
+  NTRUENCRYPT_LIBS=-lntruencrypt
+  available_pubkey_ciphers="$available_pubkey_ciphers ntru"
+
+  AC_SUBST(NTRUENCRYPT_LIBS)
+fi
 
 AC_ARG_ENABLE(endian-check,
               AC_HELP_STRING([--disable-endian-check],
@@ -2019,6 +2031,12 @@ if test "$found" = "1" ; then
    AC_DEFINE(USE_ECC, 1, [Defined if this module should be included])
 fi
 
+LIST_MEMBER(ntru, $enabled_pubkey_ciphers)
+if test "$found" = "1" ; then
+   GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS ntru-gcrypt-wrapper.lo"
+   AC_DEFINE(USE_NTRU, 1, [Defined if this module should be included])
+fi
+
 LIST_MEMBER(crc, $enabled_digests)
 if test "$found" = "1" ; then
    GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc.lo"
diff --git a/sample/test_ntru_gcrypt.cpp b/sample/test_ntru_gcrypt.cpp
new file mode 100644
index 0000000..68eda77
--- /dev/null
+++ b/sample/test_ntru_gcrypt.cpp
@@ -0,0 +1,151 @@
+/* test_ntru_gcrypt.cpp
+ * Copyright (C) 2015, Security Innovation.
+ * Author Zhenfei Zhang <zzhang at securityinnovation.com>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt 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.
+ *
+ * Libgcrypt 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This code is an example of using libgcrypt instantiated with NTRUEncrypt
+ * For the latest version of the NTRUEncrypt specs, visit
+ *  https://github.com/NTRUOpenSourceProject/NTRUEncrypt
+ */
+
+#include <iostream>
+#include <gcrypt.h>
+
+using namespace std;
+
+#ifndef _MAX_NTRU_BUF_SIZE_
+#define _MAX_NTRU_BUF_SIZE_ 4000
+#endif
+
+#define DEBUG
+
+/* Dumps a buffer in hex to the screen for debugging */
+
+void gcrypt_init();
+
+int main() {
+
+    gcrypt_init();
+    gcry_error_t err = 0;
+    gcry_sexp_t ntru_parms;
+    gcry_sexp_t ntru_keypair;
+    gcry_sexp_t data;
+    gcry_sexp_t cipher;
+
+    /*
+     * Check if NTRU is avaliable
+     */
+    err = gcry_pk_test_algo (GCRY_PK_NTRU);
+    if (err)
+        cerr<<"NTRUEncrypt is not supported: "<<err<<endl;
+
+    /*
+     * initialization
+     * (genkey(ntru(b256))), (genkey(ntru(n743))) = 256 bits security with dimension 743
+     * (genkey(ntru(b192))), (genkey(ntru(n593))) = 192 bits security with dimension 593
+     * (genkey(ntru(b128))), (genkey(ntru(n439))) = 128 bits security with dimension 439
+     *
+     */
+    err = gcry_sexp_build(&ntru_parms, NULL, "(genkey(ntru(b128)))");
+
+    /*
+     * start key generation
+     */
+    err = gcry_pk_genkey(&ntru_keypair, ntru_parms);
+
+    /*
+     * parse key pair into pubk and privk
+     */
+    gcry_sexp_t pubk = gcry_sexp_find_token(ntru_keypair, "public-key", 0);
+    gcry_sexp_t privk = gcry_sexp_find_token(ntru_keypair, "private-key", 0);
+
+#ifdef  DEBUG
+    /*
+     * dump public key and private key
+     */
+    cerr<<"error in key gen ?: "<<err<<endl;
+    gcry_sexp_dump (pubk);
+    gcry_sexp_dump (privk);
+#endif
+
+    const unsigned char* msg = (const unsigned char*) "Hello SI. Let's encrypt";
+    err =   gcry_sexp_build(&data, NULL, "(data (flags raw) (value %s))", msg);
+    err +=  gcry_pk_encrypt(&cipher, data, pubk);
+
+#ifdef  DEBUG
+    /*
+     * dump message and cipher
+     */
+    cerr<<"error in encryption? : "<<err<<endl;
+    gcry_sexp_dump (data);
+    gcry_sexp_dump (cipher);
+#endif
+
+    err = gcry_pk_decrypt(&data, cipher, privk);
+
+#ifdef  DEBUG
+    /*
+     * dump recovered message
+     */
+    cerr<<"error in decryption? : "<<err<<endl;
+    gcry_sexp_dump (data);
+#endif
+
+	cout << "Hello SI" << endl; // prints Hello SI
+
+	return 0;
+}
+
+void gcrypt_init()
+{
+    /* Version check should be the very first call because it
+       makes sure that important subsystems are intialized. */
+    if (!gcry_check_version (GCRYPT_VERSION))
+    {
+        cout<<GCRYPT_VERSION<<endl;
+        printf("gcrypt: library version mismatch\n");
+    }
+
+    gcry_error_t err = 0;
+
+    /* We don't want to see any warnings, e.g. because we have not yet
+       parsed program options which might be used to suppress such
+       warnings. */
+    err = gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
+
+    /* ... If required, other initialization goes here.  Note that the
+       process might still be running with increased privileges and that
+       the secure memory has not been intialized.  */
+
+    /* Allocate a pool of 16k secure memory.  This make the secure memory
+       available and also drops privileges where needed.  */
+    err |= gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+
+    /* It is now okay to let Libgcrypt complain when there was/is
+       a problem with the secure memory. */
+    err |= gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
+
+    /* ... If required, other initialization goes here.  */
+
+    /* Tell Libgcrypt that initialization has completed. */
+    err |= gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+    if (err) {
+        printf("gcrypt: failed initialization");
+    }
+}
diff --git a/src/cipher.h b/src/cipher.h
index ef183fd..d551316 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -286,6 +286,6 @@ extern gcry_pk_spec_t _gcry_pubkey_spec_elg;
 extern gcry_pk_spec_t _gcry_pubkey_spec_elg_e;
 extern gcry_pk_spec_t _gcry_pubkey_spec_dsa;
 extern gcry_pk_spec_t _gcry_pubkey_spec_ecc;
-
+extern gcry_pk_spec_t _gcry_pubkey_spec_ntru;
 
 #endif /*G10_CIPHER_H*/
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 0984d11..a08cbaf 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -1054,7 +1054,8 @@ enum gcry_pk_algos
     GCRY_PK_ECC   = 18,     /* Generic ECC.  */
     GCRY_PK_ELG   = 20,     /* Elgamal       */
     GCRY_PK_ECDSA = 301,    /* (deprecated: use 18).  */
-    GCRY_PK_ECDH  = 302     /* (deprecated: use 18).  */
+    GCRY_PK_ECDH  = 302,    /* (deprecated: use 18).  */
+    GCRY_PK_NTRU  = 303     /* NTRU with dim = 439 */
   };
 
 /* Flags describing usage capabilities of a PK algorithm. */
diff --git a/tests/benchmark.c b/tests/benchmark.c
index b6cd7a8..efd7141 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -392,6 +392,143 @@ static const char sample_private_elg_key_3072[] =
 "  ))";
 
 
+
+/* A sample dimension 439 NTRU private key used for the selftests.  */
+static const char sample_secret_ntru_key439[] =
+"(private-key"
+"(ntru"
+"(NTRU"
+"AgMAAxD4/bZON4SkzqINu9cm4lgMLflx1zNmoGrkSSBfl4LPpCB2beJ1yyX2U7bEhr7e"
+"qZwBdYYDopvgyWFVr4H60z0XR6lh5Q01yRgs5tIzKQyUpym+Ce3fkZ/3+r2QBlGtAY4+6"
+"2irL7nZ4XYajYf0xE/9SLZfkFPXEzlJaByBgQPp/SdoC4mEDmei368+MeRz5ZfXkWaEQ3"
+"2byk7VuzuuoaVcMp3mpqxwImJmTozbUaPEo90iKZonzT9wt7n01sNUYm4ICzrYKSeLSMK"
+"cgRgOKdvJPEnGL4nRPzrLi9McNB1rITezC+3tg0f6uRvFz7ilLKjGxtI3lp7tQM2jx7wP"
+"Gw5+kaC/adaVTryEZprUZV7bRx1aALN6AS7MJsctFJXcx5ZzXHL9qc/BjBAM5bBCjnYMH"
+"SgK6f5xlS//+1Vi8A6Tzpluc37HGUJb7KEdIsXhnqrSY2ailTwjhIDVRxviAUiLn53oGn"
+"vdy+NU/gxtIxIonJ+GGm0k95/5qxyfSnyRepbU5ZQxDYPHFTiDtxs5nVpM5QoJQc6+ogx"
+"JSp8xEck52EgGSOH+GanJybIV6dWo0ykW1v8GQux2Bh3lePkI9csC7tHSZviGt+ILZdxA"
+"k/1lGofOhD7RhqFoYi8jYgdH/jPlAWIig4TilEfnEt4ynzPkcCRzk31DZYaXB1Qr86l1N"
+"wfOQWnSZjQsfVbMXVHbV5qP/f16o6SOTSy7JuzQ27giTGrdGGysRJoiRM0p2WQ5lnXPFz"
+"EU8KIFC3/ZUhUz/NPFZJL2RCdcKs0YNc44UHWJ3WRZlyGFH4n6cHlIF7mUptrykxejbhF"
+"PGimbCzGoFz5rFmagBvT7kIAZWYXqseQjextG91s8Wv0knasDCMA=)))";
+/* A sample dimension 439 NTRU public key used for the selftests.  */
+static const char sample_public_ntru_key439[] =
+"(public-key"
+"(ntru"
+"(NTRU"
+"AQMAAxD4/bZON4SkzqINu9cm4lgMLflx1zNmoGrkSSBfl4LPpCB2beJ1yyX2U7bEhr7e"
+"qZwBdYYDopvgyWFVr4H60z0XR6lh5Q01yRgs5tIzKQyUpym+Ce3fkZ/3+r2QBlGtAY4+6"
+"2irL7nZ4XYajYf0xE/9SLZfkFPXEzlJaByBgQPp/SdoC4mEDmei368+MeRz5ZfXkWaEQ3"
+"2byk7VuzuuoaVcMp3mpqxwImJmTozbUaPEo90iKZonzT9wt7n01sNUYm4ICzrYKSeLSMK"
+"cgRgOKdvJPEnGL4nRPzrLi9McNB1rITezC+3tg0f6uRvFz7ilLKjGxtI3lp7tQM2jx7wP"
+"Gw5+kaC/adaVTryEZprUZV7bRx1aALN6AS7MJsctFJXcx5ZzXHL9qc/BjBAM5bBCjnYMH"
+"SgK6f5xlS//+1Vi8A6Tzpluc37HGUJb7KEdIsXhnqrSY2ailTwjhIDVRxviAUiLn53oGn"
+"vdy+NU/gxtIxIonJ+GGm0k95/5qxyfSnyRepbU5ZQxDYPHFTiDtxs5nVpM5QoJQc6+ogx"
+"JSp8xEck52EgGSOH+GanJybIV6dWo0ykW1v8GQux2Bh3lePkI9csC7tHSZviGt+ILZdxA"
+"k/1lGofOhD7RhqFoYi8jYgdH/jPlAWIig4TilEfnEt4ynzPkcCRzk31DZYaXB1Qr86l1N"
+"wfOQWnSZjQsfVbMXVHbV5qP/f16o6SOTSy7JuzQ27giTGrdGGysRJoiRM0p2WQ5lnXPFz"
+"EU8KIFC3/ZUhUz/NPFZJL2RCdcKs0YNc44UHWJ3WRZlyGFH4n6cHlI)))";
+
+/* A sample dimension 493 NTRU private key used for the selftests.  */
+static const char sample_secret_ntru_key593[] =
+"(private-key"
+"(ntru"
+"(NTRU"
+"AgMABRDX622c5T6rDgfmUQVI2h1dgEZP/qC+8sx3CFo5Rj0+YQ5Tq/4xb95dmG5NuAEG"
+"DWb7sdiHbJgw6I/JxZmrjsu5cde8WxvVFTWT4O6jmxsuzJZhzq6iF7/99ne6DFy0sBCvk"
+"vEAEMFUgqyDCqFtc30EJpuTYZYOU7kIIKlhwnjqADeoK2hNKLgATGNSaWig3KztfO0o9x"
+"lThcVKLoeO0YNSNsL8IGsrbn7logFaSfglxGpxlAzrr0NFYrXbJ8+GPVpfLIQmqnIx6tb"
+"k7xOR/jtTLbfwpRsNGVwdtvA4wnigRDwF7QcRbfM60FWAWI3YEzGO2qbWGoaO8JZxcQBK"
+"kGbFWR5eNnK1RZfYPV3WPNg6LfTB4McgLHJH1X6qBzH5CQ0ehYL+ozKP0kurd7CkoI06D"
+"vae7oQOOMvxh1DtOq3dHMfG+r1a2dp9t8LGtRFp3fPgezfaCFOE8aa+MC6dnBvK+tZmLA"
+"0kKws0Nc8ZMfgyfL2pCicDBN2djVwmsYfdERRHGA11a16dkbajcHdF04dzK/9uioqF57E"
+"dkh2a7qnNw2fcSuLFXBTs31bDjh4vAE571JLWXKZkd0T2degI9apii3LIz/MESK1WBjkZ"
+"0zt5uG037RrKtSbFrDaTkkqsVYIow2zB/AiiU6RRkXe819fKEQRFXG7bqJz3RIjQ1QkS9"
+"2Sdc8DIiTeo/cVP8l38+Oi1hlacgw2F3A9TRN+YLfsJLRX0gcWciwz7pvrpyFUOgTIhxt"
+"FzkVgjwljffPdpcxkO8WSrwqqpZlxXuj08BuG9xpyN2IJ+Vw9SvLow5fVtGNi1nU4zx6l"
+"GTFOBP7rzLjHdPC+umCarBrCd9tmHN1heiiYDd7g8IfJfjbeKJ6p4Grq6WfU1f0TTzGkB"
+"a2rbJBIFjoI/tffbA6xm+P70kRkHq/ayWmk0qnQDTJQ51PJ+GvYl/VSVEGoIhS2V4YK26"
+"pJ2ieb98jelqLSozzgo/PczTd/KHO1srno5Id+YIeetf0bZ6J6gZja6WxfLvdmhMJNpXe"
+"ghdY6MsoT1kf4TQKOArchYFE7/wCl9rcg43Aj0JGdpLjVTDHnxvKXdiKjeOWAmDaDgny2"
+"KtSxqjIuiliQvAsc0ejVTkISjVJjXMeBxRXHUNlzi+GEvPFjmBBM3gnCuDCMPN8CoSNay"
+"xV8v4JARWynVwrzR)))";
+/* A sample dimension 439 NTRU public key used for the selftests.  */
+static const char sample_public_ntru_key593[] =
+"(public-key"
+"(ntru"
+"(NTRU"
+"AQMABRDX622c5T6rDgfmUQVI2h1dgEZP/qC+8sx3CFo5Rj0+YQ5Tq/4xb95dmG5NuAEG"
+"DWb7sdiHbJgw6I/JxZmrjsu5cde8WxvVFTWT4O6jmxsuzJZhzq6iF7/99ne6DFy0sBCvk"
+"vEAEMFUgqyDCqFtc30EJpuTYZYOU7kIIKlhwnjqADeoK2hNKLgATGNSaWig3KztfO0o9x"
+"lThcVKLoeO0YNSNsL8IGsrbn7logFaSfglxGpxlAzrr0NFYrXbJ8+GPVpfLIQmqnIx6tb"
+"k7xOR/jtTLbfwpRsNGVwdtvA4wnigRDwF7QcRbfM60FWAWI3YEzGO2qbWGoaO8JZxcQBK"
+"kGbFWR5eNnK1RZfYPV3WPNg6LfTB4McgLHJH1X6qBzH5CQ0ehYL+ozKP0kurd7CkoI06D"
+"vae7oQOOMvxh1DtOq3dHMfG+r1a2dp9t8LGtRFp3fPgezfaCFOE8aa+MC6dnBvK+tZmLA"
+"0kKws0Nc8ZMfgyfL2pCicDBN2djVwmsYfdERRHGA11a16dkbajcHdF04dzK/9uioqF57E"
+"dkh2a7qnNw2fcSuLFXBTs31bDjh4vAE571JLWXKZkd0T2degI9apii3LIz/MESK1WBjkZ"
+"0zt5uG037RrKtSbFrDaTkkqsVYIow2zB/AiiU6RRkXe819fKEQRFXG7bqJz3RIjQ1QkS9"
+"2Sdc8DIiTeo/cVP8l38+Oi1hlacgw2F3A9TRN+YLfsJLRX0gcWciwz7pvrpyFUOgTIhxt"
+"FzkVgjwljffPdpcxkO8WSrwqqpZlxXuj08BuG9xpyN2IJ+Vw9SvLow5fVtGNi1nU4zx6l"
+"GTFOBP7rzLjHdPC+umCarBrCd9tmHN1heiiYDd7g8IfJfjbeKJ6p4Grq6WfU1f0TTzGkB"
+"a2rbJBIFjoI/tffbA6xm+P70kRkHq/ayWmk0qnQDTJQ51PJ+GvYl/VSVEGoIhS2V4YK26"
+"pJ2ieb98jelqLSozzgo/PczTd/KHO1srno5Id+YIeetf0bZ6J6gZja6WxfLvdmhMJNpXe"
+"ghdY6MsoT1kf4TQKOArchYFE7/wCl9rcg43Aj0JGdpLjVTDHnxvKXdiKjeOWA=)))";
+
+
+/* A sample dimension 493 NTRU private key used for the selftests.  */
+static const char sample_secret_ntru_key743[] =
+"(private-key"
+"(ntru"
+"(NTRU"
+"AgMABhAKHhcsXOolid9nt56VJoRJiSfPdJzbH2BrvpbAj/05uFFDZcU6On43z7/cPuTv"
+"X/Ql3p/W10CZ7ymVAneaL1EqBAspeO+gkndJgBiEyo5W5DOgyB4pWpBupfLFXw5QXzpHb"
+"1m2GLQPtFFzadflevoAaf4XjlRcYB+/cQT+Z0Lrbrixd9BHdGQyw/esMZ8/FjnY8ikzx0"
+"iNCchFYNB6gPspEfrI28BQQxWRo0+lO1BaWqC9dxPHE7/WBxWErJP5YgrB/fR3UjrTJk5"
+"jSlvlRbQNPKqgWa8osjwbeJBFdvsWflA/uJPVZvrElAZ59o133CmjWnMoDpWfS8AiXDZU"
+"PP/UvSTFH78h4d71xTzxt+xZvrOnSIjDibJQyOnQ0owxSE2oBXEsjcI8zPrFtQjE0jeww"
+"MFhJagOHWHkV3S9NFrqUrFyRbLHO2ojGrUUzGwTxGyjQ8V0Mp2kkLks+wdx42BFsRnpsq"
+"3+C9mxEggLc1nIXb59c1hLBPZYAl13dE1K8wuY8J5dVWtmcZOv0Qll3qc861fGPlNwvn2"
+"Cgw81Y4HrNp4KRZNrgqnO8RV/ZVVMfY+lyXloKCPB7y+15SrXjAipFAPnXaIhwH2HAlSG"
+"onxfcsPRSXvEDNCAvjc9od0+ABW5bKLpCgiYR1o3p1iagTk6uHim47wJeogdpobrFkm40"
+"Oddub5ywml7x6Ovu9xz4nFXPMY+ptvMDRC24YsvXsWRfKCeZrWsrlA+kSNU9x3EBTD+sp"
+"hkkiXXXGh3mjYKG1jh6rxXVAV7nmclhiI1iouoo5lTpn7sPPlgQzSF+N2Kf5YywFFYgAD"
+"VQZqQHQYkbbiTUrmNqDYwx82LCPGuR2hH4SCbN5QEkI81gSiAQrGYgmk2LeOnmb5EpG9t"
+"xzYcuQ6nGlFX6LsB6Hhzf9AfPTDFAHRk7ACqw8cV8aGFb4qesfO+kEPqnzAoYqKg6hmTq"
+"R5RnKpqasgE3oiRKEM3z2vAV8SmA1FUotu1BW07n9QCnmq9VA6y9wR8jv5315XXQ6SHnw"
+"G2FBOQSTO3/XxW2/cBZIU8e+KSUE3QwY0Zj0dAM+alRJGfogpR6BDvonr34yu3jdzuCWT"
+"A9LBiLj5JRdeaIIRFHYCQYEnwl84rkPJFR7vDcv2zvNjokCU9KAd7LW3VN3EBIhDzwD7E"
+"ZWJWYzntkiWF8qgsZMqIlK/Yso7olwSUx7KFeNls00SvSpw2rM+muEfOmTq3VO7ZSYPeP"
+"QilbJoCzr0Ab5f0i0C6D/dxmM+gAaqTfr9hg/m+xBGXe0G4oDSqRaG2tl67daxwpapxqB"
+"vXUCVDj+E2WeiGKe+7CN5poVteiTvyymiwbySI8wOlaaXdBrhzNA/NnUVXIDNDSaC7fep"
+"pXOxRnfuAsSRuKRWRdJZgze+PJCTYppesCqacRpAp3Tdn6PkSP2EeAgazB6Dqjleex1sU"
+"twJqyJwNeyk37LQGEofADCzGJvR9RBQnrnchW/Kav7WtMA==)))";
+/* A sample dimension 439 NTRU public key used for the selftests.  */
+static const char sample_public_ntru_key743[] =
+"(public-key"
+"(ntru"
+"(NTRU"
+"AQMABhAKHhcsXOolid9nt56VJoRJiSfPdJzbH2BrvpbAj/05uFFDZcU6On43z7/cPuTv"
+"X/Ql3p/W10CZ7ymVAneaL1EqBAspeO+gkndJgBiEyo5W5DOgyB4pWpBupfLFXw5QXzpHb"
+"1m2GLQPtFFzadflevoAaf4XjlRcYB+/cQT+Z0Lrbrixd9BHdGQyw/esMZ8/FjnY8ikzx0"
+"iNCchFYNB6gPspEfrI28BQQxWRo0+lO1BaWqC9dxPHE7/WBxWErJP5YgrB/fR3UjrTJk5"
+"jSlvlRbQNPKqgWa8osjwbeJBFdvsWflA/uJPVZvrElAZ59o133CmjWnMoDpWfS8AiXDZU"
+"PP/UvSTFH78h4d71xTzxt+xZvrOnSIjDibJQyOnQ0owxSE2oBXEsjcI8zPrFtQjE0jeww"
+"MFhJagOHWHkV3S9NFrqUrFyRbLHO2ojGrUUzGwTxGyjQ8V0Mp2kkLks+wdx42BFsRnpsq"
+"3+C9mxEggLc1nIXb59c1hLBPZYAl13dE1K8wuY8J5dVWtmcZOv0Qll3qc861fGPlNwvn2"
+"Cgw81Y4HrNp4KRZNrgqnO8RV/ZVVMfY+lyXloKCPB7y+15SrXjAipFAPnXaIhwH2HAlSG"
+"onxfcsPRSXvEDNCAvjc9od0+ABW5bKLpCgiYR1o3p1iagTk6uHim47wJeogdpobrFkm40"
+"Oddub5ywml7x6Ovu9xz4nFXPMY+ptvMDRC24YsvXsWRfKCeZrWsrlA+kSNU9x3EBTD+sp"
+"hkkiXXXGh3mjYKG1jh6rxXVAV7nmclhiI1iouoo5lTpn7sPPlgQzSF+N2Kf5YywFFYgAD"
+"VQZqQHQYkbbiTUrmNqDYwx82LCPGuR2hH4SCbN5QEkI81gSiAQrGYgmk2LeOnmb5EpG9t"
+"xzYcuQ6nGlFX6LsB6Hhzf9AfPTDFAHRk7ACqw8cV8aGFb4qesfO+kEPqnzAoYqKg6hmTq"
+"R5RnKpqasgE3oiRKEM3z2vAV8SmA1FUotu1BW07n9QCnmq9VA6y9wR8jv5315XXQ6SHnw"
+"G2FBOQSTO3/XxW2/cBZIU8e+KSUE3QwY0Zj0dAM+alRJGfogpR6BDvonr34yu3jdzuCWT"
+"A9LBiLj5JRdeaIIRFHYCQYEnwl84rkPJFR7vDcv2zvNjokCU9KAd7LW3VN3EBIhDzwD7E"
+"ZWJWYzntkiWF8qgsZMqIlK/Yso7olwSUx7KFeNls00SvSpw2rM+muEfOmTq3VO7ZSYPeP"
+"QilbJoCzr0Ab5f0i0C6D/dxmM+gAaqTfr9hg/m+xBGXe0G4oDSqRaG2tl67daxwpapxqB"
+"vXUCVDj+E2WeiGKe+7CN5poVteiTvyymiwbySI8wOlaaXdBrhzNA/NnUVXIA==)))";
+
+
 #define DIM(v)		     (sizeof(v)/sizeof((v)[0]))
 #define DIMof(type,member)   DIM(((type *)0)->member)
 #define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\
@@ -1540,6 +1677,106 @@ ecc_bench (int iterations, int print_header)
     }
 #endif /*USE_ECC*/
 }
+static void
+ntru_bench (int iterations, int print_header)
+{
+#if USE_NTRU
+  gpg_error_t err;
+  gcry_sexp_t pub_key[3], sec_key[3];
+  int i, counter;
+  int dim[3] = { 439, 593,743 };
+  gcry_sexp_t data;
+  gcry_sexp_t enc[iterations];
+  gcry_sexp_t plain[iterations];
+  const unsigned char* msg = (const unsigned char*) "Hello SI. Let's encrypt.";
+  char timerbuf1[100];
+
+  err =   gcry_sexp_new(pub_key+0,sample_public_ntru_key439,strlen (sample_public_ntru_key439),1);
+  if (!err)
+	  err =   gcry_sexp_new(pub_key+1,sample_public_ntru_key593,strlen (sample_public_ntru_key593),1);
+  if (!err)
+	  err =   gcry_sexp_new(pub_key+2,sample_public_ntru_key743,strlen (sample_public_ntru_key743),1);
+  if (!err)
+	  err =   gcry_sexp_new(sec_key+0,sample_secret_ntru_key439,strlen (sample_secret_ntru_key439),1);
+  if (!err)
+	  err =   gcry_sexp_new(sec_key+1,sample_secret_ntru_key593,strlen (sample_secret_ntru_key593),1);
+  if (!err)
+	  err =   gcry_sexp_new(sec_key+2,sample_secret_ntru_key743,strlen (sample_secret_ntru_key743),1);
+
+  if (err)
+    {
+      fprintf (stderr, PGM ": converting sample keys failed: %s\n",
+               gcry_strerror (err));
+      exit (1);
+    }
+  err = gcry_sexp_build(&data, NULL, "(data (flags raw) (value %s))", msg);
+
+  if (print_header)
+    printf ("Algorithm         generate %4d*priv %4d*public\n"
+            "------------------------------------------------\n",
+            iterations, iterations );
+
+
+  for(i=0;i<3;i++)
+  {
+      for (counter=0;counter<iterations;counter++)
+      {
+          enc[counter] = NULL;
+          plain[counter] = NULL;
+      }
+
+      printf ("ntru %d dim             -", dim[i]);
+      fflush (stdout);
+
+      start_timer ();
+      for (counter=0; counter< iterations; counter++)
+        {
+          err = gcry_pk_encrypt (enc+counter, data, pub_key[i]);
+          if (err)
+            {
+              putchar ('\n');
+              fprintf (stderr, PGM ": encrypt failed: %s\n",
+                       gpg_strerror (err));
+              exit (1);
+            }
+        }
+      stop_timer ();
+
+      snprintf (timerbuf1, sizeof timerbuf1, "   %s", elapsed_time (1));
+      fflush (stdout);
+
+      start_timer ();
+      for (counter=0; counter < iterations; counter++)
+        {
+          err = gcry_pk_decrypt (plain+counter, enc[counter], sec_key[i]);
+          if (err)
+            {
+              putchar ('\n');
+              fprintf (stderr, PGM ":    decrypt failed: %s\n",
+                       gpg_strerror (err));
+              exit (1);
+            }
+        }
+      stop_timer ();
+      printf ("   %s  %s\n", elapsed_time (1), timerbuf1);
+      fflush (stdout);
+  }
+
+
+    for (counter=0; counter < iterations; counter++)
+    {
+        gcry_sexp_release (plain[counter]);
+        gcry_sexp_release (enc[counter]);
+    }
+    gcry_sexp_release (data);
+    for (i=0; i < 3; i++)
+    {
+        gcry_sexp_release (sec_key[i]);
+        gcry_sexp_release (pub_key[i]);
+    }
+
+#endif /*USE_NTRU*/
+}
 
 
 
@@ -1864,6 +2101,7 @@ main( int argc, char **argv )
       rsa_bench (pk_count, 1, no_blinding);
       elg_bench (pk_count, 0);
       dsa_bench (pk_count, 0);
+      ntru_bench(pk_count, 0);
       ecc_bench (pk_count, 0);
       putchar ('\n');
       mpi_bench ();
@@ -1917,6 +2155,7 @@ main( int argc, char **argv )
         rsa_bench (pk_count, 1, no_blinding);
         elg_bench (pk_count, 0);
         dsa_bench (pk_count, 0);
+        ntru_bench(pk_count, 0);
         ecc_bench (pk_count, 0);
     }
   else if ( !strcmp (*argv, "rsa"))
@@ -1939,6 +2178,11 @@ main( int argc, char **argv )
         gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
         ecc_bench (pk_count, 1);
     }
+  else if ( !strcmp (*argv, "ntru"))
+    {
+        gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        ntru_bench (pk_count, 1);
+    }
   else if ( !strcmp (*argv, "prime"))
     {
         gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);


More information about the Gcrypt-devel mailing list