]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Added own MGF1 mask generating function
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 5 Dec 2013 21:55:47 +0000 (22:55 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 5 Dec 2013 21:55:47 +0000 (22:55 +0100)
src/libstrongswan/plugins/ntru/Makefile.am
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto.h
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h [deleted file]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_encrypt.c
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.c [moved from src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.c with 55% similarity]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.h [moved from src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.h with 67% similarity]
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.c
src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_poly.h
src/libstrongswan/plugins/ntru/ntru_mgf1.c [new file with mode: 0644]
src/libstrongswan/plugins/ntru/ntru_mgf1.h [new file with mode: 0644]
src/libstrongswan/tests/suites/test_ntru.c

index b11c08132033065cf6bc8ffdf3dc48a407769a58..b1e5fe394573b00a312710356984313b9f94f771 100644 (file)
@@ -14,7 +14,8 @@ libstrongswan_ntru_la_SOURCES = \
        ntru_plugin.h ntru_plugin.c \
        ntru_drbg.h ntru_drbg.c \
        ntru_ke.h ntru_ke.c \
-       ntru_crypto/ntru_crypto.h ntru_crypto/ntru_crypto_error.h \
+       ntru_mgf1.h ntru_mgf1.c \
+       ntru_crypto/ntru_crypto.h \
        ntru_crypto/ntru_crypto_ntru_convert.h \
        ntru_crypto/ntru_crypto_ntru_convert.c \
        ntru_crypto/ntru_crypto_ntru_encrypt.c \
@@ -22,8 +23,10 @@ libstrongswan_ntru_la_SOURCES = \
        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_ntru_mgftp1.h \
+       ntru_crypto/ntru_crypto_ntru_mgftp1.c \
+       ntru_crypto/ntru_crypto_ntru_poly.h \
+       ntru_crypto/ntru_crypto_ntru_poly.c
 
 libstrongswan_ntru_la_LDFLAGS = -module -avoid-version
 
index ebd444058e8ed9793d9cdbfb52043825774c46a1..72f47035e0f3eb6227448736a186c1b2db4edb25 100644 (file)
@@ -34,8 +34,6 @@
 #ifndef NTRU_CRYPTO_H
 #define NTRU_CRYPTO_H
 
-#include "ntru_crypto_error.h"
-
 #include <library.h>
 
 #include "ntru_drbg.h"
@@ -88,10 +86,8 @@ typedef enum _NTRU_ENCRYPT_PARAM_SET_ID {
 #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))
-
+#define NTRU_DRBG_FAIL             11
+#define NTRU_MGF1_FAIL             12
 
 /* function declarations */
 
@@ -116,18 +112,14 @@ typedef enum _NTRU_ENCRYPT_PARAM_SET_ID {
  * 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.
+ * Returns NTRU_DRBG_FAIL if the DRBG handle is invalid.
+ * Returns NTRU_BAD_PARAMETER if an argument pointer (other than ct) is NULL.
+ * Returns 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_BAD_PUBLIC_KEY if the public-key blob is invalid
+ *  (unknown format, corrupt, bad length).
+ * Returns NTRU_BUFFER_TOO_SMALL if the ciphertext buffer is too small.
+ * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
  */
 
 NTRUCALL
@@ -159,17 +151,14 @@ ntru_crypto_ntru_encrypt(
  * 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.
+ * Returns NTRU_BAD_PARAMETER if an argument pointer (other than pt) is NULL.
+ * Returns NTRU_BAD_LENGTH if a length argument (privkey_blob) is zero, or if
+ *  ct_len is invalid for the parameter set.
+ * Returns NTRU_BAD_PRIVATE_KEY if the private-key blob is invalid
+ *  (unknown format, corrupt, bad length).
+ * Returns NTRU_BUFFER_TOO_SMALL if the plaintext buffer is too small.
+ * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
+ * Returns NTRU_FAIL if a decryption error occurs.
  */
 
 NTRUCALL
@@ -193,7 +182,7 @@ ntru_crypto_ntru_decrypt(
  * 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.
+ * result in this function returning NTRU_DRBG_FAIL.
  *
  * The required minimum size of the output public-key buffer (pubkey_blob)
  * may be queried by invoking this function with pubkey_blob = NULL.
@@ -215,17 +204,15 @@ ntru_crypto_ntru_decrypt(
  * 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.
+ * Returns NTRU_BAD_PARAMETER if an argument pointer (other than pubkey_blob
+ * or privkey_blob) is NULL.
+ * Returns NTRU_INVALID_PARAMETER_SET if the parameter-set ID is invalid.
+ * Returns NTRU_BAD_LENGTH if a length argument is invalid.
+ * Returns NTRU_BUFFER_TOO_SMALL if either the pubkey_blob buffer or the
+ *  privkey_blob buffer is too small.
+ * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
+ * Returns 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.
  */
 
diff --git a/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h b/src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_error.h
deleted file mode 100644 (file)
index daf88e7..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/******************************************************************************
- * 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 */
index 40d80d316a01fe23824b59b073f88cbececcbe52..5271d7cb37ca7d4012b6530cf7e5b6c581817f44 100644 (file)
@@ -40,7 +40,7 @@
 #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_ntru_mgftp1.h"
 
 /* ntru_crypto_ntru_encrypt
  *
  * 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.
+ * Returns NTRU_DRBG_FAIL if the DRBG handle is invalid.
+ * Returns NTRU_BAD_PARAMETER if an argument pointer (other than ct) is NULL.
+ * Returns 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_BAD_PUBLIC_KEY if the public-key blob is invalid
+ *  (unknown format, corrupt, bad length).
+ * Returns NTRU_BUFFER_TOO_SMALL if the ciphertext buffer is too small.
+ * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
  */
 
 uint32_t
@@ -107,17 +103,20 @@ ntru_crypto_ntru_encrypt(
     uint8_t                *tmp_buf = NULL;
     bool                    msg_rep_good = FALSE;
     hash_algorithm_t        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);
+       if (!pubkey_blob || !pt || !ct_len)
+       {
+               return NTRU_BAD_PARAMETER;
+       }
+       if ((pubkey_blob_len == 0) || (pt_len == 0))
+       {
+               return 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
@@ -127,37 +126,45 @@ ntru_crypto_ntru_encrypt(
                                             pubkey_blob, &pubkey_pack_type,
                                             NULL, &params, &pubkey_packed,
                                             NULL))
-        NTRU_RET(NTRU_BAD_PUBLIC_KEY);
+       {
+               return NTRU_BAD_PUBLIC_KEY;
+       }
 
     /* return the ciphertext size if requested */
 
     packed_ct_len = (params->N * params->q_bits + 7) >> 3;
-    if (!ct) {
+    if (!ct)
+       {
         *ct_len = packed_ct_len;
-        NTRU_RET(NTRU_OK);
+               return NTRU_OK;
     }
 
     /* check the ciphertext buffer size */
 
-    if (*ct_len < packed_ct_len) {
-        NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+    if (*ct_len < packed_ct_len)
+       {
+               return NTRU_BUFFER_TOO_SMALL;
     }
 
     /* check the plaintext length */
 
-    if (pt_len > params->m_len_max) {
-        NTRU_RET(NTRU_BAD_LENGTH);
+    if (pt_len > params->m_len_max)
+       {
+               return NTRU_BAD_LENGTH;
     }
 
     /* allocate memory for all operations */
 
-    if (params->is_product_form) {
+    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 {
+    }
+       else
+       {
         ring_mult_tmp_len = params->N;      /* N 16-bit word buffer */
         dr = params->dF_r;
     }
@@ -170,8 +177,9 @@ ntru_crypto_ntru_encrypt(
                       params->sec_strength_len;
                                             /* buffer for b */
     scratch_buf = malloc(scratch_buf_len);
-    if (!scratch_buf) {
-        NTRU_RET(NTRU_OUT_OF_MEMORY);
+    if (!scratch_buf)
+       {
+               return NTRU_OUT_OF_MEMORY;
     }
     ringel_buf = scratch_buf + ring_mult_tmp_len;
     r_buf = ringel_buf + params->N;
@@ -179,20 +187,10 @@ ntru_crypto_ntru_encrypt(
     tmp_buf = (uint8_t *)scratch_buf;
 
        /* set hash algorithm based on security strength */
-       if (params->sec_strength_len <= 20)
-       {
-               hash_algid = HASH_SHA1;
-               md_len = 20;
-       }
-       else
-       {
-               hash_algid = HASH_SHA256;
-               md_len = 32;
-       }
+        hash_algid = (params->sec_strength_len <= 20) ? HASH_SHA1 : HASH_SHA256;
 
     /* set constants */
-
-    mod_q_mask = params->q - 1;
+       mod_q_mask = params->q - 1;
 
     /* loop until a message representative with proper weight is achieved */
 
@@ -210,10 +208,10 @@ ntru_crypto_ntru_encrypt(
                        result = NTRU_FAIL;
                }
 
-        if (result == NTRU_OK) {
+               if (result == NTRU_OK)
+               {
 
             /* form sData (OID || m || b || hTrunc) */
-
             memcpy(ptr, params->OID, 3);
             ptr += 3;
             memcpy(ptr, pt, pt_len);
@@ -225,8 +223,7 @@ ntru_crypto_ntru_encrypt(
 
 
             /* generate r */
-
-            result = ntru_gen_poly(hash_algid, md_len,
+            result = ntru_gen_poly(hash_algid,
                                    params->min_IGF_hash_calls,
                                    (uint16_t)(ptr - tmp_buf),
                                    tmp_buf, tmp_buf,
@@ -236,11 +233,11 @@ ntru_crypto_ntru_encrypt(
                                    params->dF_r << 1, r_buf);
         }
 
-        if (result == NTRU_OK) {
+               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,
@@ -259,17 +256,15 @@ ntru_crypto_ntru_encrypt(
                                        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,
+            result = ntru_mgftp1(hash_algid, params->min_MGF_hash_calls,
                                  (params->N + 3) / 4, tmp_buf,
                                  tmp_buf + params->N, params->N, tmp_buf);
         }
-        if (result == NTRU_OK) {
+               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 +
@@ -277,7 +272,6 @@ ntru_crypto_ntru_encrypt(
             uint16_t  i;
 
             /* form the padded message M */
-
             ptr = M_buf;
             memcpy(ptr, b_buf, params->sec_strength_len);
             ptr += params->sec_strength_len;
@@ -295,10 +289,11 @@ ntru_crypto_ntru_encrypt(
             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)
+                       if (params->is_product_form)
+                       {
                 --mprime_len;
+                       }
 
             ntru_bits_2_trits(M_buf, mprime_len, Mtrin_buf);
 
@@ -336,7 +331,8 @@ ntru_crypto_ntru_encrypt(
         }
     } while ((result == NTRU_OK) && !msg_rep_good);
 
-    if (result == NTRU_OK) {
+       if (result == NTRU_OK)
+       {
         uint16_t i;
 
         /* form ciphertext e by adding m' to R mod q */
@@ -351,17 +347,15 @@ ntru_crypto_ntru_encrypt(
             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;
+       return result;
 }
 
 
@@ -381,17 +375,14 @@ ntru_crypto_ntru_encrypt(
  * 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.
+ * Returns NTRU_BAD_PARAMETER if an argument pointer (other than pt) is NULL.
+ * Returns NTRU_BAD_LENGTH if a length argument (privkey_blob) is zero, or if
+ *  ct_len is invalid for the parameter set.
+ * Returns NTRU_BAD_PRIVATE_KEY if the private-key blob is invalid
+ *  (unknown format, corrupt, bad length).
+ * Returns NTRU_BUFFER_TOO_SMALL if the plaintext buffer is too small.
+ * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
+ * Returns NTRU_FAIL if a decryption error occurs.
  */
 
 uint32_t
@@ -427,7 +418,6 @@ ntru_crypto_ntru_decrypt(
     uint8_t                *M_buf = NULL;
     uint8_t                *ptr = NULL;
     hash_algorithm_t        hash_algid;
-    uint8_t                 md_len;
     uint16_t                cmprime_len;
     uint16_t                mod_q_mask;
     uint16_t                q_mod_p;
@@ -439,28 +429,35 @@ ntru_crypto_ntru_decrypt(
 
     /* 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);
+       if (!privkey_blob || !ct || !pt_len)
+       {
+               return NTRU_BAD_PARAMETER;
+       }
+       if ((privkey_blob_len == 0) || (ct_len == 0))
+       {
+               return 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 */,
+       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 NTRU_BAD_PRIVATE_KEY;
+       }
 
     /* return the max plaintext size if requested */
 
-    if (!pt) {
+       if (!pt)
+       {
         *pt_len = params->m_len_max;
-        NTRU_RET(NTRU_OK);
+               return NTRU_OK;
     }
 
     /* cannot check the plaintext buffer size until after the plaintext
@@ -470,12 +467,15 @@ ntru_crypto_ntru_decrypt(
 
     /* check the ciphertext length */
 
-    if (ct_len != (params->N * params->q_bits + 7) >> 3)
-        NTRU_RET(NTRU_BAD_LENGTH);
+       if (ct_len != (params->N * params->q_bits + 7) >> 3)
+       {
+               return NTRU_BAD_LENGTH;
+       }
 
     /* allocate memory for all operations */
 
-    if (params->is_product_form) {
+       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;
@@ -493,8 +493,9 @@ ntru_crypto_ntru_decrypt(
                       (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);
+       if (!scratch_buf)
+       {
+               return NTRU_OUT_OF_MEMORY;
     }
     ringel_buf1 = scratch_buf + ring_mult_tmp_len;
     ringel_buf2 = ringel_buf1 + params->N;
@@ -505,38 +506,31 @@ ntru_crypto_ntru_decrypt(
     M_buf = Mtrin_buf + params->N;
 
        /* set hash algorithm based on security strength */
-       if (params->sec_strength_len <= 20)
-       {
-               hash_algid = HASH_SHA1;
-               md_len = 20;
-       }
-       else
-       {
-               hash_algid = HASH_SHA256;
-               md_len = 32;
-    }
+       hash_algid = (params->sec_strength_len <= 20) ? HASH_SHA1 : HASH_SHA256;
 
     /* 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) {
+    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) {
+    }
+       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 {
+    }
+       else
+       {
         assert(FALSE);
     }
 
@@ -548,7 +542,8 @@ ntru_crypto_ntru_decrypt(
      */
 
     cmprime_len = params->N;
-    if (params->is_product_form) {
+    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,
@@ -564,7 +559,9 @@ ntru_crypto_ntru_decrypt(
             else if (Mtrin_buf[i] == 2)
                 --m1;
         }
-    } else {
+    }
+       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);
@@ -581,11 +578,15 @@ ntru_crypto_ntru_decrypt(
      */
 
     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 = 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);
+                                                                                                  params->min_msg_rep_wt);
+       }
 
     /* form cR = e - cm' mod q */
 
@@ -605,12 +606,12 @@ ntru_crypto_ntru_decrypt(
 
     /* form mask */
 
-    result = ntru_mgftp1(hash_algid, md_len,
-                         params->min_MGF_hash_calls,
+    result = ntru_mgftp1(hash_algid, params->min_MGF_hash_calls,
                          (params->N + 3) / 4, tmp_buf,
                          tmp_buf + params->N, params->N, tmp_buf);
 
-    if (result == NTRU_OK) {
+       if (result == NTRU_OK)
+       {
 
         /* form cMtrin by subtracting mask from cm', mod p */
 
@@ -665,7 +666,7 @@ ntru_crypto_ntru_decrypt(
 
         /* generate cr */
 
-        result = ntru_gen_poly(hash_algid, md_len,
+        result = ntru_gen_poly(hash_algid,
                                params->min_IGF_hash_calls,
                                (uint16_t)(ptr - tmp_buf),
                                tmp_buf, tmp_buf,
@@ -675,7 +676,8 @@ ntru_crypto_ntru_decrypt(
                                params->dF_r << 1, i_buf);
     }
 
-    if (result == NTRU_OK) {
+       if (result == NTRU_OK)
+       {
 
         /* unpack the public key */
 
@@ -709,9 +711,12 @@ ntru_crypto_ntru_decrypt(
 
         /* output plaintext and plaintext length */
 
-        if (decryption_ok) {
+        if (decryption_ok)
+               {
             if (*pt_len < cm_len)
-                NTRU_RET(NTRU_BUFFER_TOO_SMALL);
+                       {
+                               return NTRU_BUFFER_TOO_SMALL;
+                       }
             memcpy(pt, m_buf, cm_len);
             *pt_len = cm_len;
         }
@@ -723,8 +728,11 @@ ntru_crypto_ntru_decrypt(
     free(scratch_buf);
     
     if (!decryption_ok)
-        NTRU_RET(NTRU_FAIL);
-    return result;
+       {
+               return NTRU_FAIL;
+       }
+
+       return result;
 }
 
 
@@ -732,13 +740,6 @@ ntru_crypto_ntru_decrypt(
  *
  * 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
@@ -759,17 +760,15 @@ ntru_crypto_ntru_decrypt(
  * 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.
+ * Returns NTRU_BAD_PARAMETER if an argument pointer (other than pubkey_blob or
+ *  privkey_blob) is NULL.
+ * Returns NTRU_INVALID_PARAMETER_SET if the parameter-set ID is invalid.
+ * Returns NTRU_BAD_LENGTH if a length argument is invalid.
+ * Returns NTRU_BUFFER_TOO_SMALL if either the pubkey_blob buffer or the
+ *  privkey_blob buffer is too small.
+ * Returns NTRU_NO_MEMORY if memory needed cannot be allocated from the heap.
+ * Returns 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.
  */
 
@@ -814,12 +813,16 @@ ntru_crypto_ntru_encrypt_keygen(
     /* 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);
+       {
+               return NTRU_INVALID_PARAMETER_SET;
+       }
 
     /* check for bad parameters */
 
     if (!pubkey_blob_len || !privkey_blob_len)
-        NTRU_RET(NTRU_BAD_PARAMETER);
+       {
+               return NTRU_BAD_PARAMETER;
+       }
 
     /* get public and private key packing types and blob lengths */
 
@@ -830,22 +833,24 @@ ntru_crypto_ntru_encrypt_keygen(
 
     /* return the pubkey_blob size and/or privkey_blob size if requested */
 
-    if (!pubkey_blob || !privkey_blob) {
+    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);
+               return 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);
+       {
+               return 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;
@@ -862,8 +867,9 @@ ntru_crypto_ntru_encrypt_keygen(
                                                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);
+       if (!scratch_buf)
+       {
+               return NTRU_OUT_OF_MEMORY;
     }
     ringel_buf1 = scratch_buf + (params->N << 1);
     ringel_buf2 = ringel_buf1 + params->N;
@@ -897,14 +903,14 @@ ntru_crypto_ntru_encrypt_keygen(
        }
        else
        {
-               result = NTRU_FAIL;
+               result = NTRU_DRBG_FAIL;
        }
 
-    if (result == NTRU_OK) {
+       if (result == NTRU_OK)
+       {
 
         /* generate F */
-
-        result = ntru_gen_poly(hash_algid, md_len,
+        result = ntru_gen_poly(hash_algid,
                                params->min_IGF_hash_calls,
                                seed_len, tmp_buf, tmp_buf,
                                params->N, params->c_bits,
@@ -913,7 +919,8 @@ ntru_crypto_ntru_encrypt_keygen(
                                params->dF_r << 1, F_buf);
     }
 
-    if (result == NTRU_OK) {
+       if (result == NTRU_OK)
+       {
         uint32_t i;
 
         memset(ringel_buf1, 0, params->N * sizeof(uint16_t));
@@ -967,10 +974,13 @@ ntru_crypto_ntru_encrypt_keygen(
 
         if (!ntru_ring_inv(ringel_buf1, params->N, params->q,
                            scratch_buf, ringel_buf2))
-            result = NTRU_ERROR_BASE + NTRU_FAIL;
+               {
+                       result = NTRU_FAIL;
+               }
     }
 
-    if (result == NTRU_OK) {
+       if (result == NTRU_OK)
+       {
 
         /* get random bytes for seed for generating trinary g
          * as a list of indices
@@ -978,18 +988,19 @@ ntru_crypto_ntru_encrypt_keygen(
         if (!drbg->generate(drbg, params->sec_strength_len << 3, seed_len,
                                                                  tmp_buf))
                {
-                       result = NTRU_FAIL;
+                       result = NTRU_DRBG_FAIL;
                }
     }
 
-    if (result == NTRU_OK) {
+       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,
+        result = ntru_gen_poly(hash_algid,
                                (uint8_t)min_IGF_hash_calls,
                                seed_len, tmp_buf, tmp_buf,
                                params->N, params->c_bits,
@@ -997,7 +1008,8 @@ ntru_crypto_ntru_encrypt_keygen(
                                (params->dg << 1) + 1, ringel_buf1);
     }
 
-    if (result == NTRU_OK) {
+       if (result == NTRU_OK)
+       {
         uint16_t i;
 
         /* compute h = p * (f^-1 * g) mod q */
similarity index 55%
rename from src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.c
rename to src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.c
index fbbd6b63edca7dbda76aa59d27651f930c2e6eaa..d0427982bc03aab3b618af21ae7d95e50572d41e 100644 (file)
@@ -2,7 +2,7 @@
  * 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.
+ * ntru_crypto_ntru_mgftp1.c is a component of ntru-crypto.
  *
  * Copyright (C) 2009-2013  Security Innovation
  * 
  
 /******************************************************************************
  *
- * File: ntru_crypto_ntru_mgf1.c
+ * File: ntru_crypto_ntru_mgftp1.c
  *
- * Contents: Routines implementing MGF-TP-1 and MGF-1.
+ * Contents: Routines implementing MGF-TP-1.
  *
  *****************************************************************************/
 
 
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
-#include "ntru_crypto_ntru_mgf1.h"
+#include "ntru_crypto_ntru_mgftp1.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 */
-       hash_algorithm_t        hash_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                *seed,       /*     in - pointer to seed */
-       uint8_t                *out)        /*    out - address for output */
-{
-       uint8_t  *ctr = state + md_len;
-       hasher_t *hasher;
-
-       assert(state);
-       assert(out);
-
-       hasher = lib->crypto->create_hasher(lib->crypto, hash_algid);
-       if (!hasher)
-       {
-           NTRU_RET(NTRU_FAIL);
-       }
-
-       /* if seed present, init state */
-       if (seed)
-       {
-               if (!hasher->get_hash(hasher, chunk_create(seed, seed_len), state))
-               {
-                       hasher->destroy(hasher);
-                       NTRU_RET(NTRU_FAIL);
-               }
-               memset(ctr, 0, 4);
-       }
-
-       /* generate output */
-       while (num_calls-- > 0)
-       {
-               if (!hasher->get_hash(hasher, chunk_create(state, md_len + 4), out))
-               {
-                       hasher->destroy(hasher);
-                       NTRU_RET(NTRU_FAIL);
-               }
-               out += md_len;
-
-               /* increment counter */
-               if (++ctr[3] == 0)
-               {
-                       if (++ctr[2] == 0)
-                       {
-                               if (++ctr[1] == 0)
-                               {
-                                       ++ctr[0];
-                               }
-                       }
-               }
-    }
-       hasher->destroy(hasher);
-
-    NTRU_RET(NTRU_OK);
-}
-
+#include "ntru_mgf1.h"
 
 /* ntru_mgftp1
  *
@@ -122,7 +48,7 @@ ntru_mgf1(
  * 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.
+ * Returns NTRU_MGF1_FAIL if the MGF1 mask generator function fails
  *
  */
 
@@ -130,8 +56,6 @@ uint32_t
 ntru_mgftp1(
        hash_algorithm_t        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 */
@@ -141,38 +65,43 @@ ntru_mgftp1(
        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   md_len;
        uint8_t  *octets;
        uint16_t  octets_available;
-       uint32_t  retcode;
-
-       assert(seed);
-       assert(buf);
-       assert(mask);
+       ntru_mgf1_t *mgf1;
 
        /* 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)
+       mgf1 = ntru_mgf1_create(hash_algid, chunk_create(seed, seed_len), TRUE);
+       if (!mgf1)
        {
-               return retcode;
+           return NTRU_MGF1_FAIL;
        }
-       octets = mgf_out;
+       md_len = mgf1->get_hash_size(mgf1);
+       octets = buf;
        octets_available = min_calls * md_len;
 
+       DBG2(DBG_LIB, "MGF1 generates %u octets", octets_available);
+       if (!mgf1->get_mask(mgf1, octets_available, octets))
+       {
+               mgf1->destroy(mgf1);
+               return NTRU_MGF1_FAIL;
+       }
+
        /* 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)
+                       octets = buf;
+                       octets_available = md_len;
+
+                       DBG2(DBG_LIB, "MGF1 generates another %u octets", octets_available);
+                       if (!mgf1->get_mask(mgf1, octets_available, octets))
                        {
-                               return retcode;
+                               mgf1->destroy(mgf1);
+                               return NTRU_MGF1_FAIL;
                        }
-                       octets = mgf_out;
-                       octets_available = md_len;
                }
 
                if (*octets < 243)
@@ -193,13 +122,15 @@ ntru_mgftp1(
                /* 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)
+                       octets = buf;
+                       octets_available = md_len;
+
+                       DBG2(DBG_LIB, "MGF1 generates another %u octets", octets_available);
+                       if (!mgf1->get_mask(mgf1, octets_available, octets))
                        {
-                               return retcode;
+                               mgf1->destroy(mgf1);
+                           return NTRU_MGF1_FAIL;
                        }
-                       octets = mgf_out;
-                       octets_available = md_len;
                }
                if (*octets < 243)
                {
@@ -213,8 +144,9 @@ ntru_mgftp1(
                        --octets_available;
                }
        }
+       mgf1->destroy(mgf1);
 
-       NTRU_RET(NTRU_OK);
+       return NTRU_OK;
 }
 
 
similarity index 67%
rename from src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgf1.h
rename to src/libstrongswan/plugins/ntru/ntru_crypto/ntru_crypto_ntru_mgftp1.h
index 43d710217c19034075f28d5ff6029af95f5e2291..6f85efc898a404b9d35d213e5b79d85ae51c6a61 100644 (file)
@@ -2,7 +2,7 @@
  * 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.
+ * ntru_crypto_ntru_mgftp1.h is a component of ntru-crypto.
  *
  * Copyright (C) 2009-2013  Security Innovation
  * 
@@ -24,9 +24,9 @@
  
 /******************************************************************************
  *
- * File:  ntru_crypto_ntru_mgf1.h
+ * File:  ntru_crypto_ntru_mgftp1.h
  *
- * Contents: Public header file for MGF-1 in the NTRU algorithm.
+ * Contents: Public header file for MGF-TP-1 in the NTRU algorithm.
  *
  *****************************************************************************/
 
 
 #include <crypto/hashers/hasher.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 */
-    hash_algorithm_t        hash_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                *seed,       /*     in - pointer to seed */
-    uint8_t                *out);       /*    out - address for output */
-
-
 /* ntru_mgftp1
  *
  * Implements a mask-generation function for trinary polynomials,
@@ -83,8 +57,6 @@ extern uint32_t
 ntru_mgftp1(
     hash_algorithm_t        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 */
index be45954373a44694ce97fd9893ce921223b14b67..955544f2f8fd2454293710bb6551a248c913b33e 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 #include "ntru_crypto_ntru_poly.h"
-#include "ntru_crypto_ntru_mgf1.h"
+#include "ntru_crypto_ntru_mgftp1.h"
 
+#include "ntru_mgf1.h"
+
+#include <utils/debug.h>
 
 /* ntru_gen_poly
  *
@@ -64,7 +66,6 @@ uint32_t
 ntru_gen_poly(
     hash_algorithm_t        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 */
@@ -80,7 +81,7 @@ ntru_gen_poly(
     uint32_t                indices_counts,  /*  in - nos. of indices needed */
     uint16_t               *indices)         /* out - address for indices */
 {
-    uint8_t  *mgf_out;
+       uint8_t   md_len;
     uint8_t  *octets;
     uint8_t  *used;
     uint8_t   num_polys;
@@ -89,23 +90,26 @@ ntru_gen_poly(
     uint16_t  index_cnt = 0;
     uint8_t   left = 0;
     uint8_t   num_left = 0;
-    uint32_t  retcode;
-
-    assert(seed);
-    assert(buf);
-    assert(indices);
+       ntru_mgf1_t *mgf1;
 
     /* 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;
+       mgf1 = ntru_mgf1_create(hash_algid, chunk_create(seed, seed_len), TRUE);
+       if (!mgf1)
+       {
+               return NTRU_MGF1_FAIL;
+       }
+       md_len = mgf1->get_hash_size(mgf1);
+    octets = buf;
     octets_available = min_calls * md_len;
 
-    /* init indices counts for number of polynomials being generated */
+       DBG2(DBG_LIB, "MGF1 generates %u octets", octets_available);
+       if (!mgf1->get_mask(mgf1, octets_available, octets))
+       {
+               mgf1->destroy(mgf1);
+               return NTRU_MGF1_FAIL;
+       }
 
+    /* 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,
@@ -126,7 +130,7 @@ ntru_gen_poly(
 
     /* init used-index array */
 
-    used = mgf_out + octets_available;
+    used = buf + octets_available;
     memset(used, 0, N);
 
     /* generate indices (IGF-2) for all polynomials */
@@ -153,21 +157,28 @@ ntru_gen_poly(
                 /* get the rest of the bits needed from new octets */
 
                 num_needed = c_bits - num_left;
-                while (num_needed != 0) {
+                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;
+                    if (octets_available == 0)
+                                       {
+                        octets = buf;
                         octets_available = md_len;
+
+                                               DBG2(DBG_LIB, "MGF1 generates another %u octets",
+                                                                          octets_available);
+                                               if (!mgf1->get_mask(mgf1, octets_available, octets))
+                                               {
+                                                       mgf1->destroy(mgf1);
+                                                       return NTRU_MGF1_FAIL;
+                                               }
                     }
                     left = *octets++;
                     --octets_available;
 
-                    if (num_needed <= 8) {
+                                       if (num_needed <= 8)
+                                       {
 
                         /* all bits needed to fill the index are in this octet */
 
@@ -191,7 +202,8 @@ ntru_gen_poly(
             /* form index and check if unique */
 
             index %= N;
-            if (!used[index]) {
+                       if (!used[index])
+                       {
                 used[index] = 1;
                 indices[index_cnt] = index;
                 ++index_cnt;
@@ -201,15 +213,17 @@ ntru_gen_poly(
 
         /* init for next polynomial if another polynomial to be generated */
 
-        if (num_polys > 0) {
+               if (num_polys > 0)
+               {
             memset(used, 0, N);
             num_indices = num_indices +
                           (uint16_t)(indices_counts & 0xff);
             indices_counts >>= 8;
         }
     }
+       mgf1->destroy(mgf1);
 
-    NTRU_RET(NTRU_OK);
+       return NTRU_OK;
 }
 
 
@@ -276,11 +290,6 @@ ntru_ring_mult_indices(
     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++)
@@ -356,27 +365,19 @@ ntru_ring_mult_product_indices(
     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;
 }
@@ -406,12 +407,7 @@ ntru_ring_mult_coefficients(
     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;
@@ -457,31 +453,22 @@ ntru_ring_inv(
     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 */
+    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;
@@ -489,7 +476,8 @@ ntru_ring_inv(
 
     /* until f(X) = 1 */
 
-    while (!done) {
+       while (!done)
+       {
 
         /* while f[0] = 0, f(X) /= X, c(X) *= X, k++ */
 
index 33939fe05861a1da83bb3af41c05f870cccf6cd8..9d0406b0d049cd15a58d5e0e881280f8fc9301a8 100644 (file)
@@ -68,7 +68,6 @@ extern uint32_t
 ntru_gen_poly(
     hash_algorithm_t       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 */
diff --git a/src/libstrongswan/plugins/ntru/ntru_mgf1.c b/src/libstrongswan/plugins/ntru/ntru_mgf1.c
new file mode 100644 (file)
index 0000000..5a17703
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "ntru_mgf1.h"
+
+#include <crypto/hashers/hasher.h>
+#include <utils/debug.h>
+#include <utils/test.h>
+
+typedef struct private_ntru_mgf1_t private_ntru_mgf1_t;
+
+/**
+ * Private data of an ntru_mgf1_t object.
+ */
+struct private_ntru_mgf1_t {
+
+       /**
+        * Public ntru_mgf1_t interface.
+        */
+       ntru_mgf1_t public;
+
+       /**
+        * Hasher the MGF1 Mask Generation Function is based on
+        */
+       hasher_t *hasher;
+
+       /**
+        * Counter
+        */
+       u_int32_t counter;
+
+       /**
+        * Set if counter has reached 2^32
+        */
+       bool overflow;
+
+       /**
+        * Current state to be hashed
+        */
+       chunk_t state;
+
+       /**
+        * Position of the 4 octet counter string
+        */
+       u_char *ctr_str;
+
+};
+
+METHOD(ntru_mgf1_t, get_hash_size, size_t,
+       private_ntru_mgf1_t *this)
+{
+       return this->hasher->get_hash_size(this->hasher);
+}
+
+METHOD(ntru_mgf1_t, get_mask, bool,
+       private_ntru_mgf1_t *this, size_t mask_len, u_char *mask)
+{
+       u_char buf[HASH_SIZE_SHA512];
+       size_t len;
+
+       while (mask_len > 0)
+       {
+               /* detect overflow, set counter string and increment counter */
+               if (this->overflow)
+               {
+                       return FALSE;
+               }
+               htoun32(this->ctr_str, this->counter++);
+               if (this->counter == 0)
+               {
+                       this->overflow = TRUE;
+               }
+
+               if (!this->hasher->get_hash(this->hasher, this->state, buf))
+               {
+                       return FALSE;
+               }
+
+               len = min(mask_len, this->hasher->get_hash_size(this->hasher)); 
+               memcpy(mask, buf, len);
+               mask_len -= len;
+               mask += len;
+       }
+
+       return TRUE;
+}
+
+METHOD(ntru_mgf1_t, allocate_mask, bool,
+       private_ntru_mgf1_t *this, size_t mask_len, chunk_t *mask)
+{
+       if (mask_len == 0)
+       {
+               *mask = chunk_empty;
+               return TRUE;
+       }
+       *mask = chunk_alloc(mask_len);
+
+       return get_mask(this, mask_len, mask->ptr);
+}
+
+METHOD(ntru_mgf1_t, destroy, void,
+       private_ntru_mgf1_t *this)
+{
+       this->hasher->destroy(this->hasher);
+       chunk_clear(&this->state);
+       free(this);
+}
+
+/*
+ * Described in header.
+ */
+ntru_mgf1_t *ntru_mgf1_create(hash_algorithm_t alg, chunk_t seed,
+                                                         bool hash_seed)
+{
+       private_ntru_mgf1_t *this;
+       hasher_t *hasher;
+       size_t state_len;
+
+       if (seed.len == 0)
+       {
+               DBG1(DBG_LIB, "empty seed for MGF1");
+               return NULL;
+       }
+
+       hasher = lib->crypto->create_hasher(lib->crypto, alg);
+       if (!hasher)
+       {
+               DBG1(DBG_LIB, "failed to create %N hasher for MGF1",
+                        hash_algorithm_names, alg);
+               return NULL;
+       }
+       state_len = (hash_seed ? hasher->get_hash_size(hasher) : seed.len) + 4;
+       
+       INIT(this,
+               .public = {
+                       .get_hash_size = _get_hash_size,
+                       .allocate_mask = _allocate_mask,
+                       .get_mask = _get_mask,
+                       .destroy = _destroy,
+               },
+               .hasher = hasher,
+               .state = chunk_alloc(state_len),
+       );
+
+       /* determine position of the 4 octet counter string */
+       this->ctr_str = this->state.ptr + state_len - 4;
+
+       if (hash_seed)
+       {
+               if (!hasher->get_hash(hasher, seed, this->state.ptr))
+               {
+                       DBG1(DBG_LIB, "failed to hash seed for MGF1");
+                       destroy(this);
+                       return NULL;
+               }
+       }
+       else
+       {
+               memcpy(this->state.ptr, seed.ptr, seed.len);
+       }
+
+       return &this->public;
+}
+
+EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_mgf1_create);
diff --git a/src/libstrongswan/plugins/ntru/ntru_mgf1.h b/src/libstrongswan/plugins/ntru/ntru_mgf1.h
new file mode 100644 (file)
index 0000000..53e9041
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup ntru_mgf1 ntru_mgf1
+ * @{ @ingroup ntru_p
+ */
+
+#ifndef NTRU_MGF1_H_
+#define NTRU_MGF1_H_
+
+typedef struct ntru_mgf1_t ntru_mgf1_t;
+
+#include <library.h>
+
+/**
+ * Implements the PKCS#1 MGF1 Mask Generation Function based on a hash function
+ * defined in section 10.2.1 of RFC 2437 
+ */
+struct ntru_mgf1_t {
+
+       /**
+        * Get the hash size of the underlying hash function
+        *
+        * @return                      hash size in bytes
+        */
+       size_t (*get_hash_size)(ntru_mgf1_t *this);
+
+       /**
+        * Generate a mask pattern and copy it to an output buffer
+        * If the maximum number of requests has been reached, reseeding occurs
+        *
+        * @param mask_len      number of mask bytes to generate
+        * @param mask          output buffer of minimum size mask_len
+        * @return                      TRUE if successful
+        */
+       bool (*get_mask)(ntru_mgf1_t *this, size_t mask_len, u_char *mask);
+
+       /**
+        * Generate a mask pattern and return it in an allocated chunk
+        *
+        * @param mask_len      number of mask bytes to generate
+        * @param mask          chunk containing generated mask
+        * @return                      TRUE if successful
+        */
+       bool (*allocate_mask)(ntru_mgf1_t *this, size_t mask_len, chunk_t *mask);
+
+       /**
+        * Destroy the MGF1 object
+        */
+       void (*destroy)(ntru_mgf1_t *this);
+};
+
+/**
+ * Create an MGF1 object
+ *
+ * @param alg                  hash algorithm to be used by MGF1
+ * @param seed                 seed used by MGF1 to generate mask from
+ * @param hash_seed            hash seed before using it as a seed from MGF1
+ */
+ntru_mgf1_t *ntru_mgf1_create(hash_algorithm_t alg, chunk_t seed,
+                                                         bool hash_seed);
+
+#endif /** NTRU_MGF1_H_ @}*/
+
index 73156208f65a2ed9ff1ef10a97dc519da5c41ed9..2548d3134db8077e45fd0d2718a30bb2c1da915e 100644 (file)
 
 #include <tests/utils/test_rng.h>
 #include <plugins/ntru/ntru_drbg.h>
+#include <plugins/ntru/ntru_mgf1.h>
 #include <utils/test.h>
 
 IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_drbg_create, ntru_drbg_t*,
                                                  u_int32_t strength, chunk_t pers_str, rng_t *entropy)
 
+IMPORT_FUNCTION_FOR_TESTS(ntru, ntru_mgf1_create, ntru_mgf1_t*,
+                                                 hash_algorithm_t alg, chunk_t seed, bool hash_seed)
+
 /**
  * NTRU parameter sets to test
  */
@@ -286,6 +290,169 @@ START_TEST(test_ntru_drbg_reseed)
 }
 END_TEST
 
+typedef struct {
+       hash_algorithm_t alg;
+       size_t hash_size;
+       size_t ml1, ml2, ml3;
+       chunk_t seed;
+       chunk_t hashed_seed;
+       chunk_t mask;
+} mgf1_test_t;
+
+/**
+ * MGF1 Mask Generation Function Test Vectors
+ */
+mgf1_test_t mgf1_tests[] = {
+       {       HASH_SHA1, 20, 60, 20, 15,
+               chunk_from_chars( 
+                                               0xED, 0xA5, 0xC3, 0xBC, 0xAF, 0xB3, 0x20, 0x7D,
+                                               0x14, 0xA1, 0x54, 0xF7, 0x8B, 0x37, 0xF2, 0x8D,
+                                               0x8C, 0x9B, 0xD5, 0x63, 0x57, 0x38, 0x11, 0xC2,
+                                               0xB5, 0xCA, 0xBF, 0x06, 0x43, 0x45, 0x19, 0xD5,
+                                               0xE7, 0x36, 0xD0, 0x29, 0x21, 0xDA, 0x02, 0x20,
+                                               0x45, 0xF6, 0x5F, 0x0F, 0x10, 0x04, 0x2A, 0xE3,
+                                               0x6A, 0x1D, 0xD5, 0x9F, 0x1D, 0x66, 0x44, 0x8F,
+                                               0xFA, 0xC6, 0xCA, 0xA4, 0x6E, 0x3B, 0x00, 0x66,
+                                               0xA6, 0xC9, 0x80, 0x5C, 0xF5, 0x2D, 0xD7, 0x72,
+                                               0xC6, 0xD4, 0x4F, 0x30, 0x72, 0xA2, 0xAD, 0xE0,
+                                               0x33, 0xE8, 0x55, 0xD5, 0xE6, 0xD6, 0x00, 0x1D,
+                                               0xA8, 0x68, 0xFF, 0x97, 0x36, 0x8A, 0xF4, 0xD6,
+                                               0xF1, 0xB6, 0x7E, 0x1F, 0x06, 0xCB, 0x57, 0xCB,
+                                               0x35, 0x38, 0xF2, 0x2D, 0xF6, 0x20),
+               chunk_from_chars(
+                                               0xF3, 0x9B, 0x0B, 0xB4, 0x97, 0x50, 0xB5, 0xA7,
+                                               0xE6, 0xBD, 0xDA, 0xD0, 0x9A, 0x52, 0xBE, 0xA0,
+                                               0x21, 0xC4, 0x90, 0xB6),
+               chunk_from_chars(
+                                               0x10, 0x43, 0x76, 0x72, 0x6C, 0xDE, 0xA0, 0x0E,
+                                               0x77, 0x51, 0xFB, 0x58, 0x39, 0x8A, 0x36, 0xE1,
+                                               0x63, 0x2B, 0xC9, 0x17, 0x56, 0x0C, 0x4B, 0x46,
+                                               0xA4, 0x07, 0xA4, 0x3B, 0x8E, 0x33, 0x4D, 0xD1,
+                                               0x65, 0xF1, 0xAC, 0xC8, 0x59, 0x21, 0x32, 0x16,
+                                               0x44, 0x2B, 0x7F, 0xB2, 0xA8, 0xA7, 0x26, 0x5D,
+                                               0xE8, 0x02, 0xBE, 0x8E, 0xDC, 0x34, 0xEB, 0x10,
+                                               0x76, 0x16, 0x8C, 0xDD, 0x90, 0x92, 0x3D, 0x29,
+                                               0x90, 0x98, 0x46, 0x11, 0x73, 0x53, 0x47, 0xB1,
+                                               0x2C, 0xD4, 0x83, 0x78, 0x9B, 0x93, 0x2F, 0x5B,
+                                               0xFC, 0x26, 0xFF, 0x42, 0x08, 0x1F, 0x70, 0x66,
+                                               0x40, 0x4B, 0xE7, 0x22, 0x3A, 0x56, 0x10, 0x6D,
+                                               0x4D, 0x29, 0x0B, 0xCE, 0xA6, 0x21, 0xB5, 0x5C,
+                                               0x71, 0x66, 0x2F, 0x70, 0x35, 0xD8, 0x8A, 0x92,
+                                               0x33, 0xF0, 0x16, 0xD4, 0x0E, 0x43, 0x8A, 0x14) },
+       {       HASH_SHA256, 32, 64, 32, 33,
+               chunk_from_chars(
+                                               0x52, 0xC5, 0xDD, 0x1E, 0xEF, 0x76, 0x1B, 0x53,
+                                               0x08, 0xE4, 0x86, 0x3F, 0x91, 0x12, 0x98, 0x69,
+                                               0xC5, 0x9D, 0xDE, 0xF6, 0xFC, 0xFA, 0x93, 0xCE,
+                                               0x32, 0x52, 0x66, 0xF9, 0xC9, 0x97, 0xF6, 0x42,
+                                               0x00, 0x2C, 0x64, 0xED, 0x1A, 0x6B, 0x14, 0x0A,
+                                               0x4B, 0x04, 0xCF, 0x6D, 0x2D, 0x82, 0x0A, 0x07,
+                                               0xA2, 0x3B, 0xDE, 0xCE, 0x19, 0x8A, 0x39, 0x43,
+                                               0x16, 0x61, 0x29, 0x98, 0x68, 0xEA, 0xE5, 0xCC,
+                                               0x0A, 0xF8, 0xE9, 0x71, 0x26, 0xF1, 0x07, 0x36,
+                                               0x2C, 0x07, 0x1E, 0xEB, 0xE4, 0x28, 0xA2, 0xF4,
+                                               0xA8, 0x12, 0xC0, 0xC8, 0x20, 0x37, 0xF8, 0xF2,
+                                               0x6C, 0xAF, 0xDC, 0x6F, 0x2E, 0xD0, 0x62, 0x58,
+                                               0xD2, 0x37, 0x03, 0x6D, 0xFA, 0x6E, 0x1A, 0xAC,
+                                               0x9F, 0xCA, 0x56, 0xC6, 0xA4, 0x52, 0x41, 0xE8,
+                                               0x0F, 0x1B, 0x0C, 0xB9, 0xE6, 0xBA, 0xDE, 0xE1,
+                                               0x03, 0x5E, 0xC2, 0xE5, 0xF8, 0xF4, 0xF3, 0x46,
+                                               0x3A, 0x12, 0xC0, 0x1F, 0x3A, 0x00, 0xD0, 0x91,
+                                               0x18, 0xDD, 0x53, 0xE4, 0x22, 0xF5, 0x26, 0xA4,
+                                               0x54, 0xEE, 0x20, 0xF0, 0x80),
+               chunk_from_chars(
+                                               0x76, 0x89, 0x8B, 0x1B, 0x60, 0xEC, 0x10, 0x9D,
+                                               0x8F, 0x13, 0xF2, 0xFE, 0xD9, 0x85, 0xC1, 0xAB,
+                                               0x7E, 0xEE, 0xB1, 0x31, 0xDD, 0xF7, 0x7F, 0x0C,
+                                               0x7D, 0xF9, 0x6B, 0x7B, 0x19, 0x80, 0xBD, 0x28), 
+               chunk_from_chars(
+                                               0xF1, 0x19, 0x02, 0x4F, 0xDA, 0x58, 0x05, 0x9A,
+                                               0x07, 0xDF, 0x61, 0x81, 0x22, 0x0E, 0x15, 0x46,
+                                               0xCB, 0x35, 0x3C, 0xDC, 0xAD, 0x20, 0xD9, 0x3F,
+                                               0x0D, 0xD1, 0xAA, 0x64, 0x66, 0x5C, 0xFA, 0x4A,
+                                               0xFE, 0xD6, 0x8F, 0x55, 0x57, 0x15, 0xB2, 0xA6,
+                                               0xA0, 0xE6, 0xA8, 0xC6, 0xBD, 0x28, 0xB4, 0xD5,
+                                               0x6E, 0x5B, 0x4B, 0xB0, 0x97, 0x09, 0xF5, 0xAC,
+                                               0x57, 0x65, 0x13, 0x97, 0x71, 0x2C, 0x45, 0x13,
+                                               0x3D, 0xEE, 0xFB, 0xBF, 0xFE, 0xAF, 0xBB, 0x4B,
+                                               0x0D, 0x5C, 0x45, 0xD4, 0x2F, 0x17, 0x92, 0x07,
+                                               0x66, 0x11, 0xF5, 0x46, 0xF8, 0x0C, 0x03, 0x92,
+                                               0xF5, 0xF5, 0xFF, 0xA4, 0xF3, 0x52, 0xF4, 0x08,
+                                               0x2C, 0x49, 0x32, 0x1A, 0x93, 0x51, 0x98, 0xB6,
+                                               0x94, 0x83, 0x39, 0xCF, 0x6B, 0x1F, 0x2F, 0xFC,
+                                               0x2B, 0xFF, 0x10, 0x71, 0x7D, 0x35, 0x6C, 0xEA,
+                                               0xC5, 0x66, 0xC7, 0x26, 0x7D, 0x9E, 0xAC, 0xDD,
+                                               0x35, 0xD7, 0x06, 0x3F, 0x40, 0x82, 0xDA, 0xC3,
+                                               0x2B, 0x3C, 0x91, 0x3A, 0x32, 0xF8, 0xB2, 0xC6,
+                                               0x44, 0x4D, 0xCD, 0xB6, 0x54, 0x5F, 0x81, 0x95,
+                                               0x59, 0xA1, 0xE5, 0x4E, 0xA5, 0x0A, 0x4A, 0x42) }
+};
+
+START_TEST(test_ntru_mgf1)
+{
+       ntru_mgf1_t *mgf1;
+       chunk_t mask, mask1, mask2, mask3;
+
+       mask1 = mgf1_tests[_i].mask;
+       mask2 = chunk_skip(mask1, mgf1_tests[_i].ml1);
+       mask3 = chunk_skip(mask2, mgf1_tests[_i].ml2);
+       mask1.len = mgf1_tests[_i].ml1;
+       mask2.len = mgf1_tests[_i].ml2;
+       mask3.len = mgf1_tests[_i].ml3;
+
+       mgf1 = ntru_mgf1_create(HASH_UNKNOWN, mgf1_tests[_i].seed, TRUE);
+       ck_assert(mgf1 == NULL);
+
+       mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, chunk_empty, TRUE);
+       ck_assert(mgf1 == NULL);
+
+       /* return mask in allocated chunk */
+       mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].seed, TRUE);
+       ck_assert(mgf1);
+
+       /* check hash size */
+       ck_assert(mgf1->get_hash_size(mgf1) == mgf1_tests[_i].hash_size);
+
+       /* get zero number of octets */
+       ck_assert(mgf1->allocate_mask(mgf1, 0, &mask));
+       ck_assert(mask.len == 0 && mask.ptr == NULL);
+
+       /* get non-zero number of octets */
+       ck_assert(mgf1->allocate_mask(mgf1, mgf1_tests[_i].mask.len, &mask));
+       ck_assert(chunk_equals(mask, mgf1_tests[_i].mask));
+       mgf1->destroy(mgf1);
+
+       /* copy mask to pre-allocated buffer */
+       mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].seed, TRUE);
+       ck_assert(mgf1);
+       ck_assert(mgf1->get_mask(mgf1, mgf1_tests[_i].mask.len, mask.ptr));
+       ck_assert(chunk_equals(mask, mgf1_tests[_i].mask));
+       mgf1->destroy(mgf1);
+
+       /* get mask in batches without hashing the seed */
+       mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].hashed_seed, FALSE);
+       ck_assert(mgf1);
+
+       /* first batch */
+       ck_assert(mgf1->get_mask(mgf1, mask1.len, mask.ptr));
+       mask.len = mask1.len;
+       ck_assert(chunk_equals(mask, mask1));
+
+       /* second batch */
+       ck_assert(mgf1->get_mask(mgf1, mask2.len, mask.ptr));
+       mask.len = mask2.len;
+       ck_assert(chunk_equals(mask, mask2));
+
+       /* third batch */
+       ck_assert(mgf1->get_mask(mgf1, mask3.len, mask.ptr));
+       mask.len = mask3.len;
+       ck_assert(chunk_equals(mask, mask3));
+
+       mgf1->destroy(mgf1);
+       chunk_free(&mask);
+}
+END_TEST
+
 START_TEST(test_ntru_ke)
 {
        chunk_t pub_key, cipher_text, i_shared_secret, r_shared_secret;
@@ -488,6 +655,10 @@ Suite *ntru_suite_create()
        tcase_add_test(tc, test_ntru_drbg_reseed);
        suite_add_tcase(s, tc);
 
+       tc = tcase_create("mgf1");
+       tcase_add_loop_test(tc, test_ntru_mgf1, 0, countof(mgf1_tests));
+       suite_add_tcase(s, tc);
+
        tc = tcase_create("ke");
        tcase_add_loop_test(tc, test_ntru_ke, 0, countof(params));
        suite_add_tcase(s, tc);