Added own MGF1 mask generating function
This commit is contained in:
@@ -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, ¶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;
|
||||
}
|
||||
@@ -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, ¶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
|
||||
@@ -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 */
|
||||
|
||||
+38
-106
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+3
-31
@@ -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 */
|
||||
|
||||
@@ -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_ @}*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user