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 \
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
#ifndef NTRU_CRYPTO_H
#define NTRU_CRYPTO_H
-#include "ntru_crypto_error.h"
-
#include <library.h>
#include "ntru_drbg.h"
#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 */
* 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
* 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
* 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.
* 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.
*/
+++ /dev/null
-/******************************************************************************
- * 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 */
#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
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
pubkey_blob, &pubkey_pack_type,
NULL, ¶ms, &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;
}
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;
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 */
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);
/* 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,
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,
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 +
uint16_t i;
/* form the padded message M */
-
ptr = M_buf;
memcpy(ptr, b_buf, params->sec_strength_len);
ptr += params->sec_strength_len;
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);
}
} 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 */
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;
}
* 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
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;
/* 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, ¶ms,
&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
/* 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;
(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;
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);
}
*/
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,
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);
*/
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 */
/* 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 */
/* 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,
params->dF_r << 1, i_buf);
}
- if (result == NTRU_OK) {
+ if (result == NTRU_OK)
+ {
/* unpack the public key */
/* 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;
}
free(scratch_buf);
if (!decryption_ok)
- NTRU_RET(NTRU_FAIL);
- return result;
+ {
+ return NTRU_FAIL;
+ }
+
+ return result;
}
*
* 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
* 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.
*/
/* 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 */
/* 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;
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;
}
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,
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));
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
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,
(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 */
* 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
*
* 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
*
*/
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 */
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)
/* 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)
{
--octets_available;
}
}
+ mgf1->destroy(mgf1);
- NTRU_RET(NTRU_OK);
+ return NTRU_OK;
}
* 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
*
/******************************************************************************
*
- * 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,
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 */
#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
*
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 */
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;
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,
/* init used-index array */
- used = mgf_out + octets_available;
+ used = buf + octets_available;
memset(used, 0, N);
/* generate indices (IGF-2) for all polynomials */
/* 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 */
/* form index and check if unique */
index %= N;
- if (!used[index]) {
+ if (!used[index])
+ {
used[index] = 1;
indices[index_cnt] = index;
++index_cnt;
/* 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;
}
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++)
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;
}
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;
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;
/* until f(X) = 1 */
- while (!done) {
+ while (!done)
+ {
/* while f[0] = 0, f(X) /= X, c(X) *= X, k++ */
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 */
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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_ @}*/
+
#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
*/
}
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;
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);