Prototype implementation of IKE key exchange via NTRU encryption
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 18 Nov 2013 20:11:03 +0000 (21:11 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 27 Nov 2013 19:21:40 +0000 (20:21 +0100)
42 files changed:
configure.ac
src/libstrongswan/Makefile.am
src/libstrongswan/asn1/oid.txt
src/libstrongswan/crypto/diffie_hellman.c
src/libstrongswan/crypto/diffie_hellman.h
src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
src/libstrongswan/plugins/ntru/Makefile.am [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_drbg.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_drbg.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash_basics.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hmac.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hmac.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_msbyte_uint32.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_msbyte_uint32.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_platform.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha1.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha1.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha2.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha2.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha256.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha256.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_ke.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_ke.h [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_plugin.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_plugin.h [new file with mode: 0644]
testing/scripts/recipes/013_strongswan.mk

index 054870d..a3fb712 100644 (file)
@@ -239,6 +239,7 @@ ARG_ENABL_SET([pkcs11],         [enables the PKCS11 token support plugin.])
 ARG_ENABL_SET([ctr],            [enables the Counter Mode wrapper crypto plugin.])
 ARG_ENABL_SET([ccm],            [enables the CCM AEAD wrapper crypto plugin.])
 ARG_ENABL_SET([gcm],            [enables the GCM AEAD wrapper crypto plugin.])
+ARG_ENABL_SET([ntru],           [enables the NTRU crypto plugin.])
 ARG_ENABL_SET([addrblock],      [enables RFC 3779 address block constraint support.])
 ARG_ENABL_SET([unity],          [enables Cisco Unity extension plugin.])
 ARG_ENABL_SET([uci],            [enable OpenWRT UCI configuration plugin.])
@@ -1033,6 +1034,7 @@ ADD_PLUGIN([hmac],                 [s charon scripts nm cmd])
 ADD_PLUGIN([ctr],                  [s charon scripts nm cmd])
 ADD_PLUGIN([ccm],                  [s charon scripts nm cmd])
 ADD_PLUGIN([gcm],                  [s charon scripts nm cmd])
+ADD_PLUGIN([ntru],                 [s charon scripts nm cmd])
 ADD_PLUGIN([attr],                 [h charon])
 ADD_PLUGIN([attr-sql],             [h charon])
 ADD_PLUGIN([load-tester],          [c charon])
@@ -1170,6 +1172,7 @@ AM_CONDITIONAL(USE_CTR, test x$ctr = xtrue)
 AM_CONDITIONAL(USE_CCM, test x$ccm = xtrue)
 AM_CONDITIONAL(USE_GCM, test x$gcm = xtrue)
 AM_CONDITIONAL(USE_AF_ALG, test x$af_alg = xtrue)
+AM_CONDITIONAL(USE_NTRU, test x$ntru = xtrue)
 
 #  charon plugins
 # ----------------
@@ -1375,6 +1378,7 @@ AC_CONFIG_FILES([
        src/libstrongswan/plugins/ccm/Makefile
        src/libstrongswan/plugins/gcm/Makefile
        src/libstrongswan/plugins/af_alg/Makefile
+       src/libstrongswan/plugins/ntru/Makefile
        src/libstrongswan/plugins/test_vectors/Makefile
        src/libstrongswan/tests/Makefile
        src/libhydra/Makefile
index 63603bf..0b2bbff 100644 (file)
@@ -481,6 +481,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_NTRU
+  SUBDIRS += plugins/ntru
+if MONOLITHIC
+  libstrongswan_la_LIBADD += plugins/ntru/libstrongswan-ntru.la
+endif
+endif
+
 if USE_TEST_VECTORS
   SUBDIRS += plugins/test_vectors
 if MONOLITHIC
index 740dc50..c15a1cc 100644 (file)
@@ -93,6 +93,7 @@
                 0x04         "md5WithRSAEncryption"            OID_MD5_WITH_RSA
                 0x05         "sha-1WithRSAEncryption"  OID_SHA1_WITH_RSA
                 0x07         "id-RSAES-OAEP"                   OID_RSAES_OAEP
+                0x08         "id-mgf1"
                 0x09         "id-pSpecified"
                 0x0B         "sha256WithRSAEncryption" OID_SHA256_WITH_RSA
                 0x0C         "sha384WithRSAEncryption" OID_SHA384_WITH_RSA
                   0x02       ""
                     0x02     ""
                       0x4B   "TCGID"                                   OID_TCGID
+          0xc1               ""
+            0x16             "ntruCryptosystems"
+              0x01           "eess"
+                0x01         "eess1"
+                  0x01       "eess1-algs"
+                    0x01     "ntru-EESS1v1-SVES"
+                    0x02     "ntru-EESS1v1-SVSSA"
+                    0x03     "ntru-EESS1v1-NTRUSign"
+                  0x02       "eess1-params"
+                    0x01     "ees251ep1"
+                    0x02     "ees347ep1"
+                    0x03     "ees503ep1"
+                    0x07     "ees251sp2"
+                    0x0C     "ees251ep4"
+                    0x0D     "ees251ep5"
+                    0x0E     "ees251sp3"
+                    0x0F     "ees251sp4"
+                    0x10     "ees251sp5"
+                    0x11     "ees251sp6"
+                    0x12     "ees251sp7"
+                    0x13     "ees251sp8"
+                    0x14     "ees251sp9"
+                  0x03       "eess1-encodingMethods"
       0x05                   "security"
         0x05                 "mechanisms"
           0x07               "id-pkix"
index 3d319d2..f71ebc6 100644 (file)
@@ -45,7 +45,12 @@ ENUM_NEXT(diffie_hellman_group_names, MODP_1024_160, ECP_512_BP, ECP_521_BIT,
 ENUM_NEXT(diffie_hellman_group_names, MODP_NULL, MODP_CUSTOM, ECP_512_BP,
        "MODP_NULL",
        "MODP_CUSTOM");
-ENUM_END(diffie_hellman_group_names, MODP_CUSTOM);
+ENUM_NEXT(diffie_hellman_group_names, NTRU_112_BIT, NTRU_256_BIT, MODP_CUSTOM,
+       "NTRU_112",
+       "NTRU_128",
+       "NTRU_192",
+       "NTRU_256");
+ENUM_END(diffie_hellman_group_names, NTRU_256_BIT);
 
 
 /**
index edf6bbd..00d7003 100644 (file)
@@ -64,6 +64,11 @@ enum diffie_hellman_group_t {
        MODP_NULL = 1024,
        /** MODP group with custom generator/prime */
        MODP_CUSTOM = 1025,
+       /** Parameters defined by IEEE 1363.1, in PRIVATE USE */
+       NTRU_112_BIT = 1030,
+       NTRU_128_BIT = 1031,
+       NTRU_192_BIT = 1032,
+       NTRU_256_BIT = 1033
 };
 
 /**
index c484320..70e7915 100644 (file)
@@ -1,7 +1,7 @@
 %{
 /*
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+ * Copyright (C) 2009-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil, Switzerland
  *
  * 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
@@ -161,5 +161,9 @@ ecp224bp,         DIFFIE_HELLMAN_GROUP, ECP_224_BP,                0
 ecp256bp,         DIFFIE_HELLMAN_GROUP, ECP_256_BP,                0
 ecp384bp,         DIFFIE_HELLMAN_GROUP, ECP_384_BP,                0
 ecp512bp,         DIFFIE_HELLMAN_GROUP, ECP_512_BP,                0
+ntru112,          DIFFIE_HELLMAN_GROUP, NTRU_112_BIT,              0
+ntru128,          DIFFIE_HELLMAN_GROUP, NTRU_128_BIT,              0
+ntru192,          DIFFIE_HELLMAN_GROUP, NTRU_192_BIT,              0
+ntru256,          DIFFIE_HELLMAN_GROUP, NTRU_256_BIT,              0
 noesn,            EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS,   0
 esn,              EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS,      0
diff --git a/src/libstrongswan/plugins/ntru/Makefile.am b/src/libstrongswan/plugins/ntru/Makefile.am
new file mode 100644 (file)
index 0000000..67f4a57
--- /dev/null
@@ -0,0 +1,39 @@
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+       -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-ntru.la
+else
+plugin_LTLIBRARIES = libstrongswan-ntru.la
+endif
+
+libstrongswan_ntru_la_SOURCES = \
+       ntru_plugin.h ntru_plugin.c \
+       ntru_ke.h ntru_ke.c \
+       ntru_crypto/ntru_crypto.h ntru_crypto/ntru_crypto_error.h \
+       ntru_crypto/ntru_crypto_drbg.h ntru_crypto/ntru_crypto_drbg.c \
+       ntru_crypto/ntru_crypto_hash_basics.h \
+       ntru_crypto/ntru_crypto_hash.h ntru_crypto/ntru_crypto_hash.c \
+       ntru_crypto/ntru_crypto_hmac.h ntru_crypto/ntru_crypto_hmac.c \
+       ntru_crypto/ntru_crypto_msbyte_uint32.h \
+       ntru_crypto/ntru_crypto_msbyte_uint32.c \
+       ntru_crypto/ntru_crypto_ntru_convert.h \
+       ntru_crypto/ntru_crypto_ntru_convert.c \
+       ntru_crypto/ntru_crypto_ntru_encrypt.c \
+       ntru_crypto/ntru_crypto_ntru_encrypt_key.h \
+       ntru_crypto/ntru_crypto_ntru_encrypt_key.c \
+       ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h \
+       ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c \
+       ntru_crypto/ntru_crypto_ntru_mgf1.h ntru_crypto/ntru_crypto_ntru_mgf1.c \
+       ntru_crypto/ntru_crypto_ntru_poly.h ntru_crypto/ntru_crypto_ntru_poly.c \
+       ntru_crypto/ntru_crypto_platform.h ntru_crypto/ntru_crypto_sha.h\
+       ntru_crypto/ntru_crypto_sha1.h ntru_crypto/ntru_crypto_sha1.c\
+       ntru_crypto/ntru_crypto_sha2.h ntru_crypto/ntru_crypto_sha2.c\
+       ntru_crypto/ntru_crypto_sha256.h ntru_crypto/ntru_crypto_sha256.c
+
+libstrongswan_ntru_la_LDFLAGS = -module -avoid-version
+
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h
new file mode 100644 (file)
index 0000000..bb0f4b3
--- /dev/null
@@ -0,0 +1,337 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto.h
+ *
+ * Contents: Public header file for NTRUEncrypt.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_H
+#define NTRU_CRYPTO_H
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_drbg.h"
+#include "ntru_crypto_error.h"
+
+#if !defined( NTRUCALL )
+  #if !defined(WIN32) || defined (NTRUCRYPTO_STATIC)
+    // Linux, or a Win32 static library
+    #define NTRUCALL extern uint32_t
+  #elif defined (NTRUCRYPTO_EXPORTS)
+    // Win32 DLL build
+    #define NTRUCALL extern __declspec(dllexport) uint32_t
+  #else
+    // Win32 DLL import
+    #define NTRUCALL extern __declspec(dllimport) uint32_t
+  #endif
+#endif /* NTRUCALL */
+
+#if defined ( __cplusplus )
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* parameter set ID list */
+
+typedef enum _NTRU_ENCRYPT_PARAM_SET_ID {
+    NTRU_EES401EP1,
+    NTRU_EES449EP1,
+    NTRU_EES677EP1,
+    NTRU_EES1087EP2,
+    NTRU_EES541EP1,
+    NTRU_EES613EP1,
+    NTRU_EES887EP1,
+    NTRU_EES1171EP1,
+    NTRU_EES659EP1,
+    NTRU_EES761EP1,
+    NTRU_EES1087EP1,
+    NTRU_EES1499EP1,
+    NTRU_EES401EP2,
+    NTRU_EES439EP1,
+    NTRU_EES593EP1,
+    NTRU_EES743EP1,
+} NTRU_ENCRYPT_PARAM_SET_ID;
+
+
+/* error codes */
+
+#define NTRU_OK                     0
+#define NTRU_FAIL                   1
+#define NTRU_BAD_PARAMETER          2
+#define NTRU_BAD_LENGTH             3
+#define NTRU_BUFFER_TOO_SMALL       4
+#define NTRU_INVALID_PARAMETER_SET  5
+#define NTRU_BAD_PUBLIC_KEY         6
+#define NTRU_BAD_PRIVATE_KEY        7
+#define NTRU_OUT_OF_MEMORY          8
+#define NTRU_BAD_ENCODING           9
+#define NTRU_OID_NOT_RECOGNIZED    10
+
+#define NTRU_RESULT(r)   ((uint32_t)((r) ? NTRU_ERROR_BASE + (r) : (r)))
+#define NTRU_RET(r)      return NTRU_RESULT((r))
+
+
+/* function declarations */
+
+/* ntru_crypto_ntru_encrypt
+ *
+ * Implements NTRU encryption (SVES) for the parameter set specified in
+ * the public key blob.
+ *
+ * Before invoking this function, a DRBG must be instantiated using
+ * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that
+ * instantiation the requested security strength must be at least as large
+ * as the security strength of the NTRU parameter set being used.
+ * Failure to instantiate the DRBG with the proper security strength will
+ * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH.
+ *
+ * The required minimum size of the output ciphertext buffer (ct) may be
+ * queried by invoking this function with ct = NULL.  In this case, no
+ * encryption is performed, NTRU_OK is returned, and the required minimum
+ * size for ct is returned in ct_len.
+ *
+ * When ct != NULL, at invocation *ct_len must be the size of the ct buffer.
+ * Upon return it is the actual size of the ciphertext.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if the DRBG handle is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than ct) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
+ *  (pubkey_blob_len or pt_len) is zero, or if pt_len exceeds the
+ *  maximum plaintext length for the parameter set.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
+ *  invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the ciphertext buffer
+ *  is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ *  allocated from the heap.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_encrypt(
+    DRBG_HANDLE     drbg_handle,     /*     in - handle for DRBG */
+    uint16_t        pubkey_blob_len, /*     in - no. of octets in public key
+                                                 blob */
+    uint8_t const  *pubkey_blob,     /*     in - pointer to public key */
+    uint16_t        pt_len,          /*     in - no. of octets in plaintext */
+    uint8_t const  *pt,              /*     in - pointer to plaintext */
+    uint16_t       *ct_len,          /* in/out - no. of octets in ct, addr for
+                                                 no. of octets in ciphertext */
+    uint8_t        *ct);             /*    out - address for ciphertext */
+
+
+/* ntru_crypto_ntru_decrypt
+ *
+ * Implements NTRU decryption (SVES) for the parameter set specified in
+ * the private key blob.
+ *
+ * The maximum size of the output plaintext may be queried by invoking
+ * this function with pt = NULL.  In this case, no decryption is performed,
+ * NTRU_OK is returned, and the maximum size the plaintext could be is
+ * returned in pt_len.
+ * Note that until the decryption is performed successfully, the actual size
+ * of the resulting plaintext cannot be known.
+ *
+ * When pt != NULL, at invocation *pt_len must be the size of the pt buffer.
+ * Upon return it is the actual size of the plaintext.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than pt) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
+ *  (privkey_blob) is zero, or if ct_len is invalid for the parameter set.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PRIVATE_KEY if the private-key blob is
+ *  invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the plaintext buffer
+ *  is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ *  allocated from the heap.
+ * Returns NTRU_ERROR_BASE + NTRU_FAIL if a decryption error occurs.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_decrypt(
+    uint16_t       privkey_blob_len, /*     in - no. of octets in private key
+                                                 blob */
+    uint8_t const *privkey_blob,     /*     in - pointer to private key */
+    uint16_t       ct_len,           /*     in - no. of octets in ciphertext */
+    uint8_t const *ct,               /*     in - pointer to ciphertext */
+    uint16_t      *pt_len,           /* in/out - no. of octets in pt, addr for
+                                                 no. of octets in plaintext */
+    uint8_t       *pt);              /*    out - address for plaintext */
+
+
+/* ntru_crypto_ntru_encrypt_keygen
+ *
+ * Implements key generation for NTRUEncrypt for the parameter set specified.
+ *
+ * Before invoking this function, a DRBG must be instantiated using
+ * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that
+ * instantiation the requested security strength must be at least as large
+ * as the security strength of the NTRU parameter set being used.
+ * Failure to instantiate the DRBG with the proper security strength will
+ * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH.
+ *
+ * The required minimum size of the output public-key buffer (pubkey_blob)
+ * may be queried by invoking this function with pubkey_blob = NULL.
+ * In this case, no key generation is performed, NTRU_OK is returned, and
+ * the required minimum size for pubkey_blob is returned in pubkey_blob_len.
+ *
+ * The required minimum size of the output private-key buffer (privkey_blob)
+ * may be queried by invoking this function with privkey_blob = NULL.
+ * In this case, no key generation is performed, NTRU_OK is returned, and
+ * the required minimum size for privkey_blob is returned in privkey_blob_len.
+ *
+ * The required minimum sizes of both pubkey_blob and privkey_blob may be
+ * queried as described above, in a single invocation of this function.
+ *
+ * When pubkey_blob != NULL and privkey_blob != NULL, at invocation
+ * *pubkey_blob_len must be the size of the pubkey_blob buffer and
+ * *privkey_blob_len must be the size of the privkey_blob buffer.
+ * Upon return, *pubkey_blob_len is the actual size of the public-key blob
+ * and *privkey_blob_len is the actual size of the private-key blob.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than pubkey_blob or privkey_blob) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_INVALID_PARAMETER_SET if the parameter-set
+ *  ID is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if either the pubkey_blob
+ * buffer or the privkey_blob buffer is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ *  allocated from the heap.
+ * Returns NTRU_ERROR_BASE + NTRU_FAIL if the polynomial generated for f is
+ *  not invertible in (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
+ *  Should this occur, this function should simply be invoked again.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_encrypt_keygen(
+    DRBG_HANDLE                drbg_handle,      /*     in - handle of DRBG */
+    NTRU_ENCRYPT_PARAM_SET_ID  param_set_id,     /*     in - parameter set ID */
+    uint16_t                  *pubkey_blob_len,  /* in/out - no. of octets in
+                                                             pubkey_blob, addr
+                                                             for no. of octets
+                                                             in pubkey_blob */
+    uint8_t                   *pubkey_blob,      /*    out - address for
+                                                             public key blob */
+    uint16_t                  *privkey_blob_len, /* in/out - no. of octets in
+                                                             privkey_blob, addr
+                                                             for no. of octets
+                                                             in privkey_blob */
+    uint8_t                   *privkey_blob);    /*    out - address for
+                                                             private key blob */
+
+
+/* ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo
+ *
+ * DER-encodes an NTRUEncrypt public-key from a public-key blob into a
+ * SubjectPublicKeyInfo field for inclusion in an X.509 certificate.
+ *
+ * The required minimum size of the output SubjectPublicKeyInfo buffer
+ * (encoded_subjectPublicKeyInfo) may be queried by invoking this function
+ * with encoded_subjectPublicKeyInfo = NULL.  In this case, no encoding is
+ * performed, NTRU_OK is returned, and the required minimum size for
+ * encoded_subjectPublicKeyInfo is returned in encoded_subjectPublicKeyInfo_len.
+ *
+ * When encoded_subjectPublicKeyInfo != NULL, at invocation
+ * *encoded_subjectPublicKeyInfo_len must be the size of the
+ * encoded_subjectPublicKeyInfo buffer.
+ * Upon return, it is the actual size of the encoded public key.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than encoded_subjectPublicKeyInfo) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if pubkey_blob_len is zero.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
+ *  invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the SubjectPublicKeyInfo
+ *  buffer is too small.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
+    uint16_t       pubkey_blob_len, /*     in - no. of octets in public-key
+                                                blob */
+    uint8_t const *pubkey_blob,     /*     in - ptr to public-key blob */
+    uint16_t      *encoded_subjectPublicKeyInfo_len,
+                                    /* in/out - no. of octets in encoded info,
+                                                address for no. of octets in
+                                                encoded info */
+    uint8_t       *encoded_subjectPublicKeyInfo);
+                                    /*    out - address for encoded info */
+
+
+/* ntru_crypto_ntru_encrypt_SubjectPublicKeyInfo2PublicKey
+ *
+ * Decodes a DER-encoded NTRUEncrypt public-key from a
+ * SubjectPublicKeyInfo field in an X.509 certificate and returns the
+ * public-key blob itself.
+ *
+ * The required minimum size of the output public-key buffer (pubkey_blob)
+ * may be queried by invoking this function with pubkey_blob = NULL.
+ * In this case, no decoding is performed, NTRU_OK is returned, and the
+ * required minimum size for pubkey_blob is returned in pubkey_blob_len.
+ *
+ * When pubkey_blob != NULL, at invocation *pubkey_blob_len must be the
+ * size of the pubkey_blob buffer.
+ * Upon return, it is the actual size of the public-key blob.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than pubkey_blob) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_ENCODING if the encoded data is
+ *  an invalid encoding of an NTRU public key.
+ * Returns NTRU_ERROR_BASE + NTRU_OID_NOT_RECOGNIZED if the
+ *  encoded data contains an OID that identifies an object other than
+ *  an NTRU public key.
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the pubkey_blob buffer
+ *  is too small.
+ */
+
+NTRUCALL
+ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(
+    uint8_t const  *encoded_data,    /*     in - ptr to subjectPublicKeyInfo
+                                                 in the encoded data */
+    uint16_t       *pubkey_blob_len, /* in/out - no. of octets in pubkey blob,
+                                                 address for no. of octets in
+                                                 pubkey blob */
+    uint8_t        *pubkey_blob,     /*    out - address for pubkey blob */
+    uint8_t       **next);           /*    out - address for ptr to encoded
+                                                 data following the 
+                                                 subjectPublicKeyInfo */
+
+
+#if defined ( __cplusplus )
+}
+#endif /* __cplusplus */
+
+
+#endif /* NTRU_CRYPTO_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_drbg.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_drbg.c
new file mode 100644 (file)
index 0000000..7f5a7c8
--- /dev/null
@@ -0,0 +1,724 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_drbg.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File:  ntru_crypto_drbg.c
+ *
+ * Contents: Implementation of a SHA-256 HMAC-based deterministic random byte
+ *           generator (HMAC_DRBG) as defined in ANSI X9.82, Part 3 - 2007.
+ *
+ * This implementation:
+ *   - allows for MAX_INSTANTIATIONS simultaneous drbg instantiations
+ *     (may be overridden on compiler command line)
+ *   - has a maximum security strength of 256 bits
+ *   - automatically uses SHA-256 for all security strengths
+ *   - allows a personalization string of up to MAX_PERS_STR_BYTES bytes
+ *   - implments reseeding
+ *   - does not implement additional input for reseeding or generation
+ *   - does not implement predictive resistance
+ *   - limits the number of bytes requested in one invocation of generate to
+ *     MAX_BYTES_PER_REQUEST
+ *   - uses a callback function to allow the caller to supply the
+ *     Get_entropy_input routine (entropy function)
+ *   - limits the number of bytes returned from the entropy function to
+ *     MAX_ENTROPY_NONCE_BYTES
+ *   - gets the nonce bytes along with the entropy input from the entropy
+ *     function
+ *   - automatically reseeds an instantitation after MAX_REQUESTS calls to
+ *     generate
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ntru_crypto_drbg.h"
+#include "ntru_crypto_hmac.h"
+
+
+/************************
+ * HMAC_DRBG parameters *
+ ************************/
+
+/* Note: nonce size is sec_strength_bits/2 */
+#define HMAC_DRBG_MAX_MIN_ENTROPY_NONCE_BYTES                                 \
+    (DRBG_MAX_SEC_STRENGTH_BITS + DRBG_MAX_SEC_STRENGTH_BITS/2)/8
+#define HMAC_DRBG_MAX_ENTROPY_NONCE_BYTES                                     \
+    HMAC_DRBG_MAX_MIN_ENTROPY_NONCE_BYTES * DRBG_MAX_BYTES_PER_BYTE_OF_ENTROPY
+#define HMAC_DRBG_MAX_REQUESTS            0xffffffff
+
+
+/*******************
+ * DRBG structures *
+ *******************/
+
+/* SHA256_HMAC_DRBG state structure */
+
+typedef struct {
+    uint32_t              sec_strength;  /* security strength in bits */
+    uint32_t              requests_left; /* generation requests remaining
+                                            before reseeding */
+    ENTROPY_FN            entropy_fn;    /* pointer to entropy function */
+    NTRU_CRYPTO_HMAC_CTX *hmac_ctx;      /* pointer to HMAC context */
+    uint8_t               V[33];         /* md_len size internal state + 1 */
+} SHA256_HMAC_DRBG_STATE;
+
+
+/* DRBG state structure
+ * Note: this could contain a DRBG_TYPE to direct allocation, instantiation,
+ *       and generation to multiple types of DRBGs; at present only the
+ *       SHA256_HMAC_DRBG is implemented
+ */
+
+typedef struct {
+    uint32_t    handle;
+    void       *state;
+} DRBG_STATE;
+
+
+/*************
+ * DRBG DATA *
+ *************/
+
+/* array of drbg states */
+
+static DRBG_STATE drbg_state[DRBG_MAX_INSTANTIATIONS];
+
+
+/******************************
+ * SHA256 HMAC_DRBG functions *
+ ******************************/
+
+/* sha256_hmac_drbg_update
+ *
+ * This routine is the SHA-256 HMAC_DRBG derivation function for
+ * instantiation, and reseeding, and it is used in generation as well.
+ * It updates the internal state.
+ *
+ * For instantiation, provided_data1 holds the entropy input and nonce;
+ * provided_data2 holds the optional personalization string.  Combined, this
+ * is the seed material.
+ *
+ * For reseeding, provided_data1 holds the entropy input;
+ * provided_data2 is NULL (because this implementation does not support
+ * additional input).
+ *
+ * For byte generation, both provided_data1 and provided_data2 are NULL.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns HMAC errors if they occur.
+ */
+
+static uint32_t
+sha256_hmac_drbg_update(
+    SHA256_HMAC_DRBG_STATE *s,
+    uint8_t                *key,                    /* md_len size array */
+    uint32_t                md_len,
+    uint8_t const          *provided_data1,
+    uint32_t                provided_data1_bytes,
+    uint8_t const          *provided_data2,
+    uint32_t                provided_data2_bytes)
+{
+    uint32_t result;
+
+    /* new key = HMAC(K, V || 0x00 [|| provided data1 [|| provided data2]] */
+
+    if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) != NTRU_CRYPTO_HMAC_OK)
+        return result;
+    s->V[md_len] = 0x00;
+    if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V, md_len + 1)) !=
+            NTRU_CRYPTO_HMAC_OK)
+        return result;
+    if (provided_data1) {
+        if ((result = ntru_crypto_hmac_update(s->hmac_ctx, provided_data1,
+                                              provided_data1_bytes)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        if (provided_data2) {
+            if ((result = ntru_crypto_hmac_update(s->hmac_ctx, provided_data2,
+                                                  provided_data2_bytes)) !=
+                    NTRU_CRYPTO_HMAC_OK)
+                return result;
+        }
+    }
+    if ((result = ntru_crypto_hmac_final(s->hmac_ctx, key)) !=
+            NTRU_CRYPTO_HMAC_OK)
+        return result;
+    if ((result = ntru_crypto_hmac_set_key(s->hmac_ctx, key)) !=
+            NTRU_CRYPTO_HMAC_OK)
+        return result;
+
+    /* new V = HMAC(K, V) */
+
+    if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) != NTRU_CRYPTO_HMAC_OK)
+        return result;
+    if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V, md_len)) !=
+            NTRU_CRYPTO_HMAC_OK)
+        return result;
+    if ((result = ntru_crypto_hmac_final(s->hmac_ctx, s->V)) !=
+            NTRU_CRYPTO_HMAC_OK)
+        return result;
+
+    /* if provided data exists, update K and V again */
+
+    if (provided_data1) {
+
+        /* new key = HMAC(K, V || 0x01 || provided data1 [|| provided data2] */
+
+        if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        s->V[md_len] = 0x01;
+        if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V, md_len + 1)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        if ((result = ntru_crypto_hmac_update(s->hmac_ctx, provided_data1,
+                                              provided_data1_bytes)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        if (provided_data2) {
+            if ((result = ntru_crypto_hmac_update(s->hmac_ctx, provided_data2,
+                                                  provided_data2_bytes)) !=
+                    NTRU_CRYPTO_HMAC_OK)
+                return result;
+        }
+        if ((result = ntru_crypto_hmac_final(s->hmac_ctx, key)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        if ((result = ntru_crypto_hmac_set_key(s->hmac_ctx, key)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+
+        /* new V = HMAC(K, V) */
+
+        if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V, md_len)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        if ((result = ntru_crypto_hmac_final(s->hmac_ctx, s->V)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+    }
+
+    memset(key, 0, md_len);
+    DRBG_RET(DRBG_OK);
+}
+
+
+/* sha256_hmac_drbg_instantiate
+ *
+ * This routine allocates and initializes a SHA-256 HMAC_DRBG internal state. 
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_BAD_LENGTH if the personalization string is too long.
+ * Returns DRBG_OUT_OF_MEMORY if the internal state cannot be allocated.
+ * Returns errors from HASH or SHA256 if those errors occur.
+ */
+
+static uint32_t
+sha256_hmac_drbg_instantiate(
+    uint32_t                 sec_strength_bits,  /* strength to instantiate */
+    uint8_t const           *pers_str,
+    uint32_t                 pers_str_bytes,
+    ENTROPY_FN               entropy_fn,
+    SHA256_HMAC_DRBG_STATE **state)
+{
+    uint8_t                 entropy_nonce[HMAC_DRBG_MAX_ENTROPY_NONCE_BYTES];
+    uint32_t                entropy_nonce_bytes;
+    uint32_t                min_bytes_of_entropy;
+    uint8_t                 num_bytes_per_byte_of_entropy;
+    uint8_t                 key[32];             /* array of md_len size */
+    SHA256_HMAC_DRBG_STATE *s;
+    uint32_t                result;
+    uint32_t                i;
+
+    /* check arguments */
+
+    if (pers_str_bytes > HMAC_DRBG_MAX_PERS_STR_BYTES)
+        DRBG_RET(DRBG_BAD_LENGTH);
+
+    /* calculate number of bytes needed for the entropy input and nonce
+     * for a SHA256_HMAC_DRBG, and get them from the entropy source
+     */
+
+    if (entropy_fn(GET_NUM_BYTES_PER_BYTE_OF_ENTROPY,
+                   &num_bytes_per_byte_of_entropy) == 0)
+        DRBG_RET(DRBG_ENTROPY_FAIL);
+    if ((num_bytes_per_byte_of_entropy == 0) ||
+            (num_bytes_per_byte_of_entropy >
+             DRBG_MAX_BYTES_PER_BYTE_OF_ENTROPY))
+        DRBG_RET(DRBG_ENTROPY_FAIL);
+
+    min_bytes_of_entropy = (sec_strength_bits + sec_strength_bits/2) / 8;
+    entropy_nonce_bytes = min_bytes_of_entropy * num_bytes_per_byte_of_entropy;
+    for (i = 0; i < entropy_nonce_bytes; i++)
+        if (entropy_fn(GET_BYTE_OF_ENTROPY, entropy_nonce+i) == 0)
+            DRBG_RET(DRBG_ENTROPY_FAIL);
+
+    /* allocate SHA256_HMAC_DRBG state */
+
+    s = (SHA256_HMAC_DRBG_STATE*) malloc(sizeof(SHA256_HMAC_DRBG_STATE));
+    if (s == NULL) {
+        DRBG_RET(DRBG_OUT_OF_MEMORY);
+    }
+
+    /* allocate HMAC context */
+
+    memset(key, 0, sizeof(key));
+    if ((result = ntru_crypto_hmac_create_ctx(NTRU_CRYPTO_HASH_ALGID_SHA256,
+                                            key, sizeof(key),
+                                            &s->hmac_ctx)) !=
+            NTRU_CRYPTO_HMAC_OK) {
+        free(s);
+        return  result;
+    }
+
+    /* init and update internal state */
+
+    memset(s->V, 0x01, sizeof(s->V));
+    if ((result = sha256_hmac_drbg_update(s, key, sizeof(key),
+                                       entropy_nonce, entropy_nonce_bytes,
+                                       pers_str, pers_str_bytes)) != DRBG_OK) {
+        (void) ntru_crypto_hmac_destroy_ctx(s->hmac_ctx);
+        memset(s->V, 0, sizeof(s->V));
+        free(s);
+    }
+    memset(entropy_nonce, 0, sizeof(entropy_nonce));
+
+    /* init instantiation parameters */
+
+    s->sec_strength = sec_strength_bits;
+    s->requests_left = HMAC_DRBG_MAX_REQUESTS;             
+    s->entropy_fn = entropy_fn;
+    *state = s;
+
+    return result;
+}
+
+
+/* sha256_hmac_drbg_free
+ *
+ * This routine frees a SHA-256 HMAC_DRBG internal state.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ */
+
+static void
+sha256_hmac_drbg_free(
+    SHA256_HMAC_DRBG_STATE *s)
+{
+    if (s->hmac_ctx) {
+        (void) ntru_crypto_hmac_destroy_ctx(s->hmac_ctx);
+    }
+    memset(s->V, 0, sizeof(s->V));
+    s->sec_strength = 0;
+    s->requests_left = 0;
+    s->entropy_fn = NULL;
+    free(s);
+}
+
+
+/* sha256_hmac_drbg_reseed
+ *
+ * This function reseeds an instantiated SHA256_HMAC DRBG.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns HMAC errors if they occur.
+ */
+
+static uint32_t
+sha256_hmac_drbg_reseed(
+    SHA256_HMAC_DRBG_STATE *s)
+{
+    uint8_t  entropy[HMAC_DRBG_MAX_ENTROPY_NONCE_BYTES];
+    uint32_t entropy_bytes;
+    uint32_t min_bytes_of_entropy;
+    uint8_t  num_bytes_per_byte_of_entropy;
+    uint8_t  key[32];   // array of md_len size for sha256_hmac_drbg_update()
+    uint32_t result;
+    uint32_t i;
+
+    /* calculate number of bytes needed for the entropy input
+     * for a SHA256_HMAC_DRBG, and get them from the entropy source
+     */
+
+    if (s->entropy_fn(GET_NUM_BYTES_PER_BYTE_OF_ENTROPY,
+                      &num_bytes_per_byte_of_entropy) == 0)
+        DRBG_RET(DRBG_ENTROPY_FAIL);
+    if ((num_bytes_per_byte_of_entropy == 0) ||
+            (num_bytes_per_byte_of_entropy >
+             DRBG_MAX_BYTES_PER_BYTE_OF_ENTROPY))
+        DRBG_RET(DRBG_ENTROPY_FAIL);
+
+    min_bytes_of_entropy = s->sec_strength / 8;
+    entropy_bytes = min_bytes_of_entropy * num_bytes_per_byte_of_entropy;
+    for (i = 0; i < entropy_bytes; i++)
+        if (s->entropy_fn(GET_BYTE_OF_ENTROPY, entropy+i) == 0)
+            DRBG_RET(DRBG_ENTROPY_FAIL);
+
+    /* update internal state */
+
+    if ((result = sha256_hmac_drbg_update(s, key, sizeof(key),
+                                          entropy, entropy_bytes, NULL, 0)) !=
+            DRBG_OK)
+        return result;
+
+    /* reset request counter */
+
+    s->requests_left = HMAC_DRBG_MAX_REQUESTS;             
+    DRBG_RET(DRBG_OK);
+}
+
+
+/* sha256_hmac_drbg_generate
+ *
+ * This routine generates pseudorandom bytes from a SHA256_HMAC DRBG.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_BAD_LENGTH if too many bytes are requested or the requested
+ *  security strength is too large.
+ * Returns HMAC errors if they occur.
+ */
+
+static uint32_t
+sha256_hmac_drbg_generate(
+    SHA256_HMAC_DRBG_STATE *s,
+    uint32_t                sec_strength_bits,
+    uint32_t                num_bytes,
+    uint8_t                *out)
+{
+    uint8_t  key[32];   // array of md_len size for sha256_hmac_drbg_update()
+    uint32_t result;
+
+    /* check if number of bytes requested exceeds the maximum allowed */
+
+    if (num_bytes > HMAC_DRBG_MAX_BYTES_PER_REQUEST)
+        DRBG_RET(DRBG_BAD_LENGTH);
+
+    /* check if drbg has adequate security strength */
+
+    if (sec_strength_bits > s->sec_strength)
+        DRBG_RET(DRBG_BAD_LENGTH);
+
+    /* check if max requests have been exceeded */
+
+    if (s->requests_left == 0)
+        if ((result = sha256_hmac_drbg_reseed(s)) != DRBG_OK)
+            return result;
+
+    /* generate pseudorandom bytes */
+
+    while (num_bytes > 0) {
+
+        /* generate md_len bytes = V = HMAC(K, V) */
+
+        if ((result = ntru_crypto_hmac_init(s->hmac_ctx)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        if ((result = ntru_crypto_hmac_update(s->hmac_ctx, s->V,
+                                              sizeof(key))) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+        if ((result = ntru_crypto_hmac_final(s->hmac_ctx, s->V)) !=
+                NTRU_CRYPTO_HMAC_OK)
+            return result;
+
+        /* copy generated bytes to output buffer */
+
+        if (num_bytes < sizeof(key)) {
+            memcpy(out, s->V, num_bytes);
+            num_bytes = 0;
+        } else {
+            memcpy(out, s->V, sizeof(key));
+            out += sizeof(key);
+            num_bytes -= sizeof(key);
+        }
+    }
+
+    /* update internal state */
+
+    if ((result = sha256_hmac_drbg_update(s, key, sizeof(key),
+                                          NULL, 0, NULL, 0)) != DRBG_OK)
+        return result;
+    s->requests_left--;
+
+    DRBG_RET(DRBG_OK);
+}
+
+
+/******************
+ * DRBG functions *
+ ******************/
+
+/* drbg_get_new_drbg
+ *
+ * This routine finds an uninstantiated drbg state and returns a pointer to it.
+ *
+ * Returns a pointer to an uninstantiated drbg state if found.
+ * Returns NULL if all drbg states are instantiated.
+ */
+
+static DRBG_STATE *
+drbg_get_new_drbg()
+{
+    int i;
+
+    for (i = 0; i < DRBG_MAX_INSTANTIATIONS; i++) {
+        if (drbg_state[i].state == NULL)
+            return drbg_state+i;
+    }
+    return NULL;
+}
+
+
+/* drbg_get_drbg
+ *
+ * This routine finds an instantiated drbg state given its handle, and returns
+ * a pointer to it.
+ *
+ * Returns a pointer to the drbg state if found.
+ * Returns NULL if the drbg state is not found.
+ */
+
+static DRBG_STATE *
+drbg_get_drbg(
+    DRBG_HANDLE handle)             /* in/out - drbg handle */
+{
+    int i;
+
+    for (i = 0; i < DRBG_MAX_INSTANTIATIONS; i++) {
+        if ((drbg_state[i].handle == handle) && drbg_state[i].state)
+            return drbg_state+i;
+    }
+    return NULL;
+}
+
+
+/* drbg_get_new_handle
+ *
+ * This routine gets a new, unique 32-bit handle.
+ *
+ * Returns the new DRBG handle.
+ */
+
+static DRBG_HANDLE
+drbg_get_new_handle(void)
+{
+    DRBG_HANDLE h = 0;
+
+    /* ensure the new handle is unique:
+     *  if it already exists, increment it
+     */
+
+    while (drbg_get_drbg(h) != NULL)
+        ++h;
+
+    return h;
+}
+
+
+/********************
+ * Public functions *
+ ********************/
+
+/* ntru_crypto_drbg_instantiate
+ *
+ * This routine instantiates a drbg with the requested security strength.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if an argument pointer is NULL.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_LENGTH if the security strength requested
+ *  or the personalization string is too large.
+ * Returns DRBG_ERROR_BASE + DRBG_OUT_OF_MEMORY if the internal state cannot be
+ *  allocated from the heap.
+ */
+
+uint32_t
+ntru_crypto_drbg_instantiate(
+    uint32_t       sec_strength_bits, /*  in - requested sec strength in bits */
+    uint8_t const *pers_str,          /*  in - ptr to personalization string */
+    uint32_t       pers_str_bytes,    /*  in - no. personalization str bytes */
+    ENTROPY_FN     entropy_fn,        /*  in - pointer to entropy function */
+    DRBG_HANDLE   *handle)            /* out - address for drbg handle */
+{
+    DRBG_STATE             *drbg = NULL;
+    SHA256_HMAC_DRBG_STATE *state = NULL;
+    uint32_t                result;
+
+    /* check arguments */
+
+    if ((!pers_str && pers_str_bytes) || !entropy_fn || !handle)
+        DRBG_RET(DRBG_BAD_PARAMETER);
+    if (sec_strength_bits > DRBG_MAX_SEC_STRENGTH_BITS)
+        DRBG_RET(DRBG_BAD_LENGTH);
+    if (pers_str && (pers_str_bytes == 0))
+        pers_str = NULL;
+
+    /* set security strength */
+
+    if (sec_strength_bits <= 112) {
+        sec_strength_bits = 112;
+    } else if (sec_strength_bits <= 128) {
+        sec_strength_bits = 128;
+    } else if (sec_strength_bits <= 192) {
+        sec_strength_bits = 192;
+    } else {
+        sec_strength_bits = 256;
+    }
+
+    /* get an uninstantiated drbg */
+
+    if ((drbg = drbg_get_new_drbg()) == NULL)
+        DRBG_RET(DRBG_NOT_AVAILABLE);
+
+    /* init entropy function */
+
+    if (entropy_fn(INIT, NULL) == 0)
+        DRBG_RET(DRBG_ENTROPY_FAIL);
+
+    /* instantiate a SHA-256 HMAC_DRBG */
+
+    if ((result = sha256_hmac_drbg_instantiate(sec_strength_bits,
+                                               pers_str, pers_str_bytes,
+                                               entropy_fn,
+                                               &state)) != DRBG_OK)
+        return result;
+
+    /* init drbg state */
+
+    drbg->handle = drbg_get_new_handle();
+    drbg->state = state;
+
+    /* return drbg handle */
+
+    *handle = drbg->handle;
+    DRBG_RET(DRBG_OK);
+} 
+
+
+/* ntru_crypto_drbg_uninstantiate
+ *
+ * This routine frees a drbg given its handle.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid.
+ */
+
+uint32_t
+ntru_crypto_drbg_uninstantiate(
+    DRBG_HANDLE handle)             /* in - drbg handle */
+{
+    DRBG_STATE *drbg = NULL;
+
+    /* find the instantiated drbg */
+
+    if ((drbg = drbg_get_drbg(handle)) == NULL)
+        DRBG_RET(DRBG_BAD_PARAMETER);
+
+    /* zero and free drbg state */
+
+    if (drbg->state) {
+        sha256_hmac_drbg_free((SHA256_HMAC_DRBG_STATE *)drbg->state);
+        drbg->state = NULL;
+    }
+
+    drbg->handle = 0;
+    DRBG_RET(DRBG_OK);
+}
+
+
+/* ntru_crypto_drbg_reseed
+ *
+ * This routine reseeds an instantiated drbg.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid.
+ * Returns HMAC errors if they occur.
+ */
+
+uint32_t
+ntru_crypto_drbg_reseed(
+    DRBG_HANDLE handle)             /* in - drbg handle */
+{
+    DRBG_STATE *drbg = NULL;
+
+    /* find the instantiated drbg */
+
+    if ((drbg = drbg_get_drbg(handle)) == NULL)
+        DRBG_RET(DRBG_BAD_PARAMETER);
+
+    /* reseed the SHA-256 HMAC_DRBG */
+
+    return sha256_hmac_drbg_reseed((SHA256_HMAC_DRBG_STATE *)drbg->state);
+}
+
+
+/* ntru_crypto_drbg_generate
+ *
+ * This routine generates pseudorandom bytes using an instantiated drbg.
+ * If the maximum number of requests has been reached, reseeding will occur.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid or if
+ *  an argument pointer is NULL.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_LENGTH if the security strength requested
+ *  is too large or the number of bytes requested is zero or too large.
+ * Returns HMAC errors if they occur.
+ */
+
+uint32_t
+ntru_crypto_drbg_generate(
+    DRBG_HANDLE handle,             /*  in - drbg handle */
+    uint32_t    sec_strength_bits,  /*  in - requested sec strength in bits */
+    uint32_t    num_bytes,          /*  in - number of octets to generate */
+    uint8_t    *out)                /* out - address for generated octets */
+{
+    DRBG_STATE *drbg = NULL;
+
+    /* find the instantiated drbg */
+
+    if ((drbg = drbg_get_drbg(handle)) == NULL)
+        DRBG_RET(DRBG_BAD_PARAMETER);
+
+    /* check arguments */
+
+    if (!out)
+        DRBG_RET(DRBG_BAD_PARAMETER);
+    if (num_bytes == 0)
+        DRBG_RET(DRBG_BAD_LENGTH);
+
+    /* generate pseudorandom output from the SHA256_HMAC_DRBG */
+
+    return sha256_hmac_drbg_generate((SHA256_HMAC_DRBG_STATE *)drbg->state,
+                                     sec_strength_bits, num_bytes, out);
+}
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_drbg.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_drbg.h
new file mode 100644 (file)
index 0000000..3f02979
--- /dev/null
@@ -0,0 +1,193 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_drbg.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File:  ntru_crypto_drbg.h
+ *
+ * Contents: Public header file for ntru_crypto_drbg.c.
+ *
+ *****************************************************************************/
+
+
+#ifndef NTRU_CRYPTO_DRBG_H
+#define NTRU_CRYPTO_DRBG_H
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_error.h"
+
+#if !defined( NTRUCALL )
+  #if !defined(WIN32) || defined (NTRUCRYPTO_STATIC)
+    // Linux, or a Win32 static library
+    #define NTRUCALL extern uint32_t
+  #elif defined (NTRUCRYPTO_EXPORTS)
+    // Win32 DLL build
+    #define NTRUCALL extern __declspec(dllexport) uint32_t
+  #else
+    // Win32 DLL import
+    #define NTRUCALL extern __declspec(dllimport) uint32_t
+  #endif
+#endif /* NTRUCALL */
+
+#if defined ( __cplusplus )
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*******************
+ * DRBG parameters *
+ *******************/
+
+#if !defined(DRBG_MAX_INSTANTIATIONS)
+#define DRBG_MAX_INSTANTIATIONS                 4
+#endif
+#define DRBG_MAX_SEC_STRENGTH_BITS              256
+#define DRBG_MAX_BYTES_PER_BYTE_OF_ENTROPY      8
+
+
+/************************
+ * HMAC_DRBG parameters *
+ ************************/
+
+#define HMAC_DRBG_MAX_PERS_STR_BYTES            32
+#define HMAC_DRBG_MAX_BYTES_PER_REQUEST         1024
+
+
+/********************
+ * type definitions *
+ ********************/
+
+typedef uint32_t DRBG_HANDLE;               /* drbg handle */
+typedef enum {                              /* entropy-function commands */
+    GET_NUM_BYTES_PER_BYTE_OF_ENTROPY = 0,
+    INIT,
+    GET_BYTE_OF_ENTROPY,
+} ENTROPY_CMD;
+typedef uint8_t (*ENTROPY_FN)(              /* get entropy function */
+                    ENTROPY_CMD  cmd,       /* command */
+                    uint8_t     *out);      /* address for output */
+
+
+/***************
+ * error codes *
+ ***************/
+
+#define DRBG_OK             0x00000000 /* no errors */
+#define DRBG_OUT_OF_MEMORY  0x00000001 /* can't allocate memory */
+#define DRBG_BAD_PARAMETER  0x00000002 /* null pointer */
+#define DRBG_BAD_LENGTH     0x00000003 /* invalid no. of bytes */
+#define DRBG_NOT_AVAILABLE  0x00000004 /* no instantiation slot available */
+#define DRBG_ENTROPY_FAIL   0x00000005 /* entropy function failure */
+
+/***************
+ * error macro *
+ ***************/
+
+#define DRBG_RESULT(r)  ((uint32_t)((r) ? DRBG_ERROR_BASE + (r) : (r)))
+#define DRBG_RET(r)     return DRBG_RESULT(r);
+
+
+/*************************
+ * function declarations *
+ *************************/
+
+/* ntru_crypto_drbg_instantiate
+ *
+ * This routine instantiates a drbg with the requested security strength.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if an argument pointer is NULL.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_LENGTH if the security strength requested
+ *  or the personalization string is too large.
+ * Returns DRBG_ERROR_BASE + DRBG_OUT_OF_MEMORY if the internal state cannot be
+ *  allocated from the heap.
+ */
+
+NTRUCALL
+ntru_crypto_drbg_instantiate(
+    uint32_t       sec_strength_bits, /*  in - requested sec strength in bits */
+    uint8_t const *pers_str,          /*  in - ptr to personalization string */
+    uint32_t       pers_str_bytes,    /*  in - no. personalization str bytes */
+    ENTROPY_FN     entropy_fn,        /*  in - pointer to entropy function */
+    DRBG_HANDLE   *handle);           /* out - address for drbg handle */
+
+
+/* ntru_crypto_drbg_uninstantiate
+ *
+ * This routine frees a drbg given its handle.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid.
+ */
+
+NTRUCALL
+ntru_crypto_drbg_uninstantiate(
+    DRBG_HANDLE handle);            /* in - drbg handle */
+
+
+/* ntru_crypto_drbg_reseed
+ *
+ * This routine reseeds an instantiated drbg.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid.
+ * Returns NTRU_CRYPTO_HMAC errors if they occur.
+ */
+
+NTRUCALL
+ntru_crypto_drbg_reseed(
+    DRBG_HANDLE handle);            /* in - drbg handle */
+
+
+/* ntru_crypto_drbg_generate
+ *
+ * This routine generates pseudorandom bytes using an instantiated drbg.
+ * If the maximum number of requests has been reached, reseeding will occur.
+ * See ANS X9.82: Part 3-2007.
+ *
+ * Returns DRBG_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if handle is not valid or if
+ *  an argument pointer is NULL.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_LENGTH if the security strength requested
+ *  is too large or the number of bytes requested is zero or too large.
+ * Returns NTRU_CRYPTO_HMAC errors if they occur.
+ */
+
+NTRUCALL
+ntru_crypto_drbg_generate(
+    DRBG_HANDLE handle,             /*  in - drbg handle */
+    uint32_t    sec_strength_bits,  /*  in - requested sec strength in bits */
+    uint32_t    num_bytes,          /*  in - number of octets to generate */
+    uint8_t    *out);               /* out - address for generated octets */
+
+
+#if defined ( __cplusplus )
+}
+#endif /* __cplusplus */
+
+
+#endif /* NTRU_CRYPTO_DRBG_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h
new file mode 100644 (file)
index 0000000..daf88e7
--- /dev/null
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_serror.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File:  ntru_crypto_error.h
+ *
+ * Contents: Contains base values for crypto error codes.
+ *
+ *****************************************************************************/
+
+
+#ifndef NTRU_CRYPTO_ERROR_H
+#define NTRU_CRYPTO_ERROR_H
+
+/* define base values for crypto error codes */
+
+#define HASH_ERROR_BASE     ((uint32_t)0x00000100)
+#define HMAC_ERROR_BASE     ((uint32_t)0x00000200)
+#define SHA_ERROR_BASE      ((uint32_t)0x00000400)
+#define DRBG_ERROR_BASE     ((uint32_t)0x00000a00)
+#define NTRU_ERROR_BASE     ((uint32_t)0x00003000)
+#define MGF1_ERROR_BASE     ((uint32_t)0x00004100)
+
+#endif /* NTRU_CRYPTO_ERROR_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash.c
new file mode 100644 (file)
index 0000000..e67bbfe
--- /dev/null
@@ -0,0 +1,335 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_hash.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_hash.c
+ *
+ * Contents: Routines implementing the hash object abstraction.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include "ntru_crypto_hash.h"
+
+
+typedef uint32_t (*NTRU_CRYPTO_HASH_INIT_FN)(
+    void        *c);
+typedef uint32_t (*NTRU_CRYPTO_HASH_UPDATE_FN)(
+    void        *c,
+    void const  *data,
+    uint32_t     len);
+typedef uint32_t (*NTRU_CRYPTO_HASH_FINAL_FN)(
+    void        *c,
+    void        *md);
+typedef uint32_t (*NTRU_CRYPTO_HASH_DIGEST_FN)(
+    void const  *data,
+    uint32_t     len,
+    void        *md);
+
+typedef struct _NTRU_CRYPTO_HASH_ALG_PARAMS {
+    uint8_t                     algid;
+    uint16_t                    block_length;
+    uint16_t                    digest_length;
+    NTRU_CRYPTO_HASH_INIT_FN    init;
+    NTRU_CRYPTO_HASH_UPDATE_FN  update;
+    NTRU_CRYPTO_HASH_FINAL_FN   final;
+    NTRU_CRYPTO_HASH_FINAL_FN   final_zero_pad;
+    NTRU_CRYPTO_HASH_DIGEST_FN  digest;
+} NTRU_CRYPTO_HASH_ALG_PARAMS;
+
+static NTRU_CRYPTO_HASH_ALG_PARAMS const algs_params[] = {
+    {
+        NTRU_CRYPTO_HASH_ALGID_SHA1,
+        SHA_1_BLK_LEN,
+        SHA_1_MD_LEN,
+        (NTRU_CRYPTO_HASH_INIT_FN) SHA_1_INIT_FN,
+        (NTRU_CRYPTO_HASH_UPDATE_FN) SHA_1_UPDATE_FN,
+        (NTRU_CRYPTO_HASH_FINAL_FN) SHA_1_FINAL_FN,
+        (NTRU_CRYPTO_HASH_FINAL_FN) SHA_1_FINAL_ZERO_PAD_FN,
+        (NTRU_CRYPTO_HASH_DIGEST_FN) SHA_1_DIGEST_FN,
+    },
+    {
+        NTRU_CRYPTO_HASH_ALGID_SHA256,
+        SHA_256_BLK_LEN,
+        SHA_256_MD_LEN,
+        (NTRU_CRYPTO_HASH_INIT_FN) SHA_256_INIT_FN,
+        (NTRU_CRYPTO_HASH_UPDATE_FN) SHA_256_UPDATE_FN,
+        (NTRU_CRYPTO_HASH_FINAL_FN) SHA_256_FINAL_FN,
+        (NTRU_CRYPTO_HASH_FINAL_FN) SHA_256_FINAL_ZERO_PAD_FN,
+        (NTRU_CRYPTO_HASH_DIGEST_FN) SHA_256_DIGEST_FN,
+    },
+};
+
+static int const numalgs = (sizeof(algs_params)/sizeof(algs_params[0]));
+
+
+/* get_alg_params
+ *
+ * Return a pointer to the hash algorithm parameters for the hash algorithm
+ * specified, by looking for algid in the global algs_params table.
+ * If not found, return NULL.
+ */
+static NTRU_CRYPTO_HASH_ALG_PARAMS const *
+get_alg_params(
+    NTRU_CRYPTO_HASH_ALGID algid)        //  in - the hash algorithm to find
+{
+    int i;
+
+    for (i = 0; i < numalgs; i++)
+        if (algs_params[i].algid == algid)
+            return &algs_params[i];
+
+    return NULL;
+}
+
+
+/* ntru_crypto_hash_set_alg
+ *
+ * Sets the hash algorithm for the hash context.  This must be called before
+ * any calls to ntru_crypto_hash_block_length(),
+ * ntru_crypto_hash_digest_length(), or ntru_crypto_hash_init() are made.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported.
+ */
+
+uint32_t
+ntru_crypto_hash_set_alg(
+    NTRU_CRYPTO_HASH_ALGID  algid,  //      in - hash algoirithm to be used
+    NTRU_CRYPTO_HASH_CTX   *c)      //  in/out - pointer to the hash context
+{
+    if (!c)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+    c->alg_params = get_alg_params(algid);
+    if (!c->alg_params) {
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+    }
+
+    HASH_RET(NTRU_CRYPTO_HASH_OK);
+}
+
+
+/* ntru_crypto_hash_block_length
+ *
+ * Gets the number of bytes in an input block for the hash algorithm
+ * specified in the hash context.  The hash algorithm must have been set
+ * in the hash context with a call to ntru_crypto_hash_set_alg() prior to
+ * calling this function.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_block_length(
+   NTRU_CRYPTO_HASH_CTX *c,         //  in - pointer to the hash context
+   uint16_t             *blk_len)   // out - address for block length in bytes
+{
+    if (!c || !blk_len)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+    if (!c->alg_params)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+    *blk_len = c->alg_params->block_length;
+    HASH_RET(NTRU_CRYPTO_HASH_OK);
+}
+
+
+/* ntru_crypto_hash_digest_length
+ *
+ * Gets the number of bytes needed to hold the message digest for the
+ * hash algorithm specified in the hash context.  The algorithm must have
+ * been set in the hash context with a call to ntru_crypto_hash_set_alg() prior
+ * to calling this function.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_digest_length(
+   NTRU_CRYPTO_HASH_CTX const *c,      //  in - pointer to the hash context
+   uint16_t                   *md_len) // out - addr for digest length in bytes
+{
+    if (!c || !md_len)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+    if (!c->alg_params)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+    *md_len = c->alg_params->digest_length;
+    HASH_RET(NTRU_CRYPTO_HASH_OK);
+}
+
+
+/* ntru_crypto_hash_init
+ *
+ * This routine performs standard initialization of the hash state.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_init(
+   NTRU_CRYPTO_HASH_CTX *c)         // in/out - pointer to hash context
+{
+    if (!c)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+    if (!c->alg_params)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+    return c->alg_params->init(&c->alg_ctx);
+}
+
+
+/* ntru_crypto_hash_update
+ *
+ * This routine processes input data and updates the hash calculation.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the
+ *         hash algorithm. The size limit is dependent on the hash algorithm,
+ *         and not all algorithms have this limit.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_update(
+   NTRU_CRYPTO_HASH_CTX *c,         // in/out - pointer to hash context
+   uint8_t const        *data,      //     in - pointer to input data
+   uint32_t              data_len)  //     in - number of bytes of input data
+{
+    if (!c || (data_len && !data))
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+    if (!c->alg_params)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+    return c->alg_params->update(&c->alg_ctx, data, data_len);
+}
+
+
+/* ntru_crypto_hash_final
+ *
+ * This routine completes the hash calculation and returns the message digest.
+ * 
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_final(
+   NTRU_CRYPTO_HASH_CTX *c,         // in/out - pointer to hash context
+   uint8_t              *md)        //   out  - address for message digest
+{
+    if (!c || !md)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+    if (!c->alg_params)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+    return c->alg_params->final(&c->alg_ctx, md);
+}
+
+
+/* ntru_crypto_hash_final_zero_pad
+ *
+ * This routine completes the hash calculation using zero padding and
+ * returns the message digest.
+ * 
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+uint32_t
+ntru_crypto_hash_final_zero_pad(
+   NTRU_CRYPTO_HASH_CTX *c,         // in/out - pointer to hash context
+   uint8_t              *md)        //   out  - address for message digest
+{
+    if (!c || !md)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+    if (!c->alg_params)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+    return c->alg_params->final_zero_pad(&c->alg_ctx, md);
+}
+
+
+/* ntru_crypto_hash_digest
+ *
+ * This routine computes a message digest. It is assumed that the
+ * output buffer md is large enough to hold the output (see
+ * ntru_crypto_hash_digest_length)
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the
+ *         hash algorithm. The size limit is dependent on the hash algorithm,
+ *         and not all algorithms have this limit.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported.
+ */
+
+uint32_t
+ntru_crypto_hash_digest(
+   NTRU_CRYPTO_HASH_ALGID  algid,    //  in - the hash algorithm to use
+   uint8_t const          *data,     //  in - pointer to input data
+   uint32_t                data_len, //  in - number of bytes of input data
+   uint8_t                *md)       // out - address for message digest
+{
+    NTRU_CRYPTO_HASH_ALG_PARAMS const *alg_params = get_alg_params(algid);
+
+    if (!alg_params)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG);
+
+    if ((data_len && !data) || !md)
+        HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER);
+
+    return alg_params->digest(data, data_len, md);
+}
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash.h
new file mode 100644 (file)
index 0000000..cf023f3
--- /dev/null
@@ -0,0 +1,233 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_hash.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_hash.h
+ *
+ * Contents: Definitions and declarations for the hash object abstraction.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_HASH_H
+#define NTRU_CRYPTO_HASH_H
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_error.h"
+#include "ntru_crypto_hash_basics.h"
+#include "ntru_crypto_sha1.h"
+#include "ntru_crypto_sha256.h"
+
+
+/***************
+ * error macro *
+ ***************/
+
+#define HASH_RESULT(r)   ((uint32_t)((r) ? HASH_ERROR_BASE + (r) : (r)))
+#define HASH_RET(r)      return HASH_RESULT(r);
+
+
+/*************************
+ * structure definitions *
+ *************************/
+
+/* _NTRU_CRYPTO_HASH_ALG_PARAMS
+ *
+ * An opaque forward declaration for a private structure used
+ * internally by the hash object interface.
+ */
+
+struct _NTRU_CRYPTO_HASH_ALG_PARAMS;
+
+
+/* NTRU_CRYPTO_HASH_CTX
+ *
+ * Hash object context information.
+ */
+
+typedef struct {
+    struct _NTRU_CRYPTO_HASH_ALG_PARAMS const *alg_params;
+    union {
+        NTRU_CRYPTO_SHA1_CTX    sha1;
+        NTRU_CRYPTO_SHA2_CTX    sha256;
+    } alg_ctx;
+} NTRU_CRYPTO_HASH_CTX;
+
+
+/*************************
+ * function declarations *
+ *************************/
+
+/* ntru_crypto_hash_set_alg
+ *
+ * Sets the hash algorithm for the hash context.  This must be called before
+ * any calls to crypto_hash_block_length(), crypto_hash_digest_length(), or
+ * crypto_hash_init() are made.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported.
+ */
+
+extern uint32_t
+ntru_crypto_hash_set_alg(
+    NTRU_CRYPTO_HASH_ALGID algid,   //      in - hash algoirithm to be used
+    NTRU_CRYPTO_HASH_CTX  *c);      //  in/out - pointer to the hash context
+
+
+/* ntru_crypto_hash_block_length
+ *
+ * Gets the number of bytes in an input block for the hash algorithm
+ * specified in the hash context.  The hash algorithm must have been set
+ * in the hash context with a call to crypto_hash_set_alg() prior to
+ * calling this function.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_block_length(
+   NTRU_CRYPTO_HASH_CTX *c,         //  in - pointer to the hash context
+   uint16_t             *blk_len);  // out - address for block length in bytes
+
+
+/* ntru_crypto_hash_digest_length
+ *
+ * Gets the number of bytes needed to hold the message digest for the
+ * hash algorithm specified in the hash context.  The algorithm must have
+ * been set in the hash context with a call to crypto_hash_set_alg() prior
+ * to calling this function.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_digest_length(
+   NTRU_CRYPTO_HASH_CTX const *c,       //  in - pointer to the hash context
+   uint16_t                   *md_len); // out - addrfor digest length in bytes
+
+
+/* ntru_crypto_hash_init
+ *
+ * This routine initializes the hash state.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_init(
+   NTRU_CRYPTO_HASH_CTX *c);        // in/out - pointer to hash context
+
+
+/* ntru_crypto_hash_update
+ *
+ * This routine processes input data and updates the hash calculation.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the
+ *         hash algorithm. The size limit is dependent on the hash algorithm,
+ *         and not all algorithms have this limit.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_update(
+   NTRU_CRYPTO_HASH_CTX *c,         // in/out - pointer to hash context
+   uint8_t const        *data,      //     in - pointer to input data
+   uint32_t              data_len); //     in - number of bytes of input data
+
+
+/* ntru_crypto_hash_final
+ *
+ * This routine completes the hash calculation and returns the message digest.
+ * 
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_final(
+   NTRU_CRYPTO_HASH_CTX *c,         // in/out - pointer to hash context
+   uint8_t              *md);       //   out  - address for message digest
+
+
+/* ntru_crypto_hash_final_zero_pad
+ *
+ * This routine completes the hash calculation using zero padding and
+ * returns the message digest.
+ * 
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set.
+ */
+
+extern uint32_t
+ntru_crypto_hash_final_zero_pad(
+   NTRU_CRYPTO_HASH_CTX *c,         // in/out - pointer to hash context
+   uint8_t              *md);       //   out  - address for message digest
+
+
+/* ntru_crypto_hash_digest
+ *
+ * This routine computes a message digest. It is assumed that the
+ * output buffer md is large enough to hold the output (see
+ * crypto_hash_digest_length)
+ *
+ * Returns NTRU_CRYPTO_HASH_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the
+ *         hash algorithm. The size limit is dependent on the hash algorithm,
+ *         and not all algorithms have this limit.
+ * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported.
+ */
+
+extern uint32_t
+ntru_crypto_hash_digest(
+   NTRU_CRYPTO_HASH_ALGID  algid,    //  in - the hash algorithm to use
+   uint8_t const          *data,     //  in - pointer to input data
+   uint32_t                data_len, //  in - number of bytes of input data
+   uint8_t                *md);      // out - address for message digest
+
+
+#endif /* NTRU_CRYPTO_HASH_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash_basics.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hash_basics.h
new file mode 100644 (file)
index 0000000..99448d1
--- /dev/null
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_hash_basics.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_hash_basics.h
+ *
+ * Contents: Common definitions for all hash algorithms.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_HASH_BASICS_H
+#define NTRU_CRYPTO_HASH_BASICS_H
+
+#include "ntru_crypto_platform.h"
+
+
+/**************
+ * algorithms *
+ **************/
+
+typedef enum {
+    NTRU_CRYPTO_HASH_ALGID_NONE = 0,
+    NTRU_CRYPTO_HASH_ALGID_SHA1,
+    NTRU_CRYPTO_HASH_ALGID_SHA256,
+} NTRU_CRYPTO_HASH_ALGID;
+
+
+/***************
+ * error codes *
+ ***************/
+
+#define NTRU_CRYPTO_HASH_OK              ((uint32_t)0x00)
+#define NTRU_CRYPTO_HASH_FAIL            ((uint32_t)0x01)
+#define NTRU_CRYPTO_HASH_BAD_PARAMETER   ((uint32_t)0x02)
+#define NTRU_CRYPTO_HASH_OVERFLOW        ((uint32_t)0x03)
+#define NTRU_CRYPTO_HASH_BAD_ALG         ((uint32_t)0x20)
+#define NTRU_CRYPTO_HASH_OUT_OF_MEMORY   ((uint32_t)0x21)
+
+// For backward-compatibility
+typedef uint32_t NTRU_CRYPTO_HASH_ERROR;
+
+
+/*********
+ * flags *
+ *********/
+
+#define HASH_DATA_ONLY      0
+#define HASH_INIT           (1 << 0)
+#define HASH_FINISH         (1 << 1)
+#define HASH_ZERO_PAD       (1 << 2)
+
+
+#endif /* NTRU_CRYPTO_HASH_BASICS_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hmac.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hmac.c
new file mode 100644 (file)
index 0000000..715331b
--- /dev/null
@@ -0,0 +1,320 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_hmac.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_hmac.c
+ *
+ * Contents: Routines implementing the HMAC hash calculation.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "ntru_crypto_hmac.h"
+
+
+/* HMAC context */
+
+struct _NTRU_CRYPTO_HMAC_CTX {
+    NTRU_CRYPTO_HASH_CTX  hash_ctx;
+    uint8_t              *k0;
+    uint16_t              blk_len;
+    uint16_t              md_len;
+};
+
+
+/* ntru_crypto_hmac_create_ctx
+ *
+ * This routine creates an HMAC context, setting the hash algorithm and
+ * the key to be used.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK if successful.
+ * Returns NTRU_CRYPTO_HMAC_BAD_ALG if the specified algorithm is not supported.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HMAC_OUT_OF_MEMORY if memory cannot be allocated.
+ */
+
+uint32_t
+ntru_crypto_hmac_create_ctx(
+    NTRU_CRYPTO_HASH_ALGID   algid,   /*  in - the hash algorithm to be used */
+    uint8_t const           *key,     /*  in - pointer to the HMAC key */
+    uint32_t                 key_len, /*  in - number of bytes in HMAC key */
+    NTRU_CRYPTO_HMAC_CTX   **c)       /* out - address for pointer to HMAC
+                                               context */
+{
+    NTRU_CRYPTO_HMAC_CTX *ctx = NULL;
+    uint32_t              result;
+
+    /* check parameters */
+
+    if (!c || !key)
+        HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+    *c = NULL;
+
+    /* allocate memory for an HMAC context */
+
+    if ((ctx = (NTRU_CRYPTO_HMAC_CTX*) malloc(sizeof(NTRU_CRYPTO_HMAC_CTX))) ==
+            NULL)
+        HMAC_RET(NTRU_CRYPTO_HMAC_OUT_OF_MEMORY);
+
+    /* set the algorithm */
+
+    if (result = ntru_crypto_hash_set_alg(algid, &ctx->hash_ctx)) {
+        free(ctx);
+        HMAC_RET(NTRU_CRYPTO_HMAC_BAD_ALG);
+    }
+
+    /* set block length and digest length */
+
+    if ((result = ntru_crypto_hash_block_length(&ctx->hash_ctx,
+                                                &ctx->blk_len))  ||
+        (result = ntru_crypto_hash_digest_length(&ctx->hash_ctx,
+                                                 &ctx->md_len))) {
+        free(ctx);
+        return result;
+    }
+
+    /* allocate memory for K0 */
+
+    if ((ctx->k0 = (uint8_t*) malloc(ctx->blk_len)) == NULL) {
+        free(ctx);
+        HMAC_RET(NTRU_CRYPTO_HMAC_OUT_OF_MEMORY);
+    }
+
+    /* calculate K0 and store in HMAC context */
+
+    memset(ctx->k0, 0, ctx->blk_len);
+
+    /* check if key is too large */
+
+    if (key_len > ctx->blk_len) {
+
+        if (result = ntru_crypto_hash_digest(algid, key, key_len, ctx->k0)) {
+            memset(ctx->k0, 0, ctx->blk_len);
+            free(ctx->k0);
+            free(ctx);
+            return result;
+        }
+
+    } else
+        memcpy(ctx->k0, key, key_len);
+
+    /* return pointer to HMAC context */
+
+    *c = ctx;
+    HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_destroy_ctx
+ *
+ * Destroys an HMAC context.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK if successful.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_destroy_ctx(
+    NTRU_CRYPTO_HMAC_CTX *c)        /* in/out - pointer to HMAC context */
+{
+    if (!c || !c->k0)
+        HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+    /* clear key and release memory */
+
+    memset(c->k0, 0, c->blk_len);
+    free(c->k0);
+    free(c);
+
+    HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_get_md_len
+ *
+ * This routine gets the digest length of the HMAC.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_get_md_len(
+    NTRU_CRYPTO_HMAC_CTX const *c,       /*  in - pointer to HMAC context */
+    uint16_t                   *md_len)  /* out - address for digest length */
+{
+    /* check parameters */
+
+    if (!c || !md_len)
+        HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+    /* get digest length */
+
+    *md_len = c->md_len;
+    HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_set_key
+ *
+ * This routine sets a digest-length key into the HMAC context.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_set_key(
+    NTRU_CRYPTO_HMAC_CTX *c,        /*  in - pointer to HMAC context */
+    uint8_t const        *key)      /*  in - pointer to new HMAC key */
+{
+    /* check parameters */
+
+    if (!c || !key)
+        HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+    /* copy key */
+
+    memcpy(c->k0, key, c->md_len);
+    HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_init
+ *
+ * This routine performs standard initialization of the HMAC state.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_init(
+    NTRU_CRYPTO_HMAC_CTX *c)        /* in/out - pointer to HMAC context */
+{
+    uint32_t    result;
+    int         i;
+
+    /* check parameters */
+
+    if (!c)
+        HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+    /* init hash context and compute H(K0 ^ ipad) */
+
+    for (i = 0; i < c->blk_len; i++)
+        c->k0[i] ^= 0x36;                           /* K0 ^ ipad */
+    if ((result = ntru_crypto_hash_init(&c->hash_ctx))                       ||
+        (result = ntru_crypto_hash_update(&c->hash_ctx, c->k0, c->blk_len)))
+        return result;
+
+    HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_update
+ *
+ * This routine processes input data and updates the HMAC hash calculation.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OVERFLOW if more than bytes are hashed than the
+ *         underlying hash algorithm can handle.
+ */
+
+uint32_t
+ntru_crypto_hmac_update(
+    NTRU_CRYPTO_HMAC_CTX *c,         /* in/out - pointer to HMAC context */
+    const uint8_t        *data,      /*     in - pointer to input data */
+    uint32_t              data_len)  /*     in - no. of bytes of input data */
+{
+    uint32_t    result;
+
+    /* check parameters */
+
+    if (!c || (data_len && !data))
+        HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+    if (result = ntru_crypto_hash_update(&c->hash_ctx, data, data_len))
+        return result;
+
+    HMAC_RET(NTRU_CRYPTO_HMAC_OK);
+}
+
+
+/* ntru_crypto_hmac_final
+ *
+ * This routine completes the HMAC hash calculation and returns the
+ * message digest.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+uint32_t
+ntru_crypto_hmac_final(
+    NTRU_CRYPTO_HMAC_CTX *c,        /* in/out - pointer to HMAC context */
+    uint8_t              *md)       /*   out - address for message digest */
+{
+    uint32_t    result = NTRU_CRYPTO_HMAC_OK;
+    int         i;
+
+    /* check parameters */
+
+    if (!c || !md)
+        HMAC_RET(NTRU_CRYPTO_HMAC_BAD_PARAMETER);
+
+    /* form K0 ^ opad
+     * complete md = H((K0 ^ ipad) || data)
+     * compute  md = H((K0 ^ opad) || md)
+     * re-form K0
+     */
+
+    for (i = 0; i < c->blk_len; i++)
+        c->k0[i] ^= (0x36^0x5c);
+    if ((result = ntru_crypto_hash_final(&c->hash_ctx, md))                  ||
+        (result = ntru_crypto_hash_init(&c->hash_ctx))                       ||
+        (result = ntru_crypto_hash_update(&c->hash_ctx, c->k0, c->blk_len))  ||
+        (result = ntru_crypto_hash_update(&c->hash_ctx, md, c->md_len))      ||
+        (result = ntru_crypto_hash_final(&c->hash_ctx, md))) {
+    }
+    for (i = 0; i < c->blk_len; i++)
+        c->k0[i] ^= 0x5c;
+    return result;
+}
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hmac.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_hmac.h
new file mode 100644 (file)
index 0000000..1ec426b
--- /dev/null
@@ -0,0 +1,183 @@
+/*/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_hmac.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_hmac.h
+ *
+ * Contents: Definitions and declarations for the HMAC implementation.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_HMAC_H
+#define NTRU_CRYPTO_HMAC_H
+
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_hash.h"
+
+
+/***************
+ * error codes *
+ ***************/
+
+#define NTRU_CRYPTO_HMAC_OK              ((uint32_t)NTRU_CRYPTO_HASH_OK)
+#define NTRU_CRYPTO_HMAC_BAD_PARAMETER   ((uint32_t)NTRU_CRYPTO_HASH_BAD_PARAMETER)
+#define NTRU_CRYPTO_HMAC_BAD_ALG         ((uint32_t)NTRU_CRYPTO_HASH_BAD_ALG)
+#define NTRU_CRYPTO_HMAC_OUT_OF_MEMORY   ((uint32_t)NTRU_CRYPTO_HASH_OUT_OF_MEMORY)
+
+#define HMAC_RESULT(e)  ((uint32_t)((e) ? HMAC_ERROR_BASE + (e) : (e)))
+#define HMAC_RET(e)     return HMAC_RESULT(e)
+
+
+/*************************
+ * structure definitions *
+ *************************/
+
+/* HMAC context structure */
+
+struct _NTRU_CRYPTO_HMAC_CTX;            /* opaque forward reference */
+typedef struct _NTRU_CRYPTO_HMAC_CTX NTRU_CRYPTO_HMAC_CTX;
+
+
+/*************************
+ * function declarations *
+ *************************/
+
+/* ntru_crypto_hmac_create_ctx
+ *
+ * This routine creates an HMAC context, setting the hash algorithm and
+ * the key to be used.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK if successful.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HASH_OUT_OF_MEMORY if memory cannot be allocated.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_create_ctx(
+    NTRU_CRYPTO_HASH_ALGID   algid,   /*  in - the hash algorithm to be used */
+    uint8_t const           *key,     /*  in - pointer to the HMAC key */
+    uint32_t                 key_len, /*  in - number of bytes in HMAC key */
+    NTRU_CRYPTO_HMAC_CTX   **c);      /* out - address for pointer to HMAC
+                                               context */
+
+
+/* ntru_crypto_hmac_destroy_ctx
+ *
+ * Destroys an HMAC context.
+ *
+ * Returns NTRU_CRYPTO_HASH_OK if successful.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_destroy_ctx(
+    NTRU_CRYPTO_HMAC_CTX *c);       /* in/out - pointer to HMAC context */
+
+
+/* ntru_crypto_hmac_get_md_len
+ *
+ * This routine gets the digest length of the HMAC.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_get_md_len(
+    NTRU_CRYPTO_HMAC_CTX const *c,       /*  in - pointer to HMAC context */
+    uint16_t                   *md_len); /* out - address for digest length */
+
+
+/* ntru_crypto_hmac_set_key
+ *
+ * This routine sets a digest-length key into the HMAC context.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_set_key(
+    NTRU_CRYPTO_HMAC_CTX *c,        /*  in - pointer to HMAC context */
+    uint8_t const        *key);     /*  in - pointer to new HMAC key */
+
+
+/* ntru_crypto_hmac_init
+ *
+ * This routine performs standard initialization of the HMAC state.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_init(
+    NTRU_CRYPTO_HMAC_CTX *c);       /* in/out - pointer to HMAC context */
+
+
+/* ntru_crypto_hmac_update
+ *
+ * This routine processes input data and updates the HMAC hash calculation.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ * Returns NTRU_CRYPTO_HMAC_OVERFLOW if more than bytes are hashed than the underlying
+ *         hash algorithm can handle.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_update(
+    NTRU_CRYPTO_HMAC_CTX *c,         /* in/out - pointer to HMAC context */
+    uint8_t const        *data,      /*     in - pointer to input data */
+    uint32_t              data_len); /*     in - no. of bytes of input data */
+
+
+/* ntru_crypto_hmac_final
+ *
+ * This routine completes the HMAC hash calculation and returns the
+ * message digest.
+ *
+ * Returns NTRU_CRYPTO_HMAC_OK on success.
+ * Returns NTRU_CRYPTO_HMAC_FAIL with corrupted context.
+ * Returns NTRU_CRYPTO_HMAC_BAD_PARAMETER if inappropriate NULL pointers are
+ * passed.
+ */
+
+extern uint32_t
+ntru_crypto_hmac_final(
+    NTRU_CRYPTO_HMAC_CTX  *c,       /* in/out - pointer to HMAC context */
+    uint8_t              *md);      /*    out - address for message digest */
+
+
+#endif /* NTRU_CRYPTO_HMAC_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_msbyte_uint32.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_msbyte_uint32.c
new file mode 100644 (file)
index 0000000..e9492e3
--- /dev/null
@@ -0,0 +1,92 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_mbyte_uint32.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_msbyte_uint32.c
+ *
+ * Contents: Routines to convert between an array of bytes in network byte
+ *           order (most-significant byte first) and an array of uint32 words.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include "ntru_crypto_msbyte_uint32.h"
+
+
+/* ntru_crypto_msbyte_2_uint32()
+ *
+ * This routine converts an array of bytes in network byte order to an array
+ * of uint32_t, placing the first byte in the most significant byte of the
+ * first uint32_t word.
+ *
+ * The number of bytes in the input stream MUST be at least 4 times the
+ * number of words expected in the output array.
+ */
+
+void
+ntru_crypto_msbyte_2_uint32(
+    uint32_t       *words,      // out - pointer to the output uint32_t array
+    uint8_t const  *bytes,      //  in - pointer to the input byte array
+    uint32_t        n)          //  in - number of words in the output array
+{
+    uint32_t    i;
+
+    for (i = 0; i < n; i++) {
+        words[i]  = ((uint32_t) (*bytes++)) << 24;
+        words[i] |= ((uint32_t) (*bytes++)) << 16;
+        words[i] |= ((uint32_t) (*bytes++)) <<  8;
+        words[i] |=  (uint32_t) (*bytes++);
+    }
+}
+
+
+/* ntru_crypto_uint32_2_msbyte()
+ *
+ * This routine converts an array of uint32_t to an array of bytes in
+ * network byte order, placing the most significant byte of the first uint32_t
+ * word as the first byte of the output array.
+ *
+ * The number of bytes in the output stream will be 4 times the number of words
+ * specified in the input array.
+ */
+
+void
+ntru_crypto_uint32_2_msbyte(
+    uint8_t        *bytes,      // out - pointer to the output byte array
+    uint32_t const *words,      //  in - pointer to the input uint32_t array
+    uint32_t        n)          //  in - number of words in the input array
+{
+    uint32_t i;
+
+    for (i = 0; i < n; i++) {
+        *bytes++ = (uint8_t) (words[i] >> 24);
+        *bytes++ = (uint8_t) (words[i] >> 16);
+        *bytes++ = (uint8_t) (words[i] >>  8);
+        *bytes++ = (uint8_t) (words[i]      );
+    }
+}
+
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_msbyte_uint32.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_msbyte_uint32.h
new file mode 100644 (file)
index 0000000..7d2b0a6
--- /dev/null
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_msbyte_uint32.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_msbyte_uint32.h
+ *
+ * Contents: Definitions and declarations for converting between a most-
+ *           significant-first byte stream and a uint32_t array.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_MSBYTE_UINT32_H
+#define NTRU_CRYPTO_MSBYTE_UINT32_H
+
+
+#include "ntru_crypto_platform.h"
+
+
+/* ntru_crypto_msbyte_2_uint32()
+ *
+ * This routine converts an array of bytes in network byte order to an array
+ * of uint32_t, placing the first byte in the most significant byte of the
+ * first uint32_t word.
+ *
+ * The number of bytes in the input stream MUST be at least 4 times the
+ * number of words expected in the output array.
+ */
+
+extern void
+ntru_crypto_msbyte_2_uint32(
+    uint32_t       *words,      // out - pointer to the output uint32_t array
+    uint8_t const  *bytes,      //  in - pointer to the input byte array
+    uint32_t        n);         //  in - number of words in the output array
+
+
+/* ntru_crypto_uint32_2_msbyte()
+ *
+ * This routine converts an array of uint32_t to an array of bytes in
+ * network byte order, placing the most significant byte of the first uint32_t
+ * word as the first byte of the output array.
+ *
+ * The number of bytes in the output stream will be 4 times the number of words
+ * specified in the input array.
+ */
+
+extern void
+ntru_crypto_uint32_2_msbyte(
+    uint8_t        *bytes,      // out - pointer to the output byte array
+    uint32_t const *words,      //  in - pointer to the input uint32_t array
+    uint32_t        n);         //  in - number of words in the input array
+
+
+#endif /* NTRU_CRYPTO_MSBYTE_UINT32_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.c
new file mode 100644 (file)
index 0000000..3d6dfde
--- /dev/null
@@ -0,0 +1,581 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_convert.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_convert.c
+ *
+ * Contents: Conversion routines for NTRUEncrypt, including packing, unpacking,
+ *           and others.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto_ntru_convert.h"
+
+
+/* 3-bit to 2-trit conversion tables: 2 represents -1 */
+
+static uint8_t const bits_2_trit1[] = {0, 0, 0, 1, 1, 1, 2, 2};
+static uint8_t const bits_2_trit2[] = {0, 1, 2, 0, 1, 2, 0, 1};
+
+
+/* ntru_bits_2_trits
+ *
+ * Each 3 bits in an array of octets is converted to 2 trits in an array
+ * of trits.
+ *
+ * The octet array may overlap the end of the trit array.
+ */
+
+void
+ntru_bits_2_trits(
+    uint8_t const *octets,          /*  in - pointer to array of octets */
+    uint16_t       num_trits,       /*  in - number of trits to produce */
+    uint8_t       *trits)           /* out - address for array of trits */
+{
+    uint32_t bits24;
+    uint32_t bits3;
+    uint32_t shift;
+
+    assert(octets);
+    assert(trits);
+
+    while (num_trits >= 16) {
+
+        /* get next three octets */
+
+        bits24  = ((uint32_t)(*octets++)) << 16;
+        bits24 |= ((uint32_t)(*octets++)) <<  8;
+        bits24 |=  (uint32_t)(*octets++);
+
+        /* for each 3 bits in the three octets, output 2 trits */
+
+        bits3 = (bits24 >> 21) & 0x7;
+        *trits++ = bits_2_trit1[bits3];
+        *trits++ = bits_2_trit2[bits3];
+
+        bits3 = (bits24 >> 18) & 0x7;
+        *trits++ = bits_2_trit1[bits3];
+        *trits++ = bits_2_trit2[bits3];
+
+        bits3 = (bits24 >> 15) & 0x7;
+        *trits++ = bits_2_trit1[bits3];
+        *trits++ = bits_2_trit2[bits3];
+
+        bits3 = (bits24 >> 12) & 0x7;
+        *trits++ = bits_2_trit1[bits3];
+        *trits++ = bits_2_trit2[bits3];
+
+        bits3 = (bits24 >>  9) & 0x7;
+        *trits++ = bits_2_trit1[bits3];
+        *trits++ = bits_2_trit2[bits3];
+
+        bits3 = (bits24 >>  6) & 0x7;
+        *trits++ = bits_2_trit1[bits3];
+        *trits++ = bits_2_trit2[bits3];
+
+        bits3 = (bits24 >>  3) & 0x7;
+        *trits++ = bits_2_trit1[bits3];
+        *trits++ = bits_2_trit2[bits3];
+
+        bits3 = bits24 & 0x7;
+        *trits++ = bits_2_trit1[bits3];
+        *trits++ = bits_2_trit2[bits3];
+
+        num_trits -= 16;
+    }
+    if (num_trits == 0)
+        return;
+
+    /* get three octets */
+
+    bits24  = ((uint32_t)(*octets++)) << 16;
+    bits24 |= ((uint32_t)(*octets++)) <<  8;
+    bits24 |=  (uint32_t)(*octets++);
+
+    shift = 21;
+    while (num_trits) {
+
+        /* for each 3 bits in the three octets, output up to 2 trits
+         * until all trits needed are produced
+         */
+
+        bits3 = (bits24 >> shift) & 0x7;
+        shift -= 3;
+        *trits++ = bits_2_trit1[bits3];
+        if (--num_trits) {
+            *trits++ = bits_2_trit2[bits3];
+            --num_trits;
+        }
+    }
+}
+
+
+/* ntru_trits_2_bits
+ *
+ * Each 2 trits in an array of trits is converted to 3 bits, and the bits
+ * are packed in an array of octets.  A multiple of 3 octets is output.
+ * Any bits in the final octets not derived from trits are zero.
+ *
+ * Returns TRUE if all trits were valid.
+ * Returns FALSE if invalid trits were found.
+ */
+
+bool
+ntru_trits_2_bits(
+    uint8_t const *trits,           /*  in - pointer to array of trits */
+    uint32_t       num_trits,       /*  in - number of trits to convert */
+    uint8_t       *octets)          /* out - address for array of octets */
+{
+    bool     all_trits_valid = TRUE;
+    uint32_t bits24;
+    uint32_t bits3;
+    uint32_t shift;
+
+    assert(octets);
+    assert(trits);
+
+    while (num_trits >= 16) {
+
+        /* convert each 2 trits to 3 bits and pack */
+
+        bits3  = *trits++ * 3;
+        bits3 += *trits++;
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 = (bits3 << 21);
+
+        bits3  = *trits++ * 3;
+        bits3 += *trits++;
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 |= (bits3 << 18);
+
+        bits3  = *trits++ * 3;
+        bits3 += *trits++;
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 |= (bits3 << 15);
+
+        bits3  = *trits++ * 3;
+        bits3 += *trits++;
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 |= (bits3 << 12);
+
+        bits3  = *trits++ * 3;
+        bits3 += *trits++;
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 |= (bits3 <<  9);
+
+        bits3  = *trits++ * 3;
+        bits3 += *trits++;
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 |= (bits3 <<  6);
+
+        bits3  = *trits++ * 3;
+        bits3 += *trits++;
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 |= (bits3 <<  3);
+
+        bits3  = *trits++ * 3;
+        bits3 += *trits++;
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 |= bits3;
+
+        num_trits -= 16;
+
+        /* output three octets */
+
+        *octets++ = (uint8_t)((bits24 >> 16) & 0xff);
+        *octets++ = (uint8_t)((bits24 >>  8) & 0xff);
+        *octets++ = (uint8_t)(bits24 & 0xff);
+    }
+
+    bits24 = 0;
+    shift = 21;
+    while (num_trits) {
+
+        /* convert each 2 trits to 3 bits and pack */
+
+        bits3 = *trits++ * 3;
+        if (--num_trits) {
+            bits3 += *trits++;
+            --num_trits;
+        }
+        if (bits3 > 7) {
+            bits3 = 7;
+            all_trits_valid = FALSE;
+        }
+        bits24 |= (bits3 << shift);
+        shift -= 3;
+    }
+
+    /* output three octets */
+
+    *octets++ = (uint8_t)((bits24 >> 16) & 0xff);
+    *octets++ = (uint8_t)((bits24 >>  8) & 0xff);
+    *octets++ = (uint8_t)(bits24 & 0xff);
+
+    return all_trits_valid;
+}
+
+
+/* ntru_coeffs_mod4_2_octets
+ *
+ * Takes an array of ring element coefficients mod 4 and packs the
+ * results into an octet string.
+ */
+
+void
+ntru_coeffs_mod4_2_octets(
+    uint16_t        num_coeffs,     /*  in - number of coefficients */
+    uint16_t const *coeffs,         /*  in - pointer to coefficients */
+    uint8_t        *octets)         /* out - address for octets */
+{
+    uint8_t  bits2;
+    int      shift;
+    uint16_t i;
+
+    assert(coeffs);
+    assert(octets);
+
+    *octets = 0;
+    shift = 6;
+    for (i = 0; i < num_coeffs; i++) {
+        bits2 = (uint8_t)(coeffs[i] & 0x3);
+        *octets |= bits2 << shift;
+        shift -= 2;
+        if (shift < 0) {
+            ++octets;
+            *octets = 0;
+            shift = 6;
+        }
+    }
+}
+
+
+/* ntru_trits_2_octet
+ *
+ * Packs 5 trits in an octet, where a trit is 0, 1, or 2 (-1).
+ */
+
+void
+ntru_trits_2_octet(
+    uint8_t const *trits,           /*  in - pointer to trits */
+    uint8_t *octet)                 /* out - address for octet */
+{
+    int i;
+
+    assert(trits);
+    assert(octet);
+
+    *octet = 0;
+    for (i = 4; i >= 0; i--) {
+        *octet = (*octet * 3) + trits[i];
+    }
+}
+
+
+/* ntru_octet_2_trits
+ *
+ * Unpacks an octet to 5 trits, where a trit is 0, 1, or 2 (-1).
+ */
+
+void
+ntru_octet_2_trits(
+    uint8_t  octet,                 /*  in - octet to be unpacked */
+    uint8_t *trits)                 /* out - address for trits */
+{
+    int i;
+
+    assert(trits);
+
+    for (i = 0; i < 5; i++) {
+        trits[i] = octet % 3;
+        octet = (octet - trits[i]) / 3;
+    }
+}
+
+
+/* ntru_indices_2_trits
+ *
+ * Converts a list of the nonzero indices of a polynomial into an array of
+ * trits.
+ */
+
+void
+ntru_indices_2_trits(
+    uint16_t        in_len,         /*  in - no. of indices */
+    uint16_t const *in,             /*  in - pointer to list of indices */
+    bool            plus1,          /*  in - if list is +1 cofficients */
+    uint8_t        *out)            /* out - address of output polynomial */
+{
+    uint8_t     trit = plus1 ? 1 : 2;
+    uint16_t    i;
+
+    assert(in);
+    assert(out);
+
+    for (i = 0; i < in_len; i++) {
+        out[in[i]] = trit;
+    }
+}
+
+
+/* ntru_packed_trits_2_indices
+ *
+ * Unpacks an array of N trits and creates a list of array indices 
+ * corresponding to trits = +1, and list of array indices corresponding to
+ * trits = -1.
+ */
+
+void
+ntru_packed_trits_2_indices(
+    uint8_t const *in,              /*  in - pointer to packed-trit octets */
+    uint16_t       num_trits,       /*  in - no. of packed trits */
+    uint16_t      *indices_plus1,   /* out - address for indices of +1 trits */
+    uint16_t      *indices_minus1)  /* out - address for indices of -1 trits */
+{
+    uint8_t  trits[5];
+    uint16_t i = 0;
+    int      j;
+
+    assert(in);
+    assert(indices_plus1);
+    assert(indices_minus1);
+
+    while (num_trits >= 5) {
+        ntru_octet_2_trits(*in++, trits);
+        num_trits -= 5;
+        for (j = 0; j < 5; j++, i++) {
+            if (trits[j] == 1) {
+                *indices_plus1 = i;
+                ++indices_plus1;
+            } else if (trits[j] == 2) {
+                *indices_minus1 = i;
+                ++indices_minus1;
+            }
+        }
+    }
+    if (num_trits) {
+        ntru_octet_2_trits(*in, trits);
+        for (j = 0; num_trits && (j < 5); j++, i++) {
+            if (trits[j] == 1) {
+                *indices_plus1 = i;
+                ++indices_plus1;
+            } else if (trits[j] == 2) {
+                *indices_minus1 = i;
+                ++indices_minus1;
+            }
+            --num_trits;
+        }
+    }
+}
+
+
+/* ntru_indices_2_packed_trits
+ *
+ * Takes a list of array indices corresponding to elements whose values
+ * are +1 or -1, and packs the N-element array of trits described by these
+ * lists into octets, 5 trits per octet.
+ */
+
+void
+ntru_indices_2_packed_trits(
+    uint16_t const *indices,        /*  in - pointer to indices */
+    uint16_t        num_plus1,      /*  in - no. of indices for +1 trits */
+    uint16_t        num_minus1,     /*  in - no. of indices for -1 trits */
+    uint16_t        num_trits,      /*  in - N, no. of trits in array */
+    uint8_t        *buf,            /*  in - temp buf, N octets */
+    uint8_t        *out)            /* out - address for packed octets */
+{
+    assert(indices);
+    assert(buf);
+    assert(out);
+
+    /* convert indices to an array of trits */
+
+    memset(buf, 0, num_trits);
+    ntru_indices_2_trits(num_plus1, indices, TRUE, buf);
+    ntru_indices_2_trits(num_minus1, indices + num_plus1, FALSE, buf);
+
+    /* pack the array of trits */
+
+    while (num_trits >= 5) {
+        ntru_trits_2_octet(buf, out);
+        num_trits -= 5;
+        buf += 5;
+        ++out;
+    }
+    if (num_trits) {
+        uint8_t trits[5];
+
+        memcpy(trits, buf, num_trits);
+        memset(trits + num_trits, 0, sizeof(trits) - num_trits);
+        ntru_trits_2_octet(trits, out);
+    }
+}
+
+
+/* ntru_elements_2_octets
+ *
+ * Packs an array of n-bit elements into an array of
+ * ((in_len * n_bits) + 7) / 8 octets, 8 < n_bits < 16.
+ */
+
+void
+ntru_elements_2_octets(
+    uint16_t        in_len,         /*  in - no. of elements to be packed */
+    uint16_t const *in,             /*  in - ptr to elements to be packed */
+    uint8_t         n_bits,         /*  in - no. of bits in input element */
+    uint8_t        *out)            /* out - addr for output octets */
+{
+    uint16_t  temp;
+    int       shift;
+    uint16_t  i;
+
+    assert(in_len);
+    assert(in);
+    assert((n_bits > 8) && (n_bits < 16));
+    assert(out);
+
+    /* pack */
+
+    temp = 0;
+    shift = n_bits - 8;
+    i = 0;
+    while (i < in_len) {
+
+        /* add bits to temp to fill an octet and output the octet */
+
+        temp |= in[i] >> shift;
+        *out++ = (uint8_t)(temp & 0xff);
+        shift = 8 - shift;
+        if (shift < 1) {
+
+            /* next full octet is in current input word */
+
+            shift += n_bits;
+            temp = 0;
+
+        } else {
+
+            /* put remaining bits of input word in temp as partial octet,
+             * and increment index to next input word
+             */
+            temp = in[i] << (uint16_t)shift;
+
+            ++i;
+        }
+        shift = n_bits - shift;
+    }
+
+    /* output any bits remaining in last input word */
+
+    if (shift != n_bits - 8) {
+        *out++ = (uint8_t)(temp & 0xff);
+    }
+}
+
+
+/* ntru_octets_2_elements
+ *
+ * Unpacks an octet string into an array of ((in_len * 8) / n_bits)
+ * n-bit elements, 8 < n_bits < 16.  Any extra bits are discarded.
+ */
+
+void
+ntru_octets_2_elements(
+    uint16_t        in_len,         /*  in - no. of octets to be unpacked */
+    uint8_t const  *in,             /*  in - ptr to octets to be unpacked */
+    uint8_t         n_bits,         /*  in - no. of bits in output element */
+    uint16_t       *out)            /* out - addr for output elements */
+{
+    uint16_t  temp;
+    uint16_t  mask = (1 << n_bits) - 1;
+    int       shift;
+    uint16_t  i;
+
+    assert(in_len > 1);
+    assert(in);
+    assert((n_bits > 8) && (n_bits < 16));
+    assert(out);
+
+    /* unpack */
+
+    temp = 0;
+    shift = n_bits;
+    i = 0;
+    while (i < in_len) {
+        shift = 8 - shift;
+        if (shift < 0) {
+
+            /* the current octet will not fill the current element */
+
+            shift += n_bits;
+
+        } else {
+
+            /* add bits from the current octet to fill the current element and
+             * output the element
+             */
+
+            temp |= ((uint16_t)in[i]) >> shift;
+            *out++ = temp & mask;
+            temp = 0;
+        }
+
+        /* add the remaining bits of the current octet to start an element */
+
+        shift = n_bits - shift;
+        temp |= ((uint16_t)in[i]) << shift;
+        ++i;
+    }
+}
+
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_convert.h
new file mode 100644 (file)
index 0000000..1c4b35b
--- /dev/null
@@ -0,0 +1,183 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_convert.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_convert.h
+ *
+ * Contents: Definitions and declarations for conversion routines
+ *           for NTRUEncrypt, including packing, unpacking and others.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_NTRU_CONVERT_H
+#define NTRU_CRYPTO_NTRU_CONVERT_H
+
+#include "ntru_crypto.h"
+
+
+/* function declarations */
+
+/* ntru_bits_2_trits
+ *
+ * Each 3 bits in an array of octets is converted to 2 trits in an array
+ * of trits.
+ */
+
+extern void
+ntru_bits_2_trits(
+    uint8_t const *octets,          /*  in - pointer to array of octets */
+    uint16_t       num_trits,       /*  in - number of trits to produce */
+    uint8_t       *trits);          /* out - address for array of trits */
+
+
+/* ntru_trits_2_bits
+ *
+ * Each 2 trits in an array of trits is converted to 3 bits, and the bits
+ * are packed in an array of octets.  A multiple of 3 octets is output.
+ * Any bits in the final octets not derived from trits are zero.
+ *
+ * Returns TRUE if all trits were valid.
+ * Returns FALSE if invalid trits were found.
+ */
+
+extern bool
+ntru_trits_2_bits(
+    uint8_t const *trits,           /*  in - pointer to array of trits */
+    uint32_t       num_trits,       /*  in - number of trits to convert */
+    uint8_t       *octets);         /* out - address for array of octets */
+
+
+/* ntru_coeffs_mod4_2_octets
+ *
+ * Takes an array of coefficients mod 4 and packs the results into an
+ * octet string.
+ */
+
+extern void
+ntru_coeffs_mod4_2_octets(
+    uint16_t        num_coeffs,     /*  in - number of coefficients */
+    uint16_t const *coeffs,         /*  in - pointer to coefficients */
+    uint8_t        *octets);        /* out - address for octets */
+
+
+/* ntru_trits_2_octet
+ *
+ * Packs 5 trits in an octet, where a trit is 0, 1, or 2 (-1).
+ */
+
+extern void
+ntru_trits_2_octet(
+    uint8_t const *trits,           /*  in - pointer to trits */
+    uint8_t *octet);                /* out - address for octet */
+
+
+/* ntru_octet_2_trits
+ *
+ * Unpacks an octet to 5 trits, where a trit is 0, 1, or 2 (-1).
+ */
+
+extern void
+ntru_octet_2_trits(
+    uint8_t  octet,                 /*  in - octet to be unpacked */
+    uint8_t *trits);                /* out - address for trits */
+
+
+/* ntru_indices_2_trits
+ *
+ * Converts a list of the nonzero indices of a polynomial into an array of
+ * trits.
+ */
+
+extern void
+ntru_indices_2_trits(
+    uint16_t        in_len,         /*  in - no. of indices */
+    uint16_t const *in,             /*  in - pointer to list of indices */
+    bool            plus1,          /*  in - if list is +1 coefficients */
+    uint8_t        *out);           /* out - address of output polynomial */
+
+
+/* ntru_packed_trits_2_indices
+ *
+ * Unpacks an array of N trits and creates a list of array indices 
+ * corresponding to trits = +1, and list of array indices corresponding to
+ * trits = -1.
+ */
+
+extern void
+ntru_packed_trits_2_indices(
+    uint8_t const *in,              /*  in - pointer to packed-trit octets */
+    uint16_t       num_trits,       /*  in - no. of packed trits */
+    uint16_t      *indices_plus1,   /* out - address for indices of +1 trits */
+    uint16_t      *indices_minus1); /* out - address for indices of -1 trits */
+
+
+/* ntru_indices_2_packed_trits
+ *
+ * Takes a list of array indices corresponding to elements whose values
+ * are +1 or -1, and packs the N-element array of trits described by these
+ * lists into octets, 5 trits per octet.
+ */
+
+extern void
+ntru_indices_2_packed_trits(
+    uint16_t const *indices,        /*  in - pointer to indices */
+    uint16_t        num_plus1,      /*  in - no. of indices for +1 trits */
+    uint16_t        num_minus1,     /*  in - no. of indices for -1 trits */
+    uint16_t        num_trits,      /*  in - N, no. of trits in array */
+    uint8_t        *buf,            /*  in - temp buf, N octets */
+    uint8_t        *out);           /* out - address for packed octets */
+
+
+/* ntru_elements_2_octets
+ *
+ * Packs an array of n-bit elements into an array of
+ * ((in_len * n_bits) + 7) / 8 octets, 8 < n_bits < 16.
+ */
+
+extern void
+ntru_elements_2_octets(
+    uint16_t        in_len,         /*  in - no. of elements to be packed */
+    uint16_t const *in,             /*  in - ptr to elements to be packed */
+    uint8_t         n_bits,         /*  in - no. of bits in input element */
+    uint8_t        *out);           /* out - addr for output octets */
+
+
+/* ntru_octets_2_elements
+ *
+ * Unpacks an octet string into an array of ((in_len * 8) / n_bits)
+ * n-bit elements, 8 < n < 16.  Any extra bits are discarded.
+ */
+
+extern void
+ntru_octets_2_elements(
+    uint16_t        in_len,         /*  in - no. of octets to be unpacked */
+    uint8_t const  *in,             /*  in - ptr to octets to be unpacked */
+    uint8_t         n_bits,         /*  in - no. of bits in output element */
+    uint16_t       *out);           /* out - addr for output elements */
+
+
+#endif /* NTRU_CRYPTO_NTRU_CONVERT_H */
+
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c
new file mode 100644 (file)
index 0000000..5f99446
--- /dev/null
@@ -0,0 +1,1292 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_encrypt.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_encrypt.c
+ *
+ * Contents: Routines implementing NTRUEncrypt encryption and decryption and
+ *           key generation.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto.h"
+#include "ntru_crypto_ntru_encrypt_param_sets.h"
+#include "ntru_crypto_ntru_encrypt_key.h"
+#include "ntru_crypto_ntru_convert.h"
+#include "ntru_crypto_ntru_poly.h"
+#include "ntru_crypto_ntru_mgf1.h"
+#include "ntru_crypto_drbg.h"
+
+
+/* ntru_crypto_ntru_encrypt
+ *
+ * Implements NTRU encryption (SVES) for the parameter set specified in
+ * the public key blob.
+ *
+ * Before invoking this function, a DRBG must be instantiated using
+ * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that
+ * instantiation the requested security strength must be at least as large
+ * as the security strength of the NTRU parameter set being used.
+ * Failure to instantiate the DRBG with the proper security strength will
+ * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH.
+ *
+ * The required minimum size of the output ciphertext buffer (ct) may be
+ * queried by invoking this function with ct = NULL.  In this case, no
+ * encryption is performed, NTRU_OK is returned, and the required minimum
+ * size for ct is returned in ct_len.
+ *
+ * When ct != NULL, at invocation *ct_len must be the size of the ct buffer.
+ * Upon return it is the actual size of the ciphertext.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if the DRBG handle is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than ct) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
+ *  (pubkey_blob_len or pt_len) is zero, or if pt_len exceeds the
+ *  maximum plaintext length for the parameter set.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
+ *  invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the ciphertext buffer
+ *  is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ *  allocated from the heap.
+ */
+
+uint32_t
+ntru_crypto_ntru_encrypt(
+    DRBG_HANDLE     drbg_handle,     /*     in - handle of DRBG */
+    uint16_t        pubkey_blob_len, /*     in - no. of octets in public key
+                                                 blob */
+    uint8_t const  *pubkey_blob,     /*     in - pointer to public key */
+    uint16_t        pt_len,          /*     in - no. of octets in plaintext */
+    uint8_t const  *pt,              /*     in - pointer to plaintext */
+    uint16_t       *ct_len,          /* in/out - no. of octets in ct, addr for
+                                                 no. of octets in ciphertext */
+    uint8_t        *ct)              /*    out - address for ciphertext */
+{
+    NTRU_ENCRYPT_PARAM_SET *params = NULL;
+    uint8_t const          *pubkey_packed = NULL;
+    uint8_t                 pubkey_pack_type = 0x00;
+    uint16_t                packed_ct_len;
+    size_t                  scratch_buf_len;
+    uint32_t                dr;
+    uint32_t                dr1 = 0;
+    uint32_t                dr2 = 0;
+    uint32_t                dr3 = 0;
+    uint16_t                ring_mult_tmp_len;
+    int16_t                 m1 = 0;
+    uint16_t               *scratch_buf = NULL;
+    uint16_t               *ringel_buf = NULL;
+    uint16_t               *r_buf = NULL;
+    uint8_t                *b_buf = NULL;
+    uint8_t                *tmp_buf = NULL;
+    bool                    msg_rep_good = FALSE;
+    NTRU_CRYPTO_HASH_ALGID  hash_algid;
+    uint8_t                 md_len;
+    uint16_t                mprime_len = 0;
+    uint16_t                mod_q_mask;
+    uint32_t                result = NTRU_OK;
+
+    /* check for bad parameters */
+
+    if (!pubkey_blob || !pt || !ct_len)
+        NTRU_RET(NTRU_BAD_PARAMETER);
+    if ((pubkey_blob_len == 0) || (pt_len == 0))
+        NTRU_RET(NTRU_BAD_LENGTH);
+
+    /* get a pointer to the parameter-set parameters, the packing type for
+     * the public key, and a pointer to the packed public key
+     */
+
+    if (!ntru_crypto_ntru_encrypt_key_parse(TRUE /* pubkey */, pubkey_blob_len,
+                                            pubkey_blob, &pubkey_pack_type,
+                                            NULL, &params, &pubkey_packed,
+                                            NULL))
+        NTRU_RET(NTRU_BAD_PUBLIC_KEY);
+
+    /* return the ciphertext size if requested */
+
+    packed_ct_len = (params->N * params->q_bits + 7) >> 3;
+    if (!ct) {
+        *ct_len = packed_ct_len;
+        NTRU_RET(NTRU_OK);
+    }
+
+    /* check the ciphertext buffer size */
+
+    if (*ct_len < packed_ct_len) {
+        NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+    }
+
+    /* check the plaintext length */
+
+    if (pt_len > params->m_len_max) {
+        NTRU_RET(NTRU_BAD_LENGTH);
+    }
+
+    /* allocate memory for all operations */
+
+    if (params->is_product_form) {
+        ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */
+        dr1 =  params->dF_r & 0xff;
+        dr2 = (params->dF_r >>  8) & 0xff;
+        dr3 = (params->dF_r >> 16) & 0xff;
+        dr = dr1 + dr2 + dr3;
+    } else {
+        ring_mult_tmp_len = params->N;      /* N 16-bit word buffer */
+        dr = params->dF_r;
+    }
+    scratch_buf_len = (ring_mult_tmp_len << 1) +
+                                            /* X-byte temp buf for ring mult and
+                                                other intermediate results */
+                      (params->N << 1) +    /* 2N-byte buffer for ring elements
+                                                and overflow from temp buffer */
+                      (dr << 2) +           /* buffer for r indices */
+                      params->sec_strength_len;
+                                            /* buffer for b */
+    scratch_buf = malloc(scratch_buf_len);
+    if (!scratch_buf) {
+        NTRU_RET(NTRU_OUT_OF_MEMORY);
+    }
+    ringel_buf = scratch_buf + ring_mult_tmp_len;
+    r_buf = ringel_buf + params->N;
+    b_buf = (uint8_t *)(r_buf + (dr << 1));
+    tmp_buf = (uint8_t *)scratch_buf;
+
+    /* set hash algorithm based on security strength */
+
+    if (params->sec_strength_len <= 20) {
+        hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
+        md_len = 20;
+    } else {
+        hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
+        md_len = 32;
+    }
+
+    /* set constants */
+
+    mod_q_mask = params->q - 1;
+
+    /* loop until a message representative with proper weight is achieved */
+
+    do {
+        uint8_t *ptr = tmp_buf;
+
+        /* get b */
+        result = ntru_crypto_drbg_generate(drbg_handle,
+                                           params->sec_strength_len << 3,
+                                           params->sec_strength_len, b_buf);
+
+        if (result == NTRU_OK) {
+
+            /* form sData (OID || m || b || hTrunc) */
+
+            memcpy(ptr, params->OID, 3);
+            ptr += 3;
+            memcpy(ptr, pt, pt_len);
+            ptr += pt_len;
+            memcpy(ptr, b_buf, params->sec_strength_len);
+            ptr += params->sec_strength_len;
+            memcpy(ptr, pubkey_packed, params->sec_strength_len);
+            ptr += params->sec_strength_len;
+
+
+            /* generate r */
+
+            result = ntru_gen_poly(hash_algid, md_len,
+                                   params->min_IGF_hash_calls,
+                                   (uint16_t)(ptr - tmp_buf),
+                                   tmp_buf, tmp_buf,
+                                   params->N, params->c_bits,
+                                   params->no_bias_limit,
+                                   params->is_product_form,
+                                   params->dF_r << 1, r_buf);
+        }
+
+        if (result == NTRU_OK) {
+            uint16_t pubkey_packed_len;
+
+            /* unpack the public key */
+
+            assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS);
+            pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
+            ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
+                                   params->q_bits, ringel_buf);
+
+            /* form R = h * r */
+
+            if (params->is_product_form)
+                ntru_ring_mult_product_indices(ringel_buf, (uint16_t)dr1,
+                                               (uint16_t)dr2, (uint16_t)dr3,
+                                               r_buf, params->N, params->q,
+                                               scratch_buf, ringel_buf);
+            else
+                ntru_ring_mult_indices(ringel_buf, (uint16_t)dr, (uint16_t)dr,
+                                       r_buf, params->N, params->q,
+                                       scratch_buf, ringel_buf);
+
+            /* form R mod 4 */
+
+            ntru_coeffs_mod4_2_octets(params->N, ringel_buf, tmp_buf);
+
+            /* form mask */
+
+            result = ntru_mgftp1(hash_algid, md_len,
+                                 params->min_MGF_hash_calls,
+                                 (params->N + 3) / 4, tmp_buf,
+                                 tmp_buf + params->N, params->N, tmp_buf);
+        }
+        if (result == NTRU_OK) {
+            uint8_t  *Mtrin_buf = tmp_buf + params->N;
+            uint8_t  *M_buf = Mtrin_buf + params->N -
+                              (params->sec_strength_len + params->m_len_len +
+                               params->m_len_max + 2);
+            uint16_t  i;
+
+            /* form the padded message M */
+
+            ptr = M_buf;
+            memcpy(ptr, b_buf, params->sec_strength_len);
+            ptr += params->sec_strength_len;
+            if (params->m_len_len == 2)
+                *ptr++ = (uint8_t)((pt_len >> 8) & 0xff);
+            *ptr++ = (uint8_t)(pt_len & 0xff);
+            memcpy(ptr, pt, pt_len);
+            ptr += pt_len;
+
+            /* add an extra zero byte in case without it the bit string
+             * is not a multiple of 3 bits and therefore might not be
+             * able to produce enough trits
+             */
+
+            memset(ptr, 0, params->m_len_max - pt_len + 2);
+
+            /* convert M to trits (Mbin to Mtrin) */
+
+            mprime_len = params->N;
+            if (params->is_product_form)
+                --mprime_len;
+
+            ntru_bits_2_trits(M_buf, mprime_len, Mtrin_buf);
+
+            /* form the msg representative m' by adding Mtrin to mask, mod p */
+
+            if (params->is_product_form) {
+                for (i = 0; i < mprime_len; i++) {
+                    tmp_buf[i] = tmp_buf[i] + Mtrin_buf[i];
+                    if (tmp_buf[i] >= 3)
+                        tmp_buf[i] -= 3;
+                    if (tmp_buf[i] == 1)
+                        ++m1;
+                    else if (tmp_buf[i] == 2)
+                        --m1;
+                }
+            } else {
+                for (i = 0; i < mprime_len; i++) {
+                    tmp_buf[i] = tmp_buf[i] + Mtrin_buf[i];
+                    if (tmp_buf[i] >= 3)
+                        tmp_buf[i] -= 3;
+                }
+            }
+
+            /* check that message representative meets minimum weight
+             * requirements
+             */
+
+            if (params->is_product_form)
+                msg_rep_good = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) : 
+                                        (bool)( m1 <= params->min_msg_rep_wt);
+            else
+                msg_rep_good = ntru_poly_check_min_weight(mprime_len, tmp_buf,
+                                                       params->min_msg_rep_wt);
+            msg_rep_good = TRUE;
+        }
+    } while ((result == NTRU_OK) && !msg_rep_good);
+
+    if (result == NTRU_OK) {
+        uint16_t i;
+
+        /* form ciphertext e by adding m' to R mod q */
+
+        for (i = 0; i < mprime_len; i++) {
+            if (tmp_buf[i] == 1)
+                ringel_buf[i] = (ringel_buf[i] + 1) & mod_q_mask;
+            else if (tmp_buf[i] == 2)
+                ringel_buf[i] = (ringel_buf[i] - 1) & mod_q_mask;
+        }
+        if (params->is_product_form)
+            ringel_buf[i] = (ringel_buf[i] - m1) & mod_q_mask;
+
+        /* pack ciphertext */
+
+        ntru_elements_2_octets(params->N, ringel_buf, params->q_bits, ct);
+        *ct_len = packed_ct_len;
+    }
+
+    /* cleanup */
+
+    memset(scratch_buf, 0, scratch_buf_len);
+    free(scratch_buf);
+    
+    return result;
+}
+
+
+/* ntru_crypto_ntru_decrypt
+ *
+ * Implements NTRU decryption (SVES) for the parameter set specified in
+ * the private key blob.
+ *
+ * The maximum size of the output plaintext may be queried by invoking
+ * this function with pt = NULL.  In this case, no decryption is performed,
+ * NTRU_OK is returned, and the maximum size the plaintext could be is
+ * returned in pt_len.
+ * Note that until the decryption is performed successfully, the actual size
+ * of the resulting plaintext cannot be known.
+ *
+ * When pt != NULL, at invocation *pt_len must be the size of the pt buffer.
+ * Upon return it is the actual size of the plaintext.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than pt) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
+ *  (privkey_blob) is zero, or if ct_len is invalid for the parameter set.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PRIVATE_KEY if the private-key blob is
+ *  invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the plaintext buffer
+ *  is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ *  allocated from the heap.
+ * Returns NTRU_ERROR_BASE + NTRU_FAIL if a decryption error occurs.
+ */
+
+uint32_t
+ntru_crypto_ntru_decrypt(
+    uint16_t       privkey_blob_len, /*     in - no. of octets in private key
+                                                 blob */
+    uint8_t const *privkey_blob,     /*     in - pointer to private key */
+    uint16_t       ct_len,           /*     in - no. of octets in ciphertext */
+    uint8_t const *ct,               /*     in - pointer to ciphertext */
+    uint16_t      *pt_len,           /* in/out - no. of octets in pt, addr for
+                                                 no. of octets in plaintext */
+    uint8_t       *pt)               /*    out - address for plaintext */
+{
+    NTRU_ENCRYPT_PARAM_SET *params = NULL;
+    uint8_t const          *privkey_packed = NULL;
+    uint8_t const          *pubkey_packed = NULL;
+    uint8_t                 privkey_pack_type = 0x00;
+    uint8_t                 pubkey_pack_type = 0x00;
+    size_t                  scratch_buf_len;
+    uint32_t                dF_r;
+    uint32_t                dF_r1 = 0;
+    uint32_t                dF_r2 = 0;
+    uint32_t                dF_r3 = 0;
+    uint16_t                ring_mult_tmp_len;
+    int16_t                 m1 = 0;
+    uint16_t               *scratch_buf = NULL;
+    uint16_t               *ringel_buf1 = NULL;
+    uint16_t               *ringel_buf2 = NULL;
+    uint16_t               *i_buf = NULL;
+    uint8_t                *m_buf = NULL;
+    uint8_t                *tmp_buf = NULL;
+    uint8_t                *Mtrin_buf = NULL;
+    uint8_t                *M_buf = NULL;
+    uint8_t                *ptr = NULL;
+    NTRU_CRYPTO_HASH_ALGID  hash_algid;
+    uint8_t                 md_len;
+    uint16_t                cmprime_len;
+    uint16_t                mod_q_mask;
+    uint16_t                q_mod_p;
+    uint16_t                cm_len = 0;
+    uint16_t                num_zeros;
+    uint16_t                i;
+    bool                    decryption_ok = TRUE;
+    uint32_t                result = NTRU_OK;
+
+    /* check for bad parameters */
+
+    if (!privkey_blob || !ct || !pt_len)
+        NTRU_RET(NTRU_BAD_PARAMETER);
+    if ((privkey_blob_len == 0) || (ct_len == 0))
+        NTRU_RET(NTRU_BAD_LENGTH);
+
+    /* get a pointer to the parameter-set parameters, the packing types for
+     * the public and private keys, and pointers to the packed public and
+     * private keys
+     */
+
+    if (!ntru_crypto_ntru_encrypt_key_parse(FALSE /* privkey */,
+                                            privkey_blob_len,
+                                            privkey_blob, &pubkey_pack_type,
+                                            &privkey_pack_type, &params,
+                                            &pubkey_packed, &privkey_packed))
+        NTRU_RET(NTRU_BAD_PRIVATE_KEY);
+
+    /* return the max plaintext size if requested */
+
+    if (!pt) {
+        *pt_len = params->m_len_max;
+        NTRU_RET(NTRU_OK);
+    }
+
+    /* cannot check the plaintext buffer size until after the plaintext
+     * is derived, if we allow plaintext buffers only as large as the
+     * actual plaintext
+     */
+
+    /* check the ciphertext length */
+
+    if (ct_len != (params->N * params->q_bits + 7) >> 3)
+        NTRU_RET(NTRU_BAD_LENGTH);
+
+    /* allocate memory for all operations */
+
+    if (params->is_product_form) {
+        ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */
+        dF_r1 =  params->dF_r & 0xff;
+        dF_r2 = (params->dF_r >>  8) & 0xff;
+        dF_r3 = (params->dF_r >> 16) & 0xff;
+        dF_r = dF_r1 + dF_r2 + dF_r3;
+    } else {
+        ring_mult_tmp_len = params->N;      /* N 16-bit word buffer */
+        dF_r = params->dF_r;
+    }
+    scratch_buf_len = (ring_mult_tmp_len << 1) +
+                                            /* X-byte temp buf for ring mult and
+                                                other intermediate results */
+                      (params->N << 2) +    /* 2 2N-byte bufs for ring elements
+                                                and overflow from temp buffer */
+                      (dF_r << 2) +         /* buffer for F, r indices */
+                      params->m_len_max;    /* buffer for plaintext */
+    scratch_buf = malloc(scratch_buf_len);
+    if (!scratch_buf) {
+        NTRU_RET(NTRU_OUT_OF_MEMORY);
+    }
+    ringel_buf1 = scratch_buf + ring_mult_tmp_len;
+    ringel_buf2 = ringel_buf1 + params->N;
+    i_buf = ringel_buf2 + params->N;
+    m_buf = (uint8_t *)(i_buf + (dF_r << 1));
+    tmp_buf = (uint8_t *)scratch_buf;
+    Mtrin_buf = (uint8_t *)ringel_buf1;
+    M_buf = Mtrin_buf + params->N;
+
+    /* set hash algorithm based on security strength */
+
+    if (params->sec_strength_len <= 20) {
+        hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
+        md_len = 20;
+    } else {
+        hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
+        md_len = 32;
+    }
+
+    /* set constants */
+
+    mod_q_mask = params->q - 1;
+    q_mod_p = params->q % 3;
+
+    /* unpack the ciphertext */
+
+    ntru_octets_2_elements(ct_len, ct, params->q_bits, ringel_buf2);
+
+    /* unpack the private key */
+
+    if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS) {
+        ntru_packed_trits_2_indices(privkey_packed, params->N, i_buf,
+                                    i_buf + dF_r);
+
+    } else if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_INDICES) {
+        ntru_octets_2_elements(
+                (((uint16_t)dF_r << 1) * params->N_bits + 7) >> 3,
+                privkey_packed, params->N_bits, i_buf);
+
+    } else {
+        assert(FALSE);
+    }
+
+    /* form cm':
+     *  F * e
+     *  A = e * (1 + pF) mod q = e + pFe mod q
+     *  a = A in the range [-q/2, q/2)
+     *  cm' = a mod p
+     */
+
+    cmprime_len = params->N;
+    if (params->is_product_form) {
+         --cmprime_len;
+        ntru_ring_mult_product_indices(ringel_buf2, (uint16_t)dF_r1,
+                                       (uint16_t)dF_r2, (uint16_t)dF_r3,
+                                       i_buf, params->N, params->q,
+                                       scratch_buf, ringel_buf1);
+        for (i = 0; i < cmprime_len; i++) {
+            ringel_buf1[i] = (ringel_buf2[i] + 3 * ringel_buf1[i]) & mod_q_mask;
+            if (ringel_buf1[i] >= (params->q >> 1))
+                    ringel_buf1[i] = ringel_buf1[i] - q_mod_p;
+            Mtrin_buf[i] = (uint8_t)(ringel_buf1[i] % 3);
+            if (Mtrin_buf[i] == 1)
+                ++m1;
+            else if (Mtrin_buf[i] == 2)
+                --m1;
+        }
+    } else {
+        ntru_ring_mult_indices(ringel_buf2, (uint16_t)dF_r, (uint16_t)dF_r,
+                               i_buf, params->N, params->q,
+                               scratch_buf, ringel_buf1);
+        for (i = 0; i < cmprime_len; i++) {
+            ringel_buf1[i] = (ringel_buf2[i] + 3 * ringel_buf1[i]) & mod_q_mask;
+            if (ringel_buf1[i] >= (params->q >> 1))
+                    ringel_buf1[i] = ringel_buf1[i] - q_mod_p;
+            Mtrin_buf[i] = (uint8_t)(ringel_buf1[i] % 3);
+        }
+    }
+
+    /* check that the candidate message representative meets minimum weight
+     * requirements
+     */
+
+    if (params->is_product_form)
+    decryption_ok = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) : 
+                             (bool)( m1 <= params->min_msg_rep_wt);
+    else
+        decryption_ok = ntru_poly_check_min_weight(cmprime_len, Mtrin_buf,
+                                                   params->min_msg_rep_wt);
+
+    /* form cR = e - cm' mod q */
+
+    for (i = 0; i < cmprime_len; i++) {
+        if (Mtrin_buf[i] == 1)
+            ringel_buf2[i] = --ringel_buf2[i] & mod_q_mask;
+        else if (Mtrin_buf[i] == 2)
+            ringel_buf2[i] = ++ringel_buf2[i] & mod_q_mask;
+    }
+    if (params->is_product_form)
+        ringel_buf2[i] = (ringel_buf2[i] + m1) & mod_q_mask;
+
+
+    /* form cR mod 4 */
+
+    ntru_coeffs_mod4_2_octets(params->N, ringel_buf2, tmp_buf);
+
+    /* form mask */
+
+    result = ntru_mgftp1(hash_algid, md_len,
+                         params->min_MGF_hash_calls,
+                         (params->N + 3) / 4, tmp_buf,
+                         tmp_buf + params->N, params->N, tmp_buf);
+
+    if (result == NTRU_OK) {
+
+        /* form cMtrin by subtracting mask from cm', mod p */
+
+        for (i = 0; i < cmprime_len; i++) {
+            Mtrin_buf[i] = Mtrin_buf[i] - tmp_buf[i];
+            if (Mtrin_buf[i] >= 3)
+                Mtrin_buf[i] += 3;
+        }
+        if (params->is_product_form)
+
+            /* set the last trit to zero since that's what it was, and
+             * because it can't be calculated from (cm' - mask) since
+             * we don't have the correct value for the last cm' trit
+             */
+
+            Mtrin_buf[i] = 0;
+
+        /* convert cMtrin to cM (Mtrin to Mbin) */
+
+        if (!ntru_trits_2_bits(Mtrin_buf, params->N, M_buf))
+            decryption_ok = FALSE;
+
+        /* validate the padded message cM and copy cm to m_buf */
+
+        ptr = M_buf + params->sec_strength_len;
+        if (params->m_len_len == 2)
+            cm_len = (uint16_t)(*ptr++) << 16;
+        cm_len |= (uint16_t)(*ptr++);
+        if (cm_len > params->m_len_max) {
+            cm_len = params->m_len_max;
+            decryption_ok = FALSE;
+        }
+        memcpy(m_buf, ptr, cm_len);
+        ptr += cm_len;
+        num_zeros = params->m_len_max - cm_len + 1;
+        for (i = 0; i < num_zeros; i++) {
+            if (ptr[i] != 0)
+                decryption_ok = FALSE;
+        }
+
+        /* form sData (OID || m || b || hTrunc) */
+
+        ptr = tmp_buf;
+        memcpy(ptr, params->OID, 3);
+        ptr += 3;
+        memcpy(ptr, m_buf, cm_len);
+        ptr += cm_len;
+        memcpy(ptr, M_buf, params->sec_strength_len);
+        ptr += params->sec_strength_len;
+        memcpy(ptr, pubkey_packed, params->sec_strength_len);
+        ptr += params->sec_strength_len;
+
+        /* generate cr */
+
+        result = ntru_gen_poly(hash_algid, md_len,
+                               params->min_IGF_hash_calls,
+                               (uint16_t)(ptr - tmp_buf),
+                               tmp_buf, tmp_buf,
+                               params->N, params->c_bits,
+                               params->no_bias_limit,
+                               params->is_product_form,
+                               params->dF_r << 1, i_buf);
+    }
+
+    if (result == NTRU_OK) {
+
+        /* unpack the public key */
+
+        {
+            uint16_t pubkey_packed_len;
+
+            assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS);
+            pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
+            ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
+                                   params->q_bits, ringel_buf1);
+        }
+
+        /* form cR' = h * cr */
+
+        if (params->is_product_form)
+            ntru_ring_mult_product_indices(ringel_buf1, (uint16_t)dF_r1,
+                                           (uint16_t)dF_r2, (uint16_t)dF_r3,
+                                           i_buf, params->N, params->q,
+                                           scratch_buf, ringel_buf1);
+        else
+            ntru_ring_mult_indices(ringel_buf1, (uint16_t)dF_r, (uint16_t)dF_r,
+                                   i_buf, params->N, params->q,
+                                   scratch_buf, ringel_buf1);
+
+        /* compare cR' to cR */
+
+        for (i = 0; i < params->N; i++) {
+            if (ringel_buf1[i] != ringel_buf2[i])
+                decryption_ok = FALSE;
+        }
+
+        /* output plaintext and plaintext length */
+
+        if (decryption_ok) {
+            if (*pt_len < cm_len)
+                NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+            memcpy(pt, m_buf, cm_len);
+            *pt_len = cm_len;
+        }
+    }
+
+    /* cleanup */
+
+    memset(scratch_buf, 0, scratch_buf_len);
+    free(scratch_buf);
+    
+    if (!decryption_ok)
+        NTRU_RET(NTRU_FAIL);
+    return result;
+}
+
+
+/* ntru_crypto_ntru_encrypt_keygen
+ *
+ * Implements key generation for NTRUEncrypt for the parameter set specified.
+ *
+ * Before invoking this function, a DRBG must be instantiated using
+ * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that
+ * instantiation the requested security strength must be at least as large
+ * as the security strength of the NTRU parameter set being used.
+ * Failure to instantiate the DRBG with the proper security strength will
+ * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH.
+ *
+ * The required minimum size of the output public-key buffer (pubkey_blob)
+ * may be queried by invoking this function with pubkey_blob = NULL.
+ * In this case, no key generation is performed, NTRU_OK is returned, and
+ * the required minimum size for pubkey_blob is returned in pubkey_blob_len.
+ *
+ * The required minimum size of the output private-key buffer (privkey_blob)
+ * may be queried by invoking this function with privkey_blob = NULL.
+ * In this case, no key generation is performed, NTRU_OK is returned, and
+ * the required minimum size for privkey_blob is returned in privkey_blob_len.
+ *
+ * The required minimum sizes of both pubkey_blob and privkey_blob may be
+ * queried as described above, in a single invocation of this function.
+ *
+ * When pubkey_blob != NULL and privkey_blob != NULL, at invocation
+ * *pubkey_blob_len must be the size of the pubkey_blob buffer and
+ * *privkey_blob_len must be the size of the privkey_blob buffer.
+ * Upon return, *pubkey_blob_len is the actual size of the public-key blob
+ * and *privkey_blob_len is the actual size of the private-key blob.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than pubkey_blob or privkey_blob) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_INVALID_PARAMETER_SET if the parameter-set
+ *  ID is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument is invalid.
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if either the pubkey_blob
+ * buffer or the privkey_blob buffer is too small.
+ * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
+ *  allocated from the heap.
+ * Returns NTRU_ERROR_BASE + NTRU_FAIL if the polynomial generated for f is
+ *  not invertible in (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
+ *  Should this occur, this function should simply be invoked again.
+ */
+
+uint32_t
+ntru_crypto_ntru_encrypt_keygen(
+    DRBG_HANDLE                drbg_handle,      /*     in - handle of DRBG */
+    NTRU_ENCRYPT_PARAM_SET_ID  param_set_id,     /*     in - parameter set ID */
+    uint16_t                  *pubkey_blob_len,  /* in/out - no. of octets in
+                                                             pubkey_blob, addr
+                                                             for no. of octets
+                                                             in pubkey_blob */
+    uint8_t                   *pubkey_blob,      /*    out - address for
+                                                             public key blob */
+    uint16_t                  *privkey_blob_len, /* in/out - no. of octets in
+                                                             privkey_blob, addr
+                                                             for no. of octets
+                                                             in privkey_blob */
+    uint8_t                   *privkey_blob)     /*    out - address for
+                                                             private key blob */
+{
+    NTRU_ENCRYPT_PARAM_SET *params = NULL;
+    uint16_t                public_key_blob_len;
+    uint16_t                private_key_blob_len;
+    uint8_t                 pubkey_pack_type;
+    uint8_t                 privkey_pack_type;
+    size_t                  scratch_buf_len;
+    uint32_t                dF;
+    uint32_t                dF1 = 0;
+    uint32_t                dF2 = 0;
+    uint32_t                dF3 = 0;
+    uint16_t               *scratch_buf = NULL;
+    uint16_t               *ringel_buf1 = NULL;
+    uint16_t               *ringel_buf2 = NULL;
+    uint16_t               *F_buf = NULL;
+    uint8_t                *tmp_buf = NULL;
+    uint16_t                mod_q_mask;
+    NTRU_CRYPTO_HASH_ALGID  hash_algid;
+    uint8_t                 md_len;
+    uint16_t                seed_len;
+    uint32_t                result = NTRU_OK;
+
+    /* get a pointer to the parameter-set parameters */
+
+    if ((params = ntru_encrypt_get_params_with_id(param_set_id)) == NULL)
+        NTRU_RET(NTRU_INVALID_PARAMETER_SET);
+
+    /* check for bad parameters */
+
+    if (!pubkey_blob_len || !privkey_blob_len)
+        NTRU_RET(NTRU_BAD_PARAMETER);
+
+    /* get public and private key packing types and blob lengths */
+
+    ntru_crypto_ntru_encrypt_key_get_blob_params(params, &pubkey_pack_type,
+                                                 &public_key_blob_len,
+                                                 &privkey_pack_type,
+                                                 &private_key_blob_len);
+
+    /* return the pubkey_blob size and/or privkey_blob size if requested */
+
+    if (!pubkey_blob || !privkey_blob) {
+        if (!pubkey_blob)
+            *pubkey_blob_len = public_key_blob_len;
+        if (!privkey_blob)
+            *privkey_blob_len = private_key_blob_len;
+        NTRU_RET(NTRU_OK);
+    }
+
+    /* check size of output buffers */
+
+    if ((*pubkey_blob_len < public_key_blob_len) ||
+            (*privkey_blob_len < private_key_blob_len))
+        NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+
+    /* allocate memory for all operations */
+
+    if (params->is_product_form) {
+        dF1 =  params->dF_r & 0xff;
+        dF2 = (params->dF_r >> 8) & 0xff;
+        dF3 = (params->dF_r >> 16) & 0xff;
+        dF = dF1 + dF2 + dF3;
+    } else {
+        dF = params->dF_r;
+    }
+
+    scratch_buf_len = (params->N * 8) +     /* 4N-byte temp buffer for ring inv
+                                                and other intermediate results,
+                                               2N-byte buffer for f, g indices
+                                                and overflow from temp buffer,
+                                               2N-byte buffer for f^-1 */
+                      (dF << 2);            /* buffer for F indices */
+    scratch_buf = malloc(scratch_buf_len);
+    if (!scratch_buf) {
+        NTRU_RET(NTRU_OUT_OF_MEMORY);
+    }
+    ringel_buf1 = scratch_buf + (params->N << 1);
+    ringel_buf2 = ringel_buf1 + params->N;
+    F_buf = ringel_buf2 + params->N;
+    tmp_buf = (uint8_t *)scratch_buf;
+
+    /* set hash algorithm and seed length based on security strength */
+
+    if (params->sec_strength_len <= 20) {
+        hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
+        md_len = 20;
+    } else {
+        hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
+        md_len = 32;
+    }
+    seed_len = params->sec_strength_len + 8;
+
+    /* set constants */
+
+    mod_q_mask = params->q - 1;
+
+    /* get random bytes for seed for generating trinary F
+     * as a list of indices
+     */
+
+    result = ntru_crypto_drbg_generate(drbg_handle,
+                                       params->sec_strength_len << 3,
+                                       seed_len, tmp_buf);
+
+    if (result == NTRU_OK) {
+
+        /* generate F */
+
+        result = ntru_gen_poly(hash_algid, md_len,
+                               params->min_IGF_hash_calls,
+                               seed_len, tmp_buf, tmp_buf,
+                               params->N, params->c_bits,
+                               params->no_bias_limit,
+                               params->is_product_form,
+                               params->dF_r << 1, F_buf);
+    }
+
+    if (result == NTRU_OK) {
+        uint32_t i;
+
+        memset(ringel_buf1, 0, params->N * sizeof(uint16_t));
+
+        /* form F as a ring element */
+
+        if (params->is_product_form) {
+            uint32_t dF3_offset = (dF1 + dF2) << 1;
+
+            /* form F1 as a ring element */
+
+            for (i = 0; i < dF1; i++)
+                ringel_buf1[F_buf[i]] = 1;
+            for (; i < (dF1 << 1); i++)
+                ringel_buf1[F_buf[i]] = mod_q_mask;
+
+            /* form F1 * F2 */
+
+            ntru_ring_mult_indices(ringel_buf1, (uint16_t)dF2, (uint16_t)dF2,
+                                   F_buf + (dF1 << 1), params->N, params->q,
+                                   scratch_buf, ringel_buf1);
+
+            /* form (F1 * F2) + F3 */
+
+            for (i = 0; i < dF3; i++) {
+                uint16_t index = F_buf[dF3_offset + i];
+                ringel_buf1[index] = ++ringel_buf1[index] & mod_q_mask;
+            }
+            for (; i < (dF3 << 1); i++) {
+                uint16_t index = F_buf[dF3_offset + i];
+                ringel_buf1[index] = --ringel_buf1[index] & mod_q_mask;
+            }
+
+        } else {
+
+            /* form F as a ring element */
+
+            for (i = 0; i < dF; i++)
+                ringel_buf1[F_buf[i]] = 1;
+            for (; i < (dF << 1); i++)
+                ringel_buf1[F_buf[i]] = mod_q_mask;
+        }
+
+        /* form f = 1 + pF */
+
+        for (i = 0; i < params->N; i++)
+            ringel_buf1[i] = (ringel_buf1[i] * 3) & mod_q_mask;
+        ringel_buf1[0] = (ringel_buf1[0] + 1) & mod_q_mask;
+
+        /* find f^-1 in (Z/qZ)[X]/(X^N - 1) */
+
+        if (!ntru_ring_inv(ringel_buf1, params->N, params->q,
+                           scratch_buf, ringel_buf2))
+            result = NTRU_ERROR_BASE + NTRU_FAIL;
+    }
+
+    if (result == NTRU_OK) {
+
+        /* get random bytes for seed for generating trinary g
+         * as a list of indices
+         */
+        result = ntru_crypto_drbg_generate(drbg_handle,
+                                           params->sec_strength_len << 3,
+                                           seed_len, tmp_buf);
+    }
+
+    if (result == NTRU_OK) {
+        uint16_t min_IGF_hash_calls =
+            ((((params->dg << 2) + 2) * params->N_bits) + (md_len << 3) - 1) /
+            (md_len << 3);
+
+        /* generate g */
+
+        result = ntru_gen_poly(hash_algid, md_len,
+                               (uint8_t)min_IGF_hash_calls,
+                               seed_len, tmp_buf, tmp_buf,
+                               params->N, params->c_bits,
+                               params->no_bias_limit, FALSE,
+                               (params->dg << 1) + 1, ringel_buf1);
+    }
+
+    if (result == NTRU_OK) {
+        uint16_t i;
+
+        /* compute h = p * (f^-1 * g) mod q */
+
+        ntru_ring_mult_indices(ringel_buf2, params->dg + 1, params->dg,
+                               ringel_buf1, params->N, params->q, scratch_buf,
+                               ringel_buf2);
+
+        for (i = 0; i < params->N; i++)
+            ringel_buf2[i] = (ringel_buf2[i] * 3) & mod_q_mask;
+
+        /* create public key blob */
+
+        ntru_crypto_ntru_encrypt_key_create_pubkey_blob(params, ringel_buf2,
+                                                        pubkey_pack_type,
+                                                        pubkey_blob);
+        *pubkey_blob_len = public_key_blob_len;
+
+        /* create private key blob */
+
+        ntru_crypto_ntru_encrypt_key_create_privkey_blob(params, ringel_buf2,
+                                                         F_buf,
+                                                         privkey_pack_type,
+                                                         tmp_buf, privkey_blob);
+        *privkey_blob_len = private_key_blob_len;
+    }
+
+    /* cleanup */
+
+    memset(scratch_buf, 0, scratch_buf_len);
+    free(scratch_buf);
+    
+    return result;
+}
+
+
+/* DER-encoding prefix template for NTRU public keys,
+ * with parameter-set-specific fields nomalized
+ */
+
+static uint8_t const der_prefix_template[] = {
+    0x30, 0x82,
+    0x00, 0x23,                                 /* add pubkey length */
+    0x30, 0x18, 0x06, 0x0a, 0x2b, 0x06, 0x01,
+    0x04, 0x01, 0xc1, 0x70, 0x01, 0x01, 0x02,   /* end of NTRU OID compare */
+    0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
+    0xc1, 0x70, 0x01, 0x02,
+    0x00,                                       /* set param-set DER id */
+    0x03, 0x82,
+    0x00, 0x05,                                 /* add pubkey length */
+    0x00, 0x04, 0x82,
+    0x00, 0x00,                                 /* add pubkey length */
+};
+
+
+/* add_16_to_8s
+ *
+ * adds a 16-bit value to two bytes
+ */
+
+static void
+add_16_to_8s(
+    uint16_t  a,
+    uint8_t  *b)
+{
+    uint16_t tmp = ((uint16_t)b[0] << 8) + b[1];
+
+    tmp = tmp + a;
+    b[0] = (uint8_t)((tmp >> 8) & 0xff);
+    b[1] = (uint8_t)(tmp & 0xff);
+}
+
+
+/* sub_16_from_8s
+ *
+ * subtracts a 16-bit value from two bytes
+ */
+
+static void
+sub_16_from_8s(
+    uint16_t  a,
+    uint8_t  *b)
+{
+    uint16_t tmp = ((uint16_t)b[0] << 8) + b[1];
+
+    tmp = tmp - a;
+    b[0] = (uint8_t)((tmp >> 8) & 0xff);
+    b[1] = (uint8_t)(tmp & 0xff);
+}
+
+
+/* ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo
+ *
+ * DER-encodes an NTRUEncrypt public-key from a public-key blob into a
+ * SubjectPublicKeyInfo field for inclusion in an X.509 certificate.
+ *
+ * The required minimum size of the output SubjectPublicKeyInfo buffer
+ * (encoded_subjectPublicKeyInfo) may be queried by invoking this function
+ * with encoded_subjectPublicKeyInfo = NULL.  In this case, no encoding is
+ * performed, NTRU_OK is returned, and the required minimum size for
+ * encoded_subjectPublicKeyInfo is returned in encoded_subjectPublicKeyInfo_len.
+ *
+ * When encoded_subjectPublicKeyInfo != NULL, at invocation
+ * *encoded_subjectPublicKeyInfo_len must be the size of the
+ * encoded_subjectPublicKeyInfo buffer.
+ * Upon return, it is the actual size of the encoded public key.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than encoded_subjectPublicKeyInfo) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if pubkey_blob_len is zero.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
+ *  invalid (unknown format, corrupt, bad length).
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the SubjectPublicKeyInfo
+ *  buffer is too small.
+ */
+
+uint32_t
+ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
+    uint16_t       pubkey_blob_len, /*     in - no. of octets in public-key
+                                                blob */
+    uint8_t const *pubkey_blob,     /*     in - ptr to public-key blob */
+    uint16_t      *encoded_subjectPublicKeyInfo_len,
+                                    /* in/out - no. of octets in encoded info,
+                                                address for no. of octets in
+                                                encoded info */
+    uint8_t       *encoded_subjectPublicKeyInfo)
+                                    /*    out - address for encoded info */
+{
+    NTRU_ENCRYPT_PARAM_SET *params = NULL;
+    uint8_t const          *pubkey_packed = NULL;
+    uint8_t                 pubkey_pack_type;
+    uint16_t                packed_pubkey_len;
+    uint16_t                encoded_len;
+
+    /* check for bad parameters */
+
+    if (!pubkey_blob || !encoded_subjectPublicKeyInfo_len)
+        NTRU_RET(NTRU_BAD_PARAMETER);
+    if (pubkey_blob_len == 0)
+        NTRU_RET(NTRU_BAD_LENGTH);
+
+    /* get a pointer to the parameter-set parameters, the packing type for
+     * the public key, and a pointer to the packed public key
+     */
+
+    if (!ntru_crypto_ntru_encrypt_key_parse(TRUE /* pubkey */, pubkey_blob_len,
+                                            pubkey_blob, &pubkey_pack_type,
+                                            NULL, &params, &pubkey_packed,
+                                            NULL))
+        NTRU_RET(NTRU_BAD_PUBLIC_KEY);
+
+    /* return the encoded_subjectPublicKeyInfo size if requested */
+
+    packed_pubkey_len = (params->N * params->q_bits + 7) >> 3;
+    encoded_len = sizeof(der_prefix_template) + packed_pubkey_len;
+    if (!encoded_subjectPublicKeyInfo) {
+        *encoded_subjectPublicKeyInfo_len = encoded_len;
+        NTRU_RET(NTRU_OK);
+    }
+
+    /* check the encoded_subjectPublicKeyInfo buffer size */
+
+    if (*encoded_subjectPublicKeyInfo_len < encoded_len) {
+        NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+    }
+
+    /* form the encoded subjectPublicKey */
+
+    memcpy(encoded_subjectPublicKeyInfo, der_prefix_template,
+           sizeof(der_prefix_template));
+    add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 2);
+    add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 32);
+    add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 37);
+    encoded_subjectPublicKeyInfo[29] = params->der_id;
+    memcpy(encoded_subjectPublicKeyInfo + sizeof(der_prefix_template),
+           pubkey_packed, packed_pubkey_len);
+
+    *encoded_subjectPublicKeyInfo_len = encoded_len;
+
+    NTRU_RET(NTRU_OK);
+}
+
+
+/* ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey
+ *
+ * Decodes a DER-encoded NTRUEncrypt public-key from a
+ * SubjectPublicKeyInfo field in an X.509 certificate and returns the
+ * public-key blob itself.
+ *
+ * The required minimum size of the output public-key buffer (pubkey_blob)
+ * may be queried by invoking this function with pubkey_blob = NULL.
+ * In this case, no decoding is performed, NTRU_OK is returned, and the
+ * required minimum size for pubkey_blob is returned in pubkey_blob_len.
+ *
+ * When pubkey_blob != NULL, at invocation *pubkey_blob_len must be the
+ * size of the pubkey_blob buffer.
+ * Upon return, it is the actual size of the public-key blob.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
+ *  (other than pubkey_blob) is NULL.
+ * Returns NTRU_ERROR_BASE + NTRU_BAD_ENCODING if the encoded data is
+ *  an invalid encoding of an NTRU public key.
+ * Returns NTRU_ERROR_BASE + NTRU_OID_NOT_RECOGNIZED if the
+ *  encoded data contains an OID that identifies an object other than
+ *  an NTRU public key.
+ * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the pubkey_blob buffer
+ *  is too small.
+ */
+
+uint32_t
+ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(
+    uint8_t const  *encoded_data,    /*     in - ptr to subjectPublicKeyInfo
+                                                 in the encoded data */
+    uint16_t       *pubkey_blob_len, /* in/out - no. of octets in pubkey blob,
+                                                 address for no. of octets in
+                                                 pubkey blob */
+    uint8_t        *pubkey_blob,     /*    out - address for pubkey blob */
+    uint8_t       **next)            /*    out - address for ptr to encoded
+                                                 data following the 
+                                                 subjectPublicKeyInfo */
+{
+    NTRU_ENCRYPT_PARAM_SET *params = NULL;
+    uint8_t                 prefix_buf[39];
+    bool                    der_id_valid;
+    uint16_t                packed_pubkey_len = 0;
+    uint8_t                 pubkey_pack_type;
+    uint16_t                public_key_blob_len;
+
+    /* check for bad parameters */
+
+    if (!encoded_data || !pubkey_blob_len || !next)
+        NTRU_RET(NTRU_BAD_PARAMETER);
+
+    /* determine if data to be decoded is a valid encoding of an NTRU
+     * public key
+     */
+
+    memcpy(prefix_buf, encoded_data, sizeof(prefix_buf));
+
+    /* get a pointer to the parameter-set parameters */
+
+    if ((params = ntru_encrypt_get_params_with_DER_id(encoded_data[29])) ==
+            NULL) {
+        der_id_valid = FALSE;
+
+        /* normalize the prefix-buffer data used in an NTRU OID comparison */
+
+        prefix_buf[2] = der_prefix_template[2];
+        prefix_buf[3] = der_prefix_template[3];
+
+    } else {
+        der_id_valid = TRUE;
+
+        /* normalize the prefix-buffer data for the specific parameter set */
+
+        packed_pubkey_len = (params->N * params->q_bits + 7) >> 3;
+        sub_16_from_8s(packed_pubkey_len, prefix_buf + 2);
+        sub_16_from_8s(packed_pubkey_len, prefix_buf + 32);
+        sub_16_from_8s(packed_pubkey_len, prefix_buf + 37);
+        prefix_buf[29] = 0;
+    }
+
+    /* validate the DER prefix encoding */
+
+    if (!der_id_valid || memcmp(prefix_buf, der_prefix_template,
+               sizeof(der_prefix_template))) {
+
+        /* bad DER prefix, so determine if this is a bad NTRU encoding or an
+         * unknown OID by comparing the first 18 octets
+         */
+
+        if (memcmp(prefix_buf, der_prefix_template, 18))
+            NTRU_RET(NTRU_OID_NOT_RECOGNIZED);
+        else
+            NTRU_RET(NTRU_BAD_ENCODING);
+    }
+
+    /* get public key packing type and blob length */
+
+    ntru_crypto_ntru_encrypt_key_get_blob_params(params, &pubkey_pack_type,
+                                                 &public_key_blob_len, NULL,
+                                                 NULL);
+
+    /* return the pubkey_blob size if requested */
+
+    if (!pubkey_blob) {
+        *pubkey_blob_len = public_key_blob_len;
+        NTRU_RET(NTRU_OK);
+    }
+
+    /* check size of output buffer */
+
+    if (*pubkey_blob_len < public_key_blob_len)
+        NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+
+    /* create the public-key blob */
+
+    ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob(params, packed_pubkey_len,
+                                     encoded_data + sizeof(der_prefix_template),
+                                     pubkey_pack_type, pubkey_blob);
+    *pubkey_blob_len = public_key_blob_len;
+
+    *next = *next + sizeof(der_prefix_template) + packed_pubkey_len;
+
+    NTRU_RET(NTRU_OK);
+}
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.c
new file mode 100644 (file)
index 0000000..b44ca81
--- /dev/null
@@ -0,0 +1,397 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_encrypt_key.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_encrypt_key.c
+ *
+ * Contents: Routines for exporting and importing public and private keys
+ *           for NTRUEncrypt.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto_ntru_encrypt_key.h"
+
+
+/* ntru_crypto_ntru_encrypt_key_parse
+ *
+ * Parses an NTRUEncrypt key blob.
+ * If the blob is not corrupt, returns packing types for public and private
+ * keys, a pointer to the parameter set, a pointer to the public key, and
+ * a pointer to the private key if it exists.
+ *
+ * Returns TRUE if successful.
+ * Returns FALSE if the blob is invalid.
+ */
+
+bool
+ntru_crypto_ntru_encrypt_key_parse(
+    bool                     pubkey_parse,      /*  in - if parsing pubkey
+                                                         blob */
+    uint16_t                 key_blob_len,      /*  in - no. octets in key
+                                                         blob */
+    uint8_t const           *key_blob,          /*  in - pointer to key blob */
+    uint8_t                 *pubkey_pack_type,  /* out - addr for pubkey
+                                                         packing type */
+    uint8_t                 *privkey_pack_type, /* out - addr for privkey
+                                                         packing type */
+    NTRU_ENCRYPT_PARAM_SET **params,            /* out - addr for ptr to
+                                                         parameter set */
+    uint8_t const          **pubkey,            /* out - addr for ptr to
+                                                         packed pubkey */
+    uint8_t const          **privkey)           /* out - addr for ptr to
+                                                         packed privkey */
+{
+    uint8_t tag;
+
+    assert(key_blob_len);
+    assert(key_blob);
+    assert(pubkey_pack_type);
+    assert(params);
+    assert(pubkey);
+
+    /* parse key blob based on tag */
+
+    tag = key_blob[0];
+    switch (tag) {
+        case NTRU_ENCRYPT_PUBKEY_TAG:
+            if (!pubkey_parse)
+                return FALSE;
+            break;
+        case NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG:
+        case NTRU_ENCRYPT_PRIVKEY_TRITS_TAG:
+        case NTRU_ENCRYPT_PRIVKEY_INDICES_TAG:
+            assert(privkey_pack_type);
+            assert(privkey);
+            if (pubkey_parse)
+                return FALSE;
+            break;
+        default:
+            return FALSE;
+    }
+
+    switch (tag) {
+        case NTRU_ENCRYPT_PUBKEY_TAG:
+        case NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG:
+        case NTRU_ENCRYPT_PRIVKEY_TRITS_TAG:
+        case NTRU_ENCRYPT_PRIVKEY_INDICES_TAG:
+
+            /* Version 0:
+             *  byte  0:   tag
+             *  byte  1:   no. of octets in OID
+             *  bytes 2-4: OID
+             *  bytes 5- : packed pubkey
+             *             [packed privkey]
+             */
+
+        {
+            NTRU_ENCRYPT_PARAM_SET *p = NULL;
+            uint16_t pubkey_packed_len;
+
+            /* check OID length and minimum blob length for tag and OID */
+
+            if ((key_blob_len < 5) || (key_blob[1] != 3))
+                return FALSE;
+
+            /* get a pointer to the parameter set corresponding to the OID */
+
+            if ((p = ntru_encrypt_get_params_with_OID(key_blob + 2)) == NULL)
+                return FALSE;
+
+            /* check blob length and assign pointers to blob fields */
+
+            pubkey_packed_len = (p->N * p->q_bits + 7) / 8;
+            if (pubkey_parse) { /* public-key parsing */
+                if (key_blob_len != 5 + pubkey_packed_len)
+                    return FALSE;
+
+                *pubkey = key_blob + 5;
+
+            } else { /* private-key parsing */
+                uint16_t privkey_packed_len;
+                uint16_t privkey_packed_trits_len = (p->N + 4) / 5;
+                uint16_t privkey_packed_indices_len;
+                uint16_t dF;
+
+                /* check packing type for product-form private keys */
+
+                if (p->is_product_form &&
+                        (tag == NTRU_ENCRYPT_PRIVKEY_TRITS_TAG))
+                    return FALSE;
+
+                /* set packed-key length for packed indices */
+
+                if (p->is_product_form)
+                    dF = (uint16_t)( (p->dF_r & 0xff) +            /* df1 */
+                                    ((p->dF_r >>  8) & 0xff) +     /* df2 */
+                                    ((p->dF_r >> 16) & 0xff));     /* df3 */
+                else
+                    dF = (uint16_t)p->dF_r;
+                privkey_packed_indices_len = ((dF << 1) * p->N_bits + 7) >> 3;
+
+                /* set private-key packing type if defaulted */
+
+                if (tag == NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG) {
+                    if (p->is_product_form ||
+                            (privkey_packed_indices_len <=
+                             privkey_packed_trits_len))
+                        tag = NTRU_ENCRYPT_PRIVKEY_INDICES_TAG;
+                    else
+                        tag = NTRU_ENCRYPT_PRIVKEY_TRITS_TAG;
+                }
+
+                if (tag == NTRU_ENCRYPT_PRIVKEY_TRITS_TAG)
+                    privkey_packed_len = privkey_packed_trits_len;
+                else
+                    privkey_packed_len = privkey_packed_indices_len;
+
+                if (key_blob_len != 5 + pubkey_packed_len + privkey_packed_len)
+                    return FALSE;
+
+                *pubkey = key_blob + 5;
+                *privkey = *pubkey + pubkey_packed_len;
+                *privkey_pack_type = (tag == NTRU_ENCRYPT_PRIVKEY_TRITS_TAG) ?
+                    NTRU_ENCRYPT_KEY_PACKED_TRITS :
+                    NTRU_ENCRYPT_KEY_PACKED_INDICES;
+            }
+
+            /* return parameter set pointer */
+
+            *pubkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS;
+            *params = p;
+        }
+        default:
+            break;  /* can't get here */
+    }
+    return TRUE;
+}
+
+
+/* ntru_crypto_ntru_encrypt_key_get_blob_params
+ *
+ * Returns public and private key packing types and blob lengths given
+ * a packing format.  For now, only a default packing format exists.
+ *
+ * Only public-key params may be returned by setting privkey_pack_type
+ * and privkey_blob_len to NULL.
+ */
+
+void
+ntru_crypto_ntru_encrypt_key_get_blob_params(
+    NTRU_ENCRYPT_PARAM_SET const *params,             /*  in - pointer to
+                                                               param set
+                                                               parameters */
+    uint8_t                      *pubkey_pack_type,   /* out - addr for pubkey
+                                                               packing type */
+    uint16_t                     *pubkey_blob_len,    /* out - addr for no. of
+                                                               bytes in
+                                                               pubkey blob */
+    uint8_t                      *privkey_pack_type,  /* out - addr for privkey
+                                                               packing type */
+    uint16_t                     *privkey_blob_len)   /* out - addr for no. of
+                                                               bytes in
+                                                               privkey blob */
+{
+    uint16_t pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
+
+    assert(params);
+    assert(pubkey_pack_type);
+    assert(pubkey_blob_len);
+
+    *pubkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS;
+    *pubkey_blob_len = 5 + pubkey_packed_len;
+
+    if (privkey_pack_type && privkey_blob_len) {
+        uint16_t privkey_packed_trits_len = (params->N + 4) / 5;
+        uint16_t privkey_packed_indices_len;
+        uint16_t dF;
+
+        if (params->is_product_form)
+            dF = (uint16_t)( (params->dF_r & 0xff) +            /* df1 */
+                            ((params->dF_r >>  8) & 0xff) +     /* df2 */
+                            ((params->dF_r >> 16) & 0xff));     /* df3 */
+        else
+            dF = (uint16_t)params->dF_r;
+        privkey_packed_indices_len = ((dF << 1) * params->N_bits + 7) >> 3;
+
+        if (params->is_product_form ||
+                (privkey_packed_indices_len <= privkey_packed_trits_len)) {
+            *privkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_INDICES;
+            *privkey_blob_len =
+                5 + pubkey_packed_len + privkey_packed_indices_len;
+        } else {
+            *privkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_TRITS;
+            *privkey_blob_len =
+                5 + pubkey_packed_len + privkey_packed_trits_len;
+        }
+    }
+}
+
+
+/* ntru_crypto_ntru_encrypt_key_create_pubkey_blob
+ *
+ * Returns a public key blob, packed according to the packing type provided.
+ */
+
+void
+ntru_crypto_ntru_encrypt_key_create_pubkey_blob(
+    NTRU_ENCRYPT_PARAM_SET const *params,             /*  in - pointer to
+                                                               param set
+                                                               parameters */
+    uint16_t const               *pubkey,             /*  in - pointer to the
+                                                               coefficients
+                                                               of the pubkey */
+    uint8_t                       pubkey_pack_type,   /* out - pubkey packing
+                                                               type */
+    uint8_t                      *pubkey_blob)        /* out - addr for the
+                                                               pubkey blob */
+{
+    assert(params);
+    assert(pubkey);
+    assert(pubkey_blob);
+
+    switch (pubkey_pack_type) {
+        case NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS:
+            *pubkey_blob++ = NTRU_ENCRYPT_PUBKEY_TAG;
+            *pubkey_blob++ = (uint8_t)sizeof(params->OID);
+            memcpy(pubkey_blob, params->OID, sizeof(params->OID));
+            pubkey_blob += sizeof(params->OID);
+            ntru_elements_2_octets(params->N, pubkey, params->q_bits,
+                                   pubkey_blob);
+            break;
+        default:
+            assert(FALSE);
+    }
+}
+
+
+/* ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob
+ *
+ * Returns a public key blob, recreated from an already-packed public key.
+ */
+
+void
+ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob(
+    NTRU_ENCRYPT_PARAM_SET const *params,             /*  in - pointer to
+                                                               param set
+                                                               parameters */
+    uint16_t                      packed_pubkey_len,  /*  in - no. octets in
+                                                               packed pubkey */
+    uint8_t const                *packed_pubkey,      /*  in - pointer to the
+                                                               packed pubkey */
+    uint8_t                       pubkey_pack_type,   /* out - pubkey packing
+                                                               type */
+    uint8_t                      *pubkey_blob)        /* out - addr for the
+                                                               pubkey blob */
+{
+    assert(params);
+    assert(packed_pubkey);
+    assert(pubkey_blob);
+
+    switch (pubkey_pack_type) {
+        case NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS:
+            *pubkey_blob++ = NTRU_ENCRYPT_PUBKEY_TAG;
+            *pubkey_blob++ = (uint8_t)sizeof(params->OID);
+            memcpy(pubkey_blob, params->OID, sizeof(params->OID));
+            pubkey_blob += sizeof(params->OID);
+            memcpy(pubkey_blob, packed_pubkey, packed_pubkey_len);
+            break;
+        default:
+            assert(FALSE);
+    }
+}
+
+
+/* ntru_crypto_ntru_encrypt_key_create_privkey_blob
+ *
+ * Returns a private key blob, packed according to the packing type provided.
+ */
+
+void
+ntru_crypto_ntru_encrypt_key_create_privkey_blob(
+    NTRU_ENCRYPT_PARAM_SET const *params,             /*  in - pointer to
+                                                               param set
+                                                               parameters */
+    uint16_t const               *pubkey,             /*  in - pointer to the
+                                                               coefficients
+                                                               of the pubkey */
+    uint16_t const               *privkey,            /*  in - pointer to the
+                                                               indices of the
+                                                               privkey */
+    uint8_t                       privkey_pack_type,  /*  in - privkey packing
+                                                               type */
+    uint8_t                      *buf,                /*  in - temp, N bytes */
+    uint8_t                      *privkey_blob)       /* out - addr for the
+                                                               privkey blob */
+{
+    assert(params);
+    assert(pubkey);
+    assert(privkey);
+    assert(privkey_blob);
+
+    switch (privkey_pack_type) {
+        case NTRU_ENCRYPT_KEY_PACKED_TRITS:
+        case NTRU_ENCRYPT_KEY_PACKED_INDICES:
+
+            /* format header and packed public key */
+
+            *privkey_blob++ = NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG;
+            *privkey_blob++ = (uint8_t)sizeof(params->OID);
+            memcpy(privkey_blob, params->OID, sizeof(params->OID));
+            privkey_blob += sizeof(params->OID);
+            ntru_elements_2_octets(params->N, pubkey, params->q_bits,
+                                   privkey_blob);
+            privkey_blob += (params->N * params->q_bits + 7) >> 3;
+
+            /* add packed private key */
+
+            if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS) {
+                ntru_indices_2_packed_trits(privkey, (uint16_t)params->dF_r,
+                                            (uint16_t)params->dF_r,
+                                            params->N, buf, privkey_blob);
+            } else {
+                uint32_t dF;
+
+                if (params->is_product_form) {
+                    dF =  (params->dF_r & 0xff) +
+                         ((params->dF_r >> 8) & 0xff) +
+                         ((params->dF_r >> 16) & 0xff);
+                } else {
+                    dF = params->dF_r;
+                }
+                ntru_elements_2_octets((uint16_t)dF << 1, privkey,
+                                       params->N_bits, privkey_blob);
+            }
+            break;
+        default:
+            assert(FALSE);
+            break;
+    }
+}
+
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_key.h
new file mode 100644 (file)
index 0000000..6734f2a
--- /dev/null
@@ -0,0 +1,167 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_cencrypt_key.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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 NTRU_CRYPTO_NTRU_ENCRYPT_KEY_H
+#define NTRU_CRYPTO_NTRU_ENCRYPT_KEY_H
+
+#include "ntru_crypto_ntru_convert.h"
+#include "ntru_crypto_ntru_encrypt_param_sets.h"
+
+
+/* key-blob definitions */
+
+#define NTRU_ENCRYPT_PUBKEY_TAG           0x01
+#define NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG  0x02
+#define NTRU_ENCRYPT_PRIVKEY_TRITS_TAG    0xfe
+#define NTRU_ENCRYPT_PRIVKEY_INDICES_TAG  0xff
+
+/* packing types */
+
+#define NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS    0x01
+#define NTRU_ENCRYPT_KEY_PACKED_INDICES         0x02
+#define NTRU_ENCRYPT_KEY_PACKED_TRITS           0x03
+
+/* function declarations */
+
+
+/* ntru_crypto_ntru_encrypt_key_parse
+ *
+ * Parses an NTRUEncrypt key blob.
+ * If the blob is not corrupt, returns packing types for public and private
+ * keys, a pointer to the parameter set, a pointer to the public key, and
+ * a pointer to the private key if it exists.
+ *
+ * Returns TRUE if successful.
+ * Returns FALSE if the blob is invalid.
+ */
+
+extern bool
+ntru_crypto_ntru_encrypt_key_parse(
+    bool                     pubkey_parse,      /*  in - if parsing pubkey
+                                                         blob */
+    uint16_t                 key_blob_len,      /*  in - no. octets in key
+                                                         blob */
+    uint8_t const           *key_blob,          /*  in - pointer to key blob */
+    uint8_t                 *pubkey_pack_type,  /* out - addr for pubkey
+                                                         packing type */
+    uint8_t                 *privkey_pack_type, /* out - addr for privkey
+                                                         packing type */
+    NTRU_ENCRYPT_PARAM_SET **params,            /* out - addr for ptr to
+                                                         parameter set */
+    uint8_t const          **pubkey,            /* out - addr for ptr to
+                                                         packed pubkey */
+    uint8_t const          **privkey);          /* out - addr for ptr to
+                                                         packed privkey */
+
+
+/* ntru_crypto_ntru_encrypt_key_get_blob_params
+ *
+ * Returns public and private key packing types and blob lengths given
+ * a packing format.  For now, only a default packing format exists.
+ *
+ * Only public-key params may be returned by setting privkey_pack_type
+ * and privkey_blob_len to NULL.
+ */
+
+extern void
+ntru_crypto_ntru_encrypt_key_get_blob_params(
+    NTRU_ENCRYPT_PARAM_SET const *params,             /*  in - pointer to
+                                                               param set
+                                                               parameters */
+    uint8_t                      *pubkey_pack_type,   /* out - addr for pubkey
+                                                               packing type */
+    uint16_t                     *pubkey_blob_len,    /* out - addr for no. of
+                                                               bytes in
+                                                               pubkey blob */
+    uint8_t                      *privkey_pack_type,  /* out - addr for privkey
+                                                               packing type */
+    uint16_t                     *privkey_blob_len);  /* out - addr for no. of
+                                                               bytes in
+                                                               privkey blob */
+
+
+/* ntru_crypto_ntru_encrypt_key_create_pubkey_blob
+ *
+ * Returns a public key blob, packed according to the packing type provided.
+ */
+
+extern void
+ntru_crypto_ntru_encrypt_key_create_pubkey_blob(
+    NTRU_ENCRYPT_PARAM_SET const *params,             /*  in - pointer to
+                                                               param set
+                                                               parameters */
+    uint16_t const               *pubkey,             /*  in - pointer to the
+                                                               coefficients
+                                                               of the pubkey */
+    uint8_t                       pubkey_pack_type,   /* out - addr for pubkey
+                                                               packing type */
+    uint8_t                      *pubkey_blob);       /* out - addr for the
+                                                               pubkey blob */
+
+
+/* ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob
+ *
+ * Returns a public key blob, recreated from an already-packed public key.
+ */
+
+extern void
+ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob(
+    NTRU_ENCRYPT_PARAM_SET const *params,             /*  in - pointer to
+                                                               param set
+                                                               parameters */
+    uint16_t                      packed_pubkey_len,  /*  in - no. octets in
+                                                               packed pubkey */
+    uint8_t const                *packed_pubkey,      /*  in - pointer to the
+                                                               packed pubkey */
+    uint8_t                       pubkey_pack_type,   /* out - pubkey packing
+                                                               type */
+    uint8_t                      *pubkey_blob);       /* out - addr for the
+                                                               pubkey blob */
+
+
+/* ntru_crypto_ntru_encrypt_key_create_privkey_blob
+ *
+ * Returns a privlic key blob, packed according to the packing type provided.
+ */
+
+extern void
+ntru_crypto_ntru_encrypt_key_create_privkey_blob(
+    NTRU_ENCRYPT_PARAM_SET const *params,             /*  in - pointer to
+                                                               param set
+                                                               parameters */
+    uint16_t const               *pubkey,             /*  in - pointer to the
+                                                               coefficients
+                                                               of the pubkey */
+    uint16_t const               *privkey,            /*  in - pointer to the
+                                                               indices of the
+                                                               privkey */
+    uint8_t                       privkey_pack_type,  /*  in - privkey packing
+                                                               type */
+    uint8_t                      *buf,                /*  in - temp, N bytes */
+    uint8_t                      *privkey_blob);      /* out - addr for the
+                                                               privkey blob */
+
+
+#endif /* NTRU_CRYPTO_NTRU_ENCRYPT_KEY_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.c
new file mode 100644 (file)
index 0000000..d99b7d6
--- /dev/null
@@ -0,0 +1,457 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_param_sets.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_encrypt_param_sets.c
+ *
+ * Contents: Defines the NTRUEncrypt parameter sets.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "ntru_crypto_ntru_encrypt_param_sets.h"
+
+
+/* parameter sets */
+
+static NTRU_ENCRYPT_PARAM_SET ntruParamSets[] = {
+
+    {
+        NTRU_EES401EP1,              /* parameter-set id */
+        {0x00, 0x02, 0x04},          /* OID */
+        0x22,                        /* DER id */
+        9,                           /* no. of bits in N (i.e., in an index) */
+        401,                         /* N */
+        14,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        113,                         /* df, dr */
+        133,                         /* dg */
+        60,                          /* maxMsgLenBytes */
+        113,                         /* dm0 */
+        2005,                        /* 2^c - (2^c mod N) */
+        11,                          /* c */
+        1,                           /* lLen */
+        32,                          /* min. no. of hash calls for IGF-2 */
+        9,                           /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES449EP1,              /* parameter-set id */
+        {0x00, 0x03, 0x03},          /* OID */
+        0x23,                        /* DER id */
+        9,                           /* no. of bits in N (i.e., in an index) */
+        449,                         /* N */
+        16,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        134,                         /* df, dr */
+        149,                         /* dg */
+        67,                          /* maxMsgLenBytes */
+        134,                         /* dm0 */
+        449,                         /* 2^c - (2^c mod N) */
+        9,                           /* c */
+        1,                           /* lLen */
+        31,                          /* min. no. of hash calls for IGF-2 */
+        9,                           /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES677EP1,              /* parameter-set id */
+        {0x00, 0x05, 0x03},          /* OID */
+        0x24,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        677,                         /* N */
+        24,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        157,                         /* df, dr */
+        225,                         /* dg */
+        101,                         /* maxMsgLenBytes */
+        157,                         /* dm0 */
+        2031,                        /* 2^c - (2^c mod N) */
+        11,                          /* c */
+        1,                           /* lLen */
+        27,                          /* min. no. of hash calls for IGF-2 */
+        9,                           /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES1087EP2,             /* parameter-set id */
+        {0x00, 0x06, 0x03},          /* OID */
+        0x25,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        1087,                        /* N */
+        32,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        120,                         /* df, dr */
+        362,                         /* dg */
+        170,                         /* maxMsgLenBytes */
+        120,                         /* dm0 */
+        7609,                        /* 2^c - (2^c mod N) */
+        13,                          /* c */
+        1,                           /* lLen */
+        25,                          /* min. no. of hash calls for IGF-2 */
+        14,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES541EP1,              /* parameter-set id */
+        {0x00, 0x02, 0x05},          /* OID */
+        0x26,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        541,                         /* N */
+        14,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        49,                          /* df, dr */
+        180,                         /* dg */
+        86,                          /* maxMsgLenBytes */
+        49,                          /* dm0 */
+        3787,                        /* 2^c - (2^c mod N) */
+        12,                          /* c */
+        1,                           /* lLen */
+        15,                          /* min. no. of hash calls for IGF-2 */
+        11,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES613EP1,              /* parameter-set id */
+        {0x00, 0x03, 0x04},          /* OID */
+        0x27,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        613,                         /* N */
+        16,                          /* securuity strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        55,                          /* df, dr */
+        204,                         /* dg */
+        97,                          /* maxMsgLenBytes */
+        55,                          /* dm0 */
+        1839,                        /* 2^c - (2^c mod N) */
+        11,                          /* c */
+        1,                           /* lLen */
+        16,                          /* min. no. of hash calls for IGF-2 */
+        13,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES887EP1,              /* parameter-set id */
+        {0x00, 0x05, 0x04},          /* OID */
+        0x28,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        887,                         /* N */
+        24,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        81,                          /* df, dr */
+        295,                         /* dg */
+        141,                         /* maxMsgLenBytes */
+        81,                          /* dm0 */
+        887,                         /* 2^c - (2^c mod N) */
+        10,                          /* c */
+        1,                           /* lLen */
+        13,                          /* min. no. of hash calls for IGF-2 */
+        12,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES1171EP1,             /* parameter-set id */
+        {0x00, 0x06, 0x04},          /* OID */
+        0x29,                        /* DER id */
+        11,                          /* no. of bits in N (i.e., in an index) */
+        1171,                        /* N */
+        32,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        106,                         /* df, dr */
+        390,                         /* dg */
+        186,                         /* maxMsgLenBytes */
+        106,                         /* dm0 */
+        3513,                        /* 2^c - (2^c mod N) */
+        12,                          /* c */
+        1,                           /* lLen */
+        20,                          /* min. no. of hash calls for IGF-2 */
+        15,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES659EP1,              /* parameter-set id */
+        {0x00, 0x02, 0x06},          /* OID */
+        0x2a,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        659,                         /* N */
+        14,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        38,                          /* df, dr */
+        219,                         /* dg */
+        108,                         /* maxMsgLenBytes */
+        38,                          /* dm0 */
+        1977,                        /* 2^c - (2^c mod N) */
+        11,                          /* c */
+        1,                           /* lLen */
+        11,                          /* min. no. of hash calls for IGF-2 */
+        14,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES761EP1,              /* parameter-set id */
+        {0x00, 0x03, 0x05},          /* OID */
+        0x2b,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        761,                         /* N */
+        16,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        42,                          /* df, dr */
+        253,                         /* dg */
+        125,                         /* maxMsgLenBytes */
+        42,                          /* dm0 */
+        3805,                        /* 2^c - (2^c mod N) */
+        12,                          /* c */
+        1,                           /* lLen */
+        13,                          /* min. no. of hash calls for IGF-2 */
+        16,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES1087EP1,             /* parameter-set id */
+        {0x00, 0x05, 0x05},          /* OID */
+        0x2c,                        /* DER id */
+        11,                          /* no. of bits in N (i.e., in an index) */
+        1087,                        /* N */
+        24,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        63,                          /* df, dr */
+        362,                         /* dg */
+        178,                         /* maxMsgLenBytes */
+        63,                          /* dm0 */
+        7609,                        /* 2^c - (2^c mod N) */
+        13,                          /* c */
+        1,                           /* lLen */
+        13,                          /* min. no. of hash calls for IGF-2 */
+        14,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES1499EP1,             /* parameter-set id */
+        {0x00, 0x06, 0x05},          /* OID */
+        0x2d,                        /* DER id */
+        11,                          /* no. of bits in N (i.e., in an index) */
+        1499,                        /* N */
+        32,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        FALSE,                       /* product form */
+        79,                          /* df, dr */
+        499,                         /* dg */
+        247,                         /* maxMsgLenBytes */
+        79,                          /* dm0 */
+        7495,                        /* 2^c - (2^c mod N) */
+        13,                          /* c */
+        1,                           /* lLen */
+        17,                          /* min. no. of hash calls for IGF-2 */
+        19,                          /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES401EP2,              /* parameter-set id */
+        {0x00, 0x02, 0x10},          /* OID */
+        0x2e,                        /* DER id */
+        9,                           /* no. of bits in N (i.e., in an index) */
+        401,                         /* N */
+        14,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        TRUE,                        /* product form */
+        8 + (8 << 8) + (6 << 16),    /* df, dr */
+        133,                         /* dg */
+        60,                          /* maxMsgLenBytes */
+        136,                         /* m(1)_max */
+        2005,                        /* 2^c - (2^c mod N) */
+        11,                          /* c */
+        1,                           /* lLen */
+        10,                          /* min. no. of hash calls for IGF-2 */
+        6,                           /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES439EP1,              /* parameter-set id */
+        {0x00, 0x03, 0x10},          /* OID */
+        0x2f,                        /* DER id */
+        9,                           /* no. of bits in N (i.e., in an index) */
+        439,                         /* N */
+        16,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        TRUE,                        /* product form */
+        9 + (8 << 8) + (5 << 16),    /* df, dr */
+        146,                         /* dg */
+        65,                          /* maxMsgLenBytes */
+        126,                         /* m(1)_max */
+        439,                         /* 2^c - (2^c mod N) */
+        9,                           /* c */
+        1,                           /* lLen */
+        15,                          /* min. no. of hash calls for IGF-2 */
+        6,                           /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES593EP1,              /* parameter-set id */
+        {0x00, 0x05, 0x10},          /* OID */
+        0x30,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        593,                         /* N */
+        24,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        TRUE,                        /* product form */
+        10 + (10 << 8) + (8 << 16),  /* df, dr */
+        197,                         /* dg */
+        86,                          /* maxMsgLenBytes */
+        90,                          /* m(1)_max */
+        1779,                        /* 2^c - (2^c mod N) */
+        11,                          /* c */
+        1,                           /* lLen */
+        12,                          /* min. no. of hash calls for IGF-2 */
+        5,                           /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+    {
+        NTRU_EES743EP1,              /* parameter-set id */
+        {0x00, 0x06, 0x10},          /* OID */
+        0x31,                        /* DER id */
+        10,                          /* no. of bits in N (i.e., in an index) */
+        743,                         /* N */
+        32,                          /* security strength in octets */
+        2048,                        /* q */
+        11,                          /* no. of bits in q (i.e., in a coeff) */
+        TRUE,                        /* product form */
+        11 + (11 << 8) + (15 << 16), /* df, dr */
+        247,                         /* dg */
+        106,                         /* maxMsgLenBytes */
+        60,                          /* m(1)_max */
+        8173,                        /* 2^c - (2^c mod N) */
+        13,                          /* c */
+        1,                           /* lLen */
+        12,                          /* min. no. of hash calls for IGF-2 */
+        7,                           /* min. no. of hash calls for MGF-TP-1 */
+    },
+
+};
+
+static size_t numParamSets =
+                sizeof(ntruParamSets)/sizeof(NTRU_ENCRYPT_PARAM_SET);
+
+
+/* functions */
+
+/* ntru_encrypt_get_params_with_id
+ *
+ * Looks up a set of NTRUEncrypt parameters based on the id of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_id(
+    NTRU_ENCRYPT_PARAM_SET_ID id)   /*  in - parameter-set id */
+{
+    size_t i;
+
+    for (i = 0; i < numParamSets; i++) {
+        if (ntruParamSets[i].id == id) {
+            return &(ntruParamSets[i]);
+        }
+    }
+    return NULL;
+}
+
+
+/* ntru_encrypt_get_params_with_OID
+ *
+ * Looks up a set of NTRUEncrypt parameters based on the OID of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_OID(
+    uint8_t const *oid)             /*  in - pointer to parameter-set OID */
+{
+    size_t i;
+
+    for (i = 0; i < numParamSets; i++) {
+        if (!memcmp(ntruParamSets[i].OID, oid, 3)) {
+            return &(ntruParamSets[i]);
+        }
+    }
+    return NULL;
+}
+
+
+/* ntru_encrypt_get_params_with_DER_id
+ *
+ * Looks up a set of NTRUEncrypt parameters based on the DER id of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_DER_id(
+    uint8_t der_id)                 /*  in - parameter-set DER id */
+{
+    size_t i;
+
+    for (i = 0; i < numParamSets; i++) {
+        if (ntruParamSets[i].der_id == der_id) {
+            return &(ntruParamSets[i]);
+        }
+    }
+    return NULL;
+}
+
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt_param_sets.h
new file mode 100644 (file)
index 0000000..ad2b89b
--- /dev/null
@@ -0,0 +1,124 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_encrypt_param_sets.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_encrypt_param_sets.h
+ *
+ * Contents: Definitions and declarations for the NTRUEncrypt parameter sets.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_NTRU_ENCRYPT_PARAM_SETS_H
+#define NTRU_CRYPTO_NTRU_ENCRYPT_PARAM_SETS_H
+
+#include "ntru_crypto.h"
+#include "ntru_crypto_hash_basics.h"
+
+
+/* structures */
+
+typedef struct _NTRU_ENCRYPT_PARAM_SET {
+    NTRU_ENCRYPT_PARAM_SET_ID id;                 /* parameter-set ID */
+    uint8_t const             OID[3];             /* pointer to OID */
+    uint8_t                   der_id;             /* parameter-set DER id */
+    uint8_t                   N_bits;             /* no. of bits in N (i.e. in
+                                                     an index */
+    uint16_t                  N;                  /* ring dimension */
+    uint16_t                  sec_strength_len;   /* no. of octets of
+                                                     security strength */
+    uint16_t                  q;                  /* big modulus */
+    uint8_t                   q_bits;             /* no. of bits in q (i.e. in
+                                                     a coefficient */
+    bool                      is_product_form;    /* if product form used */
+    uint32_t                  dF_r;               /* no. of 1 or -1 coefficients
+                                                     in ring elements F, r */
+    uint16_t                  dg;                 /* no. - 1 of 1 coefficients
+                                                     or no. of -1 coefficients
+                                                     in ring element g */
+    uint16_t                  m_len_max;          /* max no. of plaintext
+                                                     octets */
+    uint16_t                  min_msg_rep_wt;     /* min. message
+                                                     representative weight */
+    uint16_t                  no_bias_limit;      /* limit for no bias in
+                                                     IGF-2 */
+    uint8_t                   c_bits;             /* no. bits in candidate for
+                                                     deriving an index in
+                                                     IGF-2 */
+    uint8_t                   m_len_len;          /* no. of octets to hold
+                                                     mLenOctets */
+    uint8_t                   min_IGF_hash_calls; /* min. no. of hash calls for
+                                                     IGF-2 */
+    uint8_t                   min_MGF_hash_calls; /* min. no. of hash calls for
+                                                     MGF-TP-1 */
+} NTRU_ENCRYPT_PARAM_SET;
+
+
+
+/* function declarations */
+
+/* ntru_encrypt_get_params_with_id
+ *
+ * Looks up a set of NTRU Encrypt parameters based on the id of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+extern NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_id(
+    NTRU_ENCRYPT_PARAM_SET_ID id);  /*  in - parameter-set id */
+
+
+/* ntru_encrypt_get_params_with_OID
+ *
+ * Looks up a set of NTRU Encrypt parameters based on the OID of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+extern NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_OID(
+    uint8_t const *oid);            /*  in - pointer to parameter-set OID */
+
+
+/* ntru_encrypt_get_params_with_DER_id
+ *
+ * Looks up a set of NTRUEncrypt parameters based on the DER id of the
+ * parameter set.
+ *
+ * Returns a pointer to the parameter set parameters if successful.
+ * Returns NULL if the parameter set cannot be found.
+ */
+
+extern NTRU_ENCRYPT_PARAM_SET *
+ntru_encrypt_get_params_with_DER_id(
+    uint8_t der_id);                /*  in - parameter-set DER id */
+
+
+#endif /* NTRU_CRYPTO_NTRU_ENCRYPT_PARAM_SETS_H */
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.c
new file mode 100644 (file)
index 0000000..194af4f
--- /dev/null
@@ -0,0 +1,197 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_mgf1.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_mgf1.c
+ *
+ * Contents: Routines implementing MGF-TP-1 and MGF-1.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto_ntru_mgf1.h"
+#include "ntru_crypto_ntru_convert.h"
+
+
+/* ntru_mgf1
+ *
+ * Implements a basic mask-generation function, generating an arbitrary
+ * number of octets based on hashing a digest-length string concatenated
+ * with a 4-octet counter.
+ *
+ * The state (string and counter) is initialized when a seed is present.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_CRYPTO_HASH_ errors if they occur.
+ *
+ */
+
+uint32_t
+ntru_mgf1(
+    uint8_t                *state,      /* in/out - pointer to the state */
+    NTRU_CRYPTO_HASH_ALGID  algid,      /*     in - hash algorithm ID */
+    uint8_t                 md_len,     /*     in - no. of octets in digest */
+    uint8_t                 num_calls,  /*     in - no. of hash calls */
+    uint16_t                seed_len,   /*     in - no. of octets in seed */
+    uint8_t const          *seed,       /*     in - pointer to seed */
+    uint8_t                *out)        /*    out - address for output */
+{
+    uint8_t  *ctr = state + md_len;
+    uint32_t  retcode;
+
+    assert(state);
+    assert(out);
+
+    /* if seed present, init state */
+
+    if (seed) {
+        if ((retcode = ntru_crypto_hash_digest(algid, seed, seed_len, state)) !=
+                NTRU_CRYPTO_HASH_OK)
+            return retcode;
+        memset(ctr, 0, 4);
+    }
+
+    /* generate output */
+
+    while (num_calls-- > 0) {
+        if ((retcode = ntru_crypto_hash_digest(algid, state, md_len + 4,
+                                               out)) !=
+                NTRU_CRYPTO_HASH_OK)
+            return retcode;
+        out += md_len;
+
+        /* increment counter */
+
+        if (++ctr[3] == 0)
+            if (++ctr[2] == 0)
+                if (++ctr[1] == 0)
+                    ++ctr[0];
+    }
+
+    NTRU_RET(NTRU_OK);
+}
+
+
+/* ntru_mgftp1
+ *
+ * Implements a mask-generation function for trinary polynomials,
+ * MGF-TP-1, generating an arbitrary number of octets based on hashing
+ * a digest-length string concatenated with a 4-octet counter.  From
+ * these octets, N trits are derived.
+ *
+ * The state (string and counter) is initialized when a seed is present.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_CRYPTO_HASH_ errors if they occur.
+ *
+ */
+
+uint32_t
+ntru_mgftp1(
+    NTRU_CRYPTO_HASH_ALGID  hash_algid,       /*  in - hash alg ID for
+                                                       MGF-TP-1 */
+    uint8_t                 md_len,           /*  in - no. of octets in
+                                                       digest */
+    uint8_t                 min_calls,        /*  in - minimum no. of hash
+                                                       calls */
+    uint16_t                seed_len,         /*  in - no. of octets in seed */
+    uint8_t                *seed,             /*  in - pointer to seed */
+    uint8_t                *buf,              /*  in - pointer to working
+                                                       buffer */
+    uint16_t                num_trits_needed, /*  in - no. of trits in mask */
+    uint8_t                *mask)             /* out - address for mask trits */
+{
+    uint8_t  *mgf_out;
+    uint8_t  *octets;
+    uint16_t  octets_available;
+    uint32_t  retcode;
+
+    assert(seed);
+    assert(buf);
+    assert(mask);
+
+    /* generate minimum MGF1 output */
+
+    mgf_out = buf + md_len + 4;
+    if ((retcode = ntru_mgf1(buf, hash_algid, md_len, min_calls,
+                             seed_len, seed, mgf_out)) != NTRU_OK)
+        return retcode;
+    octets = mgf_out;
+    octets_available = min_calls * md_len;
+
+    /* get trits for mask */
+
+    while (num_trits_needed >= 5) {
+
+        /* get another octet and convert it to 5 trits */
+
+        if (octets_available == 0) {
+            if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
+                                     0, NULL, mgf_out)) != NTRU_OK)
+                return retcode;
+            octets = mgf_out;
+            octets_available = md_len;
+        }
+
+        if (*octets < 243) {
+            ntru_octet_2_trits(*octets, mask);
+            mask += 5;
+            num_trits_needed -= 5;
+        }
+        octets++;
+        --octets_available;
+    }
+
+    /* get any remaining trits */
+
+    while (num_trits_needed) {
+        uint8_t trits[5];
+
+        /* get another octet and convert it to remaining trits */
+
+        if (octets_available == 0) {
+            if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
+                                     0, NULL, mgf_out)) != NTRU_OK)
+                return retcode;
+            octets = mgf_out;
+            octets_available = md_len;
+        }
+        if (*octets < 243) {
+            ntru_octet_2_trits(*octets, trits);
+            memcpy(mask, trits, num_trits_needed);
+            num_trits_needed = 0;
+        } else {
+            octets++;
+            --octets_available;
+        }
+    }
+
+    NTRU_RET(NTRU_OK);
+}
+
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.h
new file mode 100644 (file)
index 0000000..b3615fa
--- /dev/null
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_mgf1.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File:  ntru_crypto_ntru_mgf1.h
+ *
+ * Contents: Public header file for MGF-1 in the NTRU algorithm.
+ *
+ *****************************************************************************/
+
+
+#ifndef NTRU_CRYPTO_NTRU_MGF1_H
+#define NTRU_CRYPTO_NTRU_MGF1_H
+
+
+#include "ntru_crypto.h"
+#include "ntru_crypto_hash.h"
+
+
+/* function declarations */
+
+/* ntru_mgf1
+ *
+ * Implements a basic mask-generation function, generating an arbitrary
+ * number of octets based on hashing a digest-length string concatenated
+ * with a 4-octet counter.
+ *
+ * The state (string and counter) is initialized when a seed is present.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_CRYPTO_HASH_ errors if they occur.
+ *
+ */
+
+extern uint32_t
+ntru_mgf1(
+    uint8_t                *state,      /* in/out - pointer to the state */
+    NTRU_CRYPTO_HASH_ALGID  algid,      /*     in - hash algorithm ID */
+    uint8_t                 md_len,     /*     in - no. of octets in digest */
+    uint8_t                 num_calls,  /*     in - no. of hash calls */
+    uint16_t                seed_len,   /*     in - no. of octets in seed */
+    uint8_t const          *seed,       /*     in - pointer to seed */
+    uint8_t                *out);       /*    out - address for output */
+
+
+/* ntru_mgftp1
+ *
+ * Implements a mask-generation function for trinary polynomials,
+ * MGF-TP-1, generating an arbitrary number of octets based on hashing
+ * a digest-length string concatenated with a 4-octet counter.  From
+ * these octets, N trits are derived.
+ *
+ * The state (string and counter) is initialized when a seed is present.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns NTRU_CRYPTO_HASH_ errors if they occur.
+ *
+ */
+
+extern uint32_t
+ntru_mgftp1(
+    NTRU_CRYPTO_HASH_ALGID  hash_algid,       /*  in - hash alg ID for
+                                                       MGF-TP-1 */
+    uint8_t                 md_len,           /*  in - no. of octets in
+                                                       digest */
+    uint8_t                 min_calls,        /*  in - minimum no. of hash
+                                                       calls */
+    uint16_t                seed_len,         /*  in - no. of octets in seed */
+    uint8_t                *seed,             /*  in - pointer to seed */
+    uint8_t                *buf,              /*  in - pointer to working
+                                                       buffer */
+    uint16_t                num_trits_needed, /*  in - no. of trits in mask */
+    uint8_t                *mask);            /* out - address for mask trits */
+
+
+#endif /* NTRU_CRYPTO_NTRU_MGF1_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c
new file mode 100644 (file)
index 0000000..6fc3414
--- /dev/null
@@ -0,0 +1,586 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_poly.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_ntru_poly.c
+ *
+ * Contents: Routines for generating and operating on polynomials in the
+ *           NTRU algorithm.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ntru_crypto_ntru_poly.h"
+#include "ntru_crypto_ntru_mgf1.h"
+
+
+/* ntru_gen_poly
+ *
+ * Generates polynomials by creating for each polynomial, a list of the
+ * indices of the +1 coefficients followed by a list of the indices of
+ * the -1 coefficients.
+ *
+ * If a single polynomial is generated (non-product form), indices_counts
+ * contains a single value of the total number of indices (for +1 and -1
+ * comefficients combined).
+ *
+ * If multiple polynomials are generated (for product form), their lists of
+ * indices are sequentially stored in the indices buffer.  Each byte of
+ * indices_counts contains the total number of indices (for +1 and -1
+ * coefficients combined) for a single polynomial, beginning with the
+ * low-order byte for the first polynomial.  The high-order byte is unused.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns HASH_BAD_ALG if the algorithm is not supported.
+ *
+ */
+
+uint32_t
+ntru_gen_poly(
+    NTRU_CRYPTO_HASH_ALGID  hash_algid,      /*  in - hash algorithm ID for
+                                                      IGF-2 */
+    uint8_t                 md_len,          /*  in - no. of octets in digest */
+    uint8_t                 min_calls,       /*  in - minimum no. of hash
+                                                      calls */
+    uint16_t                seed_len,        /*  in - no. of octets in seed */
+    uint8_t                *seed,            /*  in - pointer to seed */
+    uint8_t                *buf,             /*  in - pointer to working
+                                                      buffer */
+    uint16_t                N,               /*  in - max index + 1 */
+    uint8_t                 c_bits,          /*  in - no. bits for candidate */
+    uint16_t                limit,           /*  in - conversion to index
+                                                      limit */
+    bool                    is_product_form, /*  in - if generating multiple
+                                                      polys */
+    uint32_t                indices_counts,  /*  in - nos. of indices needed */
+    uint16_t               *indices)         /* out - address for indices */
+{
+    uint8_t  *mgf_out;
+    uint8_t  *octets;
+    uint8_t  *used;
+    uint8_t   num_polys;
+    uint16_t  num_indices;
+    uint16_t  octets_available;
+    uint16_t  index_cnt = 0;
+    uint8_t   left = 0;
+    uint8_t   num_left = 0;
+    uint32_t  retcode;
+
+    assert(seed);
+    assert(buf);
+    assert(indices);
+
+    /* generate minimum MGF1 output */
+
+    mgf_out = buf + md_len + 4;
+    if ((retcode = ntru_mgf1(buf, hash_algid, md_len, min_calls,
+                             seed_len, seed, mgf_out)) != NTRU_OK)
+        return retcode;
+    octets = mgf_out;
+    octets_available = min_calls * md_len;
+
+    /* init indices counts for number of polynomials being generated */
+
+    if (is_product_form) {
+
+        /* number of indices for poly1 is in low byte of indices_counts,
+         * number of indices for poly2 and poly3 are in next higher bytes
+         */
+
+        num_polys = 3;
+        num_indices = (uint16_t)(indices_counts & 0xff);
+        indices_counts >>= 8;
+
+    } else {
+
+        /* number of bytes for poly is in low 16 bits of indices_counts */
+
+        num_polys = 1;
+        num_indices = (uint16_t)indices_counts;
+    }
+
+    /* init used-index array */
+
+    used = mgf_out + octets_available;
+    memset(used, 0, N);
+
+    /* generate indices (IGF-2) for all polynomials */
+
+    while (num_polys > 0) {
+
+        /* generate indices for a single polynomial */
+
+        while (index_cnt < num_indices) {
+            uint16_t index;
+            uint8_t  num_needed;
+
+            /* form next index to convert to an index */
+
+            do {
+                /* use any leftover bits first */
+
+                if (num_left != 0) {
+                    index = left << (c_bits - num_left);
+                } else {
+                    index = 0;
+                }
+
+                /* get the rest of the bits needed from new octets */
+
+                num_needed = c_bits - num_left;
+                while (num_needed != 0) {
+
+                    /* get another octet */
+
+                    if (octets_available == 0) {
+                        if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
+                                                 0, NULL, mgf_out)) != NTRU_OK)
+                            return retcode;
+                        octets = mgf_out;
+                        octets_available = md_len;
+                    }
+                    left = *octets++;
+                    --octets_available;
+
+                    if (num_needed <= 8) {
+
+                        /* all bits needed to fill the index are in this octet */
+
+                        index |= ((uint16_t)(left)) >> (8 - num_needed);
+                        num_left = 8 - num_needed;
+                        num_needed = 0;
+                        left &= 0xff >> (8 - num_left);
+
+                    } else {
+
+                        /* another octet will be needed after using this
+                         * whole octet
+                         */
+
+                        index |= ((uint16_t)left) << (num_needed - 8);
+                        num_needed -= 8;
+                    }
+                }
+            } while (index >= limit);
+
+            /* form index and check if unique */
+
+            index %= N;
+            if (!used[index]) {
+                used[index] = 1;
+                indices[index_cnt] = index;
+                ++index_cnt;
+            }
+        }
+        --num_polys;
+
+        /* init for next polynomial if another polynomial to be generated */
+
+        if (num_polys > 0) {
+            memset(used, 0, N);
+            num_indices = num_indices +
+                          (uint16_t)(indices_counts & 0xff);
+            indices_counts >>= 8;
+        }
+    }
+
+    NTRU_RET(NTRU_OK);
+}
+
+
+/* ntru_poly_check_min_weight
+ *
+ * Checks that the number of 0, +1, and -1 trinary ring elements meet or exceed
+ * a minimum weight.
+ */
+
+bool
+ntru_poly_check_min_weight(
+    uint16_t  num_els,              /*  in - degree of polynomial */
+    uint8_t  *ringels,              /*  in - pointer to trinary ring elements */
+    uint16_t  min_wt)               /*  in - minimum weight */
+{
+    uint16_t wt[3];
+    uint16_t i;
+
+    wt[0] = wt[1] = wt[2] = 0;
+    for (i = 0; i < num_els; i++) {
+       ++wt[ringels[i]];
+    }
+    if ((wt[0] < min_wt) || (wt[1] < min_wt) || (wt[2] < min_wt)) {
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+/* ntru_ring_mult_indices
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" is a sparse trinary polynomial with coefficients -1, 0,
+ * and 1.  It is specified by a list, bi, of its nonzero indices containing
+ * indices for the bi_P1_len +1 coefficients followed by the indices for the
+ * bi_M1_len -1 coefficients.
+ * The indices are in the range [0,N).
+ *
+ * The result array "c" may share the same memory space as input array "a",
+ * input array "b", or temp array "t".
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+void
+ntru_ring_mult_indices(
+    uint16_t const *a,          /*  in - pointer to ring element a */
+    uint16_t        bi_P1_len,  /*  in - no. of +1 coefficients in b */
+    uint16_t        bi_M1_len,  /*  in - no. of -1 coefficients in b */
+    uint16_t const *bi,         /*  in - pointer to the list of nonzero
+                                         indices of ring element b,
+                                         containing indices for the +1
+                                         coefficients followed by the
+                                         indices for -1 coefficients */
+    uint16_t        N,          /*  in - no. of coefficients in a, b, c */
+    uint16_t        q,          /*  in - large modulus */
+    uint16_t       *t,          /*  in - temp buffer of N elements */
+    uint16_t       *c)          /* out - address for polynomial c */
+{
+    uint16_t mod_q_mask = q - 1;
+    uint16_t i, j, k;
+
+    assert(a);
+    assert(bi);
+    assert(t);
+    assert(c);
+
+    /* t[(i+k)%N] = sum i=0 through N-1 of a[i], for b[k] = -1 */
+
+    for (k = 0; k < N; k++)
+        t[k] = 0;
+    for (j = bi_P1_len; j < bi_P1_len + bi_M1_len; j++) {
+        k = bi[j];
+        for (i = 0; k < N; ++i, ++k)
+            t[k] = t[k] + a[i];
+        for (k = 0; i < N; ++i, ++k)
+            t[k] = t[k] + a[i];
+    }
+
+    /* t[(i+k)%N] = -(sum i=0 through N-1 of a[i] for b[k] = -1) */
+
+    for (k = 0; k < N; k++)
+        t[k] = -t[k];
+
+    /* t[(i+k)%N] += sum i=0 through N-1 of a[i] for b[k] = +1 */
+
+    for (j = 0; j < bi_P1_len; j++) {
+        k = bi[j];
+        for (i = 0; k < N; ++i, ++k)
+            t[k] = t[k] + a[i];
+        for (k = 0; i < N; ++i, ++k)
+            t[k] = t[k] + a[i];
+    }
+
+    /* c = (a * b) mod q */
+
+    for (k = 0; k < N; k++)
+        c[k] = t[k] & mod_q_mask;
+}
+
+
+/* ntru_ring_mult_product_indices
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" is represented by the product form b1 * b2 + b3, where
+ * b1, b2, and b3 are each a sparse trinary polynomial with coefficients -1,
+ * 0, and 1.  It is specified by a list, bi, of the nonzero indices of b1, b2,
+ * and b3, containing the indices for the +1 coefficients followed by the
+ * indices for the -1 coefficients for each polynomial in that order.
+ * The indices are in the range [0,N).
+ *
+ * The result array "c" may share the same memory space as input array "a",
+ * or input array "b".
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+void
+ntru_ring_mult_product_indices(
+    uint16_t       *a,          /*  in - pointer to ring element a */
+    uint16_t        b1i_len,    /*  in - no. of +1 or -1 coefficients in b1 */
+    uint16_t        b2i_len,    /*  in - no. of +1 or -1 coefficients in b2 */
+    uint16_t        b3i_len,    /*  in - no. of +1 or -1 coefficients in b3 */
+    uint16_t const *bi,         /*  in - pointer to the list of nonzero
+                                         indices of polynomials b1, b2, b3,
+                                         containing indices for the +1
+                                         coefficients followed by the
+                                         indices for -1 coefficients for
+                                         each polynomial */
+    uint16_t        N,          /*  in - no. of coefficients in a, b, c */
+    uint16_t        q,          /*  in - large modulus */
+    uint16_t       *t,          /*  in - temp buffer of 2N elements */
+    uint16_t       *c)          /* out - address for polynomial c */
+{
+    uint16_t *t2 = t + N;
+    uint16_t  mod_q_mask = q - 1;
+    uint16_t  i;
+
+    assert(a);
+    assert(bi);
+    assert(t);
+    assert(c);
+
+    /* t2 = a * b1 */
+
+    ntru_ring_mult_indices(a, b1i_len, b1i_len, bi, N, q, t, t2);
+
+    /* t2 = (a * b1) * b2 */
+
+    ntru_ring_mult_indices(t2, b2i_len, b2i_len, bi + (b1i_len << 1), N, q,
+                           t, t2);
+
+    /* t = a * b3 */
+
+    ntru_ring_mult_indices(a, b3i_len, b3i_len,
+                           bi + ((b1i_len + b2i_len) << 1), N, q, t, t);
+
+    /* c = (a * b1 * b2) + (a * b3) */
+
+    for (i = 0; i < N; i++)
+        c[i] = (t2[i] + t[i]) & mod_q_mask;
+}
+
+
+/* ntru_ring_mult_coefficients
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" has coefficients in the range [0,N).
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+void
+ntru_ring_mult_coefficients(
+    uint16_t const *a,          /*  in - pointer to polynomial a */
+    uint16_t const *b,          /*  in - pointer to polynomial b */
+    uint16_t        N,          /*  in - no. of coefficients in a, b, c */
+    uint16_t        q,          /*  in - large modulus */
+    uint16_t       *c)          /* out - address for polynomial c */
+{
+    uint16_t const *bptr = b;
+    uint16_t        mod_q_mask = q - 1;
+    uint16_t        i, k;
+
+    assert(a);
+    assert(b);
+    assert(c);
+
+    /* c[k] = sum(a[i] * b[k-i]) mod q */
+
+    memset(c, 0, N * sizeof(uint16_t));
+    for (k = 0; k < N; k++) {
+        i = 0;
+        while (i <= k)
+            c[k] += a[i++] * *bptr--;
+        bptr += N;
+        while (i < N)
+            c[k] += a[i++] * *bptr--;
+        c[k] &= mod_q_mask;
+        ++bptr;
+    }
+}
+
+
+/* ntru_ring_inv
+ *
+ * Finds the inverse of a polynomial, a, in (Z/2^rZ)[X]/(X^N - 1).
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that operations mod q can
+ * wait until the end, and only 16-bit arrays need to be used.
+ */
+
+bool
+ntru_ring_inv(
+    uint16_t       *a,          /*  in - pointer to polynomial a */
+    uint16_t        N,          /*  in - no. of coefficients in a */
+    uint16_t        q,          /*  in - large modulus */
+    uint16_t       *t,          /*  in - temp buffer of 2N elements */
+    uint16_t       *a_inv)      /* out - address for polynomial a^-1 */
+{
+    uint8_t  *b = (uint8_t *)t;     /* b cannot be in a_inv since it must be
+                                       rotated and copied there as a^-1 mod 2 */
+    uint8_t  *c = b + N;            /* c cannot be in a_inv since it exchanges
+                                       with b, and b cannot be in a_inv */
+    uint8_t  *f = c + N;
+    uint8_t  *g = (uint8_t *)a_inv; /* g needs N + 1 bytes */
+    uint16_t *t2 = t + N;
+    uint16_t  deg_b;
+    uint16_t  deg_c;
+    uint16_t  deg_f;
+    uint16_t  deg_g;
+    uint16_t  k = 0;
+    bool      done = FALSE;
+    uint16_t  i, j;
+
+    assert(a);
+    assert(t);
+    assert(a_inv);
+
+    /* form a^-1 in (Z/2Z)[X]/X^N - 1) */
+
+    memset(b, 0, (N << 1));         /* clear to init b, c */
+
+    /* b(X) = 1 */
+
+    b[0] = 1;
+    deg_b = 0;
+
+    /* c(X) = 0 (cleared above) */
+
+    deg_c = 0;
+
+    /* f(X) = a(X) mod 2 */
+
+    for (i = 0; i < N; i++)
+        f[i] = (uint8_t)(a[i] & 1);
+    deg_f = N - 1;
+
+    /* g(X) = X^N - 1 */
+
+    g[0] = 1;
+    memset(g + 1, 0, N - 1);
+    g[N] = 1;
+    deg_g = N;
+
+    /* until f(X) = 1 */
+
+    while (!done) {
+
+        /* while f[0] = 0, f(X) /= X, c(X) *= X, k++ */
+
+        for (i = 0; (i <= deg_f) && (f[i] == 0); ++i);
+        if (i > deg_f)
+            return FALSE;
+        if (i) {
+            f = f + i;
+            deg_f = deg_f - i;
+            deg_c = deg_c + i;
+            for (j = deg_c; j >= i; j--)
+                c[j] = c[j-i];
+            for (j = 0; j < i; j++)
+                c[j] = 0;
+            k = k + i;
+        }
+
+        /* adjust degree of f(X) if the highest coefficients are zero
+         * Note: f[0] = 1 from above so the loop will terminate.
+         */
+
+        while (f[deg_f] == 0)
+            --deg_f;
+
+        /* if f(X) = 1, done
+         * Note: f[0] = 1 from above, so only check the x term and up
+         */
+
+        for (i = 1; (i <= deg_f) && (f[i] == 0); ++i);
+        if (i > deg_f) {
+            done = TRUE;
+            break;
+        }
+
+        /* if deg_f < deg_g, f <-> g, b <-> c */
+
+        if (deg_f < deg_g) {
+            uint8_t *x;
+
+            x = f;
+            f = g;
+            g = x;
+            deg_f ^= deg_g;
+            deg_g ^= deg_f;
+            deg_f ^= deg_g;
+            x = b;
+            b = c;
+            c = x;
+            deg_b ^= deg_c;
+            deg_c ^= deg_b;
+            deg_b ^= deg_c;
+        }
+
+        /* f(X) += g(X), b(X) += c(X) */
+
+        for (i = 0; i <= deg_g; i++)
+            f[i] ^= g[i];
+
+        if (deg_c > deg_b)
+            deg_b = deg_c;
+        for (i = 0; i <= deg_c; i++)
+            b[i] ^= c[i];
+    }
+
+    /* a^-1 in (Z/2Z)[X]/(X^N - 1) = b(X) shifted left k coefficients */
+
+    j = 0;
+    if (k >= N)
+        k = k - N;
+    for (i = k; i < N; i++)
+        a_inv[j++] = (uint16_t)(b[i]);
+    for (i = 0; i < k; i++)
+        a_inv[j++] = (uint16_t)(b[i]);
+
+    /* lift a^-1 in (Z/2Z)[X]/(X^N - 1) to a^-1 in (Z/qZ)[X]/(X^N -1) */
+
+    for (j = 0; j < 4; ++j) {       /* assumes 256 < q <= 65536 */
+
+        /* a^-1 = a^-1 * (2 - a * a^-1) mod q */
+
+        memcpy(t2, a_inv, N * sizeof(uint16_t));
+        ntru_ring_mult_coefficients(a, t2, N, q, t);
+        for (i = 0; i < N; ++i)
+            t[i] = q - t[i];
+        t[0] = t[0] + 2;
+        ntru_ring_mult_coefficients(t2, t, N, q, a_inv);
+    }
+
+    return TRUE;
+
+
+}
+
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h
new file mode 100644 (file)
index 0000000..242fb41
--- /dev/null
@@ -0,0 +1,211 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_poly.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File:  ntru_crypto_ntru_poly.h
+ *
+ * Contents: Public header file for generating and operating on polynomials
+ *           in the NTRU algorithm.
+ *
+ *****************************************************************************/
+
+
+#ifndef NTRU_CRYPTO_NTRU_POLY_H
+#define NTRU_CRYPTO_NTRU_POLY_H
+
+
+#include "ntru_crypto.h"
+#include "ntru_crypto_hash_basics.h"
+
+
+/* function declarations */
+
+/* ntru_gen_poly
+ *
+ * Generates polynomials by creating for each polynomial, a list of the
+ * indices of the +1 coefficients followed by a list of the indices of
+ * the -1 coefficients.
+ *
+ * If a single polynomial is generated (non-product form), indices_counts
+ * contains a single value of the total number of indices (for +1 and -1
+ * comefficients combined).
+ *
+ * If multiple polynomials are generated (for product form), their lists of
+ * indices are sequentially stored in the indices buffer.  Each byte of
+ * indices_counts contains the total number of indices (for +1 and -1
+ * coefficients combined) for a single polynomial, beginning with the
+ * low-order byte for the first polynomial.  The high-order byte is unused.
+ *
+ * Returns NTRU_OK if successful.
+ * Returns HASH_BAD_ALG if the algorithm is not supported.
+ *
+ */
+
+extern uint32_t
+ntru_gen_poly(
+    NTRU_CRYPTO_HASH_ALGID  hash_algid,      /*  in - hash algorithm ID for
+                                                      IGF-2 */
+    uint8_t                 md_len,          /*  in - no. of octets in digest */
+    uint8_t                 min_calls,       /*  in - minimum no. of hash
+                                                      calls */
+    uint16_t                seed_len,        /*  in - no. of octets in seed */
+    uint8_t                *seed,            /*  in - pointer to seed */
+    uint8_t                *buf,             /*  in - pointer to working
+                                                      buffer */
+    uint16_t                N,               /*  in - max index + 1 */
+    uint8_t                 c_bits,          /*  in - no. bits for candidate */
+    uint16_t                limit,           /*  in - conversion to index
+                                                      limit */
+    bool                    is_product_form, /*  in - if generating multiple
+                                                      polys */
+    uint32_t                indices_counts,  /*  in - nos. of indices needed */
+    uint16_t               *indices);        /* out - address for indices */
+
+
+/* ntru_poly_check_min_weight
+ *
+ * Checks that the number of 0, +1, and -1 trinary ring elements meet or exceed
+ * a minimum weight.
+ */
+
+extern bool
+ntru_poly_check_min_weight(
+    uint16_t  num_els,              /*  in - degree of polynomial */
+    uint8_t  *ringels,              /*  in - pointer to trinary ring elements */
+    uint16_t  min_wt);              /*  in - minimum weight */
+
+
+/* ntru_ring_mult_indices
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" is a sparse trinary polynomial with coefficients -1, 0,
+ * and 1.  It is specified by a list, bi, of its nonzero indices containing
+ * indices for the bi_P1_len +1 coefficients followed by the indices for the
+ * bi_M1_len -1 coefficients.
+ * The indices are in the range [0,N).
+ *
+ * The result array "c" may share the same memory space as input array "a",
+ * or input array "b".
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+extern void
+ntru_ring_mult_indices(
+    uint16_t const *a,          /*  in - pointer to ring element a */
+    uint16_t        bi_P1_len,  /*  in - no. of +1 coefficients in b */
+    uint16_t        bi_M1_len,  /*  in - no. of -1 coefficients in b */
+    uint16_t const *bi,         /*  in - pointer to the list of nonzero
+                                         indices of ring element b,
+                                         containing indices for the +1
+                                         coefficients followed by the
+                                         indices for -1 coefficients */
+    uint16_t        N,          /*  in - no. of coefficients in a, b, c */
+    uint16_t        q,          /*  in - large modulus */
+    uint16_t       *t,          /*  in - temp buffer of N elements */
+    uint16_t       *c);         /* out - address for polynomial c */
+
+
+/* ntru_ring_mult_product_indices
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" is represented by the product form b1 * b2 + b3, where
+ * b1, b2, and b3 are each a sparse trinary polynomial with coefficients -1,
+ * 0, and 1.  It is specified by a list, bi, of the nonzero indices of b1, b2,
+ * and b3, containing the indices for the +1 coefficients followed by the
+ * indices for the -1 coefficients for each polynomial in that order.
+ * The indices are in the range [0,N).
+ *
+ * The result array "c" may share the same memory space as input array "a",
+ * or input array "b".
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+extern void
+ntru_ring_mult_product_indices(
+    uint16_t       *a,          /*  in - pointer to ring element a */
+    uint16_t        b1i_len,    /*  in - no. of +1 or -1 coefficients in b1 */
+    uint16_t        b2i_len,    /*  in - no. of +1 or -1 coefficients in b2 */
+    uint16_t        b3i_len,    /*  in - no. of +1 or -1 coefficients in b3 */
+    uint16_t const *bi,         /*  in - pointer to the list of nonzero
+                                         indices of polynomials b1, b2, b3,
+                                         containing indices for the +1
+                                         coefficients followed by the
+                                         indices for -1 coefficients for
+                                         each polynomial */
+    uint16_t        N,          /*  in - no. of coefficients in a, b, c */
+    uint16_t        q,          /*  in - large modulus */
+    uint16_t       *t,          /*  in - temp buffer of 2N elements */
+    uint16_t       *c);         /* out - address for polynomial c */
+
+
+/* ntru_ring_mult_coefficients
+ *
+ * Multiplies ring element (polynomial) "a" by ring element (polynomial) "b"
+ * to produce ring element (polynomial) "c" in (Z/qZ)[X]/(X^N - 1).
+ * This is a convolution operation.
+ *
+ * Ring element "b" has coefficients in the range [0,N).
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that overflow of the sum
+ * beyond 16 bits does not matter.
+ */
+
+extern void
+ntru_ring_mult_coefficients(
+    uint16_t const *a,          /*  in - pointer to polynomial a */
+    uint16_t const *b,          /*  in - pointer to polynomial b */
+    uint16_t        N,          /*  in - no. of coefficients in a, b, c */
+    uint16_t        q,          /*  in - large modulus */
+    uint16_t       *c);         /* out - address for polynomial c */
+
+
+/* ntru_ring_inv
+ *
+ * Finds the inverse of a polynomial, a, in (Z/2^rZ)[X]/(X^N - 1).
+ *
+ * This assumes q is 2^r where 8 < r < 16, so that operations mod q can
+ * wait until the end, and only 16-bit arrays need to be used.
+ */
+
+extern bool
+ntru_ring_inv(
+    uint16_t       *a,          /*  in - pointer to polynomial a */
+    uint16_t        N,          /*  in - no. of coefficients in a */
+    uint16_t        q,          /*  in - large modulus */
+    uint16_t       *t,          /*  in - temp buffer of 2N elements */
+    uint16_t       *a_inv);     /* out - address for polynomial a^-1 */
+
+
+#endif /* NTRU_CRYPTO_NTRU_POLY_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_platform.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_platform.h
new file mode 100644 (file)
index 0000000..b236cfe
--- /dev/null
@@ -0,0 +1,39 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_platform.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_platform.h
+ *
+ * Contents: Platform-specific basic definitions.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_PLATFORM_H
+#define NTRU_CRYPTO_PLATFORM_H
+
+#include <library.h>
+
+#endif /* NTRU_CRYPTO_PLATFORM_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha.h
new file mode 100644 (file)
index 0000000..776d10a
--- /dev/null
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_sha.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_sha.h
+ *
+ * Contents: Definitions and declarations common to all SHA hash algorithms.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_SHA_H
+#define NTRU_CRYPTO_SHA_H
+
+
+#include "ntru_crypto_error.h"
+#include "ntru_crypto_hash_basics.h"
+
+
+/***************
+ * error codes *
+ ***************/
+
+#define SHA_OK              ((uint32_t)NTRU_CRYPTO_HASH_OK)
+#define SHA_FAIL            ((uint32_t)NTRU_CRYPTO_HASH_FAIL)
+#define SHA_BAD_PARAMETER   ((uint32_t)NTRU_CRYPTO_HASH_BAD_PARAMETER)
+#define SHA_OVERFLOW        ((uint32_t)NTRU_CRYPTO_HASH_OVERFLOW)
+
+#define SHA_RESULT(r)   ((uint32_t)((r) ? SHA_ERROR_BASE + (r) : (r)))
+#define SHA_RET(r)      return SHA_RESULT(r);
+
+
+/*********
+ * flags *
+ *********/
+
+#define SHA_DATA_ONLY       HASH_DATA_ONLY
+#define SHA_INIT            HASH_INIT
+#define SHA_FINISH          HASH_FINISH
+#define SHA_ZERO_PAD        HASH_ZERO_PAD
+
+
+#endif /* NTRU_CRYPTO_SHA_H */
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha1.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha1.c
new file mode 100644 (file)
index 0000000..0469ca1
--- /dev/null
@@ -0,0 +1,588 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_ntru_crypto_sha1.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_sha1.c
+ *
+ * Contents: Routines implementing the SHA-1 hash calculation.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "ntru_crypto_sha1.h"
+#include "ntru_crypto_msbyte_uint32.h"
+
+
+/* chaining state elements */
+
+#define H0      state[0]
+#define H1      state[1]
+#define H2      state[2]
+#define H3      state[3]
+#define H4      state[4]
+
+
+/* standard SHA-1 initialization values */
+
+#define H0_INIT 0x67452301UL
+#define H1_INIT 0xefcdab89UL
+#define H2_INIT 0x98badcfeUL
+#define H3_INIT 0x10325476UL
+#define H4_INIT 0xc3d2e1f0UL
+
+
+/* sha1_blk()
+ *
+ * This routine updates the current hash output (chaining state)
+ * by performing SHA-1 on a 512-bit block of data represented as sixteen
+ * 32-bit words.
+ */
+
+#define K00_19  0x5a827999UL
+#define K20_39  0x6ed9eba1UL
+#define K40_59  0x8f1bbcdcUL
+#define K60_79  0xca62c1d6UL
+
+#define RL(a, n)    ( ((a) << (n)) | ((a) >> (32 - (n))) )
+
+
+static void
+sha1_blk(
+    uint32_t const *data,       //     in - ptr to 16 32-bit word input block
+    uint32_t       *state)      // in/out - ptr to 5 32-bit word chaining state
+{
+    uint32_t A, B, C, D, E;
+    uint32_t w[16];
+
+    /* init A - E */
+
+    A = H0; B = H1; C = H2; D = H3; E = H4;
+
+    /* rounds 0 - 15 */
+
+    E += RL(A, 5) + K00_19 + (B & (C ^ D) ^ D) + data[ 0]; B = RL(B, 30);
+    D += RL(E, 5) + K00_19 + (A & (B ^ C) ^ C) + data[ 1]; A = RL(A, 30);
+    C += RL(D, 5) + K00_19 + (E & (A ^ B) ^ B) + data[ 2]; E = RL(E, 30);
+    B += RL(C, 5) + K00_19 + (D & (E ^ A) ^ A) + data[ 3]; D = RL(D, 30);
+    A += RL(B, 5) + K00_19 + (C & (D ^ E) ^ E) + data[ 4]; C = RL(C, 30);
+    E += RL(A, 5) + K00_19 + (B & (C ^ D) ^ D) + data[ 5]; B = RL(B, 30);
+    D += RL(E, 5) + K00_19 + (A & (B ^ C) ^ C) + data[ 6]; A = RL(A, 30);
+    C += RL(D, 5) + K00_19 + (E & (A ^ B) ^ B) + data[ 7]; E = RL(E, 30);
+    B += RL(C, 5) + K00_19 + (D & (E ^ A) ^ A) + data[ 8]; D = RL(D, 30);
+    A += RL(B, 5) + K00_19 + (C & (D ^ E) ^ E) + data[ 9]; C = RL(C, 30);
+    E += RL(A, 5) + K00_19 + (B & (C ^ D) ^ D) + data[10]; B = RL(B, 30);
+    D += RL(E, 5) + K00_19 + (A & (B ^ C) ^ C) + data[11]; A = RL(A, 30);
+    C += RL(D, 5) + K00_19 + (E & (A ^ B) ^ B) + data[12]; E = RL(E, 30);
+    B += RL(C, 5) + K00_19 + (D & (E ^ A) ^ A) + data[13]; D = RL(D, 30);
+    A += RL(B, 5) + K00_19 + (C & (D ^ E) ^ E) + data[14]; C = RL(C, 30);
+    E += RL(A, 5) + K00_19 + (B & (C ^ D) ^ D) + data[15]; B = RL(B, 30);
+
+    /* rounds 16 - 19 */
+
+    w[ 0] = data[ 0] ^ data[ 2] ^ data[ 8] ^ data[13]; w[ 0] = RL(w[0], 1);
+    D += RL(E, 5) + K00_19 + (A & (B ^ C) ^ C) + w[ 0]; A = RL(A, 30);
+    w[ 1] = data[ 1] ^ data[ 3] ^ data[ 9] ^ data[14]; w[ 1] = RL(w[1], 1);
+    C += RL(D, 5) + K00_19 + (E & (A ^ B) ^ B) + w[ 1]; E = RL(E, 30);
+    w[ 2] = data[ 2] ^ data[ 4] ^ data[10] ^ data[15]; w[ 2] = RL(w[ 2], 1);
+    B += RL(C, 5) + K00_19 + (D & (E ^ A) ^ A) + w[ 2]; D = RL(D, 30);
+    w[ 3] = data[ 3] ^ data[ 5] ^ data[11] ^ w[ 0]; w[ 3] = RL(w[ 3], 1);
+    A += RL(B, 5) + K00_19 + (C & (D ^ E) ^ E) + w[ 3]; C = RL(C, 30);
+
+    /* rounds 20 - 39 */
+
+    w[ 4] = data[ 4] ^ data[ 6] ^ data[12] ^ w[ 1]; w[ 4] = RL(w[ 4], 1);
+    E += RL(A, 5) + K20_39 + (B ^ C ^ D) + w[ 4]; B = RL(B, 30);
+    w[ 5] = data[ 5] ^ data[ 7] ^ data[13] ^ w[ 2]; w[ 5] = RL(w[ 5], 1);
+    D += RL(E, 5) + K20_39 + (A ^ B ^ C) + w[ 5]; A = RL(A, 30);
+    w[ 6] = data[ 6] ^ data[ 8] ^ data[14] ^ w[ 3]; w[ 6] = RL(w[ 6], 1);
+    C += RL(D, 5) + K20_39 + (E ^ A ^ B) + w[ 6]; E = RL(E, 30);
+    w[ 7] = data[ 7] ^ data[ 9] ^ data[15] ^ w[ 4]; w[ 7] = RL(w[ 7], 1);
+    B += RL(C, 5) + K20_39 + (D ^ E ^ A) + w[ 7]; D = RL(D, 30);
+    w[ 8] = data[ 8] ^ data[10] ^ w[ 0] ^ w[ 5]; w[ 8] = RL(w[ 8], 1);
+    A += RL(B, 5) + K20_39 + (C ^ D ^ E) + w[ 8]; C = RL(C, 30);
+    w[ 9] = data[ 9] ^ data[11] ^ w[ 1] ^ w[ 6]; w[ 9] = RL(w[ 9], 1);
+    E += RL(A, 5) + K20_39 + (B ^ C ^ D) + w[ 9]; B = RL(B, 30);
+    w[10] = data[10] ^ data[12] ^ w[ 2] ^ w[ 7]; w[10] = RL(w[10], 1);
+    D += RL(E, 5) + K20_39 + (A ^ B ^ C) + w[10]; A = RL(A, 30);
+    w[11] = data[11] ^ data[13] ^ w[ 3] ^ w[ 8]; w[11] = RL(w[11], 1);
+    C += RL(D, 5) + K20_39 + (E ^ A ^ B) + w[11]; E = RL(E, 30);
+    w[12] = data[12] ^ data[14] ^ w[ 4] ^ w[ 9]; w[12] = RL(w[12], 1);
+    B += RL(C, 5) + K20_39 + (D ^ E ^ A) + w[12]; D = RL(D, 30);
+    w[13] = data[13] ^ data[15] ^ w[ 5] ^ w[10]; w[13] = RL(w[13], 1);
+    A += RL(B, 5) + K20_39 + (C ^ D ^ E) + w[13]; C = RL(C, 30);
+    w[14] = data[14] ^ w[ 0] ^ w[ 6] ^ w[11]; w[14] = RL(w[14], 1);
+    E += RL(A, 5) + K20_39 + (B ^ C ^ D) + w[14]; B = RL(B, 30);
+    w[15] = data[15] ^ w[ 1] ^ w[ 7] ^ w[12]; w[15] = RL(w[15], 1);
+    D += RL(E, 5) + K20_39 + (A ^ B ^ C) + w[15]; A = RL(A, 30);
+    w[ 0] = w[ 0] ^ w[ 2] ^ w[ 8] ^ w[13]; w[ 0] = RL(w[ 0], 1);
+    C += RL(D, 5) + K20_39 + (E ^ A ^ B) + w[ 0]; E = RL(E, 30);
+    w[ 1] = w[ 1] ^ w[ 3] ^ w[ 9] ^ w[14]; w[ 1] = RL(w[ 1], 1);
+    B += RL(C, 5) + K20_39 + (D ^ E ^ A) + w[ 1]; D = RL(D, 30);
+    w[ 2] = w[ 2] ^ w[ 4] ^ w[10] ^ w[15]; w[ 2] = RL(w[ 2], 1);
+    A += RL(B, 5) + K20_39 + (C ^ D ^ E) + w[ 2]; C = RL(C, 30);
+    w[ 3] = w[ 3] ^ w[ 5] ^ w[11] ^ w[ 0]; w[ 3] = RL(w[ 3], 1);
+    E += RL(A, 5) + K20_39 + (B ^ C ^ D) + w[ 3]; B = RL(B, 30);
+    w[ 4] = w[ 4] ^ w[ 6] ^ w[12] ^ w[ 1]; w[ 4] = RL(w[ 4], 1);
+    D += RL(E, 5) + K20_39 + (A ^ B ^ C) + w[ 4]; A = RL(A, 30);
+    w[ 5] = w[ 5] ^ w[ 7] ^ w[13] ^ w[ 2]; w[ 5] = RL(w[ 5], 1);
+    C += RL(D, 5) + K20_39 + (E ^ A ^ B) + w[ 5]; E = RL(E, 30);
+    w[ 6] = w[ 6] ^ w[ 8] ^ w[14] ^ w[ 3]; w[ 6] = RL(w[ 6], 1);
+    B += RL(C, 5) + K20_39 + (D ^ E ^ A) + w[ 6]; D = RL(D, 30);
+    w[ 7] = w[ 7] ^ w[ 9] ^ w[15] ^ w[ 4]; w[ 7] = RL(w[ 7], 1);
+    A += RL(B, 5) + K20_39 + (C ^ D ^ E) + w[ 7]; C = RL(C, 30);
+
+    /* rounds 40 - 59 */
+
+    w[ 8] = w[ 8] ^ w[10] ^ w[ 0] ^ w[ 5]; w[ 8] = RL(w[ 8], 1);
+    E += RL(A, 5) + K40_59 + ((B & C) | (D & (B | C))) + w[ 8]; B = RL(B, 30);
+    w[ 9] = w[ 9] ^ w[11] ^ w[ 1] ^ w[ 6]; w[ 9] = RL(w[ 9], 1);
+    D += RL(E, 5) + K40_59 + ((A & B) | (C & (A | B))) + w[ 9]; A = RL(A, 30);
+    w[10] = w[10] ^ w[12] ^ w[ 2] ^ w[ 7]; w[10] = RL(w[10], 1);
+    C += RL(D, 5) + K40_59 + ((E & A) | (B & (E | A))) + w[10]; E = RL(E, 30);
+    w[11] = w[11] ^ w[13] ^ w[ 3] ^ w[ 8]; w[11] = RL(w[11], 1);
+    B += RL(C, 5) + K40_59 + ((D & E) | (A & (D | E))) + w[11]; D = RL(D, 30);
+    w[12] = w[12] ^ w[14] ^ w[ 4] ^ w[ 9]; w[12] = RL(w[12], 1);
+    A += RL(B, 5) + K40_59 + ((C & D) | (E & (C | D))) + w[12]; C = RL(C, 30);
+    w[13] = w[13] ^ w[15] ^ w[ 5] ^ w[10]; w[13] = RL(w[13], 1);
+    E += RL(A, 5) + K40_59 + ((B & C) | (D & (B | C))) + w[13]; B = RL(B, 30);
+    w[14] = w[14] ^ w[ 0] ^ w[ 6] ^ w[11]; w[14] = RL(w[14], 1);
+    D += RL(E, 5) + K40_59 + ((A & B) | (C & (A | B))) + w[14]; A = RL(A, 30);
+    w[15] = w[15] ^ w[ 1] ^ w[ 7] ^ w[12]; w[15] = RL(w[15], 1);
+    C += RL(D, 5) + K40_59 + ((E & A) | (B & (E | A))) + w[15]; E = RL(E, 30);
+    w[ 0] = w[ 0] ^ w[ 2] ^ w[ 8] ^ w[13]; w[ 0] = RL(w[ 0], 1);
+    B += RL(C, 5) + K40_59 + ((D & E) | (A & (D | E))) + w[ 0]; D = RL(D, 30);
+    w[ 1] = w[ 1] ^ w[ 3] ^ w[ 9] ^ w[14]; w[ 1] = RL(w[ 1], 1);
+    A += RL(B, 5) + K40_59 + ((C & D) | (E & (C | D))) + w[ 1]; C = RL(C, 30);
+    w[ 2] = w[ 2] ^ w[ 4] ^ w[10] ^ w[15]; w[ 2] = RL(w[ 2], 1);
+    E += RL(A, 5) + K40_59 + ((B & C) | (D & (B | C))) + w[ 2]; B = RL(B, 30);
+    w[ 3] = w[ 3] ^ w[ 5] ^ w[11] ^ w[ 0]; w[ 3] = RL(w[ 3], 1);
+    D += RL(E, 5) + K40_59 + ((A & B) | (C & (A | B))) + w[ 3]; A = RL(A, 30);
+    w[ 4] = w[ 4] ^ w[ 6] ^ w[12] ^ w[ 1]; w[ 4] = RL(w[ 4], 1);
+    C += RL(D, 5) + K40_59 + ((E & A) | (B & (E | A))) + w[ 4]; E = RL(E, 30);
+    w[ 5] = w[ 5] ^ w[ 7] ^ w[13] ^ w[ 2]; w[ 5] = RL(w[ 5], 1);
+    B += RL(C, 5) + K40_59 + ((D & E) | (A & (D | E))) + w[ 5]; D = RL(D, 30);
+    w[ 6] = w[ 6] ^ w[ 8] ^ w[14] ^ w[ 3]; w[ 6] = RL(w[ 6], 1);
+    A += RL(B, 5) + K40_59 + ((C & D) | (E & (C | D))) + w[ 6]; C = RL(C, 30);
+    w[ 7] = w[ 7] ^ w[ 9] ^ w[15] ^ w[ 4]; w[ 7] = RL(w[ 7], 1);
+    E += RL(A, 5) + K40_59 + ((B & C) | (D & (B | C))) + w[ 7]; B = RL(B, 30);
+    w[ 8] = w[ 8] ^ w[10] ^ w[ 0] ^ w[ 5]; w[ 8] = RL(w[ 8], 1);
+    D += RL(E, 5) + K40_59 + ((A & B) | (C & (A | B))) + w[ 8]; A = RL(A, 30);
+    w[ 9] = w[ 9] ^ w[11] ^ w[ 1] ^ w[ 6]; w[ 9] = RL(w[ 9], 1);
+    C += RL(D, 5) + K40_59 + ((E & A) | (B & (E | A))) + w[ 9]; E = RL(E, 30);
+    w[10] = w[10] ^ w[12] ^ w[ 2] ^ w[ 7]; w[10] = RL(w[10], 1);
+    B += RL(C, 5) + K40_59 + ((D & E) | (A & (D | E))) + w[10]; D = RL(D, 30);
+    w[11] = w[11] ^ w[13] ^ w[ 3] ^ w[ 8]; w[11] = RL(w[11], 1);
+    A += RL(B, 5) + K40_59 + ((C & D) | (E & (C | D))) + w[11]; C = RL(C, 30);
+
+    /* rounds 60 - 79 */
+
+    w[12] = w[12] ^ w[14] ^ w[ 4] ^ w[ 9]; w[12] = RL(w[12], 1);
+    E += RL(A, 5) + K60_79 + (B ^ C ^ D) + w[12]; B = RL(B, 30);
+    w[13] = w[13] ^ w[15] ^ w[ 5] ^ w[10]; w[13] = RL(w[13], 1);
+    D += RL(E, 5) + K60_79 + (A ^ B ^ C) + w[13]; A = RL(A, 30);
+    w[14] = w[14] ^ w[ 0] ^ w[ 6] ^ w[11]; w[14] = RL(w[14], 1);
+    C += RL(D, 5) + K60_79 + (E ^ A ^ B) + w[14]; E = RL(E, 30);
+    w[15] = w[15] ^ w[ 1] ^ w[ 7] ^ w[12]; w[15] = RL(w[15], 1);
+    B += RL(C, 5) + K60_79 + (D ^ E ^ A) + w[15]; D = RL(D, 30);
+    w[ 0] = w[ 0] ^ w[ 2] ^ w[ 8] ^ w[13]; w[ 0] = RL(w[ 0], 1);
+    A += RL(B, 5) + K60_79 + (C ^ D ^ E) + w[ 0]; C = RL(C, 30);
+    w[ 1] = w[ 1] ^ w[ 3] ^ w[ 9] ^ w[14]; w[ 1] = RL(w[ 1], 1);
+    E += RL(A, 5) + K60_79 + (B ^ C ^ D) + w[ 1]; B = RL(B, 30);
+    w[ 2] = w[ 2] ^ w[ 4] ^ w[10] ^ w[15]; w[ 2] = RL(w[ 2], 1);
+    D += RL(E, 5) + K60_79 + (A ^ B ^ C) + w[ 2]; A = RL(A, 30);
+    w[ 3] = w[ 3] ^ w[ 5] ^ w[11] ^ w[ 0]; w[ 3] = RL(w[ 3], 1);
+    C += RL(D, 5) + K60_79 + (E ^ A ^ B) + w[ 3]; E = RL(E, 30);
+    w[ 4] = w[ 4] ^ w[ 6] ^ w[12] ^ w[ 1]; w[ 4] = RL(w[ 4], 1);
+    B += RL(C, 5) + K60_79 + (D ^ E ^ A) + w[ 4]; D = RL(D, 30);
+    w[ 5] = w[ 5] ^ w[ 7] ^ w[13] ^ w[ 2]; w[ 5] = RL(w[ 5], 1);
+    A += RL(B, 5) + K60_79 + (C ^ D ^ E) + w[ 5]; C = RL(C, 30);
+    w[ 6] = w[ 6] ^ w[ 8] ^ w[14] ^ w[ 3]; w[ 6] = RL(w[ 6], 1);
+    E += RL(A, 5) + K60_79 + (B ^ C ^ D) + w[ 6]; B = RL(B, 30);
+    w[ 7] = w[ 7] ^ w[ 9] ^ w[15] ^ w[ 4]; w[ 7] = RL(w[ 7], 1);
+    D += RL(E, 5) + K60_79 + (A ^ B ^ C) + w[ 7]; A = RL(A, 30);
+    w[ 8] = w[ 8] ^ w[10] ^ w[ 0] ^ w[ 5]; w[ 8] = RL(w[ 8], 1);
+    C += RL(D, 5) + K60_79 + (E ^ A ^ B) + w[ 8]; E = RL(E, 30);
+    w[ 9] = w[ 9] ^ w[11] ^ w[ 1] ^ w[ 6]; w[ 9] = RL(w[ 9], 1);
+    B += RL(C, 5) + K60_79 + (D ^ E ^ A) + w[ 9]; D = RL(D, 30);
+    w[10] = w[10] ^ w[12] ^ w[ 2] ^ w[ 7]; w[10] = RL(w[10], 1);
+    A += RL(B, 5) + K60_79 + (C ^ D ^ E) + w[10]; C = RL(C, 30);
+    w[11] = w[11] ^ w[13] ^ w[ 3] ^ w[ 8]; w[11] = RL(w[11], 1);
+    E += RL(A, 5) + K60_79 + (B ^ C ^ D) + w[11]; B = RL(B, 30);
+    w[12] = w[12] ^ w[14] ^ w[ 4] ^ w[ 9]; w[12] = RL(w[12], 1);
+    D += RL(E, 5) + K60_79 + (A ^ B ^ C) + w[12]; A = RL(A, 30);
+    w[13] = w[13] ^ w[15] ^ w[ 5] ^ w[10];
+    C += RL(D, 5) + K60_79 + (E ^ A ^ B) + RL(w[13], 1); E = RL(E, 30);
+    w[14] = w[14] ^ w[ 0] ^ w[ 6] ^ w[11];
+    B += RL(C, 5) + K60_79 + (D ^ E ^ A) + RL(w[14], 1); D = RL(D, 30);
+
+    /* update H0 - H4 */
+
+    w[15] = w[15] ^ w[ 1] ^ w[ 7] ^ w[12];
+    H0 += A + RL(B, 5) + K60_79 + (C ^ D ^ E) + RL(w[15], 1);
+    H1 += B;
+    H2 += RL(C, 30);
+    H3 += D;
+    H4 += E;
+
+    /* clear temp variables */
+
+    A = B = C = D = E = 0;
+    memset(w, 0, sizeof(w));
+}
+
+
+/* ntru_crypto_sha1()
+ *
+ * This routine provides all operations for a SHA-1 hash, and the use
+ * of SHA-1 for DSA signing and key generation.
+ * It may be used to initialize, update, or complete a message digest,
+ * or any combination of those actions, as determined by the SHA_INIT flag,
+ * the in_len parameter, and the SHA_FINISH flag, respectively.
+ *
+ * When in_len == 0 (no data to hash), the parameter, in, may be NULL.
+ * When the SHA_FINISH flag is not set, the parameter, md, may be NULL.
+ *
+ * Initialization may be standard or use a specified initialization vector,
+ * and is indicated by setting the SHA_INIT flag.
+ * Setting init = NULL specifies standard initialization.  Otherwise, init
+ * points to the array of five alternate initialization 32-bit words.
+ *
+ * The hash operation can be updated with any number of input bytes, including
+ * zero.
+ *
+ * The hash operation can be completed with normal padding or with zero
+ * padding as required for parts of DSA parameter generation, and is indicated
+ * by setting the SHA_FINISH flag.  Using zero padding, indicated by setting
+ * the SHA_ZERO_PAD flag, never creates an extra input block because the
+ * bit count is not included in the hashed data.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if  inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1(
+    NTRU_CRYPTO_SHA1_CTX *c,        /* in/out - pointer to SHA-1 context */
+    uint32_t const       *init,     /*     in - pointer to alternate */
+                                    /*          initialization - may be NULL */
+    uint8_t const        *in,       /*     in - pointer to input data -
+                                                may be NULL if in_len == 0 */
+    uint32_t              in_len,   /*     in - number of input data bytes */
+    uint32_t              flags,    /*     in - INIT, FINISH, zero-pad flags */
+    uint8_t              *md)       /*    out - address for message digest -
+                                                may be NULL if not FINISH */
+{
+    uint32_t    in_blk[16];         /* input block */
+    uint32_t    space;
+    uint8_t    *d = NULL;
+
+    /* check error conditions */
+
+    if (!c || (in_len && !in) || ((flags & SHA_FINISH) && !md))
+        SHA_RET(SHA_BAD_PARAMETER)
+
+    /* initialize context if requested */
+
+    if (flags & SHA_INIT) {
+
+        /* init chaining state */
+
+        if (!init) {
+            c->state[0] = H0_INIT;              // standard initialization
+            c->state[1] = H1_INIT;
+            c->state[2] = H2_INIT;
+            c->state[3] = H3_INIT;
+            c->state[4] = H4_INIT;
+        } else {
+            c->state[0] = init[0];              // alternate initialization
+            c->state[1] = init[1];
+            c->state[2] = init[2];
+            c->state[3] = init[3];
+            c->state[4] = init[4];
+        }
+
+        /* init bit count and number of unhashed data bytes */
+
+        c->num_bits_hashed[0] = 0;
+        c->num_bits_hashed[1] = 0;
+        c->unhashed_len = 0;
+    }
+
+    /* determine space left in unhashed data buffer */
+
+    if (c->unhashed_len > 63)
+        SHA_RET(SHA_FAIL)
+
+    space = 64 - c->unhashed_len;
+
+    /* process input if it exists */
+
+    if (in_len) {
+
+        /* update count of bits hashed */
+
+        {
+            uint32_t    bits0, bits1;
+
+            bits0 = in_len << 3;
+            bits1 = in_len >> 29;
+            if ((c->num_bits_hashed[0] += bits0) < bits0)
+                bits1++;
+            if ((c->num_bits_hashed[1] += bits1) < bits1) {
+                memset((uint8_t *) c, 0, sizeof(NTRU_CRYPTO_SHA1_CTX));
+                space = 0;
+                memset((char *) in_blk, 0, sizeof(in_blk));
+                SHA_RET(SHA_OVERFLOW)
+            }
+        }
+
+        /* process input bytes */
+
+        if (in_len < space) {
+
+            /* input does not fill block buffer:
+             * add input to buffer
+             */
+
+            memcpy(c->unhashed + c->unhashed_len, in, in_len);
+            c->unhashed_len += in_len;
+
+        } else {
+            uint32_t    blks;
+
+            /* input will fill block buffer:
+             *  fill unhashed data buffer,
+             *  convert to block buffer,
+             *  and process block
+             */
+
+            in_len -= space;
+            for (d = c->unhashed + c->unhashed_len; space; space--)
+                *d++ = *in++;
+            ntru_crypto_msbyte_2_uint32(in_blk, (uint8_t const *) c->unhashed,
+                                        16);
+            sha1_blk((uint32_t const *) in_blk, c->state);
+
+            /* process any remaining full blocks */
+
+            for (blks = in_len >> 6; blks--; in += 64) {
+                ntru_crypto_msbyte_2_uint32(in_blk, in, 16);
+                sha1_blk((uint32_t const *) in_blk, c->state);
+            }
+
+            /* put any remaining input in the unhashed data buffer */
+
+            in_len &= 0x3f;
+            memcpy(c->unhashed, in, in_len);
+            c->unhashed_len = in_len;
+        }
+    }
+
+    /* complete message digest if requested */
+
+    if (flags & SHA_FINISH) {
+        space = 64 - c->unhashed_len;
+
+        /* check padding type */
+
+        if (!(flags & SHA_ZERO_PAD)) {
+
+            /* add 0x80 padding byte to the unhashed data buffer
+             * (there is always space since the buffer can't be full)
+             */
+
+            d = c->unhashed + c->unhashed_len;
+            *d++ = 0x80;
+            space--;
+
+            /* check for space for bit count */
+
+            if (space < 8) {
+
+                /* no space for count:
+                 *  fill remainder of unhashed data buffer with zeros,
+                 *  convert to input block,
+                 *  process block,
+                 *  fill all but 8 bytes of unhashed data buffer with zeros
+                 */
+
+                memset(d, 0, space);
+                ntru_crypto_msbyte_2_uint32(in_blk,
+                                            (uint8_t const *) c->unhashed, 16);
+                sha1_blk((uint32_t const *) in_blk, c->state);
+                memset(c->unhashed, 0, 56);
+
+            } else {
+
+                /* fill unhashed data buffer with zeros,
+                 *  leaving space for bit count
+                 */
+
+                for (space -= 8; space; space--)
+                    *d++ = 0;
+            }
+
+            /* convert partially filled unhashed data buffer to input block and
+             *  add bit count to input block
+             */
+
+            ntru_crypto_msbyte_2_uint32(in_blk, (uint8_t const *) c->unhashed,
+                                        14);
+            in_blk[14] = c->num_bits_hashed[1];
+            in_blk[15] = c->num_bits_hashed[0];
+
+        } else {
+
+            /* pad unhashed data buffer with zeros and no bit count and
+             *  convert to input block
+             */
+
+            memset(c->unhashed + c->unhashed_len, 0, space);
+            ntru_crypto_msbyte_2_uint32(in_blk, (uint8_t const *) c->unhashed,
+                                        16);
+        }
+
+        /* process last block */
+
+        sha1_blk((uint32_t const *) in_blk, c->state);
+
+        /* copy result to message digest buffer */
+
+        ntru_crypto_uint32_2_msbyte(md, c->state, 5);
+        
+        /* clear context and stack variables */
+
+        memset((uint8_t *) c, 0, sizeof(NTRU_CRYPTO_SHA1_CTX));
+        space = 0;
+        memset((char *) in_blk, 0, sizeof(in_blk));
+    }
+
+    SHA_RET(SHA_OK)
+}
+
+
+/* ntru_crypto_sha1_init
+ *
+ * This routine performs standard initialization of the SHA-1 state.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ */
+
+uint32_t
+ntru_crypto_sha1_init(
+    NTRU_CRYPTO_SHA1_CTX *c)        /* in/out - pointer to SHA-1 context */
+{
+    return ntru_crypto_sha1(c, NULL, NULL, 0, SHA_INIT, NULL);
+}
+
+
+/* ntru_crypto_sha1_update
+ *
+ * This routine processes input data and updates the SHA-1 hash calculation.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_update(
+    NTRU_CRYPTO_SHA1_CTX *c,        /* in/out - pointer to SHA-1 context */
+    uint8_t const        *data,     /*    in - pointer to input data */
+    uint32_t              data_len) /*    in - number of bytes of input data */
+{
+    return ntru_crypto_sha1(c, NULL, data, data_len, SHA_DATA_ONLY, NULL);
+}
+
+
+/* ntru_crypto_sha1_final
+ *
+ * This routine completes the SHA-1 hash calculation and returns the
+ * message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_final(
+    NTRU_CRYPTO_SHA1_CTX *c,        /* in/out - pointer to SHA-1 context */
+    uint8_t              *md)       /*   out - address for message digest */
+{
+    return ntru_crypto_sha1(c, NULL, NULL, 0, SHA_FINISH, md);
+}
+
+
+/* ntru_crypto_sha1_final_zero_pad
+ *
+ * This routine completes the SHA-1 hash calculation using zero padding
+ * and returns the message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_final_zero_pad(
+    NTRU_CRYPTO_SHA1_CTX *c,        /* in/out - pointer to SHA-1 context */
+    uint8_t              *md)       /*   out - address for message digest */
+{
+    return ntru_crypto_sha1(c, NULL, NULL, 0, SHA_FINISH | SHA_ZERO_PAD, md);
+}
+
+
+/* ntru_crypto_sha1_digest
+ *
+ * This routine computes a SHA-1 message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_digest(
+    uint8_t const  *data,           //  in - pointer to input data
+    uint32_t        data_len,       //  in - number of bytes of input data
+    uint8_t        *md)             // out - address for message digest
+{
+    NTRU_CRYPTO_SHA1_CTX c;
+
+    return ntru_crypto_sha1(&c, NULL, data, data_len, SHA_INIT | SHA_FINISH,
+                            md);
+}
+
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha1.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha1.h
new file mode 100644 (file)
index 0000000..fbb2e46
--- /dev/null
@@ -0,0 +1,205 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_crypto_sha1.h is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_sha1.h
+ *
+ * Contents: Definitions and declarations for the SHA-1 implementation.
+ *
+ *****************************************************************************/
+
+#ifndef NTRU_CRYPTO_SHA1_H
+#define NTRU_CRYPTO_SHA1_H
+
+
+#include "ntru_crypto_platform.h"
+#include "ntru_crypto_sha.h"
+
+
+/******************************************
+ * macros needed for generic hash objects * 
+ ******************************************/
+
+#define SHA_1_CTX_LEN       sizeof(SHA1_CTX)         /* no. bytes in SHA-1
+                                                        ctx */
+#define SHA_1_BLK_LEN       64                       /* 64 bytes in input
+                                                        block */
+#define SHA_1_MD_LEN        20                       /* 20 bytes in msg
+                                                        digest */
+#define SHA_1_INIT_FN       &ntru_crypto_sha1_init   /* init function */
+#define SHA_1_UPDATE_FN     &ntru_crypto_sha1_update /* update function */
+#define SHA_1_FINAL_FN      &ntru_crypto_sha1_final  /* final function */
+#define SHA_1_FINAL_ZERO_PAD_FN                                             \
+                            &ntru_crypto_sha1_final_zero_pad
+                                                     /* final function using
+                                                        zero padding */
+#define SHA_1_DIGEST_FN     &ntru_crypto_sha1_digest /* digest function */
+
+
+/*************************
+ * structure definitions *
+ *************************/
+
+/* SHA-1 context structure */
+
+typedef struct {
+    uint32_t    state[5];           // chaining state
+    uint32_t    num_bits_hashed[2]; // number of bits hashed
+    uint8_t     unhashed[64];       // input data not yet hashed
+    uint32_t    unhashed_len;       // number of bytes of unhashed input data
+} NTRU_CRYPTO_SHA1_CTX;
+
+
+/*************************
+ * function declarations *
+ *************************/
+
+/* ntru_crypto_sha1()
+ *
+ * This routine provides all operations for a SHA-1 hash, and the use
+ * of SHA-1 for DSA signing and key generation.
+ * It may be used to initialize, update, or complete a message digest,
+ * or any combination of those actions, as determined by the SHA_INIT flag,
+ * the in_len parameter, and the SHA_FINISH flag, respectively.
+ *
+ * When in_len == 0 (no data to hash), the parameter, in, may be NULL.
+ * When the SHA_FINISH flag is not set, the parameter, md, may be NULL.
+ *
+ * Initialization may be standard or use a specified initialization vector,
+ * and is indicated by setting the SHA_INIT flag.
+ * Setting init = NULL specifies standard initialization.  Otherwise, init
+ * points to the array of five alternate initialization 32-bit words.
+ *
+ * The hash operation can be updated with any number of input bytes, including
+ * zero.
+ *
+ * The hash operation can be completed with normal padding or with zero
+ * padding as required for parts of DSA parameter generation, and is indicated
+ * by setting the SHA_FINISH flag.  Using zero padding, indicated by setting
+ * the SHA_ZERO_PAD flag, never creates an extra input block because the
+ * bit count is not included in the hashed data.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1(
+    NTRU_CRYPTO_SHA1_CTX *c,        /* in/out - pointer to SHA-1 context */
+    uint32_t const       *init,     /*     in - pointer to alternate */
+                                    /*          initialization - may be NULL */
+    uint8_t const        *in,       /*     in - pointer to input data -
+                                                may be NULL if in_len == 0 */
+    uint32_t              in_len,   /*     in - number of input data bytes */
+    uint32_t              flags,    /*     in - INIT, FINISH, zero-pad flags */
+    uint8_t              *md);      /*    out - address for message digest -
+                                                may be NULL if not FINISH */
+
+
+/* ntru_crypto_sha1_init
+ *
+ * This routine performs standard initialization of the SHA-1 state.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1_init(
+    NTRU_CRYPTO_SHA1_CTX *c);       /* in/out - pointer to SHA-1 context */
+
+
+/* ntru_crypto_sha1_update
+ *
+ * This routine processes input data and updates the SHA-1 hash calculation.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1_update(
+    NTRU_CRYPTO_SHA1_CTX *c,         /* in/out - pointer to SHA-1 context */
+    uint8_t const        *data,      /*    in - pointer to input data */
+    uint32_t              data_len); /*    in - number of bytes of input data */
+
+
+/* ntru_crypto_sha1_final
+ *
+ * This routine completes the SHA-1 hash calculation and returns the
+ * message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1_final(
+    NTRU_CRYPTO_SHA1_CTX *c,        /* in/out - pointer to SHA-1 context */
+    uint8_t              *md);      /*   out - address for message digest */
+
+
+/* ntru_crypto_sha1_final_zero_pad
+ *
+ * This routine completes the SHA-1 hash calculation using zero padding
+ * and returns the message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+extern uint32_t
+ntru_crypto_sha1_final_zero_pad(
+    NTRU_CRYPTO_SHA1_CTX *c,        /* in/out - pointer to SHA-1 context */
+    uint8_t              *md);      /*   out - address for message digest */
+
+
+/* ntru_crypto_sha1_digest
+ *
+ * This routine computes a SHA-1 message digest.
+ *
+ * Returns SHA_OK on success.
+ * Returns SHA_FAIL with corrupted context.
+ * Returns SHA_BAD_PARAMETER if inappropriate NULL pointers are passed.
+ * Returns SHA_OVERFLOW if more than 2^64 - 1 bytes are hashed.
+ */
+
+uint32_t
+ntru_crypto_sha1_digest(
+    uint8_t const  *data,           /*  in - pointer to input data */
+    uint32_t        data_len,       /*  in - number of bytes of input data */
+    uint8_t        *md);            /* out - address for message digest */
+
+
+#endif /* NTRU_CRYPTO_SHA1_H */
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha2.c b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_sha2.c
new file mode 100644 (file)
index 0000000..796cc4f
--- /dev/null
@@ -0,0 +1,532 @@
+/******************************************************************************
+ * NTRU Cryptography Reference Source Code
+ * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved. 
+ *
+ * ntru_crypto_sha2.c is a component of ntru-crypto.
+ *
+ * Copyright (C) 2009-2013  Security Innovation
+ * 
+ * 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File: ntru_crypto_sha2.c
+ *
+ * Contents: Routines implementing the SHA-256 hash calculation.
+ *
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "ntru_crypto_sha2.h"
+#include "ntru_crypto_msbyte_uint32.h"
+
+
+/* chaining state elements */
+
+#define H0      state[0]
+#define H1      state[1]
+#define H2      state[2]
+#define H3      state[3]
+#define H4      state[4]
+#define H5      state[5]
+#define H6      state[6]
+#define H7      state[7]
+
+
+/* standard SHA-256 initialization values */
+
+#define H0_SHA256_INIT 0x6a09e667UL
+#define H1_SHA256_INIT 0xbb67ae85UL
+#define H2_SHA256_INIT 0x