Added own MGF1 mask generating function

This commit is contained in:
Andreas Steffen
2013-12-05 22:55:47 +01:00
parent 78affed0a0
commit fdc6c682b2
11 changed files with 709 additions and 438 deletions
+6 -3
View 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
@@ -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.
*/
@@ -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 */
@@ -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
*
@@ -63,18 +63,14 @@
* 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 */
@@ -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
*
@@ -24,93 +24,19 @@
/******************************************************************************
*
* 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)
{
return retcode;
}
octets = mgf_out;
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;
}
}
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)
{
return retcode;
}
octets = mgf_out;
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;
}
}
if (*octets < 243)
{
@@ -213,8 +144,9 @@ ntru_mgftp1(
--octets_available;
}
}
mgf1->destroy(mgf1);
NTRU_RET(NTRU_OK);
return NTRU_OK;
}
@@ -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.
*
*****************************************************************************/
@@ -39,32 +39,6 @@
#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 */
@@ -34,10 +34,12 @@
#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++ */
@@ -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 */
+177
View File
@@ -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);
@@ -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_ @}*/
+171
View File
@@ -17,11 +17,15 @@
#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);